mirror of https://git.ffmpeg.org/ffmpeg.git
hwcontext_vaapi: Improve format mapping
Give the entries in the VAAPI format map table an explicit type and add functions to do the necessary lookups. Add another field to this table indicating whether the chroma planes are swapped (as in YV12), and use that rather than explicit comparisons where swapping is needed.
This commit is contained in:
parent
930aad6a36
commit
40724026b7
|
@ -87,56 +87,81 @@ typedef struct VAAPIMapping {
|
|||
int flags;
|
||||
} VAAPIMapping;
|
||||
|
||||
#define MAP(va, rt, av) { \
|
||||
VA_FOURCC_ ## va, \
|
||||
VA_RT_FORMAT_ ## rt, \
|
||||
AV_PIX_FMT_ ## av \
|
||||
}
|
||||
// The map fourcc <-> pix_fmt isn't bijective because of the annoying U/V
|
||||
// plane swap cases. The frame handling below tries to hide these.
|
||||
static const struct {
|
||||
typedef struct VAAPIFormat {
|
||||
unsigned int fourcc;
|
||||
unsigned int rt_format;
|
||||
enum AVPixelFormat pix_fmt;
|
||||
} vaapi_format_map[] = {
|
||||
MAP(NV12, YUV420, NV12),
|
||||
MAP(YV12, YUV420, YUV420P), // With U/V planes swapped.
|
||||
MAP(IYUV, YUV420, YUV420P),
|
||||
int chroma_planes_swapped;
|
||||
} VAAPIFormatDescriptor;
|
||||
|
||||
#define MAP(va, rt, av, swap_uv) { \
|
||||
VA_FOURCC_ ## va, \
|
||||
VA_RT_FORMAT_ ## rt, \
|
||||
AV_PIX_FMT_ ## av, \
|
||||
swap_uv, \
|
||||
}
|
||||
// The map fourcc <-> pix_fmt isn't bijective because of the annoying U/V
|
||||
// plane swap cases. The frame handling below tries to hide these.
|
||||
static const VAAPIFormatDescriptor vaapi_format_map[] = {
|
||||
MAP(NV12, YUV420, NV12, 0),
|
||||
#ifdef VA_FOURCC_I420
|
||||
MAP(I420, YUV420, YUV420P),
|
||||
MAP(I420, YUV420, YUV420P, 0),
|
||||
#endif
|
||||
MAP(YV12, YUV420, YUV420P, 1),
|
||||
MAP(IYUV, YUV420, YUV420P, 0),
|
||||
MAP(422H, YUV422, YUV422P, 0),
|
||||
#ifdef VA_FOURCC_YV16
|
||||
MAP(YV16, YUV422, YUV422P), // With U/V planes swapped.
|
||||
MAP(YV16, YUV422, YUV422P, 1),
|
||||
#endif
|
||||
MAP(422H, YUV422, YUV422P),
|
||||
MAP(UYVY, YUV422, UYVY422),
|
||||
MAP(YUY2, YUV422, YUYV422),
|
||||
MAP(411P, YUV411, YUV411P),
|
||||
MAP(422V, YUV422, YUV440P),
|
||||
MAP(444P, YUV444, YUV444P),
|
||||
MAP(Y800, YUV400, GRAY8),
|
||||
MAP(UYVY, YUV422, UYVY422, 0),
|
||||
MAP(YUY2, YUV422, YUYV422, 0),
|
||||
MAP(411P, YUV411, YUV411P, 0),
|
||||
MAP(422V, YUV422, YUV440P, 0),
|
||||
MAP(444P, YUV444, YUV444P, 0),
|
||||
MAP(Y800, YUV400, GRAY8, 0),
|
||||
#ifdef VA_FOURCC_P010
|
||||
MAP(P010, YUV420_10BPP, P010),
|
||||
MAP(P010, YUV420_10BPP, P010, 0),
|
||||
#endif
|
||||
MAP(BGRA, RGB32, BGRA),
|
||||
MAP(BGRX, RGB32, BGR0),
|
||||
MAP(RGBA, RGB32, RGBA),
|
||||
MAP(RGBX, RGB32, RGB0),
|
||||
MAP(BGRA, RGB32, BGRA, 0),
|
||||
MAP(BGRX, RGB32, BGR0, 0),
|
||||
MAP(RGBA, RGB32, RGBA, 0),
|
||||
MAP(RGBX, RGB32, RGB0, 0),
|
||||
#ifdef VA_FOURCC_ABGR
|
||||
MAP(ABGR, RGB32, ABGR),
|
||||
MAP(XBGR, RGB32, 0BGR),
|
||||
MAP(ABGR, RGB32, ABGR, 0),
|
||||
MAP(XBGR, RGB32, 0BGR, 0),
|
||||
#endif
|
||||
MAP(ARGB, RGB32, ARGB),
|
||||
MAP(XRGB, RGB32, 0RGB),
|
||||
MAP(ARGB, RGB32, ARGB, 0),
|
||||
MAP(XRGB, RGB32, 0RGB, 0),
|
||||
};
|
||||
#undef MAP
|
||||
|
||||
static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc)
|
||||
static const VAAPIFormatDescriptor *
|
||||
vaapi_format_from_fourcc(unsigned int fourcc)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++)
|
||||
if (vaapi_format_map[i].fourcc == fourcc)
|
||||
return vaapi_format_map[i].pix_fmt;
|
||||
return &vaapi_format_map[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const VAAPIFormatDescriptor *
|
||||
vaapi_format_from_pix_fmt(enum AVPixelFormat pix_fmt)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++)
|
||||
if (vaapi_format_map[i].pix_fmt == pix_fmt)
|
||||
return &vaapi_format_map[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static enum AVPixelFormat vaapi_pix_fmt_from_fourcc(unsigned int fourcc)
|
||||
{
|
||||
const VAAPIFormatDescriptor *desc;
|
||||
desc = vaapi_format_from_fourcc(fourcc);
|
||||
if (desc)
|
||||
return desc->pix_fmt;
|
||||
else
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
|
@ -461,22 +486,16 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc)
|
|||
AVVAAPIFramesContext *avfc = hwfc->hwctx;
|
||||
VAAPIFramesContext *ctx = hwfc->internal->priv;
|
||||
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
||||
const VAAPIFormatDescriptor *desc;
|
||||
VAImageFormat *expected_format;
|
||||
AVBufferRef *test_surface = NULL;
|
||||
VASurfaceID test_surface_id;
|
||||
VAImage test_image;
|
||||
VAStatus vas;
|
||||
int err, i;
|
||||
unsigned int fourcc, rt_format;
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) {
|
||||
if (vaapi_format_map[i].pix_fmt == hwfc->sw_format) {
|
||||
fourcc = vaapi_format_map[i].fourcc;
|
||||
rt_format = vaapi_format_map[i].rt_format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= FF_ARRAY_ELEMS(vaapi_format_map)) {
|
||||
desc = vaapi_format_from_pix_fmt(hwfc->sw_format);
|
||||
if (!desc) {
|
||||
av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n",
|
||||
av_get_pix_fmt_name(hwfc->sw_format));
|
||||
return AVERROR(EINVAL);
|
||||
|
@ -517,7 +536,7 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc)
|
|||
.type = VASurfaceAttribPixelFormat,
|
||||
.flags = VA_SURFACE_ATTRIB_SETTABLE,
|
||||
.value.type = VAGenericValueTypeInteger,
|
||||
.value.value.i = fourcc,
|
||||
.value.value.i = desc->fourcc,
|
||||
};
|
||||
}
|
||||
av_assert0(i == ctx->nb_attributes);
|
||||
|
@ -526,7 +545,7 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc)
|
|||
ctx->nb_attributes = 0;
|
||||
}
|
||||
|
||||
ctx->rt_format = rt_format;
|
||||
ctx->rt_format = desc->rt_format;
|
||||
|
||||
if (hwfc->initial_pool_size > 0) {
|
||||
// This pool will be usable as a render target, so we need to store
|
||||
|
@ -716,6 +735,7 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc,
|
|||
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
||||
VAAPIFramesContext *ctx = hwfc->internal->priv;
|
||||
VASurfaceID surface_id;
|
||||
const VAAPIFormatDescriptor *desc;
|
||||
VAImageFormat *image_format;
|
||||
VAAPIMapping *map;
|
||||
VAStatus vas;
|
||||
|
@ -824,11 +844,9 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc,
|
|||
dst->data[i] = (uint8_t*)address + map->image.offsets[i];
|
||||
dst->linesize[i] = map->image.pitches[i];
|
||||
}
|
||||
if (
|
||||
#ifdef VA_FOURCC_YV16
|
||||
map->image.format.fourcc == VA_FOURCC_YV16 ||
|
||||
#endif
|
||||
map->image.format.fourcc == VA_FOURCC_YV12) {
|
||||
|
||||
desc = vaapi_format_from_fourcc(map->image.format.fourcc);
|
||||
if (desc && desc->chroma_planes_swapped) {
|
||||
// Chroma planes are YVU rather than YUV, so swap them.
|
||||
FFSWAP(uint8_t*, dst->data[1], dst->data[2]);
|
||||
}
|
||||
|
@ -981,9 +999,10 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst,
|
|||
(AVHWFramesContext*)dst->hw_frames_ctx->data;
|
||||
AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
|
||||
const AVDRMFrameDescriptor *desc;
|
||||
const VAAPIFormatDescriptor *format_desc;
|
||||
VASurfaceID surface_id;
|
||||
VAStatus vas;
|
||||
uint32_t va_fourcc, va_rt_format;
|
||||
uint32_t va_fourcc;
|
||||
int err, i, j, k;
|
||||
|
||||
unsigned long buffer_handle;
|
||||
|
@ -1034,14 +1053,8 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst,
|
|||
av_log(dst_fc, AV_LOG_DEBUG, "Map DRM object %d to VAAPI as "
|
||||
"%08x.\n", desc->objects[0].fd, va_fourcc);
|
||||
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) {
|
||||
if (vaapi_format_map[i].fourcc == va_fourcc) {
|
||||
va_rt_format = vaapi_format_map[i].rt_format;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
av_assert0(i < FF_ARRAY_ELEMS(vaapi_format_map));
|
||||
format_desc = vaapi_format_from_fourcc(va_fourcc);
|
||||
av_assert0(format_desc);
|
||||
|
||||
buffer_handle = desc->objects[0].fd;
|
||||
buffer_desc.pixel_format = va_fourcc;
|
||||
|
@ -1062,7 +1075,13 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst,
|
|||
}
|
||||
buffer_desc.num_planes = k;
|
||||
|
||||
vas = vaCreateSurfaces(dst_dev->display, va_rt_format,
|
||||
if (format_desc->chroma_planes_swapped &&
|
||||
buffer_desc.num_planes == 3) {
|
||||
FFSWAP(uint32_t, buffer_desc.pitches[1], buffer_desc.pitches[2]);
|
||||
FFSWAP(uint32_t, buffer_desc.offsets[1], buffer_desc.offsets[2]);
|
||||
}
|
||||
|
||||
vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format,
|
||||
src->width, src->height,
|
||||
&surface_id, 1,
|
||||
attrs, FF_ARRAY_ELEMS(attrs));
|
||||
|
|
Loading…
Reference in New Issue