[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