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

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
59 AV_PIX_FMT_P010,59 AV_PIX_FMT_P010,
60 AV_PIX_FMT_YUV444P,60 AV_PIX_FMT_YUV444P,
61 AV_PIX_FMT_P016, // Truncated to 10bits61 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
62 AV_PIX_FMT_YUV444P16, // Truncated to 10bits67 AV_PIX_FMT_YUV444P16, // Truncated to 10bits
63 AV_PIX_FMT_0RGB32,68 AV_PIX_FMT_0RGB32,
64 AV_PIX_FMT_RGB32,69 AV_PIX_FMT_RGB32,
@@ -87,6 +92,8 @@ const AVCodecHWConfigInternal *const ff_nvenc_hw_configs[] = { · 22 unmodified lines
87 92
88#define IS_10BIT(pix_fmt) (pix_fmt == AV_PIX_FMT_P010 || \93#define IS_10BIT(pix_fmt) (pix_fmt == AV_PIX_FMT_P010 || \
89 pix_fmt == AV_PIX_FMT_P016 || \94 pix_fmt == AV_PIX_FMT_P016 || \
95 pix_fmt == AV_PIX_FMT_P210 || \
96 pix_fmt == AV_PIX_FMT_P216 || \
90 pix_fmt == AV_PIX_FMT_YUV444P16 || \97 pix_fmt == AV_PIX_FMT_YUV444P16 || \
91 pix_fmt == AV_PIX_FMT_X2RGB10 || \98 pix_fmt == AV_PIX_FMT_X2RGB10 || \
92 pix_fmt == AV_PIX_FMT_X2BGR10 || \99 pix_fmt == AV_PIX_FMT_X2BGR10 || \
@@ -105,6 +112,10 @@ const AVCodecHWConfigInternal *const ff_nvenc_hw_configs[] = { · 12 unmodified lines
105 pix_fmt == AV_PIX_FMT_GBRP16 || \112 pix_fmt == AV_PIX_FMT_GBRP16 || \
106 (ctx->rgb_mode == NVENC_RGB_MODE_444 && IS_RGB(pix_fmt)))113 (ctx->rgb_mode == NVENC_RGB_MODE_444 && IS_RGB(pix_fmt)))
107 114
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
108#define IS_GBRP(pix_fmt) (pix_fmt == AV_PIX_FMT_GBRP || \119#define IS_GBRP(pix_fmt) (pix_fmt == AV_PIX_FMT_GBRP || \
109 pix_fmt == AV_PIX_FMT_GBRP16)120 pix_fmt == AV_PIX_FMT_GBRP16)
110 121
@@ -477,6 +488,16 @@ static int nvenc_check_capabilities(AVCodecContext *avctx) · 366 unmodified lines
477 return AVERROR(ENOSYS);488 return AVERROR(ENOSYS);
478 }489 }
479 490
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
480 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE);501 ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE);
481 if (ctx->flags & NVENC_LOSSLESS && ret <= 0) {502 if (ctx->flags & NVENC_LOSSLESS && ret <= 0) {
482 av_log(avctx, AV_LOG_WARNING, "Lossless encoding not supported\n");503 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
1297 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;1318 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
1298 avctx->profile = AV_PROFILE_H264_HIGH;1319 avctx->profile = AV_PROFILE_H264_HIGH;
1299 break;1320 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
1300 case NV_ENC_H264_PROFILE_HIGH_444P:1333 case NV_ENC_H264_PROFILE_HIGH_444P:
1301 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;1334 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
1302 avctx->profile = AV_PROFILE_H264_HIGH_444_PREDICTIVE;1335 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
1304 }1337 }
1305 }1338 }
1306 1339
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
1307 // force setting profile as high444p if input is AV_PIX_FMT_YUV444P1348 // force setting profile as high444p if input is AV_PIX_FMT_YUV444P
1308 if (IS_YUV444(ctx->data_pix_fmt)) {1349 if (IS_YUV444(ctx->data_pix_fmt)) {
1309 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;1350 cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID;
1310 avctx->profile = AV_PROFILE_H264_HIGH_444_PREDICTIVE;1351 avctx->profile = AV_PROFILE_H264_HIGH_444_PREDICTIVE;
1311 }1352 }
1312 1353
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
1313 vui->bitstreamRestrictionFlag = cc->gopLength != 1 || avctx->profile < AV_PROFILE_H264_HIGH;1362 vui->bitstreamRestrictionFlag = cc->gopLength != 1 || avctx->profile < AV_PROFILE_H264_HIGH;
1314 1363
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;
1316 1365
1317 h264->level = ctx->level;1366 h264->level = ctx->level;
1318 1367
1319#ifdef NVENC_HAVE_NEW_BIT_DEPTH_API1368#ifdef NVENC_HAVE_NEW_BIT_DEPTH_API
1320 h264->inputBitDepth = h264->outputBitDepth =1369 h264->inputBitDepth = IS_10BIT(ctx->data_pix_fmt) ? NV_ENC_BIT_DEPTH_10 : NV_ENC_BIT_DEPTH_8;
1321 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;
1322#endif1371#endif
1323 1372
1324 if (ctx->coder >= 0)1373 if (ctx->coder >= 0)
@@ -1428,13 +1477,13 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx) · 103 unmodified lines
1428 avctx->profile = AV_PROFILE_HEVC_MAIN_10;1477 avctx->profile = AV_PROFILE_HEVC_MAIN_10;
1429 }1478 }
1430 1479
1431 // force setting profile as rext if input is yuv4441480 // force setting profile as rext if input is yuv444 or yuv422
1432 if (IS_YUV444(ctx->data_pix_fmt)) {1481 if (IS_YUV444(ctx->data_pix_fmt) || IS_YUV422(ctx->data_pix_fmt)) {
1433 cc->profileGUID = NV_ENC_HEVC_PROFILE_FREXT_GUID;1482 cc->profileGUID = NV_ENC_HEVC_PROFILE_FREXT_GUID;
1434 avctx->profile = AV_PROFILE_HEVC_REXT;1483 avctx->profile = AV_PROFILE_HEVC_REXT;
1435 }1484 }
1436 1485
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;
1438 1487
1439#ifdef NVENC_HAVE_NEW_BIT_DEPTH_API1488#ifdef NVENC_HAVE_NEW_BIT_DEPTH_API
1440 hevc->inputBitDepth = IS_10BIT(ctx->data_pix_fmt) ? NV_ENC_BIT_DEPTH_10 : NV_ENC_BIT_DEPTH_8;1489 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
1821 return NV_ENC_BUFFER_FORMAT_ARGB10;1870 return NV_ENC_BUFFER_FORMAT_ARGB10;
1822 case AV_PIX_FMT_X2BGR10:1871 case AV_PIX_FMT_X2BGR10:
1823 return NV_ENC_BUFFER_FORMAT_ABGR10;1872 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
1824 default:1880 default:
1825 return NV_ENC_BUFFER_FORMAT_UNDEFINED;1881 return NV_ENC_BUFFER_FORMAT_UNDEFINED;
1826 }1882 }
libavcodec/nvenc.h+12−0
@@ -93,6 +93,12 @@ typedef void ID3D11Device; · 92 unmodified lines
93#define NVENC_HAVE_UNIDIR_B93#define NVENC_HAVE_UNIDIR_B
94#endif94#endif
95 95
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
96typedef struct NvencSurface102typedef struct NvencSurface
97{103{
98 NV_ENC_INPUT_PTR input_surface;104 NV_ENC_INPUT_PTR input_surface;
@@ -151,6 +157,12 @@ enum { · 52 unmodified lines
151 NV_ENC_H264_PROFILE_BASELINE,157 NV_ENC_H264_PROFILE_BASELINE,
152 NV_ENC_H264_PROFILE_MAIN,158 NV_ENC_H264_PROFILE_MAIN,
153 NV_ENC_H264_PROFILE_HIGH,159 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
154 NV_ENC_H264_PROFILE_HIGH_444P,166 NV_ENC_H264_PROFILE_HIGH_444P,
155};167};
156 168
libavcodec/nvenc_h264.c+9−0
@@ -61,6 +61,12 @@ static const AVOption options[] = { · 60 unmodified lines
61 { "baseline", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_BASELINE }, 0, 0, VE, .unit = "profile" },61 { "baseline", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_BASELINE }, 0, 0, VE, .unit = "profile" },
62 { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_MAIN }, 0, 0, VE, .unit = "profile" },62 { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_MAIN }, 0, 0, VE, .unit = "profile" },
63 { "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH }, 0, 0, VE, .unit = "profile" },63 { "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
64 { "high444p", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH_444P }, 0, 0, VE, .unit = "profile" },70 { "high444p", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH_444P }, 0, 0, VE, .unit = "profile" },
65#ifdef NVENC_HAVE_H264_LVL671#ifdef NVENC_HAVE_H264_LVL6
66 { "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" },72 { "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
199 { "fullres", "Two Pass encoding is enabled where first Pass is full resolution",205 { "fullres", "Two Pass encoding is enabled where first Pass is full resolution",
200 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TWO_PASS_FULL_RESOLUTION }, 0, 0, VE, .unit = "multipass" },206 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TWO_PASS_FULL_RESOLUTION }, 0, 0, VE, .unit = "multipass" },
201#endif207#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
202#ifdef NVENC_HAVE_LDKFS211#ifdef NVENC_HAVE_LDKFS
203 { "ldkfs", "Low delay key frame scale; Specifies the Scene Change frame size increase allowed in case of single frame VBV and CBR",212 { "ldkfs", "Low delay key frame scale; Specifies the Scene Change frame size increase allowed in case of single frame VBV and CBR",
204 OFFSET(ldkfs), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UCHAR_MAX, VE },213 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