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;
|
int flags;
|
||||||
} VAAPIMapping;
|
} VAAPIMapping;
|
||||||
|
|
||||||
#define MAP(va, rt, av) { \
|
typedef struct VAAPIFormat {
|
||||||
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 {
|
|
||||||
unsigned int fourcc;
|
unsigned int fourcc;
|
||||||
unsigned int rt_format;
|
unsigned int rt_format;
|
||||||
enum AVPixelFormat pix_fmt;
|
enum AVPixelFormat pix_fmt;
|
||||||
} vaapi_format_map[] = {
|
int chroma_planes_swapped;
|
||||||
MAP(NV12, YUV420, NV12),
|
} VAAPIFormatDescriptor;
|
||||||
MAP(YV12, YUV420, YUV420P), // With U/V planes swapped.
|
|
||||||
MAP(IYUV, YUV420, YUV420P),
|
#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
|
#ifdef VA_FOURCC_I420
|
||||||
MAP(I420, YUV420, YUV420P),
|
MAP(I420, YUV420, YUV420P, 0),
|
||||||
#endif
|
#endif
|
||||||
|
MAP(YV12, YUV420, YUV420P, 1),
|
||||||
|
MAP(IYUV, YUV420, YUV420P, 0),
|
||||||
|
MAP(422H, YUV422, YUV422P, 0),
|
||||||
#ifdef VA_FOURCC_YV16
|
#ifdef VA_FOURCC_YV16
|
||||||
MAP(YV16, YUV422, YUV422P), // With U/V planes swapped.
|
MAP(YV16, YUV422, YUV422P, 1),
|
||||||
#endif
|
#endif
|
||||||
MAP(422H, YUV422, YUV422P),
|
MAP(UYVY, YUV422, UYVY422, 0),
|
||||||
MAP(UYVY, YUV422, UYVY422),
|
MAP(YUY2, YUV422, YUYV422, 0),
|
||||||
MAP(YUY2, YUV422, YUYV422),
|
MAP(411P, YUV411, YUV411P, 0),
|
||||||
MAP(411P, YUV411, YUV411P),
|
MAP(422V, YUV422, YUV440P, 0),
|
||||||
MAP(422V, YUV422, YUV440P),
|
MAP(444P, YUV444, YUV444P, 0),
|
||||||
MAP(444P, YUV444, YUV444P),
|
MAP(Y800, YUV400, GRAY8, 0),
|
||||||
MAP(Y800, YUV400, GRAY8),
|
|
||||||
#ifdef VA_FOURCC_P010
|
#ifdef VA_FOURCC_P010
|
||||||
MAP(P010, YUV420_10BPP, P010),
|
MAP(P010, YUV420_10BPP, P010, 0),
|
||||||
#endif
|
#endif
|
||||||
MAP(BGRA, RGB32, BGRA),
|
MAP(BGRA, RGB32, BGRA, 0),
|
||||||
MAP(BGRX, RGB32, BGR0),
|
MAP(BGRX, RGB32, BGR0, 0),
|
||||||
MAP(RGBA, RGB32, RGBA),
|
MAP(RGBA, RGB32, RGBA, 0),
|
||||||
MAP(RGBX, RGB32, RGB0),
|
MAP(RGBX, RGB32, RGB0, 0),
|
||||||
#ifdef VA_FOURCC_ABGR
|
#ifdef VA_FOURCC_ABGR
|
||||||
MAP(ABGR, RGB32, ABGR),
|
MAP(ABGR, RGB32, ABGR, 0),
|
||||||
MAP(XBGR, RGB32, 0BGR),
|
MAP(XBGR, RGB32, 0BGR, 0),
|
||||||
#endif
|
#endif
|
||||||
MAP(ARGB, RGB32, ARGB),
|
MAP(ARGB, RGB32, ARGB, 0),
|
||||||
MAP(XRGB, RGB32, 0RGB),
|
MAP(XRGB, RGB32, 0RGB, 0),
|
||||||
};
|
};
|
||||||
#undef MAP
|
#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;
|
int i;
|
||||||
for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++)
|
for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++)
|
||||||
if (vaapi_format_map[i].fourcc == fourcc)
|
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;
|
return AV_PIX_FMT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,22 +486,16 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc)
|
||||||
AVVAAPIFramesContext *avfc = hwfc->hwctx;
|
AVVAAPIFramesContext *avfc = hwfc->hwctx;
|
||||||
VAAPIFramesContext *ctx = hwfc->internal->priv;
|
VAAPIFramesContext *ctx = hwfc->internal->priv;
|
||||||
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
||||||
|
const VAAPIFormatDescriptor *desc;
|
||||||
VAImageFormat *expected_format;
|
VAImageFormat *expected_format;
|
||||||
AVBufferRef *test_surface = NULL;
|
AVBufferRef *test_surface = NULL;
|
||||||
VASurfaceID test_surface_id;
|
VASurfaceID test_surface_id;
|
||||||
VAImage test_image;
|
VAImage test_image;
|
||||||
VAStatus vas;
|
VAStatus vas;
|
||||||
int err, i;
|
int err, i;
|
||||||
unsigned int fourcc, rt_format;
|
|
||||||
|
|
||||||
for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) {
|
desc = vaapi_format_from_pix_fmt(hwfc->sw_format);
|
||||||
if (vaapi_format_map[i].pix_fmt == hwfc->sw_format) {
|
if (!desc) {
|
||||||
fourcc = vaapi_format_map[i].fourcc;
|
|
||||||
rt_format = vaapi_format_map[i].rt_format;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i >= FF_ARRAY_ELEMS(vaapi_format_map)) {
|
|
||||||
av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n",
|
av_log(hwfc, AV_LOG_ERROR, "Unsupported format: %s.\n",
|
||||||
av_get_pix_fmt_name(hwfc->sw_format));
|
av_get_pix_fmt_name(hwfc->sw_format));
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
|
@ -517,7 +536,7 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc)
|
||||||
.type = VASurfaceAttribPixelFormat,
|
.type = VASurfaceAttribPixelFormat,
|
||||||
.flags = VA_SURFACE_ATTRIB_SETTABLE,
|
.flags = VA_SURFACE_ATTRIB_SETTABLE,
|
||||||
.value.type = VAGenericValueTypeInteger,
|
.value.type = VAGenericValueTypeInteger,
|
||||||
.value.value.i = fourcc,
|
.value.value.i = desc->fourcc,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
av_assert0(i == ctx->nb_attributes);
|
av_assert0(i == ctx->nb_attributes);
|
||||||
|
@ -526,7 +545,7 @@ static int vaapi_frames_init(AVHWFramesContext *hwfc)
|
||||||
ctx->nb_attributes = 0;
|
ctx->nb_attributes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->rt_format = rt_format;
|
ctx->rt_format = desc->rt_format;
|
||||||
|
|
||||||
if (hwfc->initial_pool_size > 0) {
|
if (hwfc->initial_pool_size > 0) {
|
||||||
// This pool will be usable as a render target, so we need to store
|
// 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;
|
AVVAAPIDeviceContext *hwctx = hwfc->device_ctx->hwctx;
|
||||||
VAAPIFramesContext *ctx = hwfc->internal->priv;
|
VAAPIFramesContext *ctx = hwfc->internal->priv;
|
||||||
VASurfaceID surface_id;
|
VASurfaceID surface_id;
|
||||||
|
const VAAPIFormatDescriptor *desc;
|
||||||
VAImageFormat *image_format;
|
VAImageFormat *image_format;
|
||||||
VAAPIMapping *map;
|
VAAPIMapping *map;
|
||||||
VAStatus vas;
|
VAStatus vas;
|
||||||
|
@ -824,11 +844,9 @@ static int vaapi_map_frame(AVHWFramesContext *hwfc,
|
||||||
dst->data[i] = (uint8_t*)address + map->image.offsets[i];
|
dst->data[i] = (uint8_t*)address + map->image.offsets[i];
|
||||||
dst->linesize[i] = map->image.pitches[i];
|
dst->linesize[i] = map->image.pitches[i];
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
#ifdef VA_FOURCC_YV16
|
desc = vaapi_format_from_fourcc(map->image.format.fourcc);
|
||||||
map->image.format.fourcc == VA_FOURCC_YV16 ||
|
if (desc && desc->chroma_planes_swapped) {
|
||||||
#endif
|
|
||||||
map->image.format.fourcc == VA_FOURCC_YV12) {
|
|
||||||
// Chroma planes are YVU rather than YUV, so swap them.
|
// Chroma planes are YVU rather than YUV, so swap them.
|
||||||
FFSWAP(uint8_t*, dst->data[1], dst->data[2]);
|
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;
|
(AVHWFramesContext*)dst->hw_frames_ctx->data;
|
||||||
AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
|
AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx;
|
||||||
const AVDRMFrameDescriptor *desc;
|
const AVDRMFrameDescriptor *desc;
|
||||||
|
const VAAPIFormatDescriptor *format_desc;
|
||||||
VASurfaceID surface_id;
|
VASurfaceID surface_id;
|
||||||
VAStatus vas;
|
VAStatus vas;
|
||||||
uint32_t va_fourcc, va_rt_format;
|
uint32_t va_fourcc;
|
||||||
int err, i, j, k;
|
int err, i, j, k;
|
||||||
|
|
||||||
unsigned long buffer_handle;
|
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 "
|
av_log(dst_fc, AV_LOG_DEBUG, "Map DRM object %d to VAAPI as "
|
||||||
"%08x.\n", desc->objects[0].fd, va_fourcc);
|
"%08x.\n", desc->objects[0].fd, va_fourcc);
|
||||||
|
|
||||||
for (i = 0; i < FF_ARRAY_ELEMS(vaapi_format_map); i++) {
|
format_desc = vaapi_format_from_fourcc(va_fourcc);
|
||||||
if (vaapi_format_map[i].fourcc == va_fourcc) {
|
av_assert0(format_desc);
|
||||||
va_rt_format = vaapi_format_map[i].rt_format;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
av_assert0(i < FF_ARRAY_ELEMS(vaapi_format_map));
|
|
||||||
|
|
||||||
buffer_handle = desc->objects[0].fd;
|
buffer_handle = desc->objects[0].fd;
|
||||||
buffer_desc.pixel_format = va_fourcc;
|
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;
|
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,
|
src->width, src->height,
|
||||||
&surface_id, 1,
|
&surface_id, 1,
|
||||||
attrs, FF_ARRAY_ELEMS(attrs));
|
attrs, FF_ARRAY_ELEMS(attrs));
|
||||||
|
|
Loading…
Reference in New Issue