From: Chun-Min Chang <chun.m.chang@gmail.com> To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] [PATCH] Allow enabling SVC in libaomenc Date: Tue, 11 Jun 2024 13:22:16 -0700 Message-ID: <6f46f156-5a95-4905-8028-bac6b17f872e@gmail.com> (raw) This patch updates libaomenc.c to accept parameters for SVC (Scalable Video Coding) settings via the FFmpeg API `av_opt_set`. The SVC configuration is applied based on the provided parameters. As libaom's SVC functionality only operates with constant bitrate encoding [1], these parameters will only take effect when the bitrate is set to constant. [1] https://aomedia.googlesource.com/aom/+/a7ef80c44bfb34b08254194b1ab72d4e93ff4b07/av1/encoder/svc_layercontext.h#115 Signed-off-by: Chun-Min Chang <chun.m.chang@gmail.com> --- libavcodec/libaomenc.c | 75 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index dec74ebecd..a8602a6b56 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -30,6 +30,7 @@ #include <aom/aomcx.h> #include "libavutil/avassert.h" +#include "libavutil/avstring.h" #include "libavutil/base64.h" #include "libavutil/common.h" #include "libavutil/cpu.h" @@ -137,6 +138,7 @@ typedef struct AOMEncoderContext { int enable_diff_wtd_comp; int enable_dist_wtd_comp; int enable_dual_filter; + AVDictionary *svc_parameters; AVDictionary *aom_params; } AOMContext; @@ -201,6 +203,7 @@ static const char *const ctlidstr[] = { [AV1E_GET_TARGET_SEQ_LEVEL_IDX] = "AV1E_GET_TARGET_SEQ_LEVEL_IDX", #endif [AV1_GET_NEW_FRAME_IMAGE] = "AV1_GET_NEW_FRAME_IMAGE", + [AV1E_SET_SVC_PARAMS] = "AV1E_SET_SVC_PARAMS", }; static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc) @@ -382,6 +385,31 @@ static av_cold int codecctl_imgp(AVCodecContext *avctx, return 0; } +static av_cold int codecctl_svcp(AVCodecContext *avctx, +#ifdef UENUM1BYTE + aome_enc_control_id id, +#else + enum aome_enc_control_id id, +#endif + aom_svc_params_t *svc_params) +{ + AOMContext *ctx = avctx->priv_data; + char buf[80]; + int res; + + snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); + + res = aom_codec_control(&ctx->encoder, id, svc_params); + if (res != AOM_CODEC_OK) { + snprintf(buf, sizeof(buf), "Failed to get %s codec control", + ctlidstr[id]); + log_encoder_error(avctx, buf); + return AVERROR(EINVAL); + } + + return 0; +} + static av_cold int aom_free(AVCodecContext *avctx) { AOMContext *ctx = avctx->priv_data; @@ -673,6 +701,18 @@ static int choose_tiling(AVCodecContext *avctx, return 0; } +static void aom_svc_parse_int_array(int *dest, char *value, int max_entries) +{ + int dest_idx = 0; + char *saveptr = NULL; + char *token = av_strtok(value, ",", &saveptr); + + while (token && dest_idx < max_entries) { + dest[dest_idx++] = strtoul(token, NULL, 10); + token = av_strtok(NULL, ",", &saveptr); + } +} + static av_cold int aom_init(AVCodecContext *avctx, const struct aom_codec_iface *iface) { @@ -968,6 +1008,40 @@ static av_cold int aom_init(AVCodecContext *avctx, if (ctx->enable_intrabc >= 0) codecctl_int(avctx, AV1E_SET_ENABLE_INTRABC, ctx->enable_intrabc); + if (enccfg.rc_end_usage == AOM_CBR) { + aom_svc_params_t svc_params = {}; + svc_params.framerate_factor[0] = 1; + svc_params.number_spatial_layers = 1; + svc_params.number_temporal_layers = 1; + + const AVDictionaryEntry *en = NULL; + while ((en = av_dict_iterate(ctx->svc_parameters, en))) { + if (!strlen(en->value)) + return AVERROR(EINVAL); + + if (!strcmp(en->key, "number_spatial_layers")) + svc_params.number_spatial_layers = strtoul(en->value, NULL, 10); + else if (!strcmp(en->key, "number_temporal_layers")) + svc_params.number_temporal_layers = strtoul(en->value, NULL, 10); + else if (!strcmp(en->key, "max_quantizers")) + aom_svc_parse_int_array(svc_params.max_quantizers, en->value, AOM_MAX_LAYERS); + else if (!strcmp(en->key, "min_quantizers")) + aom_svc_parse_int_array(svc_params.min_quantizers, en->value, AOM_MAX_LAYERS); + else if (!strcmp(en->key, "scaling_factor_num")) + aom_svc_parse_int_array(svc_params.scaling_factor_num, en->value, AOM_MAX_SS_LAYERS); + else if (!strcmp(en->key, "scaling_factor_den")) + aom_svc_parse_int_array(svc_params.scaling_factor_den, en->value, AOM_MAX_SS_LAYERS); + else if (!strcmp(en->key, "layer_target_bitrate")) + aom_svc_parse_int_array(svc_params.layer_target_bitrate, en->value, AOM_MAX_LAYERS); + else if (!strcmp(en->key, "framerate_factor")) + aom_svc_parse_int_array(svc_params.framerate_factor, en->value, AOM_MAX_TS_LAYERS); + } + + res = codecctl_svcp(avctx, AV1E_SET_SVC_PARAMS, &svc_params); + if (res < 0) + return res; + } + #if AOM_ENCODER_ABI_VERSION >= 23 { const AVDictionaryEntry *en = NULL; @@ -1517,6 +1591,7 @@ static const AVOption options[] = { { "enable-masked-comp", "Enable masked compound", OFFSET(enable_masked_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, { "enable-interintra-comp", "Enable interintra compound", OFFSET(enable_interintra_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, { "enable-smooth-interintra", "Enable smooth interintra mode", OFFSET(enable_smooth_interintra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, + { "svc-parameters", "SVC configuration using a :-separated list of key=value parameters (only applied in CBR mode)", OFFSET(svc_parameters), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE}, #if AOM_ENCODER_ABI_VERSION >= 23 { "aom-params", "Set libaom options using a :-separated list of key=value pairs", OFFSET(aom_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, #endif -- 2.34.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next reply other threads:[~2024-06-11 20:22 UTC|newest] Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top 2024-06-11 20:22 Chun-Min Chang [this message] 2024-06-11 20:28 ` Chun-Min Chang -- strict thread matches above, loose matches on Subject: below -- 2024-06-24 18:50 Chun-Min Chang 2024-06-25 8:45 ` Anton Khirnov 2024-06-05 21:34 Chun-Min Chang 2024-06-05 22:43 ` Michael Niedermayer
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=6f46f156-5a95-4905-8028-bac6b17f872e@gmail.com \ --to=chun.m.chang@gmail.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git