[FFmpeg-devel] [PATCH 2/3] lavd/xv: add more supported formats
Lukasz Marek
lukasz.m.luki at gmail.com
Wed Nov 13 23:40:46 CET 2013
Add support for following pixel formats:
- AV_PIX_FMT_UYVY422
- AV_PIX_FMT_YUYV422
Signed-off-by: Lukasz Marek <lukasz.m.luki at gmail.com>
---
libavdevice/xv.c | 70 +++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 53 insertions(+), 17 deletions(-)
diff --git a/libavdevice/xv.c b/libavdevice/xv.c
index fdc96c9..bfa6ff5 100644
--- a/libavdevice/xv.c
+++ b/libavdevice/xv.c
@@ -50,11 +50,36 @@ typedef struct {
char *display_name;
XvImage* yuv_image;
+ int image_format;
int image_width, image_height;
XShmSegmentInfo yuv_shminfo;
int xv_port;
} XVContext;
+typedef struct XVTagFormatMap
+{
+ int tag;
+ enum AVPixelFormat format;
+} XVTagFormatMap;
+
+static XVTagFormatMap tag_codec_map[] = {
+ { MKTAG('I','4','2','0'), AV_PIX_FMT_YUV420P },
+ { MKTAG('U','Y','V','Y'), AV_PIX_FMT_UYVY422 },
+ { MKTAG('Y','U','Y','2'), AV_PIX_FMT_YUYV422 },
+ { 0, AV_PIX_FMT_NONE }
+};
+
+static int xv_get_tag_from_format(enum AVPixelFormat format)
+{
+ XVTagFormatMap *m = tag_codec_map;
+ int i;
+ for (i = 0; m->tag; m = &tag_codec_map[++i]) {
+ if (m->format == format)
+ return m->tag;
+ }
+ return 0;
+}
+
static int xv_write_header(AVFormatContext *s)
{
XVContext *xv = s->priv_data;
@@ -71,6 +96,14 @@ static int xv_write_header(AVFormatContext *s)
return AVERROR(EINVAL);
}
+ xv->image_format = xv_get_tag_from_format(encctx->pix_fmt);
+ if (!xv->image_format) {
+ av_log(s, AV_LOG_ERROR,
+ "Unsupported pixel format '%s', only yuv420p, uyvy422, yuyv422 are currently supported\n",
+ av_get_pix_fmt_name(encctx->pix_fmt));
+ return AVERROR_PATCHWELCOME;
+ }
+
xv->display = XOpenDisplay(xv->display_name);
if (!xv->display) {
av_log(s, AV_LOG_ERROR, "Could not open the X11 display '%s'\n", xv->display_name);
@@ -99,18 +132,11 @@ static int xv_write_header(AVFormatContext *s)
xv->xv_port = ai[0].base_id;
XvFreeAdaptorInfo(ai);
- if (encctx->pix_fmt != AV_PIX_FMT_YUV420P) {
- av_log(s, AV_LOG_ERROR,
- "Unsupported pixel format '%s', only yuv420p is currently supported\n",
- av_get_pix_fmt_name(encctx->pix_fmt));
- return AVERROR_PATCHWELCOME;
- }
-
fv = XvListImageFormats(xv->display, xv->xv_port, &num_formats);
if (!fv)
return AVERROR_EXTERNAL;
for (j = 0; j < num_formats; j++) {
- if (fv[j].id == MKTAG('I','4','2','0')) {
+ if (fv[j].id == xv->image_format) {
break;
}
}
@@ -118,7 +144,8 @@ static int xv_write_header(AVFormatContext *s)
if (j >= num_formats) {
av_log(s, AV_LOG_ERROR,
- "Device does not support pixel format yuv420p, aborting\n");
+ "Device does not support pixel format %s, aborting\n",
+ av_get_pix_fmt_name(encctx->pix_fmt));
return AVERROR(EINVAL);
}
@@ -126,7 +153,7 @@ static int xv_write_header(AVFormatContext *s)
xv->image_width = encctx->width;
xv->image_height = encctx->height;
xv->yuv_image = XvShmCreateImage(xv->display, xv->xv_port,
- MKTAG('I','4','2','0'), 0,
+ xv->image_format, 0,
xv->image_width, xv->image_height, &xv->yuv_shminfo);
xv->yuv_shminfo.shmid = shmget(IPC_PRIVATE, xv->yuv_image->data_size,
IPC_CREAT | 0777);
@@ -160,13 +187,22 @@ static int xv_write_packet(AVFormatContext *s, AVPacket *pkt)
AVPicture pict;
AVCodecContext *ctx = s->streams[0]->codec;
- avpicture_fill(&pict, pkt->data, ctx->pix_fmt, ctx->width, ctx->height);
- xv_copy_line(img->height, pict.data[0], &img->data[img->offsets[0]],
- pict.linesize[0], img->pitches[0]);
- xv_copy_line(img->height / 2, pict.data[1], &img->data[img->offsets[1]],
- pict.linesize[1], img->pitches[1]);
- xv_copy_line(img->height / 2, pict.data[2], &img->data[img->offsets[2]],
- pict.linesize[2], img->pitches[2]);
+ if (xv->image_format == MKTAG('I','4','2','0')) {
+ avpicture_fill(&pict, pkt->data, ctx->pix_fmt, ctx->width, ctx->height);
+ xv_copy_line(img->height, pict.data[0], &img->data[img->offsets[0]],
+ pict.linesize[0], img->pitches[0]);
+ xv_copy_line(img->height / 2, pict.data[1], &img->data[img->offsets[1]],
+ pict.linesize[1], img->pitches[1]);
+ xv_copy_line(img->height / 2, pict.data[2], &img->data[img->offsets[2]],
+ pict.linesize[2], img->pitches[2]);
+ } else /* if (xv->image_format == MKTAG('U','Y','V','Y') ||
+ xv->image_format == MKTAG('Y','U','Y','2')) */ {
+ if (img->pitches[0] == 2 * img->width)
+ memcpy(&img->data[img->offsets[0]], pkt->data, img->pitches[0] * img->height);
+ else
+ xv_copy_line(img->height, pkt->data, &img->data[img->offsets[0]],
+ 2 * img->width, img->pitches[0]);
+ }
XGetWindowAttributes(xv->display, xv->window, &window_attrs);
if (XvShmPutImage(xv->display, xv->xv_port, xv->window, xv->gc,
--
1.7.10.4
More information about the ffmpeg-devel
mailing list