X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavdevice%2Fx11grab.c;h=e204872d06f1091025d217b6519750343aa675f8;hb=8400607267458371398b0d3f170b6c0d9c688453;hp=fdc8a6d22fd23b2012ba456a9b5dc922ba0136f4;hpb=6dc30b25c5513f6f02077825411377e167415d52;p=ffmpeg diff --git a/libavdevice/x11grab.c b/libavdevice/x11grab.c index fdc8a6d22fd..e204872d06f 100644 --- a/libavdevice/x11grab.c +++ b/libavdevice/x11grab.c @@ -35,10 +35,10 @@ * and Edouard Gomez . */ -#define _XOPEN_SOURCE 600 - #include "config.h" -#include "libavformat/avformat.h" +#include "libavutil/log.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" #include #include #include @@ -48,16 +48,19 @@ #include #include #include +#include "avdevice.h" /** * X11 Device Demuxer context */ struct x11_grab { + const AVClass *class; /**< Class for private options. */ int frame_size; /**< Size in bytes of a grabbed frame */ AVRational time_base; /**< Time base */ int64_t time_frame; /**< Current time */ + char *video_size; /**< String describing video size, set by a private option. */ int height; /**< Height of the grab frame */ int width; /**< Width of the grab frame */ int x_off; /**< Horizontal top-left corner coordinate */ @@ -67,7 +70,8 @@ struct x11_grab XImage *image; /**< X11 image holding the grab */ int use_shm; /**< !0 when using XShm extension */ XShmSegmentInfo shminfo; /**< When using XShm, keeps track of XShm infos */ - int nomouse; + int draw_mouse; /**< Set by a private option. */ + char *framerate; /**< Set by a private option. */ }; /** @@ -93,32 +97,48 @@ x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) int y_off = 0; int use_shm; char *dpyname, *offset; + int ret = 0; + AVRational framerate; dpyname = av_strdup(s1->filename); offset = strchr(dpyname, '+'); if (offset) { sscanf(offset, "%d,%d", &x_off, &y_off); - x11grab->nomouse= strstr(offset, "nomouse"); + x11grab->draw_mouse = !strstr(offset, "nomouse"); *offset= 0; } - av_log(s1, AV_LOG_INFO, "device: %s -> display: %s x: %d y: %d width: %d height: %d\n", s1->filename, dpyname, x_off, y_off, ap->width, ap->height); + 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"); + goto out; + } + if ((ret = av_parse_video_rate(&framerate, x11grab->framerate)) < 0) { + av_log(s1, AV_LOG_ERROR, "Could not parse framerate: %s.\n", x11grab->framerate); + goto out; + } +#if FF_API_FORMAT_PARAMETERS + if (ap->width > 0) + x11grab->width = ap->width; + if (ap->height > 0) + x11grab->height = ap->height; + if (ap->time_base.num) + framerate = (AVRational){ap->time_base.den, ap->time_base.num}; +#endif + av_log(s1, AV_LOG_INFO, "device: %s -> display: %s x: %d y: %d width: %d height: %d\n", + s1->filename, dpyname, x_off, y_off, x11grab->width, x11grab->height); dpy = XOpenDisplay(dpyname); av_freep(&dpyname); if(!dpy) { av_log(s1, AV_LOG_ERROR, "Could not open X display.\n"); - return AVERROR(EIO); - } - - if (ap->width <= 0 || ap->height <= 0 || ap->time_base.den <= 0) { - av_log(s1, AV_LOG_ERROR, "AVParameters don't have video size and/or rate. Use -s and -r.\n"); - return AVERROR(EIO); + ret = AVERROR(EIO); + goto out; } st = av_new_stream(s1, 0); if (!st) { - return AVERROR(ENOMEM); + ret = AVERROR(ENOMEM); + goto out; } av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ @@ -133,13 +153,14 @@ x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) ZPixmap, NULL, &x11grab->shminfo, - ap->width, ap->height); + x11grab->width, x11grab->height); x11grab->shminfo.shmid = shmget(IPC_PRIVATE, image->bytes_per_line * image->height, IPC_CREAT|0777); if (x11grab->shminfo.shmid == -1) { av_log(s1, AV_LOG_ERROR, "Fatal: Can't get shared memory!\n"); - return AVERROR(ENOMEM); + ret = AVERROR(ENOMEM); + goto out; } x11grab->shminfo.shmaddr = image->data = shmat(x11grab->shminfo.shmid, 0, 0); x11grab->shminfo.readOnly = False; @@ -147,12 +168,13 @@ x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) if (!XShmAttach(dpy, &x11grab->shminfo)) { av_log(s1, AV_LOG_ERROR, "Fatal: Failed to attach shared memory!\n"); /* needs some better error subroutine :) */ - return AVERROR(EIO); + ret = AVERROR(EIO); + goto out; } } else { image = XGetImage(dpy, RootWindow(dpy, DefaultScreen(dpy)), x_off,y_off, - ap->width,ap->height, + x11grab->width, x11grab->height, AllPlanes, ZPixmap); } @@ -175,7 +197,8 @@ x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) } else { av_log(s1, AV_LOG_ERROR, "RGB ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); - return AVERROR(EIO); + ret = AVERROR(EIO); + goto out; } break; case 24: @@ -190,38 +213,23 @@ x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) } else { av_log(s1, AV_LOG_ERROR,"rgb ordering at image depth %i not supported ... aborting\n", image->bits_per_pixel); av_log(s1, AV_LOG_ERROR, "color masks: r 0x%.6lx g 0x%.6lx b 0x%.6lx\n", image->red_mask, image->green_mask, image->blue_mask); - return AVERROR(EIO); + ret = AVERROR(EIO); + goto out; } break; case 32: -#if 0 - GetColorInfo (image, &c_info); - if ( c_info.alpha_mask == 0xff000000 && image->green_mask == 0x0000ff00) { - /* byte order is relevant here, not endianness - * endianness is handled by avcodec, but atm no such thing - * as having ABGR, instead of ARGB in a word. Since we - * need this for Solaris/SPARC, but need to do the conversion - * for every frame we do it outside of this loop, cf. below - * this matches both ARGB32 and ABGR32 */ - input_pixfmt = PIX_FMT_ARGB32; - } else { - av_log(s1, AV_LOG_ERROR,"image depth %i not supported ... aborting\n", image->bits_per_pixel); - return AVERROR(EIO); - } -#endif input_pixfmt = PIX_FMT_RGB32; break; default: av_log(s1, AV_LOG_ERROR, "image depth %i not supported ... aborting\n", image->bits_per_pixel); - return -1; + ret = AVERROR(EINVAL); + goto out; } - x11grab->frame_size = ap->width * ap->height * image->bits_per_pixel/8; + x11grab->frame_size = x11grab->width * x11grab->height * image->bits_per_pixel/8; x11grab->dpy = dpy; - x11grab->width = ap->width; - x11grab->height = ap->height; - x11grab->time_base = ap->time_base; - x11grab->time_frame = av_gettime() / av_q2d(ap->time_base); + x11grab->time_base = (AVRational){framerate.den, framerate.num}; + x11grab->time_frame = av_gettime() / av_q2d(x11grab->time_base); x11grab->x_off = x_off; x11grab->y_off = y_off; x11grab->image = image; @@ -229,13 +237,14 @@ x11grab_read_header(AVFormatContext *s1, AVFormatParameters *ap) st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = CODEC_ID_RAWVIDEO; - st->codec->width = ap->width; - st->codec->height = ap->height; + st->codec->width = x11grab->width; + st->codec->height = x11grab->height; st->codec->pix_fmt = input_pixfmt; - st->codec->time_base = ap->time_base; - st->codec->bit_rate = x11grab->frame_size * 1/av_q2d(ap->time_base) * 8; + st->codec->time_base = x11grab->time_base; + st->codec->bit_rate = x11grab->frame_size * 1/av_q2d(x11grab->time_base) * 8; - return 0; +out: + return ret; } /** @@ -402,7 +411,7 @@ x11grab_read_packet(AVFormatContext *s1, AVPacket *pkt) } } - if(!s->nomouse){ + if (s->draw_mouse) { paint_mouse_pointer(image, s); } @@ -438,6 +447,22 @@ x11grab_read_close(AVFormatContext *s1) return 0; } +#define OFFSET(x) offsetof(struct x11_grab, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +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 }, + { NULL }, +}; + +static const AVClass x11_class = { + .class_name = "X11grab indev", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + /** x11 grabber device demuxer declaration */ AVInputFormat ff_x11_grab_device_demuxer = { @@ -449,4 +474,5 @@ AVInputFormat ff_x11_grab_device_demuxer = x11grab_read_packet, x11grab_read_close, .flags = AVFMT_NOFILE, + .priv_class = &x11_class, };