This commit extends the support for Temporal Filtering in NVENC for AV1 and H.264 codecs. For natural videos with noise, NVENC temporal filtering improves video coding efficiency by 4-5%.
Showing the changes to libavcodec (4 of 4 files). Show all
Unified · Split
| @@ -627,7 +627,7 @@ static int nvenc_check_capabilities(AVCodecContext *avctx) · 626 unmodified lines | ||
| 627 | 627 | return AVERROR(ENOSYS); |
| 628 | 628 | } |
| 629 | 629 | |
| 630 | −#ifdef NVENC_HAVE_TEMPORAL_FILTER | |
| 630 | +#if defined(NVENC_HAVE_TEMPORAL_FILTER) || defined(NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER) | |
| 631 | 631 | ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_TEMPORAL_FILTER); |
| 632 | 632 | if(ctx->tf_level > 0 && ret <= 0) { |
| 633 | 633 | av_log(avctx, AV_LOG_WARNING, "Temporal filtering not supported by the device\n"); |
| @@ -1383,6 +1383,25 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx) · 749 unmodified lines | ||
| 1383 | 1383 | h264->numRefL1 = avctx->refs; |
| 1384 | 1384 | #endif |
| 1385 | 1385 | |
| 1386 | +#ifdef NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER | |
| 1387 | + if (ctx->tf_level >= 0) { | |
| 1388 | + h264->tfLevel = ctx->tf_level; | |
| 1389 | + | |
| 1390 | + switch (ctx->tf_level) | |
| 1391 | + { | |
| 1392 | + case NV_ENC_TEMPORAL_FILTER_LEVEL_0: | |
| 1393 | + case NV_ENC_TEMPORAL_FILTER_LEVEL_4: | |
| 1394 | + break; | |
| 1395 | + default: | |
| 1396 | + av_log(avctx, AV_LOG_ERROR, "Invalid temporal filtering level.\n"); | |
| 1397 | + return AVERROR(EINVAL); | |
| 1398 | + } | |
| 1399 | + | |
| 1400 | + if (ctx->encode_config.frameIntervalP < 5) | |
| 1401 | + av_log(avctx, AV_LOG_WARNING, "Temporal filtering needs at least 4 B-Frames (-bf 4).\n"); | |
| 1402 | + } | |
| 1403 | +#endif | |
| 1404 | + | |
| 1386 | 1405 | return 0; |
| 1387 | 1406 | } |
| 1388 | 1407 | |
| @@ -1608,6 +1627,25 @@ static av_cold int nvenc_setup_av1_config(AVCodecContext *avctx) · 219 unmodified lines | ||
| 1608 | 1627 | av1->numFwdRefs = avctx->refs; |
| 1609 | 1628 | av1->numBwdRefs = avctx->refs; |
| 1610 | 1629 | |
| 1630 | +#ifdef NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER | |
| 1631 | + if (ctx->tf_level >= 0) { | |
| 1632 | + av1->tfLevel = ctx->tf_level; | |
| 1633 | + | |
| 1634 | + switch (ctx->tf_level) | |
| 1635 | + { | |
| 1636 | + case NV_ENC_TEMPORAL_FILTER_LEVEL_0: | |
| 1637 | + case NV_ENC_TEMPORAL_FILTER_LEVEL_4: | |
| 1638 | + break; | |
| 1639 | + default: | |
| 1640 | + av_log(avctx, AV_LOG_ERROR, "Invalid temporal filtering level.\n"); | |
| 1641 | + return AVERROR(EINVAL); | |
| 1642 | + } | |
| 1643 | + | |
| 1644 | + if (ctx->encode_config.frameIntervalP < 5) | |
| 1645 | + av_log(avctx, AV_LOG_WARNING, "Temporal filtering needs at least 4 B-Frames (-bf 4).\n"); | |
| 1646 | + } | |
| 1647 | +#endif | |
| 1648 | + | |
| 1611 | 1649 | return 0; |
| 1612 | 1650 | } |
| 1613 | 1651 | #endif |
| @@ -98,6 +98,7 @@ typedef void ID3D11Device; · 97 unmodified lines | ||
| 98 | 98 | #define NVENC_HAVE_H264_10BIT_SUPPORT |
| 99 | 99 | #define NVENC_HAVE_422_SUPPORT |
| 100 | 100 | #define NVENC_HAVE_AV1_UHQ_TUNING |
| 101 | +#define NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER | |
| 101 | 102 | #endif |
| 102 | 103 | |
| 103 | 104 | typedef struct NvencSurface |
| @@ -152,6 +152,12 @@ static const AVOption options[] = { · 151 unmodified lines | ||
| 152 | 152 | OFFSET(extra_sei), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, |
| 153 | 153 | { "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, |
| 154 | 154 | { "s12m_tc", "Use timecode (if available)", OFFSET(s12m_tc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, |
| 155 | +#ifdef NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER | |
| 156 | + { "tf_level", "Specifies the strength of the temporal filtering", | |
| 157 | + OFFSET(tf_level), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, .unit = "tf_level" }, | |
| 158 | + { "0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TEMPORAL_FILTER_LEVEL_0 }, 0, 0, VE, .unit = "tf_level" }, | |
| 159 | + { "4", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TEMPORAL_FILTER_LEVEL_4 }, 0, 0, VE, .unit = "tf_level" }, | |
| 160 | +#endif | |
| 155 | 161 | #ifdef NVENC_HAVE_LOOKAHEAD_LEVEL |
| 156 | 162 | { "lookahead_level", "Specifies the lookahead level. Higher level may improve quality at the expense of performance.", |
| 157 | 163 | OFFSET(lookahead_level), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, NV_ENC_LOOKAHEAD_LEVEL_AUTOSELECT, VE, .unit = "lookahead_level" }, |
| @@ -224,6 +224,12 @@ static const AVOption options[] = { · 223 unmodified lines | ||
| 224 | 224 | OFFSET(max_slice_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, |
| 225 | 225 | { "constrained-encoding", "Enable constrainedFrame encoding where each slice in the constrained picture is independent of other slices", |
| 226 | 226 | OFFSET(constrained_encoding), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, |
| 227 | +#ifdef NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER | |
| 228 | + { "tf_level", "Specifies the strength of the temporal filtering", | |
| 229 | + OFFSET(tf_level), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, .unit = "tf_level" }, | |
| 230 | + { "0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TEMPORAL_FILTER_LEVEL_0 }, 0, 0, VE, .unit = "tf_level" }, | |
| 231 | + { "4", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TEMPORAL_FILTER_LEVEL_4 }, 0, 0, VE, .unit = "tf_level" }, | |
| 232 | +#endif | |
| 227 | 233 | #ifdef NVENC_HAVE_LOOKAHEAD_LEVEL |
| 228 | 234 | { "lookahead_level", "Specifies the lookahead level. Higher level may improve quality at the expense of performance.", |
| 229 | 235 | OFFSET(lookahead_level), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, NV_ENC_LOOKAHEAD_LEVEL_AUTOSELECT, VE, .unit = "lookahead_level" }, |