mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-25 00:32:31 +00:00
lavd/xv: add more supported formats
Add support for following pixel formats: - AV_PIX_FMT_UYVY422 - AV_PIX_FMT_YUYV422 Signed-off-by: Lukasz Marek <lukasz.m.luki@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com>
This commit is contained in:
parent
5d8619595b
commit
57bca5a2b6
@ -51,18 +51,43 @@ typedef struct {
|
|||||||
char *display_name;
|
char *display_name;
|
||||||
|
|
||||||
XvImage* yuv_image;
|
XvImage* yuv_image;
|
||||||
|
enum AVPixelFormat image_format;
|
||||||
int image_width, image_height;
|
int image_width, image_height;
|
||||||
XShmSegmentInfo yuv_shminfo;
|
XShmSegmentInfo yuv_shminfo;
|
||||||
int xv_port;
|
int xv_port;
|
||||||
} XVContext;
|
} 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)
|
static int xv_write_header(AVFormatContext *s)
|
||||||
{
|
{
|
||||||
XVContext *xv = s->priv_data;
|
XVContext *xv = s->priv_data;
|
||||||
unsigned int num_adaptors;
|
unsigned int num_adaptors;
|
||||||
XvAdaptorInfo *ai;
|
XvAdaptorInfo *ai;
|
||||||
XvImageFormatValues *fv;
|
XvImageFormatValues *fv;
|
||||||
int num_formats = 0, j;
|
int num_formats = 0, j, tag;
|
||||||
AVCodecContext *encctx = s->streams[0]->codec;
|
AVCodecContext *encctx = s->streams[0]->codec;
|
||||||
|
|
||||||
if ( s->nb_streams > 1
|
if ( s->nb_streams > 1
|
||||||
@ -72,6 +97,14 @@ static int xv_write_header(AVFormatContext *s)
|
|||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(tag = xv_get_tag_from_format(encctx->pix_fmt))) {
|
||||||
|
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->image_format = encctx->pix_fmt;
|
||||||
|
|
||||||
xv->display = XOpenDisplay(xv->display_name);
|
xv->display = XOpenDisplay(xv->display_name);
|
||||||
if (!xv->display) {
|
if (!xv->display) {
|
||||||
av_log(s, AV_LOG_ERROR, "Could not open the X11 display '%s'\n", xv->display_name);
|
av_log(s, AV_LOG_ERROR, "Could not open the X11 display '%s'\n", xv->display_name);
|
||||||
@ -100,18 +133,11 @@ static int xv_write_header(AVFormatContext *s)
|
|||||||
xv->xv_port = ai[0].base_id;
|
xv->xv_port = ai[0].base_id;
|
||||||
XvFreeAdaptorInfo(ai);
|
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);
|
fv = XvListImageFormats(xv->display, xv->xv_port, &num_formats);
|
||||||
if (!fv)
|
if (!fv)
|
||||||
return AVERROR_EXTERNAL;
|
return AVERROR_EXTERNAL;
|
||||||
for (j = 0; j < num_formats; j++) {
|
for (j = 0; j < num_formats; j++) {
|
||||||
if (fv[j].id == MKTAG('I','4','2','0')) {
|
if (fv[j].id == tag) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,15 +145,15 @@ static int xv_write_header(AVFormatContext *s)
|
|||||||
|
|
||||||
if (j >= num_formats) {
|
if (j >= num_formats) {
|
||||||
av_log(s, AV_LOG_ERROR,
|
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);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
xv->gc = XCreateGC(xv->display, xv->window, 0, 0);
|
xv->gc = XCreateGC(xv->display, xv->window, 0, 0);
|
||||||
xv->image_width = encctx->width;
|
xv->image_width = encctx->width;
|
||||||
xv->image_height = encctx->height;
|
xv->image_height = encctx->height;
|
||||||
xv->yuv_image = XvShmCreateImage(xv->display, xv->xv_port,
|
xv->yuv_image = XvShmCreateImage(xv->display, xv->xv_port, tag, 0,
|
||||||
MKTAG('I','4','2','0'), 0,
|
|
||||||
xv->image_width, xv->image_height, &xv->yuv_shminfo);
|
xv->image_width, xv->image_height, &xv->yuv_shminfo);
|
||||||
xv->yuv_shminfo.shmid = shmget(IPC_PRIVATE, xv->yuv_image->data_size,
|
xv->yuv_shminfo.shmid = shmget(IPC_PRIVATE, xv->yuv_image->data_size,
|
||||||
IPC_CREAT | 0777);
|
IPC_CREAT | 0777);
|
||||||
@ -157,7 +183,7 @@ static int xv_write_packet(AVFormatContext *s, AVPacket *pkt)
|
|||||||
|
|
||||||
avpicture_fill(&pict, pkt->data, ctx->pix_fmt, ctx->width, ctx->height);
|
avpicture_fill(&pict, pkt->data, ctx->pix_fmt, ctx->width, ctx->height);
|
||||||
av_image_copy(data, img->pitches, (const uint8_t **)pict.data, pict.linesize,
|
av_image_copy(data, img->pitches, (const uint8_t **)pict.data, pict.linesize,
|
||||||
AV_PIX_FMT_YUV420P, img->width, img->height);
|
xv->image_format, img->width, img->height);
|
||||||
|
|
||||||
XGetWindowAttributes(xv->display, xv->window, &window_attrs);
|
XGetWindowAttributes(xv->display, xv->window, &window_attrs);
|
||||||
if (XvShmPutImage(xv->display, xv->xv_port, xv->window, xv->gc,
|
if (XvShmPutImage(xv->display, xv->xv_port, xv->window, xv->gc,
|
||||||
|
Loading…
Reference in New Issue
Block a user