PR #23162 opened by Timo Rothenpieler (BtbN)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23162
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23162.patch

Last time this was attempted, it failed because nvenc did not properly write 
the second SPS/PPS/... with the information about the alpha layer.
Maybe this is fixed now, so time for another attempt.


>From e5adb5249f70bb6832324e573bdff09e2218bcba Mon Sep 17 00:00:00 2001
From: Timo Rothenpieler <[email protected]>
Date: Mon, 14 Nov 2022 23:10:34 +0100
Subject: [PATCH] avcodec/nvenc: add hevc alpha channel support

---
 libavcodec/nvenc.c      | 37 +++++++++++++++++++++++++++++++++++++
 libavcodec/nvenc.h      |  7 +++++++
 libavcodec/nvenc_hevc.c |  4 ++++
 3 files changed, 48 insertions(+)

diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index e9ca6e01fd..9037a73691 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -69,6 +69,7 @@ const enum AVPixelFormat ff_nvenc_pix_fmts[] = {
 #endif
     AV_PIX_FMT_YUV444P10MSB,
     AV_PIX_FMT_YUV444P16, // Truncated to 10bits
+    AV_PIX_FMT_VUYA,
     AV_PIX_FMT_0RGB32,
     AV_PIX_FMT_RGB32,
     AV_PIX_FMT_0BGR32,
@@ -119,6 +120,7 @@ const AVCodecHWConfigInternal *const ff_nvenc_hw_configs[] 
= {
                             pix_fmt == AV_PIX_FMT_GBRP         || \
                             pix_fmt == AV_PIX_FMT_GBRP10MSB    || \
                             pix_fmt == AV_PIX_FMT_GBRP16       || \
+                            (!ctx->use_alpha && pix_fmt == AV_PIX_FMT_VUYA) || 
\
                             (ctx->rgb_mode == NVENC_RGB_MODE_444 && 
IS_RGB(pix_fmt)))
 
 #define IS_YUV422(pix_fmt) (pix_fmt == AV_PIX_FMT_NV16 || \
@@ -688,6 +690,29 @@ static int nvenc_check_capabilities(AVCodecContext *avctx)
     }
 #endif
 
+    if (ctx->use_alpha) {
+#ifdef NVENC_HAVE_ALPHA_SUPPORT
+        ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_ALPHA_LAYER_ENCODING);
+#else
+        ret = 0;
+#endif
+        if (!ret) {
+            av_log(avctx, AV_LOG_WARNING, "Alpha layer encoding not supported 
by the device\n");
+            return AVERROR(ENOSYS);
+        }
+
+        if (ctx->data_pix_fmt != AV_PIX_FMT_RGB32 && ctx->data_pix_fmt != 
AV_PIX_FMT_BGR32 &&
+            ctx->data_pix_fmt != AV_PIX_FMT_VUYA) {
+            av_log(avctx, AV_LOG_WARNING, "Alpha channel encoding is only 
supported for 8 bit ARGB/BGRA/VUYA formats\n");
+            return AVERROR(EINVAL);
+        }
+
+        if (ctx->weighted_pred) {
+            av_log(avctx, AV_LOG_WARNING, "Alpha channel encoding is not 
supported with weighted prediction\n");
+            return AVERROR(EINVAL);
+        }
+    }
+
     return 0;
 }
 
@@ -1272,6 +1297,11 @@ static av_cold int 
nvenc_setup_rate_control(AVCodecContext *avctx)
         ctx->encode_config.rcParams.maxBitRate = avctx->rc_max_rate;
     }
 
+#ifdef NVENC_HAVE_ALPHA_SUPPORT
+    if (ctx->alpha_ratio > 0)
+        ctx->encode_config.rcParams.alphaLayerBitrateRatio = ctx->alpha_ratio;
+#endif
+
     return 0;
 }
 
@@ -1666,6 +1696,11 @@ static av_cold int 
nvenc_setup_hevc_config(AVCodecContext *avctx)
     }
 #endif
 
+#ifdef NVENC_HAVE_ALPHA_SUPPORT
+    if (ctx->use_alpha)
+        hevc->enableAlphaLayerEncoding = 1;
+#endif
+
     return 0;
 }
 
@@ -2025,6 +2060,8 @@ static NV_ENC_BUFFER_FORMAT nvenc_map_buffer_format(enum 
AVPixelFormat pix_fmt)
     case AV_PIX_FMT_YUV444P16:
     case AV_PIX_FMT_YUV444P10MSB:
         return NV_ENC_BUFFER_FORMAT_YUV444_10BIT;
+    case AV_PIX_FMT_VUYA:
+        return NV_ENC_BUFFER_FORMAT_AYUV;
     case AV_PIX_FMT_0RGB32:
     case AV_PIX_FMT_RGB32:
         return NV_ENC_BUFFER_FORMAT_ARGB;
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
index 069ba82bc9..a8623b44eb 100644
--- a/libavcodec/nvenc.h
+++ b/libavcodec/nvenc.h
@@ -73,6 +73,11 @@ typedef void ID3D11Device;
 #define NVENC_HAVE_HEVC_CONSTRAINED_ENCODING
 #endif
 
+// SDK 11.0 compile time feature checks
+#if NVENCAPI_CHECK_VERSION(11, 0)
+#define NVENC_HAVE_ALPHA_SUPPORT
+#endif
+
 // SDK 11.1 compile time feature checks
 #if NVENCAPI_CHECK_VERSION(11, 1)
 #define NVENC_HAVE_QP_CHROMA_OFFSETS
@@ -321,6 +326,8 @@ typedef struct NvencContext
     int cbr_padding;
     int multiview, multiview_supported;
     int display_sei_sent;
+    int use_alpha;
+    int alpha_ratio;
 } NvencContext;
 
 int ff_nvenc_encode_init(AVCodecContext *avctx);
diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
index 31624f45b1..0f0c0392f7 100644
--- a/libavcodec/nvenc_hevc.c
+++ b/libavcodec/nvenc_hevc.c
@@ -244,6 +244,10 @@ static const AVOption options[] = {
     { "4",                 "Enabled with number of horizontal strips forced to 
4 when number of NVENCs > 3", 0, AV_OPT_TYPE_CONST, { .i64 = 
NV_ENC_SPLIT_FOUR_FORCED_MODE }, 0, 0, VE, .unit = "split_encode_mode" },
 #endif
 #endif
+    { "alpha",        "Enable encoding of alpha layer (ARGB/BGRA/VUYA input 
only)",
+                                                            OFFSET(use_alpha), 
   AV_OPT_TYPE_BOOL,  { .i64 = 0 }, 0, 1, VE },
+    { "alpha_ratio",  "Bitrate allocation ratio, n:1 between base and alpha 
layer",
+                                                            
OFFSET(alpha_ratio),  AV_OPT_TYPE_INT,   { .i64 = 0 }, 0, INT_MAX, VE },
     { NULL }
 };
 
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to