From 83289a5fb7d48c38fbc34b0aae284dbbfb97a99c Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Thu, 19 Jun 2025 08:44:35 +0200 Subject: [PATCH] vcomp/lavc: nvenc no intra-refresh for HEVC/AV1 Since the pulsation issue, it was not much usable, anyways and this clean-ups the code a bit. Also the behavior will be now more deterministic - it behaved differently with patched FFmpeg (most likely GH Linux builds), othewrise differntly. + enable the header-inserter if user expliclty requesetd intra-refresh refers to GH-114 --- ...OPLENGTH-is-useless-for-UltraGrid-up.patch | 53 ------------------- src/video_compress/libavcodec.cpp | 53 +++++++++++-------- 2 files changed, 32 insertions(+), 74 deletions(-) delete mode 100644 .github/scripts/Linux/ffmpeg-patches/0001-NVENC_INFINITE_GOPLENGTH-is-useless-for-UltraGrid-up.patch diff --git a/.github/scripts/Linux/ffmpeg-patches/0001-NVENC_INFINITE_GOPLENGTH-is-useless-for-UltraGrid-up.patch b/.github/scripts/Linux/ffmpeg-patches/0001-NVENC_INFINITE_GOPLENGTH-is-useless-for-UltraGrid-up.patch deleted file mode 100644 index 11cd46aee..000000000 --- a/.github/scripts/Linux/ffmpeg-patches/0001-NVENC_INFINITE_GOPLENGTH-is-useless-for-UltraGrid-up.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 2bd65325dc20ad1ea3111e8a8b8328224fd9ee0a Mon Sep 17 00:00:00 2001 -From: Martin Pulec -Date: Mon, 24 Jul 2023 16:15:29 +0200 -Subject: [PATCH] NVENC_INFINITE_GOPLENGTH is useless for UltraGrid (updated) - ---- - libavcodec/avcodec.h | 3 +++ - libavcodec/nvenc.c | 3 --- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h -index fe41ecc3c9..15bc1f5cec 100644 ---- a/libavcodec/avcodec.h -+++ b/libavcodec/avcodec.h -@@ -3270,4 +3270,7 @@ int avcodec_is_open(AVCodecContext *s); - * @} - */ - -+// UltraGrid patch -+#define PATCHED_FF_NVENC_NO_INFINITE_GOP 1 -+ - #endif /* AVCODEC_AVCODEC_H */ -diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c -index 0b6417674e..70adc26f08 100644 ---- a/libavcodec/nvenc.c -+++ b/libavcodec/nvenc.c -@@ -1173,7 +1173,6 @@ static av_cold int nvenc_setup_h264_config(AVCodecContext *avctx) - h264->enableIntraRefresh = 1; - h264->intraRefreshPeriod = cc->gopLength; - h264->intraRefreshCnt = cc->gopLength - 1; -- cc->gopLength = NVENC_INFINITE_GOPLENGTH; - #ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH - h264->singleSliceIntraRefresh = ctx->single_slice_intra_refresh; - #endif -@@ -1294,7 +1293,6 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx) - hevc->enableIntraRefresh = 1; - hevc->intraRefreshPeriod = cc->gopLength; - hevc->intraRefreshCnt = cc->gopLength - 1; -- cc->gopLength = NVENC_INFINITE_GOPLENGTH; - #ifdef NVENC_HAVE_SINGLE_SLICE_INTRA_REFRESH - hevc->singleSliceIntraRefresh = ctx->single_slice_intra_refresh; - #endif -@@ -1409,7 +1407,6 @@ static av_cold int nvenc_setup_av1_config(AVCodecContext *avctx) - av1->enableIntraRefresh = 1; - av1->intraRefreshPeriod = cc->gopLength; - av1->intraRefreshCnt = cc->gopLength - 1; -- cc->gopLength = NVENC_INFINITE_GOPLENGTH; - } - - av1->idrPeriod = cc->gopLength; --- -2.41.0 - diff --git a/src/video_compress/libavcodec.cpp b/src/video_compress/libavcodec.cpp index e7ebbfe99..4d1079d93 100644 --- a/src/video_compress/libavcodec.cpp +++ b/src/video_compress/libavcodec.cpp @@ -3,7 +3,7 @@ * @author Martin Pulec */ /* - * Copyright (c) 2013-2024 CESNET, z. s. p. o. + * Copyright (c) 2013-2025 CESNET * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1792,19 +1792,38 @@ static void configure_nvenc(AVCodecContext *codec_ctx, struct setparam_param *pa } } - set_forced_idr(codec_ctx, 1); -#ifdef PATCHED_FF_NVENC_NO_INFINITE_GOP - const bool patched_ff = true; -#else - const bool patched_ff = false; - if (param->periodic_intra != 0) { - LOG(LOG_LEVEL_WARNING) << MOD_NAME "FFmpeg not patched, " << (param->periodic_intra != 1 ? "not " : "") << "enabling Intra Refresh.\n"; + check_av_opt_set(codec_ctx->priv_data, "forced-idr", 1); + + const bool h264 = codec_ctx->codec_id == AV_CODEC_ID_H264; + const bool hevc = codec_ctx->codec_id == AV_CODEC_ID_HEVC; + if (!h264) { + if (param->periodic_intra == 1) { + if (hevc) { + MSG(WARNING, + "Requeseted intra-refresh for NVENC " + "HEVC but there may occur artifacts!\n"); + } else { + MSG(WARNING, + "Requeseted intra-refresh for NVENC " + "AV1 but it won't most likely work with UG " + "because of NVENC_INFINITE_GOPLENGTH!\n"); + } + } + if (param->periodic_intra == -1) { + MSG(WARNING, + "Intra-refresh won't be enabled for NVENC " + "HEVC/AV1, bitrate variance will be higher!\n"); + } } -#endif - - if ((patched_ff && param->periodic_intra != 0) || param->periodic_intra == 1) { - incomp_feature_warn(INCOMP_INTRA_REFRESH, param->periodic_intra); - check_av_opt_set(codec_ctx->priv_data, "intra-refresh", 1); + if ((h264 && param->periodic_intra != 0) || + param->periodic_intra == 1) { + if (param->header_inserter_req == -1) { + MSG(INFO, + "Auto-enabling header inserter for %s when " + "intra-refresh used.\n", codec_ctx->codec->name); + param->header_inserter_req = 1; + } + param->periodic_intra = 1; } check_av_opt_set(codec_ctx->priv_data, "rc", DEFAULT_NVENC_RC); @@ -1817,14 +1836,6 @@ static void configure_nvenc(AVCodecContext *codec_ctx, struct setparam_param *pa double lavc_rc_buffer_size_factor = DEFAULT_NVENC_RC_BUF_SIZE_FACTOR; if (const char *val = get_commandline_param("lavc-rc-buffer-size-factor")) { lavc_rc_buffer_size_factor = stof(val); - } else { - LOG(LOG_LEVEL_WARNING) - << MOD_NAME - "To reduce NVENC pulsation, you can try \"--param " - "lavc-rc-buffer-size-factor=0\"" - " or a small number. 0 or higher value (than default " - << DEFAULT_NVENC_RC_BUF_SIZE_FACTOR - << ") may cause frame drops on receiver.\n"; } codec_ctx->rc_buffer_size = (int) ((double) codec_ctx->rc_max_rate / param->desc.fps *