Commit cd4faed8 authored by Michael Niedermayer's avatar Michael Niedermayer

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: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents f57ac372 de705e52
...@@ -388,19 +388,26 @@ For example, @code{dual-headed:0.1} would specify screen 1 of display ...@@ -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/}.
......
...@@ -24,7 +24,6 @@ ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 = { ...@@ -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,
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment