[FFmpeg-devel] [PATCH 2/3] lavd/xv: add more supported formats
Lukasz M
lukasz.m.luki at gmail.com
Fri Nov 15 00:33:38 CET 2013
On 14 November 2013 12:19, Stefano Sabatini <stefasab at gmail.com> wrote:
> 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().
>
I did that. I haven't tested this format, but I believe performance
difference will be similar to yuv420p.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-lavd-xv-add-more-supported-formats.patch
Type: text/x-patch
Size: 4542 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20131115/52f1c885/attachment.bin>
More information about the ffmpeg-devel
mailing list