Hi,
On Sat, 30 Jul 2011 20:26:32 +0800, Yu-Jie Lin <[email protected]> wrote:
> Hi,
>
> Example commands:
>
> ./ffmpeg -f x11grab -s cif -r 25 -i ':0.0;followmouse' /tmp/out.mpg
> ./ffmpeg -f x11grab -s cif -r 25 -i ':0.0;followmouse=100' /tmp/out.mpg
>
> In first command, the grabbing region moves as mouse moves, mouse
> pointer will be kept at center unless close to screen edges. The
> second command, the region only moves when mouse pointer reaches
> within 100 pixels to the edges of current grabbing region.
>
> There will be a second patch to be posted right after this, which
> renders a rectangle box to indicate current grabbing region.
>
> (Aside: I have tried to submit a similar patch to FFmpeg-devel, but
> after a week with no response, so I decided to continue making the
> indication box and forgot the patch submission. Yesterday, I saw the
> forwarded notice to FFmpeg-devel about the upcoming (or ongoing
> already) major changes on libav. That's my first time heard of libav,
> then I checked the logs of x11grabc, it seems the recent changes were
> made from libav. So, I think I should try here instead of bumping my
> post there.)
>
> Sincerely yours,
> Yu-Jie Lin
> From 9d3505ae4a00f6576048f4058aaeaff902ee0157 Mon Sep 17 00:00:00 2001
> From: Yu-Jie Lin <[email protected]>
> Date: Sat, 30 Jul 2011 18:46:36 +0800
> Subject: [PATCH 1/2] x11grab: add followmouse option.
>
> Two modes of followmouse are added: a) appending ";followmouse" to input
> file name will move grabbing region to where mouse pointer at center;
> b) appending ";followmouse=PIXELES" will only move when pointer reaches
> with in PIXELES to the edge of grabbing region.
>
> Signed-off-by: Yu-Jie Lin <[email protected]>
> ---
> doc/ffmpeg.texi | 16 +++++++++++
> doc/indevs.texi | 14 ++++++++++
> libavdevice/x11grab.c | 69
> ++++++++++++++++++++++++++++++++++++++++++++++---
> 3 files changed, 95 insertions(+), 4 deletions(-)
>
> diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
> index 4dca5d8..9b3728b 100644
> --- a/doc/ffmpeg.texi
> +++ b/doc/ffmpeg.texi
> @@ -903,6 +903,22 @@ ffmpeg -f x11grab -s cif -r 25 -i :0.0+10,20 /tmp/out.mpg
> 0.0 is display.screen number of your X11 server, same as the DISPLAY
> environment
> variable. 10 is the x-offset and 20 the y-offset for the grabbing.
>
> +@example
> +ffmpeg -f x11grab -s cif -r 25 -i ':0.0;followmouse' /tmp/out.mpg
> +@end example
> +
> +0.0 is display.screen number of your X11 server, same as the DISPLAY
> environment
> +variable. Grabbing region follows the mouse pointer, which stays at center of
> +grabbing region.
> +
> +@example
> +ffmpeg -f x11grab -s cif -r 25 -i ':0.0;followmouse=100' /tmp/out.mpg
> +@end example
> +
> +0.0 is display.screen number of your X11 server, same as the DISPLAY
> environment
> +variable. Grabbing region follows the mouse pointer, but only when mouse
> +pointer reaches within 100 pixels to the edge of grabbing region.
> +
> @section Video and Audio file format conversion
>
> Any supported file format and protocol can serve as input to ffmpeg:
> diff --git a/doc/indevs.texi b/doc/indevs.texi
> index c5e04b0..3876807 100644
> --- a/doc/indevs.texi
> +++ b/doc/indevs.texi
> @@ -227,6 +227,7 @@ This device allows to capture a region of an X11 display.
> The filename passed as input has the syntax:
> @example
>
> [@var{hostname}]:@var{display_number}.@var{screen_number}[+@var{x_offset},@var{y_offset}]
> +[;followmouse[=@var{follow_mouse}]]
> @end example
>
> @var{hostname}:@var{display_number}.@var{screen_number} specifies the
> @@ -251,4 +252,17 @@ ffmpeg -f x11grab -r 25 -s cif -i :0.0 out.mpg
> ffmpeg -f x11grab -25 -s cif -i :0.0+10,20 out.mpg
> @end example
>
> +If "followmouse" is specified, then the grabbing region follows the mouse
> +pointer and keeps pointer at center of region; and if @var{follow_mouse} is
> also
> +specified, then grabbing region only moves when mouse pointer reaches within
> +@var{follow_mouse} pixels to the edge of region.
> +
> +For example:
> +@example
> +ffmpeg -f x11grab -r 25 -s cif -i ':0.0;followmouse' out.mpg
> +
> +# Moving grabbing region only when mouse reaches within 100 pixels to edge
> +ffmpeg -f x11grab -r 25 -s cif -i ':0.0;followmouse=100' out.mpg
> +@end example
> +
> @c man end INPUT DEVICES
> diff --git a/libavdevice/x11grab.c b/libavdevice/x11grab.c
> index 80507ab..c04c198 100644
> --- a/libavdevice/x11grab.c
> +++ b/libavdevice/x11grab.c
> @@ -71,6 +71,7 @@ struct x11_grab
> int use_shm; /**< !0 when using XShm extension */
> XShmSegmentInfo shminfo; /**< When using XShm, keeps track of XShm infos
> */
> int draw_mouse; /**< Set by a private option. */
> + int follow_mouse; /**< Set by a private option. */
> char *framerate; /**< Set by a private option. */
> };
>
> @@ -95,6 +96,9 @@ x11grab_read_header(AVFormatContext *s1, AVFormatParameters
> *ap)
> XImage *image;
> int x_off = 0;
> int y_off = 0;
> + int screen;
> + int screen_w, screen_h;
> + Window w;
> int use_shm;
> char *param, *offset;
> int ret = 0;
> @@ -105,8 +109,15 @@ x11grab_read_header(AVFormatContext *s1,
> AVFormatParameters *ap)
> if (offset) {
> sscanf(offset, "%d,%d", &x_off, &y_off);
> x11grab->draw_mouse = !strstr(offset, "nomouse");
> - *offset= 0;
> }
> + x11grab->follow_mouse = 0;
> + if (offset = strstr(param, ";followmouse")) {
> + x11grab->follow_mouse = -1;
> + sscanf(offset, ";followmouse=%d", &x11grab->follow_mouse);
> + }
> + /* trim dpyname to only [hostname]:<display_number>.<screen_number> */
> + if (offset = strpbrk(param, "+;"))
> + *offset = 0;
>
As Luca already said, this part is unnecessary. Stacking unrelated
things onto "filename" is a relic from the time when we didn't have
demuxer-specific option. Now we do, so there's no need for this anymore.
fftools will automatically generate a commandline option '-follow_mouse
<number>' from the AVOption definition below.
> if ((ret = av_parse_video_size(&x11grab->width, &x11grab->height,
> x11grab->video_size)) < 0) {
> av_log(s1, AV_LOG_ERROR, "Couldn't parse video size.\n");
> @@ -141,6 +152,19 @@ x11grab_read_header(AVFormatContext *s1,
> AVFormatParameters *ap)
> }
> av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
>
> + screen = DefaultScreen(dpy);
> + screen_w = DisplayWidth(dpy, screen);
> + screen_h = DisplayHeight(dpy, screen);
> +
You can move those two along with their definitions inside the if(),
they're not used outside.
> + if (x11grab->follow_mouse) {
> + XQueryPointer(dpy, RootWindow(dpy, screen), &w, &w, &x_off, &y_off,
> &ret, &ret, &ret);
> + x_off -= x11grab->width >> 1;
> + y_off -= x11grab->height >> 1;
There's no shame in using / 2 ;)
> + x_off = FFMIN(FFMAX(x_off, 0), screen_w - x11grab->width);
> + y_off = FFMIN(FFMAX(y_off, 0), screen_h - x11grab->height);
> + av_log(s1, AV_LOG_INFO, "followmouse is enabled, resetting grabbing
> region to x: %d y: %d\n", x_off, y_off);
> + }
> +
> use_shm = XShmQueryExtension(dpy);
> av_log(s1, AV_LOG_INFO, "shared memory extension %s found\n", use_shm ?
> "" : "not");
>
> @@ -171,7 +195,7 @@ x11grab_read_header(AVFormatContext *s1,
> AVFormatParameters *ap)
> goto out;
> }
> } else {
> - image = XGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)),
> + image = XGetImage(dpy, RootWindow(dpy, screen),
> x_off,y_off,
> x11grab->width, x11grab->height,
> AllPlanes, ZPixmap);
> @@ -374,6 +398,13 @@ x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
> int x_off = s->x_off;
> int y_off = s->y_off;
>
> + int screen;
> + Window root, w;
> + int screen_w;
> + int screen_h;
> + int x, y, _;
> + int follow_mouse = s->follow_mouse;
> +
Again, variables only used inside the if(follow_mouse) should be
declared there. And the names could use some improving, like 'x' ->
'pointer_x' or something like that is more readable IMO/.
> int64_t curtime, delay;
> struct timespec ts;
>
> @@ -400,12 +431,41 @@ x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
> pkt->size = s->frame_size;
> pkt->pts = curtime;
>
> + screen = DefaultScreen(dpy);
> + root = RootWindow(dpy, screen);
> + if (follow_mouse) {
> + screen_w = DisplayWidth(dpy, screen);
> + screen_h = DisplayHeight(dpy, screen);
> + XQueryPointer(dpy, root, &w, &w, &x, &y, &_, &_, &_);
> + if (follow_mouse == -1) {
> + // follow the mouse, put it at center of grabbing region
> + if ((x_off <= screen_w - s->width && x_off >= 0) && x - s->width
> >> 1 != s->x_off)
I don't understand the purpose of those two if()s, if I understand this
correctly, the first condition should always be true, the second would
evaluate to 0 in the line below if it were false, so it's redundant.
> + x_off += copysign(abs(x - s->width >> 1 - s->x_off), x -
> s->width >> 1 - s->x_off);
Isn't copysign(abs(foo), foo) == foo?
--
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel