[FFmpeg-cvslog] avcodec/nvenc: add Temporal Filtering for AV1 and H.264 in NVENC
Diego de Souza
git at videolan.org
Sun Feb 2 21:04:18 EET 2025
ffmpeg | branch: master | Diego de Souza <ddesouza at nvidia.com> | Wed Jan 8 13:21:01 2025 +0100| [a583f7e2fd454acf7a279d3593fef6d48a3fef83] | committer: Timo Rothenpieler
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 at nvidia.com>
Signed-off-by: Timo Rothenpieler <timo at rothenpieler.org>
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=a583f7e2fd454acf7a279d3593fef6d48a3fef83
---
libavcodec/nvenc.c | 40 +++++++++++++++++++++++++++++++++++++++-
libavcodec/nvenc.h | 1 +
libavcodec/nvenc_av1.c | 6 ++++++
libavcodec/nvenc_h264.c | 6 ++++++
4 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index f301269dbd..3403fa8996 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -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
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
index 2d8e8bef44..6f7f8d4e7f 100644
--- a/libavcodec/nvenc.h
+++ b/libavcodec/nvenc.h
@@ -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
diff --git a/libavcodec/nvenc_av1.c b/libavcodec/nvenc_av1.c
index bccc63dd5b..5dd27fe872 100644
--- a/libavcodec/nvenc_av1.c
+++ b/libavcodec/nvenc_av1.c
@@ -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" },
diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
index ca997da209..5e9f73412f 100644
--- a/libavcodec/nvenc_h264.c
+++ b/libavcodec/nvenc_h264.c
@@ -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" },
More information about the ffmpeg-cvslog
mailing list