diff options
author | Maxim Cournoyer <maxim.cournoyer@gmail.com> | 2024-01-07 13:16:17 -0500 |
---|---|---|
committer | Maxim Cournoyer <maxim.cournoyer@gmail.com> | 2024-01-09 22:10:12 -0500 |
commit | de002b93dbc3aace41e0fbfc5c717ab73c9a1aa1 (patch) | |
tree | cbc9517964ce3f5447ce211cc4a7805fdaa1dc19 | |
parent | 5a38120c6737067b19fc724b45d15c66eb9b133c (diff) | |
download | guix-de002b93dbc3aace41e0fbfc5c717ab73c9a1aa1.tar.gz guix-de002b93dbc3aace41e0fbfc5c717ab73c9a1aa1.zip |
gnu: ffmpeg-jami: Relocate to (gnu packages video).
To avoid Guile module dependency cycles, inherited packages must be defined in
the same module. Use this opportunity to simplify the patches applying
mechanism, versioning custom patches the same as for other packages.
* gnu/packages/patches/ffmpeg-jami-change-RTCP-ratio.patch: New file.
* gnu/packages/patches/ffmpeg-jami-rtp_ext_abs_send_time.patch: Likewise.
* gnu/packages/patches/ffmpeg-jami-libopusdec-enable-FEC.patch: Likewise.
* gnu/packages/patches/ffmpeg-jami-libopusenc-enable-FEC.patch: Likewise.
* gnu/packages/patches/ffmpeg-jami-libopusenc-reload-packet-loss-at-encode.patch:
Likewise.
* gnu/packages/patches/ffmpeg-jami-remove-mjpeg-log.patch: Likewise.
* gnu/packages/patches/ffmpeg-jami-screen-sharing-x11-fix.patch: Likewise.
* gnu/local.mk (dist_patch_DATA): Register them.
* gnu/packages/jami.scm (jami-apply-custom-patches): Delete procedure.
(%ffmpeg-default-configure-flags): Delete variable.
(ffmpeg-compose-configure-flags): Delete procedure.
(ffmpeg-jami): Move to...
* gnu/packages/video.scm (ffmpeg-jami): ... here. Apply patches to origin and
repatriate configure flags.
Change-Id: Id374fae18240cd76b224915d80b61422635ccb77
-rw-r--r-- | gnu/local.mk | 7 | ||||
-rw-r--r-- | gnu/packages/jami.scm | 266 | ||||
-rw-r--r-- | gnu/packages/patches/ffmpeg-jami-change-RTCP-ratio.patch | 27 | ||||
-rw-r--r-- | gnu/packages/patches/ffmpeg-jami-libopusdec-enable-FEC.patch | 127 | ||||
-rw-r--r-- | gnu/packages/patches/ffmpeg-jami-libopusenc-enable-FEC.patch | 50 | ||||
-rw-r--r-- | gnu/packages/patches/ffmpeg-jami-libopusenc-reload-packet-loss-at-encode.patch | 44 | ||||
-rw-r--r-- | gnu/packages/patches/ffmpeg-jami-remove-mjpeg-log.patch | 26 | ||||
-rw-r--r-- | gnu/packages/patches/ffmpeg-jami-rtp_ext_abs_send_time.patch | 71 | ||||
-rw-r--r-- | gnu/packages/patches/ffmpeg-jami-screen-sharing-x11-fix.patch | 302 | ||||
-rw-r--r-- | gnu/packages/video.scm | 248 |
10 files changed, 901 insertions, 267 deletions
diff --git a/gnu/local.mk b/gnu/local.mk index 5b59aba3af..63d2e333cf 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -1167,6 +1167,13 @@ dist_patch_DATA = \ %D%/packages/patches/fenics-dolfin-demo-init.patch \ %D%/packages/patches/fenics-dolfin-boost.patch \ %D%/packages/patches/fenics-dolfin-config-slepc.patch \ + %D%/packages/patches/ffmpeg-jami-change-RTCP-ratio.patch \ + %D%/packages/patches/ffmpeg-jami-rtp_ext_abs_send_time.patch \ + %D%/packages/patches/ffmpeg-jami-libopusdec-enable-FEC.patch \ + %D%/packages/patches/ffmpeg-jami-libopusenc-enable-FEC.patch \ + %D%/packages/patches/ffmpeg-jami-libopusenc-reload-packet-loss-at-encode.patch \ + %D%/packages/patches/ffmpeg-jami-remove-mjpeg-log.patch \ + %D%/packages/patches/ffmpeg-jami-screen-sharing-x11-fix.patch \ %D%/packages/patches/fifengine-boost-compat.patch \ %D%/packages/patches/fifengine-swig-compat.patch \ %D%/packages/patches/fifo-map-fix-flags-for-gcc.patch \ diff --git a/gnu/packages/jami.scm b/gnu/packages/jami.scm index 3037d090d3..c035a966c7 100644 --- a/gnu/packages/jami.scm +++ b/gnu/packages/jami.scm @@ -89,272 +89,6 @@ (patches (search-patches "jami-disable-integration-tests.patch" "jami-libjami-headers-search.patch")))) -;; Jami maintains a set of patches for some key dependencies (currently -;; pjproject and ffmpeg) of Jami that haven't yet been integrated upstream. -;; This procedure simplifies the process of applying them. -(define jami-apply-custom-patches - #~(lambda* (#:key dep-name patches) - (let ((patches-directory "patches")) - (mkdir-p patches-directory) - (invoke "tar" "-xvf" #$%jami-sources - "-C" patches-directory - "--strip-components=5" - "--wildcards" - (string-append "jami-*/daemon/contrib/src/" dep-name)) - (for-each (lambda (f) - (invoke "patch" "--force" "--ignore-whitespace" "-p1" "-i" - (string-append patches-directory "/" f ".patch"))) - patches)))) - -;; The following variables are configure flags used by ffmpeg-jami. They're -;; from the jami/daemon/contrib/src/ffmpeg/rules.mak file. We try to keep it -;; as close to the official Jami package as possible, to provide all the -;; codecs and extra features that are expected (see: -;; https://review.jami.net/plugins/gitiles/jami-daemon/+/refs/heads/master/contrib/src/ffmpeg/rules.mak). -;; An exception are the ffnvcodec-related switches, which is not packaged in -;; Guix and would not work with Mesa. -(define %ffmpeg-default-configure-flags - '("--disable-everything" - "--enable-zlib" - "--enable-gpl" - "--enable-swscale" - "--enable-bsfs" - "--disable-filters" - "--disable-programs" - "--disable-postproc" - "--disable-protocols" - "--enable-protocol=crypto" - "--enable-protocol=file" - "--enable-protocol=rtp" - "--enable-protocol=srtp" - "--enable-protocol=tcp" - "--enable-protocol=udp" - "--enable-protocol=unix" - "--enable-protocol=pipe" - - ;; Enable muxers/demuxers. - "--disable-demuxers" - "--disable-muxers" - "--enable-muxer=rtp" - "--enable-muxer=g722" - "--enable-muxer=g726" - "--enable-muxer=g726le" - "--enable-muxer=h263" - "--enable-muxer=h264" - "--enable-muxer=hevc" - "--enable-muxer=matroska" - "--enable-muxer=wav" - "--enable-muxer=webm" - "--enable-muxer=ogg" - "--enable-muxer=pcm_s16be" - "--enable-muxer=pcm_s16le" - "--enable-demuxer=rtp" - "--enable-demuxer=mjpeg" - "--enable-demuxer=mjpeg_2000" - "--enable-demuxer=mpegvideo" - "--enable-demuxer=gif" - "--enable-demuxer=image_jpeg_pipe" - "--enable-demuxer=image_png_pipe" - "--enable-demuxer=image_webp_pipe" - "--enable-demuxer=matroska" - "--enable-demuxer=m4v" - "--enable-demuxer=mp3" - "--enable-demuxer=ogg" - "--enable-demuxer=flac" - "--enable-demuxer=wav" - "--enable-demuxer=ac3" - "--enable-demuxer=g722" - "--enable-demuxer=g723_1" - "--enable-demuxer=g726" - "--enable-demuxer=g726le" - "--enable-demuxer=pcm_mulaw" - "--enable-demuxer=pcm_alaw" - "--enable-demuxer=pcm_s16be" - "--enable-demuxer=pcm_s16le" - "--enable-demuxer=h263" - "--enable-demuxer=h264" - "--enable-demuxer=hevc" - - ;; Enable parsers. - "--enable-parser=h263" - "--enable-parser=h264" - "--enable-parser=hevc" - "--enable-parser=mpeg4video" - "--enable-parser=vp8" - "--enable-parser=vp9" - "--enable-parser=opus" - - ;; Encoders/decoders. - "--enable-encoder=adpcm_g722" - "--enable-decoder=adpcm_g722" - "--enable-encoder=adpcm_g726" - "--enable-decoder=adpcm_g726" - "--enable-encoder=adpcm_g726le" - "--enable-decoder=adpcm_g726le" - "--enable-decoder=g729" - "--enable-encoder=g723_1" - "--enable-decoder=g723_1" - "--enable-encoder=rawvideo" - "--enable-decoder=rawvideo" - "--enable-encoder=libx264" - "--enable-decoder=h264" - "--enable-encoder=pcm_alaw" - "--enable-decoder=pcm_alaw" - "--enable-encoder=pcm_mulaw" - "--enable-decoder=pcm_mulaw" - "--enable-encoder=mpeg4" - "--enable-decoder=mpeg4" - "--enable-encoder=libvpx_vp8" - "--enable-decoder=vp8" - "--enable-decoder=vp9" - "--enable-encoder=h263" - "--enable-encoder=h263p" - "--enable-decoder=h263" - "--enable-encoder=mjpeg" - "--enable-decoder=mjpeg" - "--enable-decoder=mjpegb" - "--enable-libspeex" - "--enable-libopus" - "--enable-libvpx" - "--enable-libx264" - "--enable-encoder=libspeex" - "--enable-decoder=libspeex" - "--enable-encoder=libopus" - "--enable-decoder=libopus" - - ;; Encoders/decoders for ringtones and audio streaming. - "--enable-decoder=flac" - "--enable-decoder=vorbis" - "--enable-decoder=aac" - "--enable-decoder=ac3" - "--enable-decoder=eac3" - "--enable-decoder=mp3" - "--enable-decoder=pcm_u24le" - "--enable-decoder=pcm_u32le" - "--enable-decoder=pcm_u8" - "--enable-decoder=pcm_f16le" - "--enable-decoder=pcm_f32le" - "--enable-decoder=pcm_f64le" - "--enable-decoder=pcm_s16le" - "--enable-decoder=pcm_s24le" - "--enable-decoder=pcm_s32le" - "--enable-decoder=pcm_s64le" - "--enable-decoder=pcm_u16le" - "--enable-encoder=pcm_u8" - "--enable-encoder=pcm_f32le" - "--enable-encoder=pcm_f64le" - "--enable-encoder=pcm_s16le" - "--enable-encoder=pcm_s32le" - "--enable-encoder=pcm_s64le" - - "--enable-decoder=pcm_s16be" - "--enable-decoder=pcm_s16be_planar" - "--enable-decoder=pcm_s16le_planar" - "--enable-decoder=pcm_s24be" - "--enable-decoder=pcm_s24le_planar" - "--enable-decoder=pcm_s32be" - "--enable-decoder=pcm_s32le_planar" - "--enable-decoder=pcm_s64be" - "--enable-decoder=pcm_s8" - "--enable-decoder=pcm_s8_planar" - "--enable-decoder=pcm_u16be" - - ;; Encoders/decoders for images. - "--enable-encoder=gif" - "--enable-decoder=gif" - "--enable-encoder=jpegls" - "--enable-decoder=jpegls" - "--enable-encoder=ljpeg" - "--enable-decoder=jpeg2000" - "--enable-encoder=png" - "--enable-decoder=png" - "--enable-encoder=bmp" - "--enable-decoder=bmp" - "--enable-encoder=tiff" - "--enable-decoder=tiff" - - ;; Filters. - "--enable-filter=scale" - "--enable-filter=overlay" - "--enable-filter=amix" - "--enable-filter=amerge" - "--enable-filter=aresample" - "--enable-filter=format" - "--enable-filter=aformat" - "--enable-filter=fps" - "--enable-filter=transpose" - "--enable-filter=pad" - - "--enable-filter=afir" - "--enable-filter=split" - "--enable-filter=drawbox" - "--enable-filter=drawtext" - "--enable-filter=rotate" - "--enable-filter=loop" - "--enable-filter=setpts" - "--enable-filter=movie" - "--enable-filter=alphamerge" - "--enable-filter=boxblur" - "--enable-filter=lut" - "--enable-filter=negate" - "--enable-filter=colorkey" - "--enable-filter=transpose")) - -(define %ffmpeg-linux-configure-flags - '("--enable-pic" - "--extra-cxxflags=-fPIC" - "--extra-cflags=-fPIC" - "--target-os=linux" - "--enable-indev=v4l2" - "--enable-indev=xcbgrab" - "--enable-vdpau" - "--enable-hwaccel=h264_vdpau" - "--enable-hwaccel=mpeg4_vdpau" - "--enable-vaapi" - "--enable-hwaccel=h264_vaapi" - "--enable-hwaccel=mpeg4_vaapi" - "--enable-hwaccel=h263_vaapi" - "--enable-hwaccel=vp8_vaapi" - "--enable-hwaccel=mjpeg_vaapi" - "--enable-hwaccel=hevc_vaapi" - "--enable-encoder=h264_vaapi" - "--enable-encoder=vp8_vaapi" - "--enable-encoder=mjpeg_vaapi" - "--enable-encoder=hevc_vaapi")) - -(define (ffmpeg-compose-configure-flags) - "Compose the configure flag lists of ffmpeg-jami." - #~(append '#$%ffmpeg-default-configure-flags - (if (string-contains #$(%current-system) "linux") - '#$%ffmpeg-linux-configure-flags - '()))) - -(define-public ffmpeg-jami - (package - (inherit ffmpeg) - (name "ffmpeg-jami") - (arguments - (substitute-keyword-arguments (package-arguments ffmpeg) - ((#:configure-flags _ '()) - #~(cons* "--disable-static" - "--enable-shared" - "--disable-stripping" - #$(ffmpeg-compose-configure-flags))) - ((#:phases phases) - #~(modify-phases #$phases - (add-after 'unpack 'apply-patches - (lambda _ - ;; These patches come from: - ;; "jami-project/daemon/contrib/src/ffmpeg/rules.mak". - (#$jami-apply-custom-patches - #:dep-name "ffmpeg" - #:patches '("remove-mjpeg-log" - "change-RTCP-ratio" - "rtp_ext_abs_send_time" - "libopusdec-enable-FEC" - "libopusenc-reload-packet-loss-at-encode" - "screen-sharing-x11-fix")))))))))) - (define-public libjami (package (name "libjami") diff --git a/gnu/packages/patches/ffmpeg-jami-change-RTCP-ratio.patch b/gnu/packages/patches/ffmpeg-jami-change-RTCP-ratio.patch new file mode 100644 index 0000000000..6248165d8c --- /dev/null +++ b/gnu/packages/patches/ffmpeg-jami-change-RTCP-ratio.patch @@ -0,0 +1,27 @@ +From a884b62c9e6f23b9f4369d724e25db2f42dad28d Mon Sep 17 00:00:00 2001 +From: Pierre LESPAGNOL <pierre.lespagnol@savoirfairelinux.com> +Date: Tue, 28 May 2019 16:18:20 -0400 +Subject: [PATCH] Changement du ratio de 0.5% a 5% + +--- + libavformat/rtp.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libavformat/rtp.h b/libavformat/rtp.h +index 54512c6f71..16916ff86a 100644 +--- a/libavformat/rtp.h ++++ b/libavformat/rtp.h +@@ -78,8 +78,8 @@ enum AVCodecID ff_rtp_codec_id(const char *buf, enum AVMediaType codec_type); + #define RTP_VERSION 2 + #define RTP_MAX_SDES 256 /**< maximum text length for SDES */ + +-/* RTCP packets use 0.5% of the bandwidth */ +-#define RTCP_TX_RATIO_NUM 5 ++/* RTCP packets use 2.5% of the bandwidth */ ++#define RTCP_TX_RATIO_NUM 25 + #define RTCP_TX_RATIO_DEN 1000 + + /* An arbitrary id value for RTP Xiph streams - only relevant to indicate +-- +2.17.1 + diff --git a/gnu/packages/patches/ffmpeg-jami-libopusdec-enable-FEC.patch b/gnu/packages/patches/ffmpeg-jami-libopusdec-enable-FEC.patch new file mode 100644 index 0000000000..fb9466a4fc --- /dev/null +++ b/gnu/packages/patches/ffmpeg-jami-libopusdec-enable-FEC.patch @@ -0,0 +1,127 @@ +diff --git a/libavcodec/libopusdec.c b/libavcodec/libopusdec.c +index 9b9a610343..8ec5bfc1ad 100644 +--- a/libavcodec/libopusdec.c ++++ b/libavcodec/libopusdec.c +@@ -45,6 +45,8 @@ struct libopus_context { + #ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST + int apply_phase_inv; + #endif ++ int decode_fec; ++ int64_t expected_next_pts; + }; + + #define OPUS_HEAD_SIZE 19 +@@ -141,6 +143,8 @@ static av_cold int libopus_decode_init(AVCodecContext *avc) + /* Decoder delay (in samples) at 48kHz */ + avc->delay = avc->internal->skip_samples = opus->pre_skip; + ++ opus->expected_next_pts = AV_NOPTS_VALUE; ++ + return 0; + } + +@@ -161,27 +165,82 @@ static int libopus_decode(AVCodecContext *avc, AVFrame *frame, + int *got_frame_ptr, AVPacket *pkt) + { + struct libopus_context *opus = avc->priv_data; +- int ret, nb_samples; ++ uint8_t *outptr; ++ int ret, nb_samples = 0, nb_lost_samples = 0, nb_samples_left; ++ ++ // If FEC is enabled, calculate number of lost samples ++ if (opus->decode_fec && ++ opus->expected_next_pts != AV_NOPTS_VALUE && ++ pkt->pts != AV_NOPTS_VALUE && ++ pkt->pts != opus->expected_next_pts) { ++ // Cap at recovering 120 ms of lost audio. ++ nb_lost_samples = pkt->pts - opus->expected_next_pts; ++ nb_lost_samples = FFMIN(nb_lost_samples, MAX_FRAME_SIZE); ++ } + +- frame->nb_samples = MAX_FRAME_SIZE; ++ frame->nb_samples = MAX_FRAME_SIZE + nb_lost_samples; + if ((ret = ff_get_buffer(avc, frame, 0)) < 0) + return ret; + ++ outptr = frame->data[0]; ++ nb_samples_left = frame->nb_samples; ++ ++ if (opus->decode_fec && nb_lost_samples) { ++ // Try to recover the lost samples with FEC data from this one. ++ // If there's no FEC data, the decoder will do loss concealment instead. ++ if (avc->sample_fmt == AV_SAMPLE_FMT_S16) ++ nb_samples = opus_multistream_decode(opus->dec, pkt->data, pkt->size, ++ (opus_int16 *)outptr, ++ nb_lost_samples, 1); ++ else ++ nb_samples = opus_multistream_decode_float(opus->dec, pkt->data, pkt->size, ++ (float *)outptr, ++ nb_lost_samples, 1); ++ ++ if (nb_samples < 0) { ++ av_log(avc, AV_LOG_ERROR, "Decoding error: %s\n", ++ opus_strerror(nb_samples)); ++ return ff_opus_error_to_averror(nb_samples); ++ } ++ ++ av_log(avc, AV_LOG_WARNING, "Recovered %d samples with FEC/PLC\n", ++ nb_samples); ++ ++ outptr += nb_samples * avc->channels * av_get_bytes_per_sample(avc->sample_fmt); ++ nb_samples_left -= nb_samples; ++ if (pkt->pts != AV_NOPTS_VALUE) { ++ pkt->pts -= nb_samples; ++ frame->pts = pkt->pts; ++ } ++ } ++ ++ // Decode the actual, non-lost data. + if (avc->sample_fmt == AV_SAMPLE_FMT_S16) +- nb_samples = opus_multistream_decode(opus->dec, pkt->data, pkt->size, +- (opus_int16 *)frame->data[0], +- frame->nb_samples, 0); ++ ret = opus_multistream_decode(opus->dec, pkt->data, pkt->size, ++ (opus_int16 *)outptr, ++ nb_samples_left, 0); + else +- nb_samples = opus_multistream_decode_float(opus->dec, pkt->data, pkt->size, +- (float *)frame->data[0], +- frame->nb_samples, 0); ++ ret = opus_multistream_decode_float(opus->dec, pkt->data, pkt->size, ++ (float *)outptr, ++ nb_samples_left, 0); + +- if (nb_samples < 0) { ++ if (ret < 0) { + av_log(avc, AV_LOG_ERROR, "Decoding error: %s\n", +- opus_strerror(nb_samples)); +- return ff_opus_error_to_averror(nb_samples); ++ opus_strerror(ret)); ++ return ff_opus_error_to_averror(ret); + } + ++ nb_samples += ret; ++ ++ if (opus->decode_fec) ++ { ++ // Calculate the next expected pts ++ if (pkt->pts == AV_NOPTS_VALUE) { ++ opus->expected_next_pts = AV_NOPTS_VALUE; ++ } else { ++ opus->expected_next_pts = pkt->pts + nb_samples; ++ } ++ } + #ifndef OPUS_SET_GAIN + { + int i = avc->ch_layout.nb_channels * nb_samples; +@@ -220,6 +279,7 @@ static const AVOption libopusdec_options[] = { + #ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST + { "apply_phase_inv", "Apply intensity stereo phase inversion", OFFSET(apply_phase_inv), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS }, + #endif ++ { "decode_fec", "Decode FEC data or use PLC", OFFSET(decode_fec), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, + { NULL }, + }; + +-- +2.34.1 + diff --git a/gnu/packages/patches/ffmpeg-jami-libopusenc-enable-FEC.patch b/gnu/packages/patches/ffmpeg-jami-libopusenc-enable-FEC.patch new file mode 100644 index 0000000000..43b786c567 --- /dev/null +++ b/gnu/packages/patches/ffmpeg-jami-libopusenc-enable-FEC.patch @@ -0,0 +1,50 @@ +diff --git a/libavcodec/libopusencc.c b/libavcodec/libopusencc.c +index 2a97811d18..40ee7b8fec 100644 +--- a/libavcodec/libopusenc.c ++++ b/libavcodec/libopusenc.c +@@ -33,6 +33,7 @@ + typedef struct LibopusEncOpts { + int vbr; + int application; ++ int enable_fec; + int packet_loss; + int complexity; + float frame_duration; +@@ -143,6 +144,13 @@ + "Unable to set constrained VBR: %s\n", opus_strerror(ret)); + + ret = opus_multistream_encoder_ctl(enc, ++ OPUS_SET_INBAND_FEC(opts->enable_fec)); ++ if (ret != OPUS_OK) ++ av_log(avctx, AV_LOG_WARNING, ++ "Unable to set enable FEC flag percentage: %s\n", ++ opus_strerror(ret)); ++ ++ ret = opus_multistream_encoder_ctl(enc, + OPUS_SET_PACKET_LOSS_PERC(opts->packet_loss)); + if (ret != OPUS_OK) + av_log(avctx, AV_LOG_WARNING, +@@ -452,6 +460,15 @@ + int ret; + int discard_padding; + ++ // Reload packet loss setting ++ ret = opus_multistream_encoder_ctl(opus->enc, ++ OPUS_SET_PACKET_LOSS_PERC(opus->opts.packet_loss)); ++ if (ret != OPUS_OK) ++ av_log(avctx, AV_LOG_WARNING, ++ "Unable to set expected packet loss percentage: %s\n", ++ opus_strerror(ret)); ++ ++ + if (frame) { + ret = ff_af_queue_add(&opus->afq, frame); + if (ret < 0) +@@ -543,6 +560,7 @@ + { "audio", "Favor faithfulness to the input", 0, AV_OPT_TYPE_CONST, { .i64 = OPUS_APPLICATION_AUDIO }, 0, 0, FLAGS, "application" }, + { "lowdelay", "Restrict to only the lowest delay modes", 0, AV_OPT_TYPE_CONST, { .i64 = OPUS_APPLICATION_RESTRICTED_LOWDELAY }, 0, 0, FLAGS, "application" }, + { "frame_duration", "Duration of a frame in milliseconds", OFFSET(frame_duration), AV_OPT_TYPE_FLOAT, { .dbl = 20.0 }, 2.5, 120.0, FLAGS }, ++ { "enable_fec", "Enable forward error correction", OFFSET(enable_fec), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, + { "packet_loss", "Expected packet loss percentage", OFFSET(packet_loss), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 100, FLAGS }, + { "vbr", "Variable bit rate mode", OFFSET(vbr), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 2, FLAGS, "vbr" }, + { "off", "Use constant bit rate", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "vbr" }, diff --git a/gnu/packages/patches/ffmpeg-jami-libopusenc-reload-packet-loss-at-encode.patch b/gnu/packages/patches/ffmpeg-jami-libopusenc-reload-packet-loss-at-encode.patch new file mode 100644 index 0000000000..5c4bd4d3eb --- /dev/null +++ b/gnu/packages/patches/ffmpeg-jami-libopusenc-reload-packet-loss-at-encode.patch @@ -0,0 +1,44 @@ +From dba13d03bc8e827fededc20b0ab1f574a1500f2a Mon Sep 17 00:00:00 2001 +From: Philip-Dylan Gleonec <philip-dylan.gleonec@savoirfairelinux.com> +Date: Thu, 11 Feb 2021 12:25:14 +0100 +Subject: [PATCH 2/2] avcodec/libopusenc: reload packet loss at encode + +An estimation of packet loss is required by libopus to compute its FEC +data. Currently, this estimation is constant, and can not be changed +after configuration. This means an application using libopus through +ffmpeg can not adapt the packet loss estimation when the network +quality degrades. + +This patch makes the encoder reload the packet_loss AVOption before +encoding samples, if fec is enabled. This way an application can modify +the packet loss estimation by changing the AVOption. Typical use-case +is a RTP stream, where packet loss can be estimated from RTCP packets. + +Signed-off-by: Philip-Dylan Gleonec <philip-dylan.gleonec@savoirfairelinux.com> +--- + libavcodec/libopusenc.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/libavcodec/libopusenc.c b/libavcodec/libopusenc.c +index 70d17f802b..c18e8ae7fa 100644 +--- a/libavcodec/libopusenc.c ++++ b/libavcodec/libopusenc.c +@@ -460,6 +460,15 @@ static int libopus_encode(AVCodecContext *avctx, AVPacket *avpkt, + int ret; + int discard_padding; + ++ if (opus->opts.fec) { ++ ret = opus_multistream_encoder_ctl(opus->enc, ++ OPUS_SET_PACKET_LOSS_PERC(opus->opts.packet_loss)); ++ if (ret != OPUS_OK) ++ av_log(avctx, AV_LOG_WARNING, ++ "Unable to set expected packet loss percentage: %s\n", ++ opus_strerror(ret)); ++ } ++ + if (frame) { + ret = ff_af_queue_add(&opus->afq, frame); + if (ret < 0) +-- +2.25.1 + diff --git a/gnu/packages/patches/ffmpeg-jami-remove-mjpeg-log.patch b/gnu/packages/patches/ffmpeg-jami-remove-mjpeg-log.patch new file mode 100644 index 0000000000..595baea9c9 --- /dev/null +++ b/gnu/packages/patches/ffmpeg-jami-remove-mjpeg-log.patch @@ -0,0 +1,26 @@ +From c557a6211f5a29d89fc2ab561e0fb3d8878fb6ad Mon Sep 17 00:00:00 2001 +From: philippegorley <gorley.philippe@gmail.com> +Date: Mon, 17 Dec 2018 15:27:57 -0500 +Subject: [PATCH] remove mjpeg log + +--- + libavcodec/mjpegdec.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c +index d1dca84d36..4a26c23cd4 100644 +--- a/libavcodec/mjpegdec.c ++++ b/libavcodec/mjpegdec.c +@@ -2294,9 +2294,7 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + "restart marker: %d\n", start_code & 0x0f); + /* APP fields */ + } else if (start_code >= APP0 && start_code <= APP15) { +- if ((ret = mjpeg_decode_app(s)) < 0) +- av_log(avctx, AV_LOG_ERROR, "unable to decode APP fields: %s\n", +- av_err2str(ret)); ++ ret = mjpeg_decode_app(s); + /* Comment */ + } else if (start_code == COM) { + ret = mjpeg_decode_com(s); +-- +2.17.1 diff --git a/gnu/packages/patches/ffmpeg-jami-rtp_ext_abs_send_time.patch b/gnu/packages/patches/ffmpeg-jami-rtp_ext_abs_send_time.patch new file mode 100644 index 0000000000..cf52cf972a --- /dev/null +++ b/gnu/packages/patches/ffmpeg-jami-rtp_ext_abs_send_time.patch @@ -0,0 +1,71 @@ +diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c +index 63047beccc..d59ec3dc8c 100644 +--- a/libavformat/rtpenc.c ++++ b/libavformat/rtpenc.c +@@ -28,6 +28,8 @@ + + #include "rtpenc.h" + ++#define EXT_ABS_SEND_TIME ++ + static const AVOption options[] = { + FF_RTP_FLAG_OPTS(RTPMuxContext, flags), + { "payload_type", "Specify RTP payload type", offsetof(RTPMuxContext, payload_type), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 127, AV_OPT_FLAG_ENCODING_PARAM }, +@@ -146,7 +148,11 @@ static int rtp_write_header(AVFormatContext *s1) + s1->pb->max_packet_size); + } else + s1->packet_size = s1->pb->max_packet_size; ++#ifdef EXT_ABS_SEND_TIME ++ if (s1->packet_size <= 20) { ++#else + if (s1->packet_size <= 12) { ++#endif + av_log(s1, AV_LOG_ERROR, "Max packet size %u too low\n", s1->packet_size); + return AVERROR(EIO); + } +@@ -154,7 +160,11 @@ static int rtp_write_header(AVFormatContext *s1) + if (!s->buf) { + return AVERROR(ENOMEM); + } ++#ifdef EXT_ABS_SEND_TIME ++ s->max_payload_size = s1->packet_size - 20; ++#else + s->max_payload_size = s1->packet_size - 12; ++#endif + + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate); +@@ -332,16 +342,34 @@ static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time, int bye) + void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m) + { + RTPMuxContext *s = s1->priv_data; ++ uint64_t ntp64_time; ++ uint32_t absoluteSendTime; + + av_log(s1, AV_LOG_TRACE, "rtp_send_data size=%d\n", len); + + /* build the RTP header */ ++#ifdef EXT_ABS_SEND_TIME ++ avio_w8(s1->pb, RTP_VERSION << 6 | 0x10); // extention bit ++#else + avio_w8(s1->pb, RTP_VERSION << 6); ++#endif + avio_w8(s1->pb, (s->payload_type & 0x7f) | ((m & 0x01) << 7)); + avio_wb16(s1->pb, s->seq); + avio_wb32(s1->pb, s->timestamp); + avio_wb32(s1->pb, s->ssrc); + ++#ifdef EXT_ABS_SEND_TIME ++ avio_wb16(s1->pb, 0xBEDE); // magic word ++ avio_wb16(s1->pb, 0x0001); // length=1 ++ avio_w8(s1->pb, 0x32); // ID=3 and lenght=2 ++ ntp64_time = ff_get_formatted_ntp_time(ff_ntp_time()); ++ absoluteSendTime = (uint32_t)((ntp64_time>> 14) & 0x00ffffff); ++ av_log(s1, AV_LOG_TRACE, "ntp64:%lu, abs_time:%u\n", ntp64_time, absoluteSendTime); ++ avio_w8(s1->pb, (uint8_t)(absoluteSendTime >> 16)); ++ avio_w8(s1->pb, (uint8_t)(absoluteSendTime >> 8 & 0xff)); ++ avio_w8(s1->pb, (uint8_t)(absoluteSendTime & 0xff)); ++#endif ++ + avio_write(s1->pb, buf1, len); + avio_flush(s1->pb); diff --git a/gnu/packages/patches/ffmpeg-jami-screen-sharing-x11-fix.patch b/gnu/packages/patches/ffmpeg-jami-screen-sharing-x11-fix.patch new file mode 100644 index 0000000000..e54a346706 --- /dev/null +++ b/gnu/packages/patches/ffmpeg-jami-screen-sharing-x11-fix.patch @@ -0,0 +1,302 @@ +From c1b210534b15188c964b31dc47e172f8ed4aca55 Mon Sep 17 00:00:00 2001 +From: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> +Date: Tue, 19 Jul 2022 13:35:19 -0300 +Subject: [PATCH] Screen sharing x11 fixes + ++ We can now have a single stream in the x11grab, which can be updated to follow window resizing ++ Due to stream reinit, shm may cause memory issues and was removed ++ Adds one option (is_area) that defines if we are grabing a region of the display/window or the hole screen/window. + +note: This is a custom patch for later rebase +--- + libavdevice/xcbgrab.c | 186 ++++++++++-------------------------------- + 1 file changed, 45 insertions(+), 141 deletions(-) + +diff --git a/libavdevice/xcbgrab.c b/libavdevice/xcbgrab.c +index 64a68ba497..76e654b424 100644 +--- a/libavdevice/xcbgrab.c ++++ b/libavdevice/xcbgrab.c +@@ -29,11 +29,6 @@ + #include <xcb/xfixes.h> + #endif + +-#if CONFIG_LIBXCB_SHM +-#include <sys/shm.h> +-#include <xcb/shm.h> +-#endif +- + #if CONFIG_LIBXCB_SHAPE + #include <xcb/shape.h> + #endif +@@ -53,9 +48,6 @@ typedef struct XCBGrabContext { + xcb_connection_t *conn; + xcb_screen_t *screen; + xcb_window_t window; +-#if CONFIG_LIBXCB_SHM +- AVBufferPool *shm_pool; +-#endif + int64_t time_frame; + AVRational time_base; + int64_t frame_duration; +@@ -72,10 +64,9 @@ typedef struct XCBGrabContext { + int region_border; + int centered; + int select_region; ++ int is_area; + + const char *framerate; +- +- int has_shm; + } XCBGrabContext; + + #define FOLLOW_CENTER -1 +@@ -97,6 +88,7 @@ static const AVOption options[] = { + { "show_region", "Show the grabbing region.", OFFSET(show_region), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D }, + { "region_border", "Set the region border thickness.", OFFSET(region_border), AV_OPT_TYPE_INT, { .i64 = 3 }, 1, 128, D }, + { "select_region", "Select the grabbing region graphically using the pointer.", OFFSET(select_region), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D }, ++ { "is_area", "Define if we are grabing a region of the display/window.", OFFSET(is_area), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, D }, + { NULL }, + }; + +@@ -216,99 +208,6 @@ static int64_t wait_frame(AVFormatContext *s, AVPacket *pkt) + return curtime; + } + +-#if CONFIG_LIBXCB_SHM +-static int check_shm(xcb_connection_t *conn) +-{ +- xcb_shm_query_version_cookie_t cookie = xcb_shm_query_version(conn); +- xcb_shm_query_version_reply_t *reply; +- +- reply = xcb_shm_query_version_reply(conn, cookie, NULL); +- if (reply) { +- free(reply); +- return 1; +- } +- +- return 0; +-} +- +-static void free_shm_buffer(void *opaque, uint8_t *data) +-{ +- shmdt(data); +-} +- +-static AVBufferRef *allocate_shm_buffer(void *opaque, size_t size) +-{ +- xcb_connection_t *conn = opaque; +- xcb_shm_seg_t segment; +- AVBufferRef *ref; +- uint8_t *data; +- int id; +- +- id = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777); +- if (id == -1) +- return NULL; +- +- segment = xcb_generate_id(conn); +- xcb_shm_attach(conn, segment, id, 0); +- data = shmat(id, NULL, 0); +- shmctl(id, IPC_RMID, 0); +- if ((intptr_t)data == -1 || !data) +- return NULL; +- +- ref = av_buffer_create(data, size, free_shm_buffer, (void *)(ptrdiff_t)segment, 0); +- if (!ref) +- shmdt(data); +- +- return ref; +-} +- +-static int xcbgrab_frame_shm(AVFormatContext *s, AVPacket *pkt) +-{ +- XCBGrabContext *c = s->priv_data; +- xcb_shm_get_image_cookie_t iq; +- xcb_shm_get_image_reply_t *img; +- xcb_drawable_t drawable = c->window_id; +- xcb_generic_error_t *e = NULL; +- AVBufferRef *buf; +- xcb_shm_seg_t segment; +- +- buf = av_buffer_pool_get(c->shm_pool); +- if (!buf) { +- av_log(s, AV_LOG_ERROR, "Could not get shared memory buffer.\n"); +- return AVERROR(ENOMEM); +- } +- segment = (xcb_shm_seg_t)(uintptr_t)av_buffer_pool_buffer_get_opaque(buf); +- +- iq = xcb_shm_get_image(c->conn, drawable, +- c->x, c->y, c->width, c->height, ~0, +- XCB_IMAGE_FORMAT_Z_PIXMAP, segment, 0); +- img = xcb_shm_get_image_reply(c->conn, iq, &e); +- +- xcb_flush(c->conn); +- +- if (e) { +- av_log(s, AV_LOG_ERROR, +- "Cannot get the image data " +- "event_error: response_type:%u error_code:%u " +- "sequence:%u resource_id:%u minor_code:%u major_code:%u.\n", +- e->response_type, e->error_code, +- e->sequence, e->resource_id, e->minor_code, e->major_code); +- +- free(e); +- av_buffer_unref(&buf); +- return AVERROR(EACCES); +- } +- +- free(img); +- +- pkt->buf = buf; +- pkt->data = buf->data; +- pkt->size = c->frame_size; +- +- return 0; +-} +-#endif /* CONFIG_LIBXCB_SHM */ +- + #if CONFIG_LIBXCB_XFIXES + static int check_xfixes(xcb_connection_t *conn) + { +@@ -462,14 +361,7 @@ static int xcbgrab_read_packet(AVFormatContext *s, AVPacket *pkt) + if (c->show_region) + xcbgrab_update_region(s, win_x, win_y); + +-#if CONFIG_LIBXCB_SHM +- if (c->has_shm && xcbgrab_frame_shm(s, pkt) < 0) { +- av_log(s, AV_LOG_WARNING, "Continuing without shared memory.\n"); +- c->has_shm = 0; +- } +-#endif +- if (!c->has_shm) +- ret = xcbgrab_frame(s, pkt); ++ ret = xcbgrab_frame(s, pkt); + pkt->dts = pkt->pts = pts; + pkt->duration = c->frame_duration; + +@@ -488,11 +380,8 @@ static av_cold int xcbgrab_read_close(AVFormatContext *s) + { + XCBGrabContext *ctx = s->priv_data; + +-#if CONFIG_LIBXCB_SHM +- av_buffer_pool_uninit(&ctx->shm_pool); +-#endif +- + xcb_disconnect(ctx->conn); ++ ctx->conn = NULL; + + return 0; + } +@@ -572,7 +461,15 @@ static int pixfmt_from_pixmap_format(AVFormatContext *s, int depth, + static int create_stream(AVFormatContext *s) + { + XCBGrabContext *c = s->priv_data; +- AVStream *st = avformat_new_stream(s, NULL); ++ ++ // If we try to open another stream to x11grab, there is no reason ++ // to keep more than one stream in the context. ++ AVStream *st; ++ if (!s->nb_streams) { ++ st = avformat_new_stream(s, NULL); ++ } else { ++ st = s->streams[0]; ++ } + xcb_get_geometry_cookie_t gc; + xcb_get_geometry_reply_t *geo; + int64_t frame_size_bits; +@@ -594,11 +491,26 @@ static int create_stream(AVFormatContext *s) + return AVERROR_EXTERNAL; + } + ++ // av_log(s, AV_LOG_ERROR, "Capture is_area %d\n", c->is_area); ++ // Width and Height are not 0 only when we set a window area to share ++ // This if may be valid only in the first call to create_stream + if (!c->width || !c->height) { ++ // av_log(s, AV_LOG_ERROR, "Capture area!\n"); ++ c->is_area = 0; ++ c->width = geo->width; ++ c->height = geo->height; ++ } ++ // If not a predefined area, then we should follow geometry changes ++ // This can be valid only on the second call onwards ++ if (!c->is_area && (c->width != geo->width || c->height != geo->height)) { + c->width = geo->width; + c->height = geo->height; + } + ++ // av_log(s, AV_LOG_ERROR, "Capture area %dx%d at position %d.%d\n", ++ // c->width, c->height, ++ // c->x, c->y); ++ + if (c->x + c->width > geo->width || + c->y + c->height > geo->height) { + av_log(s, AV_LOG_ERROR, +@@ -628,13 +540,6 @@ static int create_stream(AVFormatContext *s) + } + c->frame_size = frame_size_bits / 8; + +-#if CONFIG_LIBXCB_SHM +- c->shm_pool = av_buffer_pool_init2(c->frame_size + AV_INPUT_BUFFER_PADDING_SIZE, +- c->conn, allocate_shm_buffer, NULL); +- if (!c->shm_pool) +- return AVERROR(ENOMEM); +-#endif +- + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + st->codecpar->width = c->width; +@@ -829,23 +734,26 @@ static av_cold int xcbgrab_read_header(AVFormatContext *s) + sscanf(s->url, "+%d,%d", &c->x, &c->y); + } + +- c->conn = xcb_connect(display_name[0] ? display_name : NULL, &screen_num); +- av_freep(&display_name); ++ if (!c->conn || !c->screen) { ++ xcbgrab_read_close(s); ++ c->conn = xcb_connect(display_name[0] ? display_name : NULL, &screen_num); ++ av_freep(&display_name); + +- if ((ret = xcb_connection_has_error(c->conn))) { +- av_log(s, AV_LOG_ERROR, "Cannot open display %s, error %d.\n", +- s->url[0] ? s->url : "default", ret); +- return AVERROR(EIO); +- } ++ if ((ret = xcb_connection_has_error(c->conn))) { ++ av_log(s, AV_LOG_ERROR, "Cannot open display %s, error %d.\n", ++ s->url[0] ? s->url : "default", ret); ++ return AVERROR(EIO); ++ } + +- setup = xcb_get_setup(c->conn); ++ setup = xcb_get_setup(c->conn); + +- c->screen = get_screen(setup, screen_num); +- if (!c->screen) { +- av_log(s, AV_LOG_ERROR, "The screen %d does not exist.\n", +- screen_num); +- xcbgrab_read_close(s); +- return AVERROR(EIO); ++ c->screen = get_screen(setup, screen_num); ++ if (!c->screen) { ++ av_log(s, AV_LOG_ERROR, "The screen %d does not exist.\n", ++ screen_num); ++ xcbgrab_read_close(s); ++ return AVERROR(EIO); ++ } + } + + if (c->window_id == XCB_NONE) +@@ -876,10 +784,6 @@ static av_cold int xcbgrab_read_header(AVFormatContext *s) + return ret; + } + +-#if CONFIG_LIBXCB_SHM +- c->has_shm = check_shm(c->conn); +-#endif +- + #if CONFIG_LIBXCB_XFIXES + if (c->draw_mouse) { + if (!(c->draw_mouse = check_xfixes(c->conn))) { +-- +2.34.1 + diff --git a/gnu/packages/video.scm b/gnu/packages/video.scm index de812ac762..d751442561 100644 --- a/gnu/packages/video.scm +++ b/gnu/packages/video.scm @@ -50,7 +50,7 @@ ;;; Copyright © 2021 Alexey Abramov <levenson@mmer.org> ;;; Copyright © 2021, 2022, 2023 Andrew Tropin <andrew@trop.in> ;;; Copyright © 2021 David Wilson <david@daviwil.com> -;;; Copyright © 2021, 2022, 2023 Maxim Cournoyer <maxim.cournoyer@gmail.com> +;;; Copyright © 2021, 2022, 2023, 2024 Maxim Cournoyer <maxim.cournoyer@gmail.com> ;;; Copyright © 2020 Hartmut Goebel <h.goebel@crazy-compilers.com> ;;; Copyright © 2021 Raghav Gururajan <rg@raghavgururajan.name> ;;; Copyright © 2021 Thiago Jung Bauermann <bauermann@kolabnow.com> @@ -2000,6 +2000,252 @@ audio/video codec library.") "--enable-static")))) (inputs '())))) +;;; Custom ffmpeg package used by Jami, which incorporates custom patches. +(define-public ffmpeg-jami + (package + (inherit ffmpeg) + (name "ffmpeg-jami") + (source (let ((ffmpeg-origin (package-source ffmpeg))) + (origin + (inherit ffmpeg-origin) + ;; These patches originate come from + ;; <https://review.jami.net/plugins/gitiles/jami-daemon/+/refs/heads/master/contrib/src/ffmpeg/>. + ;; Make sure to keep them update and/or register any new ones + ;; here. + (patches + (append + (origin-patches ffmpeg-origin) + (search-patches + "ffmpeg-jami-remove-mjpeg-log.patch" + "ffmpeg-jami-change-RTCP-ratio.patch" + "ffmpeg-jami-rtp_ext_abs_send_time.patch" + "ffmpeg-jami-libopusdec-enable-FEC.patch" + "ffmpeg-jami-libopusenc-reload-packet-loss-at-encode.patch" + "ffmpeg-jami-screen-sharing-x11-fix.patch")))))) + (arguments + (substitute-keyword-arguments (package-arguments ffmpeg) + ((#:configure-flags _ '()) + #~(list "--disable-static" + "--enable-shared" + "--disable-stripping" + ;; The following variables are configure flags used by + ;; ffmpeg-jami. They're from the + ;; jami/daemon/contrib/src/ffmpeg/rules.mak file. We try to + ;; keep it as close to the official Jami package as possible, + ;; to provide all the codecs and extra features that are + ;; expected (see: + ;; https://review.jami.net/plugins/gitiles/jami-daemon/+/ + ;; refs/heads/master/contrib/src/ffmpeg/rules.mak). + ;; An exception are the ffnvcodec-related switches, which is + ;; not packaged in Guix and would not work with Mesa. + #$@(if (string-contains (%current-system) "linux") + '("--enable-pic" + "--extra-cxxflags=-fPIC" + "--extra-cflags=-fPIC" + "--target-os=linux" + "--enable-indev=v4l2" + "--enable-indev=xcbgrab" + "--enable-vdpau" + "--enable-hwaccel=h264_vdpau" + "--enable-hwaccel=mpeg4_vdpau" + "--enable-vaapi" + "--enable-hwaccel=h264_vaapi" + "--enable-hwaccel=mpeg4_vaapi" + "--enable-hwaccel=h263_vaapi" + "--enable-hwaccel=vp8_vaapi" + "--enable-hwaccel=mjpeg_vaapi" + "--enable-hwaccel=hevc_vaapi" + "--enable-encoder=h264_vaapi" + "--enable-encoder=vp8_vaapi" + "--enable-encoder=mjpeg_vaapi" + "--enable-encoder=hevc_vaapi") + '()) + "--disable-everything" + "--enable-zlib" + "--enable-gpl" + "--enable-swscale" + "--enable-bsfs" + "--disable-filters" + "--disable-programs" + "--disable-postproc" + "--disable-protocols" + "--enable-protocol=crypto" + "--enable-protocol=file" + "--enable-protocol=rtp" + "--enable-protocol=srtp" + "--enable-protocol=tcp" + "--enable-protocol=udp" + "--enable-protocol=unix" + "--enable-protocol=pipe" + + ;; Enable muxers/demuxers. + "--disable-demuxers" + "--disable-muxers" + "--enable-muxer=rtp" + "--enable-muxer=g722" + "--enable-muxer=g726" + "--enable-muxer=g726le" + "--enable-muxer=h263" + "--enable-muxer=h264" + "--enable-muxer=hevc" + "--enable-muxer=matroska" + "--enable-muxer=wav" + "--enable-muxer=webm" + "--enable-muxer=ogg" + "--enable-muxer=pcm_s16be" + "--enable-muxer=pcm_s16le" + "--enable-demuxer=rtp" + "--enable-demuxer=mjpeg" + "--enable-demuxer=mjpeg_2000" + "--enable-demuxer=mpegvideo" + "--enable-demuxer=gif" + "--enable-demuxer=image_jpeg_pipe" + "--enable-demuxer=image_png_pipe" + "--enable-demuxer=image_webp_pipe" + "--enable-demuxer=matroska" + "--enable-demuxer=m4v" + "--enable-demuxer=mp3" + "--enable-demuxer=ogg" + "--enable-demuxer=flac" + "--enable-demuxer=wav" + "--enable-demuxer=ac3" + "--enable-demuxer=g722" + "--enable-demuxer=g723_1" + "--enable-demuxer=g726" + "--enable-demuxer=g726le" + "--enable-demuxer=pcm_mulaw" + "--enable-demuxer=pcm_alaw" + "--enable-demuxer=pcm_s16be" + "--enable-demuxer=pcm_s16le" + "--enable-demuxer=h263" + "--enable-demuxer=h264" + "--enable-demuxer=hevc" + + ;; Enable parsers. + "--enable-parser=h263" + "--enable-parser=h264" + "--enable-parser=hevc" + "--enable-parser=mpeg4video" + "--enable-parser=vp8" + "--enable-parser=vp9" + "--enable-parser=opus" + + ;; Encoders/decoders. + "--enable-encoder=adpcm_g722" + "--enable-decoder=adpcm_g722" + "--enable-encoder=adpcm_g726" + "--enable-decoder=adpcm_g726" + "--enable-encoder=adpcm_g726le" + "--enable-decoder=adpcm_g726le" + "--enable-decoder=g729" + "--enable-encoder=g723_1" + "--enable-decoder=g723_1" + "--enable-encoder=rawvideo" + "--enable-decoder=rawvideo" + "--enable-encoder=libx264" + "--enable-decoder=h264" + "--enable-encoder=pcm_alaw" + "--enable-decoder=pcm_alaw" + "--enable-encoder=pcm_mulaw" + "--enable-decoder=pcm_mulaw" + "--enable-encoder=mpeg4" + "--enable-decoder=mpeg4" + "--enable-encoder=libvpx_vp8" + "--enable-decoder=vp8" + "--enable-decoder=vp9" + "--enable-encoder=h263" + "--enable-encoder=h263p" + "--enable-decoder=h263" + "--enable-encoder=mjpeg" + "--enable-decoder=mjpeg" + "--enable-decoder=mjpegb" + "--enable-libspeex" + "--enable-libopus" + "--enable-libvpx" + "--enable-libx264" + "--enable-encoder=libspeex" + "--enable-decoder=libspeex" + "--enable-encoder=libopus" + "--enable-decoder=libopus" + + ;; Encoders/decoders for ringtones and audio streaming. + "--enable-decoder=flac" + "--enable-decoder=vorbis" + "--enable-decoder=aac" + "--enable-decoder=ac3" + "--enable-decoder=eac3" + "--enable-decoder=mp3" + "--enable-decoder=pcm_u24le" + "--enable-decoder=pcm_u32le" + "--enable-decoder=pcm_u8" + "--enable-decoder=pcm_f16le" + "--enable-decoder=pcm_f32le" + "--enable-decoder=pcm_f64le" + "--enable-decoder=pcm_s16le" + "--enable-decoder=pcm_s24le" + "--enable-decoder=pcm_s32le" + "--enable-decoder=pcm_s64le" + "--enable-decoder=pcm_u16le" + "--enable-encoder=pcm_u8" + "--enable-encoder=pcm_f32le" + "--enable-encoder=pcm_f64le" + "--enable-encoder=pcm_s16le" + "--enable-encoder=pcm_s32le" + "--enable-encoder=pcm_s64le" + + "--enable-decoder=pcm_s16be" + "--enable-decoder=pcm_s16be_planar" + "--enable-decoder=pcm_s16le_planar" + "--enable-decoder=pcm_s24be" + "--enable-decoder=pcm_s24le_planar" + "--enable-decoder=pcm_s32be" + "--enable-decoder=pcm_s32le_planar" + "--enable-decoder=pcm_s64be" + "--enable-decoder=pcm_s8" + "--enable-decoder=pcm_s8_planar" + "--enable-decoder=pcm_u16be" + + ;; Encoders/decoders for images. + "--enable-encoder=gif" + "--enable-decoder=gif" + "--enable-encoder=jpegls" + "--enable-decoder=jpegls" + "--enable-encoder=ljpeg" + "--enable-decoder=jpeg2000" + "--enable-encoder=png" + "--enable-decoder=png" + "--enable-encoder=bmp" + "--enable-decoder=bmp" + "--enable-encoder=tiff" + "--enable-decoder=tiff" + + ;; Filters. + "--enable-filter=scale" + "--enable-filter=overlay" + "--enable-filter=amix" + "--enable-filter=amerge" + "--enable-filter=aresample" + "--enable-filter=format" + "--enable-filter=aformat" + "--enable-filter=fps" + "--enable-filter=transpose" + "--enable-filter=pad" + + "--enable-filter=afir" + "--enable-filter=split" + "--enable-filter=drawbox" + "--enable-filter=drawtext" + "--enable-filter=rotate" + "--enable-filter=loop" + "--enable-filter=setpts" + "--enable-filter=movie" + "--enable-filter=alphamerge" + "--enable-filter=boxblur" + "--enable-filter=lut" + "--enable-filter=negate" + "--enable-filter=colorkey" + "--enable-filter=transpose")))))) + (define-public ffmpegthumbnailer (package (name "ffmpegthumbnailer") |