[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