From patchwork Tue Jan 26 10:23:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: sgerwk-at-aol.com@ffmpeg.org X-Patchwork-Id: 25192 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 5642A44BABF for ; Tue, 26 Jan 2021 12:24:05 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 13E426883D3; Tue, 26 Jan 2021 12:24:05 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from sonic316-13.consmr.mail.bf2.yahoo.com (sonic316-13.consmr.mail.bf2.yahoo.com [74.6.130.123]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id C1F26680518 for ; Tue, 26 Jan 2021 12:23:58 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aol.com; s=a2048; t=1611656637; bh=oGEWv7EaLJ+FAvMo0voYpTieK221gwuCn9UjdjvTsUY=; h=Date:From:To:Subject:References:From:Subject:Reply-To; b=dlmiv1jrBPYvzRj2yFIXncl7x2c83zDTFfbR8l1O6pwTSikGtMdtrpBDv5xJQCA7ZFISe14/c1uCwK+QETiCC17XddbAguGN5Sl5ZxLEQ9y+K+oqblM9t7zxGSs5MynfxNkAiURU46MPuxiNZF+/bYwOPMpElML3m08BLiDlSA65JhB57zgmeIHChtCEvS7F28Bc1YToBFdHjpXVW/42Tnrg1+4Zg5UqBvB4VZGmdGg4C6b45SVoGQ3fXxJmJ94jSnloZqRvm7IRJCmAyJM668SKxprg5jiH0jlTaPSeove6SVLFsIiTFgqfqgiyAAhqSyAj3uluLuQnQtn9cp9h8w== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1611656637; bh=vLERzuyzZ2Yz4r5vNX9cIeRseUR4HidqZdKWZAuwbii=; h=Date:From:To:Subject:From:Subject:Reply-To; b=JsaFkClEEQHXHzZkeQqlf2/Av0wO3s6gX5nsiDfX+1T21kTKXyQRRISbB1lMIhZEb9pKp+CrIDNTI1/dQTnHIk56PHpHZPZ5PyvGQEHzzJKVWMOzlMrrFHgDgqi4/ALiVH0pkvGirfNY8uG46+S48KRdPS5pHKlVb9aaJkuwVxC1m+Cx6Mz86T8hfe+9/4pZh9IB07OwNEodrgEppT32e5UoGVBjYdMKF9Gyc09ArOfYJ8y8mdY6p5ggyTRIKAgMJJOhqfTt4Z5BfolIsIIishIY6VbJGmjbj4oQ8Zpyl40z9zthYCCWrjpFGgebtanXIqqTH/UHbrdDKCLrPoDcfw== X-YMail-OSG: 489YkJcVM1kiV7UPQ4Nvv1ShcoPNLm1iWZ0k8gfsWQZ.OT7.0B2MhfZYVq.EI.H EbxkMAklyZW3uaXqf3k_cgQNZMYuMeCPGZ2O1t5ETwcAOTzMX5UVDjfUVOWyWY9n8jA1q7BoFTPy h212EuM0X9I7ySlLQGaaQwTx4slZ1dOWUM3qMc2j1ZnvqBR.yb9Me4CSLgmeSKAe7mEZYZDo9o76 7uxP9TXfshEYzeKFIxgkgFZRXh.rd6yGlpBLucYH4qBxERCS8HEmk_zP2V561aWqG2rL0hQiBsa9 F1mh9.WJvtGwlT22_94CKfu_U.60Mk5dnjlPSSVDjNTmiIijToI7hSl0X08CiTRg4x20.fai_LNU 0Jxku5It9oPJ9CRPj.Boe4wKCJo_PRBSLuG2PWm0tNX56TvLEQFysNYaiM83LCqYbLVkfdV2N4O. _AaPiHRmpt4da01DXvXmvEL7NJfroOMkNEPdzxI7wKQyytZVmf9K6.VV.rw1YUg2BPjg3C_HTGeQ 6NSxQE0Z9pj4Kf.EOWSaObcXPh5Vo9FJ1hQOAhL9Fbr6Zdudmjm12FWNKwNNAZ_p55sGxCr9Reyz 6tdwo.KSDKFAu_q88OoUUdn1SazofUrpRU8HhYy1eANdcZteXt4kk9JmxuSk4wVf7MldV9oRgHaV gdgGgcoZGS94xFUWi5jxJdb49ZFpkf94hrbLGWHAHzoP2qeKRxYSDC8b69lZQBremD7tlDoSJ22l pkmWOJlpfLWAn6p2tB3lNjTcR_eP5QcHmtUrNpQ7E_E98NDgE.Z2GXM.6W2_yRLNj9_dFdk1p7X_ XazN.Gwx9Zpc_ojb13iv5yY7vZML8i_gMPJNsTUO3GIL.TLKBVo_kTiDlZt0dRYTwuxeZc73ezud _10H2xrBY69QYW.EPvqrGjs_ArgQla2gSWfxMybOGyysMcReYU0cjMAF.nrja0KyntttaEpDeJKE LZFY2IF2fhyBFRjzM.vzSaO53F3LXvjEvT1H2zX2tRbV13SFGd4zi81VdRoMsLRWNSHePQWG.u8Z ySdQRiVUto6Ns7pNR8AreUiBTYrrahVYD2kQ_jNX2sdIBoKqvXdn9ujh_uvAICoQlEB7uc0Swzmp _8EwEiVz1G430ME9P2FgnnXNSu5rBn9hYIsqKpE5K9J7vlS86d5mlfDEt3ey2fBJVZgrnieaG_Rg ZYyx.1TEZDQL69AThXS9Xq7b1_u15fExra89GMVADobqyUE3.ZzOkhecbIWjKSjNKWsWrmAZRU3B vFs_UhEnBmogOtrhiWBUZPy4499elRRrKXz7gmuiY2tf8OwPnMJHo3jYCtRuLi0jUKqWdbkCk6v7 MUHi701gNekY6FSmHwAnhltAUMlO9DYOJfD28TXYaB5K3XRkgTdBBgaPybV.kA1vx6NuzuEVMdwD 7YUg5YTnEoVa.V3vGX5CZbKbg6fr5LYIKT8pWlNiXcsVgTOtmXeVqZlqpgcSlWukaFEs0bbdB0ve V04lN3N.OT1vw.w4YjuAxnNOq39B8EXPBVvy4LyyLVVU7D5oJamA0Tscga1LIOvAWLceGupE06xH aHwvehmFKg__RGI.zM.sPYyhyN.zVYEfzWblTdwnLZbKw2nwPzLV_MNTYQ9Qmi1LLipJ2X5HqrQJ M3Nn3LeX2Uz1HuTvtyNveSv1F2gEBgbi4xdcpAp4cpRi1URfwo5qdJDaDkJphDOhr_qGReINiTKL Q1ulqp9H479AhsMAXQrmzbGsxv4vNfsW7KkgckSh2V5vpUSdSfFyhfRxTO9v4P15fa2bhGmyFeJW Lz0TpkLXa2O8W4yoskWXM2J7wVp1HBh2a09zFAcY949c_1Cs2RRC1PSxrCZpseM9KoAisCT8WVfK N0EpBIsAUjzXhSD7KuVtmMEvw3PUBLBfO63KTkoGNwqlrOB_4MPWBEWS0Kny4XnHu1O4pHliqSgf dVbeDN81Rs2ABObzbuRCnP5L4rbYZs4kondfp08VOrqbI935szwxV..meDfNXpiYThjbSnPi0cFX 7i9p1UWljhJH6t.lFa6y5cHumXKud4V7GYJEErRO80n7S2bzi_45bWSfGIBEdgDjDA1oQEQljBbO ZFB.Ez1g_dcZMFahwuoW_xu3vlynEdFdZjA_uquhJAdMkP8qhF7lR8Sl4cDTYJW1xDH0oaKVGU9w OqYb21.75AwOFD9yG8Ilv.I73Sv7f4LN__c3f3aWpZWMP27gghvATu8hwNA2aI2IqPz1arGqkPsK yuoBQWgLq_ntwME4t860rK75RsYy8QZa_h6mjWnGQm6zw_STo941VV.PlCUG9iZMdtv1KsLvD2ef OnuJMqbvz6O3lA.zml34rGS5d00P2_ZBUO_G8CS7_Jyo- Received: from sonic.gate.mail.ne1.yahoo.com by sonic316.consmr.mail.bf2.yahoo.com with HTTP; Tue, 26 Jan 2021 10:23:57 +0000 Received: by smtp424.mail.ir2.yahoo.com (VZM Hermes SMTP Server) with ESMTPA ID a26df131f359c54395861b43fa925340; Tue, 26 Jan 2021 10:23:54 +0000 (UTC) Date: Tue, 26 Jan 2021 11:23:51 +0100 (CET) From: sgerwk-at-aol.com@ffmpeg.org To: ffmpeg-devel@ffmpeg.org Message-ID: <26fa125b-357-dffb-1787-f7b14f8c667b@aol.com> MIME-Version: 1.0 References: <26fa125b-357-dffb-1787-f7b14f8c667b.ref@aol.com> X-Mailer: WebService/1.1.17642 mail.backend.jedi.jws.acl:role.jedi.acl.token.atz.jws.hermes.aol Apache-HttpAsyncClient/4.1.4 (Java/11.0.8) Subject: [FFmpeg-devel] [PATCH] x11grab: capture a window instead of the whole screen X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" In my previous email the patch got mangled by the web mail interface, so I am sending it again. Sorry for the duplicate. This patch allows ffmpeg to capture a specific window instead of the whole screen. An example: ffmpeg -f x11grab -window_id 0xa00000a -i :0 output.mp4 --- doc/indevs.texi | 3 +++ libavdevice/xcbgrab.c | 19 ++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index 3924d03..0738919 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -1564,6 +1564,9 @@ With @var{follow_mouse}: ffmpeg -f x11grab -follow_mouse centered -show_region 1 -framerate 25 -video_size cif -i :0.0 out.mpg @end example +@item window_id +Grab this window, instead of the whole screen. + @item video_size Set the video frame size. Default is the full desktop. diff --git a/libavdevice/xcbgrab.c b/libavdevice/xcbgrab.c index 95bdc8a..6e4ef5d 100644 --- a/libavdevice/xcbgrab.c +++ b/libavdevice/xcbgrab.c @@ -60,6 +60,7 @@ typedef struct XCBGrabContext { AVRational time_base; int64_t frame_duration; + xcb_window_t window_id; int x, y; int width, height; int frame_size; @@ -82,6 +83,7 @@ typedef struct XCBGrabContext { #define OFFSET(x) offsetof(XCBGrabContext, x) #define D AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { + { "window_id", "Window to capture", OFFSET(window_id), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, { "x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, { "y", "Initial y coordinate.", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, { "grab_x", "Initial x coordinate.", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, D }, @@ -157,7 +159,7 @@ static int xcbgrab_frame(AVFormatContext *s, AVPacket *pkt) XCBGrabContext *c = s->priv_data; xcb_get_image_cookie_t iq; xcb_get_image_reply_t *img; - xcb_drawable_t drawable = c->screen->root; + xcb_drawable_t drawable = c->window_id; xcb_generic_error_t *e = NULL; uint8_t *data; int length; @@ -267,7 +269,7 @@ 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->screen->root; + xcb_drawable_t drawable = c->window_id; xcb_generic_error_t *e = NULL; AVBufferRef *buf; xcb_shm_seg_t segment; @@ -566,7 +568,7 @@ static int create_stream(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, 1000000); - gc = xcb_get_geometry(c->conn, c->screen->root); + gc = xcb_get_geometry(c->conn, c->window_id); geo = xcb_get_geometry_reply(c->conn, gc, NULL); if (!geo) return AVERROR_EXTERNAL; @@ -745,7 +747,7 @@ static int select_region(AVFormatContext *s) press_position = (xcb_point_t){ press->event_x, press->event_y }; rectangle.x = press_position.x; rectangle.y = press_position.y; - xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle); + xcb_poly_rectangle(conn, c->window_id, gc, 1, &rectangle); was_pressed = 1; break; } @@ -754,14 +756,14 @@ static int select_region(AVFormatContext *s) xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)event; xcb_point_t cursor_position = { motion->event_x, motion->event_y }; - xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle); + xcb_poly_rectangle(conn, c->window_id, gc, 1, &rectangle); rectangle = rectangle_from_corners(&press_position, &cursor_position); - xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle); + xcb_poly_rectangle(conn, c->window_id, gc, 1, &rectangle); } break; } case XCB_BUTTON_RELEASE: { - xcb_poly_rectangle(conn, root_window, gc, 1, &rectangle); + xcb_poly_rectangle(conn, c->window_id, gc, 1, &rectangle); done = 1; break; } @@ -825,6 +827,9 @@ static av_cold int xcbgrab_read_header(AVFormatContext *s) return AVERROR(EIO); } + if (c->window_id == 0) + c->window_id = c->screen->root; + if (c->select_region) { ret = select_region(s); if (ret < 0) {