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 | 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 10bits | 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 | AV_PIX_FMT_YUV444P16, // Truncated to 10bits | 67 | 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_YUV444P | 1348 | // 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_API | 1368 | #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 | #endif | 1371 | #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 yuv444 | 1480 | // 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_API | 1488 | #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 | } |
| @@ -93,6 +93,12 @@ typedef void ID3D11Device; · 92 unmodified lines | |||
| 93 | #define NVENC_HAVE_UNIDIR_B | 93 | #define NVENC_HAVE_UNIDIR_B |
| 94 | #endif | 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 | typedef struct NvencSurface | 102 | typedef 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 | ||
| @@ -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_LVL6 | 71 | #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 | #endif | 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 | #ifdef NVENC_HAVE_LDKFS | 211 | #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 }, |