From 42ba12888b9296977237f2bca0027d8b017011db Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Fri, 29 Jul 2011 12:55:01 +0200 Subject: Do not convert RGB buffer at once when stride does not fit exact samples. When converting RGB format to RGB format with the same bits per sample, unscaled path performs conversion on the whole buffer at once. For non-multiple-of-16 BGR24 to RGB24 conversion it means that padding at the end of line will be converted too. Since it may be of arbitrary length (e.g. 8 bytes), operating on the whole buffer produces obviously wrong results. Signed-off-by: Ronald S. Bultje --- libswscale/swscale_unscaled.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 59f31c6f64..c0161c24e9 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -382,7 +382,7 @@ static int rgbToRgbWrapper(SwsContext *c, const uint8_t* src[], int srcStride[], if ((dstFormat == PIX_FMT_RGB32_1 || dstFormat == PIX_FMT_BGR32_1) && !isRGBA32(srcFormat)) dstPtr += ALT32_CORR; - if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0) + if (dstStride[0]*srcBpp == srcStride[0]*dstBpp && srcStride[0] > 0 && !(srcStride[0] % srcBpp)) conv(srcPtr, dstPtr + dstStride[0]*srcSliceY, srcSliceH*srcStride[0]); else { int i; -- cgit v1.2.3 From 085791a92e239875fed560c34db87e98083f4092 Mon Sep 17 00:00:00 2001 From: Yu-Jie Lin Date: Sat, 30 Jul 2011 18:46:36 +0800 Subject: x11grab: add follow_mouse AVOption. -follow_mouse centered|PIXELS move grabbing region to where mouse pointer at the center; or only move when pointer reaches within PIXELS to the edge. Signed-off-by: Yu-Jie Lin Signed-off-by: Anton Khirnov --- doc/ffmpeg.texi | 17 ++++++++++++-- doc/indevs.texi | 22 +++++++++++++++++- libavdevice/x11grab.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 95 insertions(+), 6 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 4dca5d8991..8d3968dbf2 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -900,8 +900,21 @@ the DISPLAY environment variable. ffmpeg -f x11grab -s cif -r 25 -i :0.0+10,20 /tmp/out.mpg @end example -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. +10 is the x-offset and 20 the y-offset for the grabbing. + +@example +ffmpeg -f x11grab -follow_mouse centered -s cif -r 25 -i :0.0 /tmp/out.mpg +@end example + +The grabbing region follows the mouse pointer, which stays at the center of +region. + +@example +ffmpeg -f x11grab -follow_mouse 100 -s cif -r 25 -i :0.0 /tmp/out.mpg +@end example + +Only follows when mouse pointer reaches within 100 pixels to the edge of +region. @section Video and Audio file format conversion diff --git a/doc/indevs.texi b/doc/indevs.texi index c5e04b029e..aa001cdb63 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -248,7 +248,27 @@ For example to grab from @file{:0.0} using @file{ffmpeg}: ffmpeg -f x11grab -r 25 -s cif -i :0.0 out.mpg # Grab at position 10,20. -ffmpeg -f x11grab -25 -s cif -i :0.0+10,20 out.mpg +ffmpeg -f x11grab -r 25 -s cif -i :0.0+10,20 out.mpg +@end example + +@subsection @var{follow_mouse} AVOption + +The syntax is: +@example +-follow_mouse centered|@var{PIXELS} +@end example + +When it is specified with "centered", the grabbing region follows the mouse +pointer and keeps the pointer at the center of region; otherwise, the region +follows only when the mouse pointer reaches within @var{PIXELS} (greater than +zero) to the edge of region. + +For example: +@example +ffmpeg -f x11grab -follow_mouse centered -r 25 -s cif -i :0.0 out.mpg + +# Follows only when the mouse pointer reaches within 100 pixels to edge +ffmpeg -f x11grab -follow_mouse 100 -r 25 -s cif -i :0.0 out.mpg @end example @c man end INPUT DEVICES diff --git a/libavdevice/x11grab.c b/libavdevice/x11grab.c index 80507abb05..0b865ad71e 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,7 @@ x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) XImage *image; int x_off = 0; int y_off = 0; + int screen; int use_shm; char *param, *offset; int ret = 0; @@ -141,6 +143,22 @@ x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) } av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ + screen = DefaultScreen(dpy); + + if (x11grab->follow_mouse) { + int screen_w, screen_h; + Window w; + + screen_w = DisplayWidth(dpy, screen); + screen_h = DisplayHeight(dpy, screen); + XQueryPointer(dpy, RootWindow(dpy, screen), &w, &w, &x_off, &y_off, &ret, &ret, &ret); + x_off -= x11grab->width / 2; + y_off -= x11grab->height / 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 +189,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 +392,10 @@ x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) int x_off = s->x_off; int y_off = s->y_off; + int screen; + Window root; + int follow_mouse = s->follow_mouse; + int64_t curtime, delay; struct timespec ts; @@ -400,12 +422,43 @@ 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) { + int screen_w, screen_h; + int pointer_x, pointer_y, _; + Window w; + + screen_w = DisplayWidth(dpy, screen); + screen_h = DisplayHeight(dpy, screen); + XQueryPointer(dpy, root, &w, &w, &pointer_x, &pointer_y, &_, &_, &_); + if (follow_mouse == -1) { + // follow the mouse, put it at center of grabbing region + x_off += pointer_x - s->width / 2 - x_off; + y_off += pointer_y - s->height / 2 - y_off; + } else { + // follow the mouse, but only move the grabbing region when mouse + // reaches within certain pixels to the edge. + if (pointer_x > x_off + s->width - follow_mouse) { + x_off += pointer_x - (x_off + s->width - follow_mouse); + } else if (pointer_x < x_off + follow_mouse) + x_off -= (x_off + follow_mouse) - pointer_x; + if (pointer_y > y_off + s->height - follow_mouse) { + y_off += pointer_y - (y_off + s->height - follow_mouse); + } else if (pointer_y < y_off + follow_mouse) + y_off -= (y_off + follow_mouse) - pointer_y; + } + // adjust grabbing region position if it goes out of screen. + s->x_off = x_off = FFMIN(FFMAX(x_off, 0), screen_w - s->width); + s->y_off = y_off = FFMIN(FFMAX(y_off, 0), screen_h - s->height); + } + if(s->use_shm) { - if (!XShmGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off, AllPlanes)) { + if (!XShmGetImage(dpy, root, image, x_off, y_off, AllPlanes)) { av_log (s1, AV_LOG_INFO, "XShmGetImage() failed\n"); } } else { - if (!xget_zpixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), image, x_off, y_off)) { + if (!xget_zpixmap(dpy, root, image, x_off, y_off)) { av_log (s1, AV_LOG_INFO, "XGetZPixmap() failed\n"); } } @@ -452,6 +505,9 @@ static const AVOption options[] = { { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), FF_OPT_TYPE_STRING, {.str = "vga"}, 0, 0, DEC }, { "framerate", "", OFFSET(framerate), FF_OPT_TYPE_STRING, {.str = "ntsc"}, 0, 0, DEC }, { "draw_mouse", "Draw the mouse pointer.", OFFSET(draw_mouse), FF_OPT_TYPE_INT, { 1 }, 0, 1, DEC }, + { "follow_mouse", "Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.", + OFFSET(follow_mouse), FF_OPT_TYPE_INT, { 0 }, -1, INT_MAX, DEC, "follow_mouse" }, + { "centered", "Keep the mouse pointer at the center of grabbing region when following.", 0, FF_OPT_TYPE_CONST, { -1 }, INT_MIN, INT_MAX, DEC, "follow_mouse" }, { NULL }, }; -- cgit v1.2.3 From 1442d295337dfc83fb66b20444c1b09a803ebb80 Mon Sep 17 00:00:00 2001 From: Yu-Jie Lin Date: Sat, 30 Jul 2011 19:13:43 +0800 Subject: x11grab: add show_region AVOption. Draw the current grabbing region for indication. Signed-off-by: Yu-Jie Lin Signed-off-by: Anton Khirnov --- doc/ffmpeg.texi | 13 ++++++++ doc/indevs.texi | 19 +++++++++++ libavdevice/x11grab.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 8d3968dbf2..f3a4689d6c 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -916,6 +916,19 @@ ffmpeg -f x11grab -follow_mouse 100 -s cif -r 25 -i :0.0 /tmp/out.mpg Only follows when mouse pointer reaches within 100 pixels to the edge of region. +@example +ffmpeg -f x11grab -show_region 1 -s cif -r 25 -i :0.0+10,20 /tmp/out.mpg +@end example + +The grabbing region will be indicated on screen. + +@example +ffmpeg -f x11grab -follow_mouse centered -show_region 1 -s cif -r 25 -i :0.0 /tmp/out.mpg +@end example + +The grabbing region indication will follow the mouse pointer. + + @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 aa001cdb63..fa21c099d5 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -271,4 +271,23 @@ ffmpeg -f x11grab -follow_mouse centered -r 25 -s cif -i :0.0 out.mpg ffmpeg -f x11grab -follow_mouse 100 -r 25 -s cif -i :0.0 out.mpg @end example +@subsection @var{show_region} AVOption + +The syntax is: +@example +-show_region 1 +@end example + +If @var{show_region} AVOption is specified with @var{1}, then the grabbing +region will be indicated on screen. With this option, it's easy to know what is +being grabbed if only a portion of the screen is grabbed. + +For example: +@example +ffmpeg -f x11grab -show_region 1 -r 25 -s cif -i :0.0+10,20 out.mpg + +# With follow_mouse +ffmpeg -f x11grab -follow_mouse centered -show_region 1 -r 25 -s cif -i :0.0 out.mpg +@end example + @c man end INPUT DEVICES diff --git a/libavdevice/x11grab.c b/libavdevice/x11grab.c index 0b865ad71e..09f6b51161 100644 --- a/libavdevice/x11grab.c +++ b/libavdevice/x11grab.c @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -72,9 +73,73 @@ struct x11_grab 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. */ + int show_region; /**< set by a private option. */ char *framerate; /**< Set by a private option. */ + + Window region_win; /**< This is used by show_region option. */ }; +#define REGION_WIN_BORDER 3 +/** + * Draw grabbing region window + * + * @param s x11_grab context + */ +static void +x11grab_draw_region_win(struct x11_grab *s) +{ + Display *dpy = s->dpy; + int screen; + Window win = s->region_win; + GC gc; + + screen = DefaultScreen(dpy); + gc = XCreateGC(dpy, win, 0, 0); + XSetForeground(dpy, gc, WhitePixel(dpy, screen)); + XSetBackground(dpy, gc, BlackPixel(dpy, screen)); + XSetLineAttributes(dpy, gc, REGION_WIN_BORDER, LineDoubleDash, 0, 0); + XDrawRectangle(dpy, win, gc, + 1, 1, + (s->width + REGION_WIN_BORDER * 2) - 1 * 2 - 1, + (s->height + REGION_WIN_BORDER * 2) - 1 * 2 - 1); + XFreeGC(dpy, gc); +} + +/** + * Initialize grabbing region window + * + * @param s x11_grab context + */ +static void +x11grab_region_win_init(struct x11_grab *s) +{ + Display *dpy = s->dpy; + int screen; + XSetWindowAttributes attribs; + XRectangle rect; + + screen = DefaultScreen(dpy); + attribs.override_redirect = True; + s->region_win = XCreateWindow(dpy, RootWindow(dpy, screen), + s->x_off - REGION_WIN_BORDER, + s->y_off - REGION_WIN_BORDER, + s->width + REGION_WIN_BORDER * 2, + s->height + REGION_WIN_BORDER * 2, + 0, CopyFromParent, + InputOutput, CopyFromParent, + CWOverrideRedirect, &attribs); + rect.x = 0; + rect.y = 0; + rect.width = s->width; + rect.height = s->height; + XShapeCombineRectangles(dpy, s->region_win, + ShapeBounding, REGION_WIN_BORDER, REGION_WIN_BORDER, + &rect, 1, ShapeSubtract, 0); + XMapWindow(dpy, s->region_win); + XSelectInput(dpy, s->region_win, ExposureMask | StructureNotifyMask); + x11grab_draw_region_win(s); +} + /** * Initialize the x11 grab device demuxer (public device demuxer API). * @@ -451,6 +516,23 @@ x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) // adjust grabbing region position if it goes out of screen. s->x_off = x_off = FFMIN(FFMAX(x_off, 0), screen_w - s->width); s->y_off = y_off = FFMIN(FFMAX(y_off, 0), screen_h - s->height); + + if (s->show_region && s->region_win) + XMoveWindow(dpy, s->region_win, + s->x_off - REGION_WIN_BORDER, + s->y_off - REGION_WIN_BORDER); + } + + if (s->show_region) { + if (s->region_win) { + XEvent evt; + // clean up the events, and do the initinal draw or redraw. + for (evt.type = NoEventMask; XCheckMaskEvent(dpy, ExposureMask | StructureNotifyMask, &evt); ); + if (evt.type) + x11grab_draw_region_win(s); + } else { + x11grab_region_win_init(s); + } } if(s->use_shm) { @@ -494,6 +576,10 @@ x11grab_read_close(AVFormatContext *s1) x11grab->image = NULL; } + if (x11grab->region_win) { + XDestroyWindow(x11grab->dpy, x11grab->region_win); + } + /* Free X11 display */ XCloseDisplay(x11grab->dpy); return 0; @@ -508,6 +594,7 @@ static const AVOption options[] = { { "follow_mouse", "Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.", OFFSET(follow_mouse), FF_OPT_TYPE_INT, { 0 }, -1, INT_MAX, DEC, "follow_mouse" }, { "centered", "Keep the mouse pointer at the center of grabbing region when following.", 0, FF_OPT_TYPE_CONST, { -1 }, INT_MIN, INT_MAX, DEC, "follow_mouse" }, + { "show_region", "Show the grabbing region.", OFFSET(show_region), FF_OPT_TYPE_INT, { 0 }, 0, 1, DEC }, { NULL }, }; -- cgit v1.2.3 From 18cb40f074ec7e79b20bf9b8c8f19c55784a071c Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Fri, 29 Jul 2011 03:25:34 -0400 Subject: lavc: Deprecate unused FF_ER_VERY_AGGRESSIVE Signed-off-by: Ronald S. Bultje --- doc/ffmpeg.texi | 2 -- libavcodec/avcodec.h | 4 ++++ libavcodec/options.c | 2 ++ libavcodec/version.h | 3 +++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index f3a4689d6c..ca801d31e4 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -469,8 +469,6 @@ FF_ER_COMPLIANT @item 3 FF_ER_AGGRESSIVE @item 4 -FF_ER_VERY_AGGRESSIVE -@item 5 FF_ER_EXPLODE @end table diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 75c107c159..e1fd475ca6 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1445,8 +1445,12 @@ typedef struct AVCodecContext { #define FF_ER_CAREFUL 1 #define FF_ER_COMPLIANT 2 #define FF_ER_AGGRESSIVE 3 +#if FF_API_VERY_AGGRESSIVE #define FF_ER_VERY_AGGRESSIVE 4 #define FF_ER_EXPLODE 5 +#else +#define FF_ER_EXPLODE 4 +#endif /* FF_API_VERY_AGGRESSIVE */ /** * Called at the beginning of each frame to get a buffer for it. diff --git a/libavcodec/options.c b/libavcodec/options.c index 0f0ca2aaa3..1ee02c0417 100644 --- a/libavcodec/options.c +++ b/libavcodec/options.c @@ -183,7 +183,9 @@ static const AVOption options[]={ {"careful", NULL, 0, FF_OPT_TYPE_CONST, {.dbl = FF_ER_CAREFUL }, INT_MIN, INT_MAX, V|D, "er"}, {"compliant", NULL, 0, FF_OPT_TYPE_CONST, {.dbl = FF_ER_COMPLIANT }, INT_MIN, INT_MAX, V|D, "er"}, {"aggressive", NULL, 0, FF_OPT_TYPE_CONST, {.dbl = FF_ER_AGGRESSIVE }, INT_MIN, INT_MAX, V|D, "er"}, +#if FF_API_VERY_AGGRESSIVE {"very_aggressive", NULL, 0, FF_OPT_TYPE_CONST, {.dbl = FF_ER_VERY_AGGRESSIVE }, INT_MIN, INT_MAX, V|D, "er"}, +#endif /* FF_API_VERY_AGGRESSIVE */ {"explode", "abort decoding on error recognition", 0, FF_OPT_TYPE_CONST, {.dbl = FF_ER_EXPLODE }, INT_MIN, INT_MAX, V|D, "er"}, {"has_b_frames", NULL, OFFSET(has_b_frames), FF_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX}, {"block_align", NULL, OFFSET(block_align), FF_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX}, diff --git a/libavcodec/version.h b/libavcodec/version.h index 8d40899557..46e54990b1 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -77,5 +77,8 @@ #ifndef FF_API_DRC_SCALE #define FF_API_DRC_SCALE (LIBAVCODEC_VERSION_MAJOR < 54) #endif +#ifndef FF_API_VERY_AGGRESSIVE +#define FF_API_VERY_AGGRESSIVE (LIBAVCODEC_VERSION_MAJOR < 54) +#endif #endif /* AVCODEC_VERSION_H */ -- cgit v1.2.3