Merge remote-tracking branch 'lukaszmluki/master'
* lukaszmluki/master: lavd/xv: implement repaint message lavd/xv: add window id param lavd/xv: keep aspect ratio Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
		
						commit
						cd4faed893
					
				@ -388,19 +388,26 @@ For example, @code{dual-headed:0.1} would specify screen 1 of display
 | 
				
			|||||||
Check the X11 specification for more detailed information about the
 | 
					Check the X11 specification for more detailed information about the
 | 
				
			||||||
display name format.
 | 
					display name format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@item window_id
 | 
				
			||||||
 | 
					When set to non-zero value then device doesn't create new window,
 | 
				
			||||||
 | 
					but uses existing one with provided @var{window_id}. By default
 | 
				
			||||||
 | 
					this options is set to zero and device creates its own window.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@item window_size
 | 
					@item window_size
 | 
				
			||||||
Set the created window size, can be a string of the form
 | 
					Set the created window size, can be a string of the form
 | 
				
			||||||
@var{width}x@var{height} or a video size abbreviation. If not
 | 
					@var{width}x@var{height} or a video size abbreviation. If not
 | 
				
			||||||
specified it defaults to the size of the input video.
 | 
					specified it defaults to the size of the input video.
 | 
				
			||||||
 | 
					Ignored when @var{window_id} is set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@item window_x
 | 
					@item window_x
 | 
				
			||||||
@item window_y
 | 
					@item window_y
 | 
				
			||||||
Set the X and Y window offsets for the created window. They are both
 | 
					Set the X and Y window offsets for the created window. They are both
 | 
				
			||||||
set to 0 by default. The values may be ignored by the window manager.
 | 
					set to 0 by default. The values may be ignored by the window manager.
 | 
				
			||||||
 | 
					Ignored when @var{window_id} is set.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@item window_title
 | 
					@item window_title
 | 
				
			||||||
Set the window title, if not specified default to the filename
 | 
					Set the window title, if not specified default to the filename
 | 
				
			||||||
specified for the output device.
 | 
					specified for the output device. Ignored when @var{window_id} is set.
 | 
				
			||||||
@end table
 | 
					@end table
 | 
				
			||||||
 | 
					
 | 
				
			||||||
For more information about XVideo see @url{http://www.x.org/}.
 | 
					For more information about XVideo see @url{http://www.x.org/}.
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										110
									
								
								libavdevice/xv.c
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								libavdevice/xv.c
									
									
									
									
									
								
							@ -24,7 +24,6 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * TODO:
 | 
					 * TODO:
 | 
				
			||||||
 * - add support to more formats
 | 
					 * - add support to more formats
 | 
				
			||||||
 * - add support to window id specification
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <X11/Xlib.h>
 | 
					#include <X11/Xlib.h>
 | 
				
			||||||
@ -44,9 +43,12 @@ typedef struct {
 | 
				
			|||||||
    GC gc;
 | 
					    GC gc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Window window;
 | 
					    Window window;
 | 
				
			||||||
 | 
					    int64_t window_id;
 | 
				
			||||||
    char *window_title;
 | 
					    char *window_title;
 | 
				
			||||||
    int window_width, window_height;
 | 
					    int window_width, window_height;
 | 
				
			||||||
    int window_x, window_y;
 | 
					    int window_x, window_y;
 | 
				
			||||||
 | 
					    int dest_x, dest_y;          /**< display area position */
 | 
				
			||||||
 | 
					    unsigned int dest_w, dest_h; /**< display area dimensions */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Display* display;
 | 
					    Display* display;
 | 
				
			||||||
    char *display_name;
 | 
					    char *display_name;
 | 
				
			||||||
@ -103,6 +105,8 @@ static int xv_write_header(AVFormatContext *s)
 | 
				
			|||||||
    unsigned int num_adaptors;
 | 
					    unsigned int num_adaptors;
 | 
				
			||||||
    XvAdaptorInfo *ai;
 | 
					    XvAdaptorInfo *ai;
 | 
				
			||||||
    XvImageFormatValues *fv;
 | 
					    XvImageFormatValues *fv;
 | 
				
			||||||
 | 
					    XColor fgcolor;
 | 
				
			||||||
 | 
					    XWindowAttributes window_attrs;
 | 
				
			||||||
    int num_formats = 0, j, tag, ret;
 | 
					    int num_formats = 0, j, tag, ret;
 | 
				
			||||||
    AVCodecContext *encctx = s->streams[0]->codec;
 | 
					    AVCodecContext *encctx = s->streams[0]->codec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -140,6 +144,8 @@ static int xv_write_header(AVFormatContext *s)
 | 
				
			|||||||
                xv->window_height = av_rescale(xv->window_height, sar.den, sar.num);
 | 
					                xv->window_height = av_rescale(xv->window_height, sar.den, sar.num);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (!xv->window_id) {
 | 
				
			||||||
 | 
					    //TODO: reident
 | 
				
			||||||
    xv->window = XCreateSimpleWindow(xv->display, DefaultRootWindow(xv->display),
 | 
					    xv->window = XCreateSimpleWindow(xv->display, DefaultRootWindow(xv->display),
 | 
				
			||||||
                                     xv->window_x, xv->window_y,
 | 
					                                     xv->window_x, xv->window_y,
 | 
				
			||||||
                                     xv->window_width, xv->window_height,
 | 
					                                     xv->window_width, xv->window_height,
 | 
				
			||||||
@ -152,6 +158,8 @@ static int xv_write_header(AVFormatContext *s)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    XStoreName(xv->display, xv->window, xv->window_title);
 | 
					    XStoreName(xv->display, xv->window, xv->window_title);
 | 
				
			||||||
    XMapWindow(xv->display, xv->window);
 | 
					    XMapWindow(xv->display, xv->window);
 | 
				
			||||||
 | 
					    } else
 | 
				
			||||||
 | 
					        xv->window = xv->window_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (XvQueryAdaptors(xv->display, DefaultRootWindow(xv->display), &num_adaptors, &ai) != Success) {
 | 
					    if (XvQueryAdaptors(xv->display, DefaultRootWindow(xv->display), &num_adaptors, &ai) != Success) {
 | 
				
			||||||
        ret = AVERROR_EXTERNAL;
 | 
					        ret = AVERROR_EXTERNAL;
 | 
				
			||||||
@ -199,33 +207,100 @@ static int xv_write_header(AVFormatContext *s)
 | 
				
			|||||||
    XSync(xv->display, False);
 | 
					    XSync(xv->display, False);
 | 
				
			||||||
    shmctl(xv->yuv_shminfo.shmid, IPC_RMID, 0);
 | 
					    shmctl(xv->yuv_shminfo.shmid, IPC_RMID, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    XGetWindowAttributes(xv->display, xv->window, &window_attrs);
 | 
				
			||||||
 | 
					    fgcolor.red = fgcolor.green = fgcolor.blue = 0;
 | 
				
			||||||
 | 
					    fgcolor.flags = DoRed | DoGreen | DoBlue;
 | 
				
			||||||
 | 
					    XAllocColor(xv->display, window_attrs.colormap, &fgcolor);
 | 
				
			||||||
 | 
					    XSetForeground(xv->display, xv->gc, fgcolor.pixel);
 | 
				
			||||||
 | 
					    //force display area recalculation at first frame
 | 
				
			||||||
 | 
					    xv->window_width = xv->window_height = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
  fail:
 | 
					  fail:
 | 
				
			||||||
    xv_write_trailer(s);
 | 
					    xv_write_trailer(s);
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void compute_display_area(AVFormatContext *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    XVContext *xv = s->priv_data;
 | 
				
			||||||
 | 
					    AVRational sar, dar; /* sample and display aspect ratios */
 | 
				
			||||||
 | 
					    AVStream *st = s->streams[0];
 | 
				
			||||||
 | 
					    AVCodecContext *encctx = st->codec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* compute overlay width and height from the codec context information */
 | 
				
			||||||
 | 
					    sar = st->sample_aspect_ratio.num ? st->sample_aspect_ratio : (AVRational){ 1, 1 };
 | 
				
			||||||
 | 
					    dar = av_mul_q(sar, (AVRational){ encctx->width, encctx->height });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* we suppose the screen has a 1/1 sample aspect ratio */
 | 
				
			||||||
 | 
					    /* fit in the window */
 | 
				
			||||||
 | 
					    if (av_cmp_q(dar, (AVRational){ xv->dest_w, xv->dest_h }) > 0) {
 | 
				
			||||||
 | 
					        /* fit in width */
 | 
				
			||||||
 | 
					        xv->dest_y = xv->dest_h;
 | 
				
			||||||
 | 
					        xv->dest_x = 0;
 | 
				
			||||||
 | 
					        xv->dest_h = av_rescale(xv->dest_w, dar.den, dar.num);
 | 
				
			||||||
 | 
					        xv->dest_y -= xv->dest_h;
 | 
				
			||||||
 | 
					        xv->dest_y /= 2;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        /* fit in height */
 | 
				
			||||||
 | 
					        xv->dest_x = xv->dest_w;
 | 
				
			||||||
 | 
					        xv->dest_y = 0;
 | 
				
			||||||
 | 
					        xv->dest_w = av_rescale(xv->dest_h, dar.num, dar.den);
 | 
				
			||||||
 | 
					        xv->dest_x -= xv->dest_w;
 | 
				
			||||||
 | 
					        xv->dest_x /= 2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int xv_repaint(AVFormatContext *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    XVContext *xv = s->priv_data;
 | 
				
			||||||
 | 
					    XWindowAttributes window_attrs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    XGetWindowAttributes(xv->display, xv->window, &window_attrs);
 | 
				
			||||||
 | 
					    if (window_attrs.width != xv->window_width || window_attrs.height != xv->window_height) {
 | 
				
			||||||
 | 
					        XRectangle rect[2];
 | 
				
			||||||
 | 
					        xv->dest_w = window_attrs.width;
 | 
				
			||||||
 | 
					        xv->dest_h = window_attrs.height;
 | 
				
			||||||
 | 
					        compute_display_area(s);
 | 
				
			||||||
 | 
					        if (xv->dest_x) {
 | 
				
			||||||
 | 
					            rect[0].width  = rect[1].width  = xv->dest_x;
 | 
				
			||||||
 | 
					            rect[0].height = rect[1].height = window_attrs.height;
 | 
				
			||||||
 | 
					            rect[0].y      = rect[1].y      = 0;
 | 
				
			||||||
 | 
					            rect[0].x = 0;
 | 
				
			||||||
 | 
					            rect[1].x = xv->dest_w + xv->dest_x;
 | 
				
			||||||
 | 
					            XFillRectangles(xv->display, xv->window, xv->gc, rect, 2);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (xv->dest_y) {
 | 
				
			||||||
 | 
					            rect[0].width  = rect[1].width  = window_attrs.width;
 | 
				
			||||||
 | 
					            rect[0].height = rect[1].height = xv->dest_y;
 | 
				
			||||||
 | 
					            rect[0].x      = rect[1].x      = 0;
 | 
				
			||||||
 | 
					            rect[0].y = 0;
 | 
				
			||||||
 | 
					            rect[1].y = xv->dest_h + xv->dest_y;
 | 
				
			||||||
 | 
					            XFillRectangles(xv->display, xv->window, xv->gc, rect, 2);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (XvShmPutImage(xv->display, xv->xv_port, xv->window, xv->gc,
 | 
				
			||||||
 | 
					                      xv->yuv_image, 0, 0, xv->image_width, xv->image_height,
 | 
				
			||||||
 | 
					                      xv->dest_x, xv->dest_y, xv->dest_w, xv->dest_h, True) != Success) {
 | 
				
			||||||
 | 
					        av_log(s, AV_LOG_ERROR, "Could not copy image to XV shared memory buffer\n");
 | 
				
			||||||
 | 
					        return AVERROR_EXTERNAL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int write_picture(AVFormatContext *s, AVPicture *pict)
 | 
					static int write_picture(AVFormatContext *s, AVPicture *pict)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    XVContext *xv = s->priv_data;
 | 
					    XVContext *xv = s->priv_data;
 | 
				
			||||||
    XvImage *img = xv->yuv_image;
 | 
					    XvImage *img = xv->yuv_image;
 | 
				
			||||||
    XWindowAttributes window_attrs;
 | 
					 | 
				
			||||||
    uint8_t *data[3] = {
 | 
					    uint8_t *data[3] = {
 | 
				
			||||||
        img->data + img->offsets[0],
 | 
					        img->data + img->offsets[0],
 | 
				
			||||||
        img->data + img->offsets[1],
 | 
					        img->data + img->offsets[1],
 | 
				
			||||||
        img->data + img->offsets[2]
 | 
					        img->data + img->offsets[2]
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					 | 
				
			||||||
    av_image_copy(data, img->pitches, (const uint8_t **)pict->data, pict->linesize,
 | 
					    av_image_copy(data, img->pitches, (const uint8_t **)pict->data, pict->linesize,
 | 
				
			||||||
                  xv->image_format, img->width, img->height);
 | 
					                  xv->image_format, img->width, img->height);
 | 
				
			||||||
    XGetWindowAttributes(xv->display, xv->window, &window_attrs);
 | 
					    return xv_repaint(s);
 | 
				
			||||||
    if (XvShmPutImage(xv->display, xv->xv_port, xv->window, xv->gc,
 | 
					 | 
				
			||||||
                      xv->yuv_image, 0, 0, xv->image_width, xv->image_height, 0, 0,
 | 
					 | 
				
			||||||
                      window_attrs.width, window_attrs.height, True) != Success) {
 | 
					 | 
				
			||||||
        av_log(s, AV_LOG_ERROR, "Could not copy image to XV shared memory buffer\n");
 | 
					 | 
				
			||||||
        return AVERROR_EXTERNAL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int xv_write_packet(AVFormatContext *s, AVPacket *pkt)
 | 
					static int xv_write_packet(AVFormatContext *s, AVPacket *pkt)
 | 
				
			||||||
@ -246,9 +321,21 @@ static int xv_write_frame(AVFormatContext *s, int stream_index, AVFrame **frame,
 | 
				
			|||||||
    return write_picture(s, (AVPicture *)*frame);
 | 
					    return write_picture(s, (AVPicture *)*frame);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int xv_control_message(AVFormatContext *s, int type, void *data, size_t data_size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    switch(type) {
 | 
				
			||||||
 | 
					    case AV_APP_TO_DEV_WINDOW_REPAINT:
 | 
				
			||||||
 | 
					        return xv_repaint(s);
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return AVERROR(ENOSYS);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define OFFSET(x) offsetof(XVContext, x)
 | 
					#define OFFSET(x) offsetof(XVContext, x)
 | 
				
			||||||
static const AVOption options[] = {
 | 
					static const AVOption options[] = {
 | 
				
			||||||
    { "display_name", "set display name",       OFFSET(display_name), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
 | 
					    { "display_name", "set display name",       OFFSET(display_name), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
 | 
				
			||||||
 | 
					    { "window_id",    "set existing window id", OFFSET(window_id),    AV_OPT_TYPE_INT64,  {.i64 = 0 }, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM },
 | 
				
			||||||
    { "window_size",  "set window forced size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
 | 
					    { "window_size",  "set window forced size", OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
 | 
				
			||||||
    { "window_title", "set window title",       OFFSET(window_title), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
 | 
					    { "window_title", "set window title",       OFFSET(window_title), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_ENCODING_PARAM },
 | 
				
			||||||
    { "window_x",     "set window x offset",    OFFSET(window_x),     AV_OPT_TYPE_INT,    {.i64 = 0 }, -INT_MAX, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
 | 
					    { "window_x",     "set window x offset",    OFFSET(window_x),     AV_OPT_TYPE_INT,    {.i64 = 0 }, -INT_MAX, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM },
 | 
				
			||||||
@ -275,6 +362,7 @@ AVOutputFormat ff_xv_muxer = {
 | 
				
			|||||||
    .write_packet   = xv_write_packet,
 | 
					    .write_packet   = xv_write_packet,
 | 
				
			||||||
    .write_uncoded_frame = xv_write_frame,
 | 
					    .write_uncoded_frame = xv_write_frame,
 | 
				
			||||||
    .write_trailer  = xv_write_trailer,
 | 
					    .write_trailer  = xv_write_trailer,
 | 
				
			||||||
 | 
					    .control_message = xv_control_message,
 | 
				
			||||||
    .flags          = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS,
 | 
					    .flags          = AVFMT_NOFILE | AVFMT_VARIABLE_FPS | AVFMT_NOTIMESTAMPS,
 | 
				
			||||||
    .priv_class     = &xv_class,
 | 
					    .priv_class     = &xv_class,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user