[FFmpeg-devel] [PATCH] Multi NVENC Split Frame Encoding in HEVC and AV1
Timo Rothenpieler
timo at rothenpieler.org
Thu Apr 11 16:50:16 EEST 2024
On 11/04/2024 13:58, Diego Felix de Souza via ffmpeg-devel wrote:
> From: Diego Felix de Souza <ddesouza at nvidia.com>
>
> When Split frame encoding is enabled, each input frame is partitioned into
> horizontal strips which are encoded independently and simultaneously by
> separate NVENCs, usually resulting in increased encoding speed compared to
> single NVENC encoding.
> ---
> libavcodec/nvenc.c | 16 ++++++++++++++++
> libavcodec/nvenc.h | 2 ++
> libavcodec/nvenc_av1.c | 8 ++++++++
> libavcodec/nvenc_hevc.c | 8 ++++++++
> 4 files changed, 34 insertions(+)
>
> diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
> index b6c5ed3e6b..f4d0d21715 100644
> --- a/libavcodec/nvenc.c
> +++ b/libavcodec/nvenc.c
> @@ -1696,6 +1696,22 @@ FF_ENABLE_DEPRECATION_WARNINGS
> if (ctx->weighted_pred == 1)
> ctx->init_encode_params.enableWeightedPrediction = 1;
>
> +#ifdef NVENC_HAVE_SPLIT_FRAME_ENCODING
> + if (avctx->codec->id != AV_CODEC_ID_H264 )
nit: superfluous space
In general, this check is probably not necessary, given the h264 encoder
does not have this AVOption so it'll always be zero-initialized there,
which should be fine?
Or would setting it to the equivalent of "auto" cause issues on h264?
> + ctx->init_encode_params.splitEncodeMode = ctx->split_encode_mode;
> +
> + if ((ctx->split_encode_mode != NV_ENC_SPLIT_DISABLE_MODE) &&
> + ((ctx->weighted_pred == 1) && (avctx->codec->id == AV_CODEC_ID_HEVC ))) {
I think the ffmpeg recommended style would indent this line by 4 spaces.
What I usually do, even though it's technically against
style-guidelines, is indent the extra lines by 4, and then put the
opening { on its own line, since imo it greatly improves readability.
also a superfluous space at the end.
> + av_log(avctx, AV_LOG_WARNING, "Split encoding is not "
> + "supported if any of the following features: weighted prediction, "
> + "alpha layer encoding, subframe mode, output into video memory "
> + "buffer, picture timing/buffering period SEI message insertion "
> + "with DX12 interface are enabled in case of HEVC. For AV1, split "
> + "encoding is not supported when output into video memory buffer "
> + "is enabled.\n");
This message is a bit of a mouthful, and most of it is not applicable to
users.
I'd maybe shorten it to something like:
"Split encoding not supported if weighted prediction enabled."
Since that's the only option that can actually cause issues with the
current nvenc.c implementation.
> + }
> +#endif
> +
> if (ctx->bluray_compat) {
> ctx->aud = 1;
> ctx->dpb_size = FFMIN(FFMAX(avctx->refs, 0), 6);
> diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
> index 85ecaf1b5f..09de00badc 100644
> --- a/libavcodec/nvenc.h
> +++ b/libavcodec/nvenc.h
> @@ -81,6 +81,7 @@ typedef void ID3D11Device;
> // SDK 12.1 compile time feature checks
> #if NVENCAPI_CHECK_VERSION(12, 1)
> #define NVENC_NO_DEPRECATED_RC
> +#define NVENC_HAVE_SPLIT_FRAME_ENCODING
> #endif
>
> // SDK 12.2 compile time feature checks
> @@ -280,6 +281,7 @@ typedef struct NvencContext
> int tf_level;
> int lookahead_level;
> int unidir_b;
> + int split_encode_mode;
> } NvencContext;
>
> int ff_nvenc_encode_init(AVCodecContext *avctx);
> diff --git a/libavcodec/nvenc_av1.c b/libavcodec/nvenc_av1.c
> index d37ee07bff..45dc3c26e0 100644
> --- a/libavcodec/nvenc_av1.c
> +++ b/libavcodec/nvenc_av1.c
> @@ -157,6 +157,14 @@ static const AVOption options[] = {
> { "1", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LOOKAHEAD_LEVEL_1 }, 0, 0, VE, .unit = "lookahead_level" },
> { "2", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LOOKAHEAD_LEVEL_2 }, 0, 0, VE, .unit = "lookahead_level" },
> { "3", "", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_LOOKAHEAD_LEVEL_3 }, 0, 0, VE, .unit = "lookahead_level" },
> +#endif
> +#ifdef NVENC_HAVE_SPLIT_FRAME_ENCODING
> + { "split_encode_mode", "Specifies the split encoding mode", OFFSET(split_encode_mode), AV_OPT_TYPE_INT, { .i64 = NV_ENC_SPLIT_DISABLE_MODE }, 0, NV_ENC_SPLIT_DISABLE_MODE, VE, .unit = "split_encode_mode" },
> + { "disabled", "Disabled for all configurations", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_SPLIT_DISABLE_MODE }, 0, 0, VE, .unit = "split_encode_mode" },
> + { "auto", "Enabled or disabled depending on the preset and tuning info", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_SPLIT_AUTO_MODE }, 0, 0, VE, .unit = "split_encode_mode" },
> + { "forced", "Enabled with number of horizontal strips selected by the driver", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_SPLIT_AUTO_FORCED_MODE }, 0, 0, VE, .unit = "split_encode_mode" },
> + { "2", "Enabled with number of horizontal strips forced to 2 when number of NVENCs > 1", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_SPLIT_TWO_FORCED_MODE }, 0, 0, VE, .unit = "split_encode_mode" },
> + { "3", "Enabled with number of horizontal strips forced to 3 when number of NVENCs > 2", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_SPLIT_THREE_FORCED_MODE }, 0, 0, VE, .unit = "split_encode_mode" },
> #endif
Shouldn't the default be "auto"?
At least I assume so far, without this option present, the field was
just zero initialized, which equates to auto.
So disabling it might surprise some users with degraded performance?
Or am I missing something?
> { NULL }
> };
> diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
> index bd8b6153f3..1f5e56ecd0 100644
> --- a/libavcodec/nvenc_hevc.c
> +++ b/libavcodec/nvenc_hevc.c
> @@ -216,6 +216,14 @@ static const AVOption options[] = {
> #endif
> #ifdef NVENC_HAVE_UNIDIR_B
> { "unidir_b", "Enable use of unidirectional B-Frames.", OFFSET(unidir_b), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
> +#endif
> +#ifdef NVENC_HAVE_SPLIT_FRAME_ENCODING
> + { "split_encode_mode", "Specifies the split encoding mode", OFFSET(split_encode_mode), AV_OPT_TYPE_INT, { .i64 = NV_ENC_SPLIT_DISABLE_MODE }, 0, NV_ENC_SPLIT_DISABLE_MODE, VE, .unit = "split_encode_mode" },
> + { "disabled", "Disabled for all configurations", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_SPLIT_DISABLE_MODE }, 0, 0, VE, .unit = "split_encode_mode" },
> + { "auto", "Enabled or disabled depending on the preset and tuning info", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_SPLIT_AUTO_MODE }, 0, 0, VE, .unit = "split_encode_mode" },
> + { "forced", "Enabled with number of horizontal strips selected by the driver", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_SPLIT_AUTO_FORCED_MODE }, 0, 0, VE, .unit = "split_encode_mode" },
> + { "2", "Enabled with number of horizontal strips forced to 2 when number of NVENCs > 1", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_SPLIT_TWO_FORCED_MODE }, 0, 0, VE, .unit = "split_encode_mode" },
> + { "3", "Enabled with number of horizontal strips forced to 3 when number of NVENCs > 2", 0, AV_OPT_TYPE_CONST, { .i64 = NV_ENC_SPLIT_THREE_FORCED_MODE }, 0, 0, VE, .unit = "split_encode_mode" },
> #endif
same as above
> { NULL }
> };
> --
> 2.34.1
>
> -----------------------------------------------------------------------------------
> NVIDIA GmbH
> Wuerselen
> Amtsgericht Aachen
> HRB 8361
> Managing Directors: Rebecca Peters, Donald Robertson, Janet Hall, Ludwig von Reiche
>
> -----------------------------------------------------------------------------------
> This email message is for the sole use of the intended recipient(s) and may contain
> confidential information. Any unauthorized review, use, disclosure or distribution
> is prohibited. If you are not the intended recipient, please contact the sender by
> reply email and destroy all copies of the original message.
> -----------------------------------------------------------------------------------
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
More information about the ffmpeg-devel
mailing list