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.
Showing the changes to libavcodec (3 of 3 files). Show all
Unified · Split
| @@ -59,6 +59,11 @@ const enum AVPixelFormat ff_nvenc_pix_fmts[] = { · 58 unmodified lines | ||
| 59 | 59 | AV_PIX_FMT_P010, |
| 60 | 60 | AV_PIX_FMT_YUV444P, |
| 61 | 61 | 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 | 67 | AV_PIX_FMT_YUV444P16, // Truncated to 10bits |
| 63 | 68 | AV_PIX_FMT_0RGB32, |
| 64 | 69 | AV_PIX_FMT_RGB32, |
| @@ -87,6 +92,8 @@ const AVCodecHWConfigInternal *const ff_nvenc_hw_configs[] = { · 22 unmodified lines | ||
| 87 | 92 | |
| 88 | 93 | #define IS_10BIT(pix_fmt) (pix_fmt == AV_PIX_FMT_P010 || \ |
| 89 | 94 | pix_fmt == AV_PIX_FMT_P016 || \ |
| 95 | + pix_fmt == AV_PIX_FMT_P210 || \ | |
| 96 | + pix_fmt == AV_PIX_FMT_P216 || \ | |
| 90 | 97 | pix_fmt == AV_PIX_FMT_YUV444P16 || \ |
| 91 | 98 | pix_fmt == AV_PIX_FMT_X2RGB10 || \ |
| 92 | 99 | pix_fmt == AV_PIX_FMT_X2BGR10 || \ |
| @@ -105,6 +112,10 @@ const AVCodecHWConfigInternal *const ff_nvenc_hw_configs[] = { · 12 unmodified lines | ||
| 105 | 112 | pix_fmt == AV_PIX_FMT_GBRP16 || \ |
| 106 | 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 | 119 | #define IS_GBRP(pix_fmt) (pix_fmt == AV_PIX_FMT_GBRP || \ |
| 109 | 120 | pix_fmt == AV_PIX_FMT_GBRP16) |
| 110 | 121 | |
| @@ -477,6 +488,16 @@ static int nvenc_check_capabilities(AVCodecContext *avctx) · 366 unmodified lines | ||
| 477 | 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 | 501 | ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_LOSSLESS_ENCODE); |
| 481 | 502 | if (ctx->flags & NVENC_LOSSLESS && ret <= 0) { |
| 482 | 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 | 1318 | cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID; |
| 1298 | 1319 | avctx->profile = AV_PROFILE_H264_HIGH; |
| 1299 | 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 | 1333 | case NV_ENC_H264_PROFILE_HIGH_444P: |
| 1301 | 1334 | cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID; |
| 1302 | 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 | 1348 | // force setting profile as high444p if input is AV_PIX_FMT_YUV444P |
| 1308 | 1349 | if (IS_YUV444(ctx->data_pix_fmt)) { |
| 1309 | 1350 | cc->profileGUID = NV_ENC_H264_PROFILE_HIGH_444_GUID; |
| 1310 | 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 | 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 | 1366 | h264->level = ctx->level; |
| 1318 | 1367 | |
| 1319 | 1368 | #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; | |
| 1322 | 1371 | #endif |
| 1323 | 1372 | |
| 1324 | 1373 | if (ctx->coder >= 0) |
| @@ -1428,13 +1477,13 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx) · 103 unmodified lines | ||
| 1428 | 1477 | avctx->profile = AV_PROFILE_HEVC_MAIN_10; |
| 1429 | 1478 | } |
| 1430 | 1479 | |
| 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)) { | |
| 1433 | 1482 | cc->profileGUID = NV_ENC_HEVC_PROFILE_FREXT_GUID; |
| 1434 | 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 | 1488 | #ifdef NVENC_HAVE_NEW_BIT_DEPTH_API |
| 1440 | 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 | 1870 | return NV_ENC_BUFFER_FORMAT_ARGB10; |
| 1822 | 1871 | case AV_PIX_FMT_X2BGR10: |
| 1823 | 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 | 1880 | default: |
| 1825 | 1881 | return NV_ENC_BUFFER_FORMAT_UNDEFINED; |
| 1826 | 1882 | } |
| @@ -93,6 +93,12 @@ typedef void ID3D11Device; · 92 unmodified lines | ||
| 93 | 93 | #define NVENC_HAVE_UNIDIR_B |
| 94 | 94 | #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 | + | |
| 96 | 102 | typedef struct NvencSurface |
| 97 | 103 | { |
| 98 | 104 | NV_ENC_INPUT_PTR input_surface; |
| @@ -151,6 +157,12 @@ enum { · 52 unmodified lines | ||
| 151 | 157 | NV_ENC_H264_PROFILE_BASELINE, |
| 152 | 158 | NV_ENC_H264_PROFILE_MAIN, |
| 153 | 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 | 166 | NV_ENC_H264_PROFILE_HIGH_444P, |
| 155 | 167 | }; |
| 156 | 168 | |
| @@ -61,6 +61,12 @@ static const AVOption options[] = { · 60 unmodified lines | ||
| 61 | 61 | { "baseline", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_BASELINE }, 0, 0, VE, .unit = "profile" }, |
| 62 | 62 | { "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_MAIN }, 0, 0, VE, .unit = "profile" }, |
| 63 | 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 | 70 | { "high444p", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_H264_PROFILE_HIGH_444P }, 0, 0, VE, .unit = "profile" }, |
| 65 | 71 | #ifdef NVENC_HAVE_H264_LVL6 |
| 66 | 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 | 205 | { "fullres", "Two Pass encoding is enabled where first Pass is full resolution", |
| 200 | 206 | 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TWO_PASS_FULL_RESOLUTION }, 0, 0, VE, .unit = "multipass" }, |
| 201 | 207 | #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 | 211 | #ifdef NVENC_HAVE_LDKFS |
| 203 | 212 | { "ldkfs", "Low delay key frame scale; Specifies the Scene Change frame size increase allowed in case of single frame VBV and CBR", |
| 204 | 213 | OFFSET(ldkfs), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UCHAR_MAX, VE }, |