1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-02-09 14:14:39 +02:00

avcodec/nvenc: add Temporal Filtering for AV1 and H.264 in NVENC

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%.

Signed-off-by: Diego de Souza <ddesouza@nvidia.com>
Signed-off-by: Timo Rothenpieler <timo@rothenpieler.org>
This commit is contained in:
Diego de Souza 2025-01-08 13:21:01 +01:00 committed by Timo Rothenpieler
parent ed80e55586
commit a583f7e2fd
4 changed files with 52 additions and 1 deletions

View File

@ -627,7 +627,7 @@ static int nvenc_check_capabilities(AVCodecContext *avctx)
return AVERROR(ENOSYS);
}
#ifdef NVENC_HAVE_TEMPORAL_FILTER
#if defined(NVENC_HAVE_TEMPORAL_FILTER) || defined(NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER)
ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_TEMPORAL_FILTER);
if(ctx->tf_level > 0 && ret <= 0) {
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)
h264->numRefL1 = avctx->refs;
#endif
#ifdef NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER
if (ctx->tf_level >= 0) {
h264->tfLevel = ctx->tf_level;
switch (ctx->tf_level)
{
case NV_ENC_TEMPORAL_FILTER_LEVEL_0:
case NV_ENC_TEMPORAL_FILTER_LEVEL_4:
break;
default:
av_log(avctx, AV_LOG_ERROR, "Invalid temporal filtering level.\n");
return AVERROR(EINVAL);
}
if (ctx->encode_config.frameIntervalP < 5)
av_log(avctx, AV_LOG_WARNING, "Temporal filtering needs at least 4 B-Frames (-bf 4).\n");
}
#endif
return 0;
}
@ -1608,6 +1627,25 @@ static av_cold int nvenc_setup_av1_config(AVCodecContext *avctx)
av1->numFwdRefs = avctx->refs;
av1->numBwdRefs = avctx->refs;
#ifdef NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER
if (ctx->tf_level >= 0) {
av1->tfLevel = ctx->tf_level;
switch (ctx->tf_level)
{
case NV_ENC_TEMPORAL_FILTER_LEVEL_0:
case NV_ENC_TEMPORAL_FILTER_LEVEL_4:
break;
default:
av_log(avctx, AV_LOG_ERROR, "Invalid temporal filtering level.\n");
return AVERROR(EINVAL);
}
if (ctx->encode_config.frameIntervalP < 5)
av_log(avctx, AV_LOG_WARNING, "Temporal filtering needs at least 4 B-Frames (-bf 4).\n");
}
#endif
return 0;
}
#endif

View File

@ -98,6 +98,7 @@ typedef void ID3D11Device;
#define NVENC_HAVE_H264_10BIT_SUPPORT
#define NVENC_HAVE_422_SUPPORT
#define NVENC_HAVE_AV1_UHQ_TUNING
#define NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER
#endif
typedef struct NvencSurface

View File

@ -152,6 +152,12 @@ static const AVOption options[] = {
OFFSET(extra_sei), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
{ "a53cc", "Use A53 Closed Captions (if available)", OFFSET(a53_cc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
{ "s12m_tc", "Use timecode (if available)", OFFSET(s12m_tc), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
#ifdef NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER
{ "tf_level", "Specifies the strength of the temporal filtering",
OFFSET(tf_level), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, .unit = "tf_level" },
{ "0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TEMPORAL_FILTER_LEVEL_0 }, 0, 0, VE, .unit = "tf_level" },
{ "4", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TEMPORAL_FILTER_LEVEL_4 }, 0, 0, VE, .unit = "tf_level" },
#endif
#ifdef NVENC_HAVE_LOOKAHEAD_LEVEL
{ "lookahead_level", "Specifies the lookahead level. Higher level may improve quality at the expense of performance.",
OFFSET(lookahead_level), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, NV_ENC_LOOKAHEAD_LEVEL_AUTOSELECT, VE, .unit = "lookahead_level" },

View File

@ -224,6 +224,12 @@ static const AVOption options[] = {
OFFSET(max_slice_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
{ "constrained-encoding", "Enable constrainedFrame encoding where each slice in the constrained picture is independent of other slices",
OFFSET(constrained_encoding), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
#ifdef NVENC_HAVE_H264_AND_AV1_TEMPORAL_FILTER
{ "tf_level", "Specifies the strength of the temporal filtering",
OFFSET(tf_level), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, VE, .unit = "tf_level" },
{ "0", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TEMPORAL_FILTER_LEVEL_0 }, 0, 0, VE, .unit = "tf_level" },
{ "4", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_TEMPORAL_FILTER_LEVEL_4 }, 0, 0, VE, .unit = "tf_level" },
#endif
#ifdef NVENC_HAVE_LOOKAHEAD_LEVEL
{ "lookahead_level", "Specifies the lookahead level. Higher level may improve quality at the expense of performance.",
OFFSET(lookahead_level), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, NV_ENC_LOOKAHEAD_LEVEL_AUTOSELECT, VE, .unit = "lookahead_level" },