History

avcodec/nvenc: add 4:2:2 encoding and H.264 10-bit support

This commit adds support for 4:2:2 encoding for HEVC and H.264 on NVIDIA Blackwell GPUs. Additionally, it supports 10-bit encoding for H.264 on Blackwell GPUs.

Diego de Souza committed 1 year ago

Commit 2cfef291 parent 7e965583 files · +83 −6Browse files

Showing the changes to libavcodec (3 of 3 files). Show all

Unified · Split

3 files
  1. libavcodec/nvenc.c +62 −6
  2. libavcodec/nvenc.h +12 −0
  3. libavcodec/nvenc_h264.c +9 −0
libavcodec/nvenc.c+62−6
@@ -59,6 +59,11 @@ const enum AVPixelFormat ff_nvenc_pix_fmts[] = { · 58 unmodified lines
5959 AV_PIX_FMT_P010,
6060 AV_PIX_FMT_YUV444P,
6161 AV_PIX_FMT_P016, // Truncated to 10bits
62+#ifdef NVENC_HAVE_422_SUPPORT
63+ AV_PIX_FMT_NV16,
64+ AV_PIX_FMT_P210,
65+ AV_PIX_FMT_P216,
66+#endif
6267 AV_PIX_FMT_YUV444P16, // Truncated to 10bits
6368 AV_PIX_FMT_0RGB32,
6469 AV_PIX_FMT_RGB32,
@@ -87,6 +92,8 @@ const AVCodecHWConfigInternal *const ff_nvenc_hw_configs[] = { · 22 unmodified lines
8792
8893 #define IS_10BIT(pix_fmt) (pix_fmt == AV_PIX_FMT_P010 || \
8994 pix_fmt == AV_PIX_FMT_P016 || \
95+ pix_fmt == AV_PIX_FMT_P210 || \
96+ pix_fmt == AV_PIX_FMT_P216 || \
9097 pix_fmt == AV_PIX_FMT_YUV444P16 || \
9198 pix_fmt == AV_PIX_FMT_X2RGB10 || \
9299 pix_fmt == AV_PIX_FMT_X2BGR10 || \
@@ -105,6 +112,10 @@ const AVCodecHWConfigInternal *const ff_nvenc_hw_configs[] = { · 12 unmodified lines
105112 pix_fmt == AV_PIX_FMT_GBRP16 || \
106113 (ctx->rgb_mode == NVENC_RGB_MODE_444 && IS_RGB(pix_fmt)))
107114
115+#define IS_YUV422(pix_fmt) (pix_fmt == AV_PIX_FMT_NV16 || \
116+ pix_fmt == AV_PIX_FMT_P210 || \
117+ pix_fmt == AV_PIX_FMT_P216)
118+
108119 #define IS_GBRP(pix_fmt) (pix_fmt == AV_PIX_FMT_GBRP || \
109120 pix_fmt == AV_PIX_FMT_GBRP16)
110121
@@ -477,6 +488,16 @@ static int nvenc_check_capabilities(AVCodecContext *avctx) · 366 unmodified lines
477488 return AVERROR(ENOSYS);
478489 }
479490
491+#ifdef NVENC_HAVE_422_SUPPORT
492+ ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_YUV422_ENCODE);
493+#else
494+ ret = 0;
495+#endif
496+ if (IS_YUV422(ctx->data_pix_fmt) && ret <= 0) {
497+ av_log(avctx, AV_LOG_WARNING, "YUV422P not supported\n");
498+ return AVERROR(ENOSYS);
499+ }
500+
480501 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE);
481502 if (ctx->flags & NVENC_LOSSLESS && ret <= 0) {
482503 av_log(avctx, AV_LOG_WARNING, "Lossless encoding not supported\n");
@@ -1297,6 +1318,18 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx) · 814 unmodified lines
12971318 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
12981319 avctx->profile = AV_PROFILE_H264_HIGH;
12991320 break;
1321+#ifdef NVENC_HAVE_H264_10BIT_SUPPORT
1322+ case NV_ENC_H264_PROFILE_HIGH_10:
1323+ cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_10_GUID;
1324+ avctx->profile = AV_PROFILE_H264_HIGH_10;
1325+ break;
1326+#endif
1327+#ifdef NVENC_HAVE_422_SUPPORT
1328+ case NV_ENC_H264_PROFILE_HIGH_422:
1329+ cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_422_GUID;
1330+ avctx->profile = AV_PROFILE_H264_HIGH_422;
1331+ break;
1332+#endif
13001333 case NV_ENC_H264_PROFILE_HIGH_444P:
13011334 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
13021335 avctx->profile = AV_PROFILE_H264_HIGH_444_PREDICTIVE;
@@ -1304,21 +1337,37 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx) · 1 unmodified line
13041337 }
13051338 }
13061339
1340+#ifdef NVENC_HAVE_H264_10BIT_SUPPORT
1341+ // force setting profile as high10 if input is 10 bit or if it should be encoded as 10 bit
1342+ if (IS_10BIT(ctx->data_pix_fmt) || ctx->highbitdepth) {
1343+ cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_10_GUID;
1344+ avctx->profile = AV_PROFILE_H264_HIGH_10;
1345+ }
1346+#endif
1347+
13071348 // force setting profile as high444p if input is AV_PIX_FMT_YUV444P
13081349 if (IS_YUV444(ctx->data_pix_fmt)) {
13091350 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
13101351 avctx->profile = AV_PROFILE_H264_HIGH_444_PREDICTIVE;
13111352 }
13121353
1354+#ifdef NVENC_HAVE_422_SUPPORT
1355+ // force setting profile as high422p if input is AV_PIX_FMT_YUV422P
1356+ if (IS_YUV422(ctx->data_pix_fmt)) {
1357+ cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_422_GUID;
1358+ avctx->profile = AV_PROFILE_H264_HIGH_422;
1359+ }
1360+#endif
1361+
13131362 vui->bitstreamRestrictionFlag = cc->gopLength != 1 || avctx->profile < AV_PROFILE_H264_HIGH;
13141363
1315− h264->chromaFormatIDC = avctx->profile == AV_PROFILE_H264_HIGH_444_PREDICTIVE ? 3 : 1;
1364+ h264->chromaFormatIDC = IS_YUV444(ctx->data_pix_fmt) ? 3 : IS_YUV422(ctx->data_pix_fmt) ? 2 : 1;
13161365
13171366 h264->level = ctx->level;
13181367
13191368 #ifdef NVENC_HAVE_NEW_BIT_DEPTH_API
1320− h264->inputBitDepth = h264->outputBitDepth =
1321− IS_10BIT(ctx->data_pix_fmt) ? NV_ENC_BIT_DEPTH_10 : NV_ENC_BIT_DEPTH_8;
1369+ h264->inputBitDepth = IS_10BIT(ctx->data_pix_fmt) ? NV_ENC_BIT_DEPTH_10 : NV_ENC_BIT_DEPTH_8;
1370+ h264->outputBitDepth = (IS_10BIT(ctx->data_pix_fmt) || ctx->highbitdepth) ? NV_ENC_BIT_DEPTH_10 : NV_ENC_BIT_DEPTH_8;
13221371 #endif
13231372
13241373 if (ctx->coder >= 0)
@@ -1428,13 +1477,13 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx) · 103 unmodified lines
14281477 avctx->profile = AV_PROFILE_HEVC_MAIN_10;
14291478 }
14301479
1431− // force setting profile as rext if input is yuv444
1432− if (IS_YUV444(ctx->data_pix_fmt)) {
1480+ // force setting profile as rext if input is yuv444 or yuv422
1481+ if (IS_YUV444(ctx->data_pix_fmt) || IS_YUV422(ctx->data_pix_fmt)) {
14331482 cc->profileGUID = NV_ENC_HEVC_PROFILE_FREXT_GUID;
14341483 avctx->profile = AV_PROFILE_HEVC_REXT;
14351484 }
14361485
1437− hevc->chromaFormatIDC = IS_YUV444(ctx->data_pix_fmt) ? 3 : 1;
1486+ hevc->chromaFormatIDC = IS_YUV444(ctx->data_pix_fmt) ? 3 : IS_YUV422(ctx->data_pix_fmt) ? 2 : 1;
14381487
14391488 #ifdef NVENC_HAVE_NEW_BIT_DEPTH_API
14401489 hevc->inputBitDepth = IS_10BIT(ctx->data_pix_fmt) ? NV_ENC_BIT_DEPTH_10 : NV_ENC_BIT_DEPTH_8;
@@ -1821,6 +1870,13 @@ static NV_ENC_BUFFER_FORMAT nvenc_map_buffer_format(enum AVPixelFormat pix_fmt) · 380 unmodified lines
18211870 return NV_ENC_BUFFER_FORMAT_ARGB10;
18221871 case AV_PIX_FMT_X2BGR10:
18231872 return NV_ENC_BUFFER_FORMAT_ABGR10;
1873+#ifdef NVENC_HAVE_422_SUPPORT
1874+ case AV_PIX_FMT_NV16:
1875+ return NV_ENC_BUFFER_FORMAT_NV16;
1876+ case AV_PIX_FMT_P210:
1877+ case AV_PIX_FMT_P216:
1878+ return NV_ENC_BUFFER_FORMAT_P210;
1879+#endif
18241880 default:
18251881 return NV_ENC_BUFFER_FORMAT_UNDEFINED;
18261882 }
libavcodec/nvenc.h+12−0
@@ -93,6 +93,12 @@ typedef void ID3D11Device; · 92 unmodified lines
9393 #define NVENC_HAVE_UNIDIR_B
9494 #endif
9595
96+// SDK 13.0 compile time feature checks
97+#if NVENCAPI_CHECK_VERSION(13, 0)
98+#define NVENC_HAVE_H264_10BIT_SUPPORT
99+#define NVENC_HAVE_422_SUPPORT
100+#endif
101+
96102 typedef struct NvencSurface
97103 {
98104 NV_ENC_INPUT_PTR input_surface;
@@ -151,6 +157,12 @@ enum { · 52 unmodified lines
151157 NV_ENC_H264_PROFILE_BASELINE,
152158 NV_ENC_H264_PROFILE_MAIN,
153159 NV_ENC_H264_PROFILE_HIGH,
160+#ifdef NVENC_HAVE_H264_10BIT_SUPPORT
161+ NV_ENC_H264_PROFILE_HIGH_10,
162+#endif
163+#ifdef NVENC_HAVE_422_SUPPORT
164+ NV_ENC_H264_PROFILE_HIGH_422,
165+#endif
154166 NV_ENC_H264_PROFILE_HIGH_444P,
155167 };
156168
libavcodec/nvenc_h264.c+9−0
@@ -61,6 +61,12 @@ static const AVOption options[] = { · 60 unmodified lines
6161 { "baseline", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_BASELINE }, 0, 0, VE, .unit = "profile" },
6262 { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_MAIN }, 0, 0, VE, .unit = "profile" },
6363 { "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH }, 0, 0, VE, .unit = "profile" },
64+#ifdef NVENC_HAVE_H264_10BIT_SUPPORT
65+ { "high10", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH_10 }, 0, 0, VE, .unit = "profile" },
66+#endif
67+#ifdef NVENC_HAVE_422_SUPPORT
68+ { "high422", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH_422 }, 0, 0, VE, .unit = "profile" },
69+#endif
6470 { "high444p", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH_444P }, 0, 0, VE, .unit = "profile" },
6571 #ifdef NVENC_HAVE_H264_LVL6
6672 { "level", "Set the encoding level restriction", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = NV_ENC_LEVEL_AUTOSELECT }, NV_ENC_LEVEL_AUTOSELECT, NV_ENC_LEVEL_H264_62, VE, .unit = "level" },
@@ -199,6 +205,9 @@ static const AVOption options[] = { · 132 unmodified lines
199205 { "fullres", "Two Pass encoding is enabled where first Pass is full resolution",
200206 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TWO_PASS_FULL_RESOLUTION }, 0, 0, VE, .unit = "multipass" },
201207 #endif
208+#ifdef NVENC_HAVE_H264_10BIT_SUPPORT
209+ { "highbitdepth", "Enable 10 bit encode for 8 bit input",OFFSET(highbitdepth),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
210+#endif
202211 #ifdef NVENC_HAVE_LDKFS
203212 { "ldkfs", "Low delay key frame scale; Specifies the Scene Change frame size increase allowed in case of single frame VBV and CBR",
204213 OFFSET(ldkfs), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UCHAR_MAX, VE },

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t