lavc/vaapi: Add support for remaining 10/12bit profiles

With the necessary pixel formats defined, we can now expose support for
the remaining 10/12bit combinations that VAAPI can handle.

Specifically, we are adding support for:

* HEVC
** 12bit 420
** 10bit 422
** 12bit 422
** 10bit 444
** 12bit 444

* VP9
** 10bit 444
** 12bit 444

These obviously require actual hardware support to be usable, but where
that exists, it is now enabled.

Note that unlike YUVA/YUVX, the Intel driver does not formally expose
support for the alphaless formats XV30 and XV360, and so we are
implicitly discarding the alpha from the decoder and passing undefined
values for the alpha to the encoder. If a future encoder iteration was
to actually do something with the alpha bits, we would need to use a
formal alpha capable format or the encoder would need to explicitly
accept the alphaless format.
This commit is contained in:
Philip Langdale 2022-08-19 17:01:07 -07:00
parent d75c4693fe
commit b982dd0d83
10 changed files with 69 additions and 3 deletions

View File

@ -8,7 +8,7 @@ version <next>:
- ffmpeg now requires threading to be built
- ffmpeg now runs every muxer in a separate thread
- Add new mode to cropdetect filter to detect crop-area based on motion vectors and edges
- VAAPI decoding and encoding for 8bit 444 HEVC and VP9
- VAAPI decoding and encoding for 10/12bit 422, 10/12bit 444 HEVC and VP9
- WBMP (Wireless Application Protocol Bitmap) image format
- a3dscope filter

View File

@ -482,11 +482,19 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#endif
case AV_PIX_FMT_YUV420P12:
case AV_PIX_FMT_YUV444P12:
#if CONFIG_HEVC_VAAPI_HWACCEL
*fmt++ = AV_PIX_FMT_VAAPI;
#endif
#if CONFIG_HEVC_VDPAU_HWACCEL
*fmt++ = AV_PIX_FMT_VDPAU;
#endif
#if CONFIG_HEVC_NVDEC_HWACCEL
*fmt++ = AV_PIX_FMT_CUDA;
#endif
break;
case AV_PIX_FMT_YUV422P12:
#if CONFIG_HEVC_VAAPI_HWACCEL
*fmt++ = AV_PIX_FMT_VAAPI;
#endif
break;
}

View File

@ -262,6 +262,9 @@ static const struct {
MAP(YUY2, YUYV422),
#ifdef VA_FOURCC_Y210
MAP(Y210, Y210),
#endif
#ifdef VA_FOURCC_Y212
MAP(Y212, Y212),
#endif
// 4:4:0
MAP(422V, YUV440P),
@ -269,11 +272,20 @@ static const struct {
MAP(444P, YUV444P),
#ifdef VA_FOURCC_XYUV
MAP(XYUV, VUYX),
#endif
#ifdef VA_FOURCC_Y410
MAP(Y410, XV30),
#endif
#ifdef VA_FOURCC_Y412
MAP(Y412, XV36),
#endif
// 4:2:0 10-bit
#ifdef VA_FOURCC_P010
MAP(P010, P010),
#endif
#ifdef VA_FOURCC_P012
MAP(P012, P012),
#endif
#ifdef VA_FOURCC_I010
MAP(I010, YUV420P10),
#endif
@ -417,6 +429,7 @@ static const struct {
#if VA_CHECK_VERSION(0, 39, 0)
MAP(VP9, VP9_1, VP9Profile1 ),
MAP(VP9, VP9_2, VP9Profile2 ),
MAP(VP9, VP9_3, VP9Profile3 ),
#endif
#if VA_CHECK_VERSION(1, 8, 0)
MAP(AV1, AV1_MAIN, AV1Profile0),

View File

@ -1305,7 +1305,11 @@ static const VAAPIEncodeRTFormat vaapi_encode_rt_formats[] = {
{ "YUV420", VA_RT_FORMAT_YUV420, 8, 3, 1, 1 },
{ "YUV422", VA_RT_FORMAT_YUV422, 8, 3, 1, 0 },
#if VA_CHECK_VERSION(1, 2, 0)
{ "YUV420_12", VA_RT_FORMAT_YUV420_12, 12, 3, 1, 1 },
{ "YUV422_10", VA_RT_FORMAT_YUV422_10, 10, 3, 1, 0 },
{ "YUV422_12", VA_RT_FORMAT_YUV422_12, 12, 3, 1, 0 },
{ "YUV444_10", VA_RT_FORMAT_YUV444_10, 10, 3, 0, 0 },
{ "YUV444_12", VA_RT_FORMAT_YUV444_12, 12, 3, 0, 0 },
#endif
{ "YUV444", VA_RT_FORMAT_YUV444, 8, 3, 0, 0 },
{ "XYUV", VA_RT_FORMAT_YUV444, 8, 3, 0, 0 },

View File

@ -1276,9 +1276,13 @@ static const VAAPIEncodeProfile vaapi_encode_h265_profiles[] = {
{ FF_PROFILE_HEVC_REXT, 10, 3, 1, 1, VAProfileHEVCMain10 },
#endif
#if VA_CHECK_VERSION(1, 2, 0)
{ FF_PROFILE_HEVC_REXT, 12, 3, 1, 1, VAProfileHEVCMain12 },
{ FF_PROFILE_HEVC_REXT, 8, 3, 1, 0, VAProfileHEVCMain422_10 },
{ FF_PROFILE_HEVC_REXT, 10, 3, 1, 0, VAProfileHEVCMain422_10 },
{ FF_PROFILE_HEVC_REXT, 12, 3, 1, 0, VAProfileHEVCMain422_12 },
{ FF_PROFILE_HEVC_REXT, 8, 3, 0, 0, VAProfileHEVCMain444 },
{ FF_PROFILE_HEVC_REXT, 10, 3, 0, 0, VAProfileHEVCMain444_10 },
{ FF_PROFILE_HEVC_REXT, 12, 3, 0, 0, VAProfileHEVCMain444_12 },
#endif
{ FF_PROFILE_UNKNOWN }
};

View File

@ -230,6 +230,7 @@ static const VAAPIEncodeProfile vaapi_encode_vp9_profiles[] = {
{ FF_PROFILE_VP9_0, 8, 3, 1, 1, VAProfileVP9Profile0 },
{ FF_PROFILE_VP9_1, 8, 3, 0, 0, VAProfileVP9Profile1 },
{ FF_PROFILE_VP9_2, 10, 3, 1, 1, VAProfileVP9Profile2 },
{ FF_PROFILE_VP9_3, 10, 3, 0, 0, VAProfileVP9Profile3 },
{ FF_PROFILE_UNKNOWN }
};

View File

@ -567,15 +567,24 @@ VAProfile ff_vaapi_parse_hevc_rext_profile(AVCodecContext *avctx)
}
#if VA_CHECK_VERSION(1, 2, 0)
if (!strcmp(profile->name, "Main 4:2:2 10") ||
if (!strcmp(profile->name, "Main 12") ||
!strcmp(profile->name, "Main 12 Intra"))
return VAProfileHEVCMain12;
else if (!strcmp(profile->name, "Main 4:2:2 10") ||
!strcmp(profile->name, "Main 4:2:2 10 Intra"))
return VAProfileHEVCMain422_10;
else if (!strcmp(profile->name, "Main 4:2:2 12") ||
!strcmp(profile->name, "Main 4:2:2 12 Intra"))
return VAProfileHEVCMain422_12;
else if (!strcmp(profile->name, "Main 4:4:4") ||
!strcmp(profile->name, "Main 4:4:4 Intra"))
return VAProfileHEVCMain444;
else if (!strcmp(profile->name, "Main 4:4:4 10") ||
!strcmp(profile->name, "Main 4:4:4 10 Intra"))
return VAProfileHEVCMain444_10;
else if (!strcmp(profile->name, "Main 4:4:4 12") ||
!strcmp(profile->name, "Main 4:4:4 12 Intra"))
return VAProfileHEVCMain444_12;
#else
av_log(avctx, AV_LOG_WARNING, "HEVC profile %s is "
"not supported with this VA version.\n", profile->name);

View File

@ -30,7 +30,7 @@
#include "version_major.h"
#define LIBAVCODEC_VERSION_MINOR 42
#define LIBAVCODEC_VERSION_MICRO 103
#define LIBAVCODEC_VERSION_MICRO 104
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \

View File

@ -235,6 +235,8 @@ static int update_size(AVCodecContext *avctx, int w, int h)
#endif
break;
case AV_PIX_FMT_YUV444P:
case AV_PIX_FMT_YUV444P10:
case AV_PIX_FMT_YUV444P12:
#if CONFIG_VP9_VAAPI_HWACCEL
*fmtp++ = AV_PIX_FMT_VAAPI;
#endif

View File

@ -121,6 +121,9 @@ static const VAAPIFormatDescriptor vaapi_format_map[] = {
MAP(YUY2, YUV422, YUYV422, 0),
#ifdef VA_FOURCC_Y210
MAP(Y210, YUV422_10, Y210, 0),
#endif
#ifdef VA_FOURCC_Y212
MAP(Y212, YUV422_12, Y212, 0),
#endif
MAP(411P, YUV411, YUV411P, 0),
MAP(422V, YUV422, YUV440P, 0),
@ -131,6 +134,9 @@ static const VAAPIFormatDescriptor vaapi_format_map[] = {
MAP(Y800, YUV400, GRAY8, 0),
#ifdef VA_FOURCC_P010
MAP(P010, YUV420_10BPP, P010, 0),
#endif
#ifdef VA_FOURCC_P012
MAP(P012, YUV420_12, P012, 0),
#endif
MAP(BGRA, RGB32, BGRA, 0),
MAP(BGRX, RGB32, BGR0, 0),
@ -145,6 +151,16 @@ static const VAAPIFormatDescriptor vaapi_format_map[] = {
#ifdef VA_FOURCC_X2R10G10B10
MAP(X2R10G10B10, RGB32_10, X2RGB10, 0),
#endif
#ifdef VA_FOURCC_Y410
// libva doesn't include a fourcc for XV30 and the driver only declares
// support for Y410, so we must fudge the mapping here.
MAP(Y410, YUV444_10, XV30, 0),
#endif
#ifdef VA_FOURCC_Y412
// libva doesn't include a fourcc for XV36 and the driver only declares
// support for Y412, so we must fudge the mapping here.
MAP(Y412, YUV444_12, XV36, 0),
#endif
};
#undef MAP
@ -1000,6 +1016,9 @@ static const struct {
DRM_MAP(NV12, 1, DRM_FORMAT_NV12),
#if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16)
DRM_MAP(P010, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
#endif
#if defined(VA_FOURCC_P012) && defined(DRM_FORMAT_R16)
DRM_MAP(P012, 2, DRM_FORMAT_R16, DRM_FORMAT_RG1616),
#endif
DRM_MAP(BGRA, 1, DRM_FORMAT_ARGB8888),
DRM_MAP(BGRX, 1, DRM_FORMAT_XRGB8888),
@ -1014,6 +1033,12 @@ static const struct {
#if defined(VA_FOURCC_XYUV) && defined(DRM_FORMAT_XYUV8888)
DRM_MAP(XYUV, 1, DRM_FORMAT_XYUV8888),
#endif
#if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU2101010)
DRM_MAP(Y410, 1, DRM_FORMAT_XVYU2101010),
#endif
#if defined(VA_FOURCC_Y412) && defined(DRM_FORMAT_XVYU12_16161616)
DRM_MAP(Y412, 1, DRM_FORMAT_XVYU12_16161616),
#endif
};
#undef DRM_MAP