[FFmpeg-devel] [PATCH 2/3] lavc/vaapi: Add support for remaining 10/12bit profiles

Philip Langdale philipl at overt.org
Tue Aug 16 08:02:55 EEST 2022


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.

I had to tweak the format matching logic slightly to account for the
reduced size alpha channel in Y410, as we can't assume all channels are
the same depth as the first channel.

Signed-off-by: Philip Langdale <philipl at overt.org>
---
 libavcodec/hevcdec.c           |  8 ++++++++
 libavcodec/vaapi_decode.c      | 13 +++++++++++++
 libavcodec/vaapi_encode.c      |  8 +++++++-
 libavcodec/vaapi_encode_h265.c |  6 +++++-
 libavcodec/vaapi_encode_vp9.c  |  4 +++-
 libavcodec/vaapi_hevc.c        | 11 ++++++++++-
 libavcodec/vp9.c               |  2 ++
 libavutil/hwcontext_vaapi.c    | 12 ++++++++++++
 8 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index f1be8af2cd..1a895800a6 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -481,11 +481,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;
     }
diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c
index bc2d3ed803..8c6fd45f3d 100644
--- a/libavcodec/vaapi_decode.c
+++ b/libavcodec/vaapi_decode.c
@@ -262,16 +262,28 @@ 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),
     // 4:4:4
     MAP(444P, YUV444P),
     MAP(AYUV, VUYA),
+#ifdef VA_FOURCC_Y410
+    MAP(Y410,    Y410),
+#endif
+#ifdef VA_FOURCC_Y412
+    MAP(Y412,    Y412),
+#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
@@ -415,6 +427,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),
diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index f13daa5cff..e45ba1938a 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -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, 4, 0, 0 },
+    { "YUV444_12", VA_RT_FORMAT_YUV444_12,    12, 4, 0, 0 },
 #endif
     { "YUV444",    VA_RT_FORMAT_YUV444,        8, 3, 0, 0 },
     { "AYUV",      VA_RT_FORMAT_YUV444,        8, 4, 0, 0 },
@@ -1365,7 +1369,9 @@ static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
     }
     depth = desc->comp[0].depth;
     for (i = 1; i < desc->nb_components; i++) {
-        if (desc->comp[i].depth != depth) {
+        // We do not apply this depth requirement to the fourth component as
+        // that will be the alpha channel when present, which can be smaller.
+        if (i < 3 && desc->comp[i].depth != depth) {
             av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%s).\n",
                    desc->name);
             return AVERROR(EINVAL);
diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index 1de323af78..c2e91a8449 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -1276,10 +1276,14 @@ 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 },
-    // Four channels because this uses the AYUV format which has Alpha
+    { FF_PROFILE_HEVC_REXT,    12, 3, 1, 0, VAProfileHEVCMain422_12 },
+    // Four channels because these use formats which have Alpha
     { FF_PROFILE_HEVC_REXT,     8, 4, 0, 0, VAProfileHEVCMain444 },
+    { FF_PROFILE_HEVC_REXT,    10, 4, 0, 0, VAProfileHEVCMain444_10 },
+    { FF_PROFILE_HEVC_REXT,    12, 4, 0, 0, VAProfileHEVCMain444_12 },
 #endif
     { FF_PROFILE_UNKNOWN }
 };
diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c
index 9b455e10c9..e6c7f01f11 100644
--- a/libavcodec/vaapi_encode_vp9.c
+++ b/libavcodec/vaapi_encode_vp9.c
@@ -228,9 +228,11 @@ static av_cold int vaapi_encode_vp9_configure(AVCodecContext *avctx)
 
 static const VAAPIEncodeProfile vaapi_encode_vp9_profiles[] = {
     { FF_PROFILE_VP9_0,  8, 3, 1, 1, VAProfileVP9Profile0 },
-    // Four channels because this uses the AYUV format which has Alpha
+    // Four channels because this uses a format which has Alpha
     { FF_PROFILE_VP9_1,  8, 4, 0, 0, VAProfileVP9Profile1 },
     { FF_PROFILE_VP9_2, 10, 3, 1, 1, VAProfileVP9Profile2 },
+    // Four channels because this uses a format which has Alpha
+    { FF_PROFILE_VP9_3, 10, 4, 0, 0, VAProfileVP9Profile3 },
     { FF_PROFILE_UNKNOWN }
 };
 
diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c
index d82975979a..20fb36adfa 100644
--- a/libavcodec/vaapi_hevc.c
+++ b/libavcodec/vaapi_hevc.c
@@ -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);
diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c
index 621627ddc5..8105956775 100644
--- a/libavcodec/vp9.c
+++ b/libavcodec/vp9.c
@@ -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
diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c
index 2ee5145727..6c057aa5fd 100644
--- a/libavutil/hwcontext_vaapi.c
+++ b/libavutil/hwcontext_vaapi.c
@@ -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),
@@ -129,6 +132,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),
@@ -143,6 +149,12 @@ static const VAAPIFormatDescriptor vaapi_format_map[] = {
 #ifdef VA_FOURCC_X2R10G10B10
     MAP(X2R10G10B10, RGB32_10, X2RGB10, 0),
 #endif
+#ifdef VA_FOURCC_Y410
+    MAP(Y410, YUV444_10,  Y410, 0),
+#endif
+#ifdef VA_FOURCC_Y412
+    MAP(Y412, YUV444_12,  Y412, 0),
+#endif
 };
 #undef MAP
 
-- 
2.34.1



More information about the ffmpeg-devel mailing list