summaryrefslogtreecommitdiff
path: root/gnu/packages/patches/ffmpeg-jami-screen-sharing-x11-fix.patch
blob: e54a3467067c0aaf940ea2a9f0885eb50f4f0c67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
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