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 | return AVERROR(ENOSYS); | 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 | ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_TEMPORAL_FILTER); | 631 | ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_TEMPORAL_FILTER); |
| 632 | if(ctx->tf_level > 0 && ret <= 0) { | 632 | if(ctx->tf_level > 0 && ret <= 0) { |
| 633 | av_log(avctx, AV_LOG_WARNING, "Temporal filtering not supported by the device\n"); | 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 | h264->numRefL1 = avctx->refs; | 1383 | h264->numRefL1 = avctx->refs; |
| 1384 | #endif | 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 | return 0; | 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 | av1->numFwdRefs = avctx->refs; | 1627 | av1->numFwdRefs = avctx->refs; |
| 1609 | av1->numBwdRefs = avctx->refs; | 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 | return 0; | 1649 | return 0; |
| 1612 | } | 1650 | } |
| 1613 | #endif | 1651 | #endif |
| @@ -98,6 +98,7 @@ typedef void ID3D11Device; · 97 unmodified lines | |||
| 98 | #define NVENC_HAVE_H264_10BIT_SUPPORT | 98 | #define NVENC_HAVE_H264_10BIT_SUPPORT |
| 99 | #define NVENC_HAVE_422_SUPPORT | 99 | #define NVENC_HAVE_422_SUPPORT |
| 100 | #define NVENC_HAVE_AV1_UHQ_TUNING | 100 | #define NVENC_HAVE_AV1_UHQ_TUNING |
| 101 | #define NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER | ||
| 101 | #endif | 102 | #endif |
| 102 | 103 | ||
| 103 | typedef struct NvencSurface | 104 | typedef struct NvencSurface |
| @@ -152,6 +152,12 @@ static const AVOption options[] = { · 151 unmodified lines | |||
| 152 | OFFSET(extra_sei), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, | 152 | OFFSET(extra_sei), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, |
| 153 | { "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, | 153 | { "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, |
| 154 | { "s12m_tc", "Use timecode (if available)", OFFSET(s12m_tc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, | 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 | #ifdef NVENC_HAVE_LOOKAHEAD_LEVEL | 161 | #ifdef NVENC_HAVE_LOOKAHEAD_LEVEL |
| 156 | { "lookahead_level", "Specifies the lookahead level. Higher level may improve quality at the expense of performance.", | 162 | { "lookahead_level", "Specifies the lookahead level. Higher level may improve quality at the expense of performance.", |
| 157 | OFFSET(lookahead_level), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, NV_ENC_LOOKAHEAD_LEVEL_AUTOSELECT, VE, .unit = "lookahead_level" }, | 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 | OFFSET(max_slice_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, | 224 | OFFSET(max_slice_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, |
| 225 | { "constrained-encoding", "Enable constrainedFrame encoding where each slice in the constrained picture is independent of other slices", | 225 | { "constrained-encoding", "Enable constrainedFrame encoding where each slice in the constrained picture is independent of other slices", |
| 226 | OFFSET(constrained_encoding), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, | 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 | #ifdef NVENC_HAVE_LOOKAHEAD_LEVEL | 233 | #ifdef NVENC_HAVE_LOOKAHEAD_LEVEL |
| 228 | { "lookahead_level", "Specifies the lookahead level. Higher level may improve quality at the expense of performance.", | 234 | { "lookahead_level", "Specifies the lookahead level. Higher level may improve quality at the expense of performance.", |
| 229 | OFFSET(lookahead_level), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, NV_ENC_LOOKAHEAD_LEVEL_AUTOSELECT, VE, .unit = "lookahead_level" }, | 235 | OFFSET(lookahead_level), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, NV_ENC_LOOKAHEAD_LEVEL_AUTOSELECT, VE, .unit = "lookahead_level" }, |