[FFmpeg-devel] [PATCH 2/3] lavd/xv: add more supported formats

Stefano Sabatini stefasab at gmail.com
Thu Nov 14 12:19:12 CET 2013


On date Wednesday 2013-11-13 23:40:46 +0100, Lukasz Marek encoded:
> 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]);
> +    }

This can be simplified by using the more generic (how much slower?)
av_copy_image().
-- 
FFmpeg = Freak and Fiendish Monstrous Philosofic Elfic God


More information about the ffmpeg-devel mailing list