summary refs log tree commit diff
path: root/gnu/packages/patches
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/packages/patches')
-rw-r--r--gnu/packages/patches/ffmpeg-jami-change-RTCP-ratio.patch27
-rw-r--r--gnu/packages/patches/ffmpeg-jami-libopusdec-enable-FEC.patch127
-rw-r--r--gnu/packages/patches/ffmpeg-jami-libopusenc-enable-FEC.patch50
-rw-r--r--gnu/packages/patches/ffmpeg-jami-libopusenc-reload-packet-loss-at-encode.patch44
-rw-r--r--gnu/packages/patches/ffmpeg-jami-remove-mjpeg-log.patch26
-rw-r--r--gnu/packages/patches/ffmpeg-jami-rtp_ext_abs_send_time.patch71
-rw-r--r--gnu/packages/patches/ffmpeg-jami-screen-sharing-x11-fix.patch302
7 files changed, 647 insertions, 0 deletions
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
+