From patchwork Mon Jun 24 18:50:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chun-Min Chang X-Patchwork-Id: 50142 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a59:ae71:0:b0:482:c625:d099 with SMTP id w17csp2201496vqz; Mon, 24 Jun 2024 11:51:27 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCUwKb8bkhuJAVyEbT3G2z09iIJUntyL6uPpsPRS8QXPGbErOsTljoGZOzqYuWcZoa+jhHcJIhqLYkJnJjPL5+gcA20xR8Ag/UNSjg== X-Google-Smtp-Source: AGHT+IHBmaFBC4pR2m3GV6d/QVJvj4/w0+E9Mk3noNWmnC4g2q48AiAgK/1vXpSJU3mzephlxAo8 X-Received: by 2002:ac2:47e8:0:b0:52c:86de:cb61 with SMTP id 2adb3069b0e04-52ce1832c4fmr3403079e87.10.1719255087260; Mon, 24 Jun 2024 11:51:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1719255087; cv=none; d=google.com; s=arc-20160816; b=ROExvrgyOQO/rKN3jTv3ExzOiKJuZhC5Kvu+j2bNgLrbRrVYwgRHUNavta4OtTPRAw eiMZI6c9UPTNmXBkeOYiH07eM1p+qQmJze3qgSjiZNQ43pONMyN6rj0Frgxg8hzPmC2a aWDf3kvHSb3Hr12+VL0K1/Pj+7BYX2BEOo6RV3PPB2tgHAGZzdZyjS2yoyUEea0sCUsd Uq+k5zve1ojtxBzhSMRX4bCvTK3aX41cc59pUrxZIpnRQcPKNy9WfFQHape+NhP1VUfT tNzsMJHBQaTFbUmJN9bRB1uIv8VCiTdlIIcGSMYNsODtb0xfEMsxxfwMq7ezvEHKDx9t YGrw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:message-id:date:to:from :dkim-signature:delivered-to; bh=0Zj8Vehieo6Stvs8iN+Yq/HiYJIRpJFSytgpUFqD85s=; fh=GTBdKvE2mKldF8ngmtQp3VF+vNrF3jFx5LbH7ThL2rQ=; b=e3xf+bW1R5UiIgHx3TpLJQ06rF4jFdtAun7sxKY0RrssxU7h+UrFvR/RngRZXfehIX f5G80cOJzdeDmluzNaDOa+OUx32p9hSsxPVcl9/Xt9msReBGdGc3khMuKwQBhnkrHHJt mrGFSO+6yYdw4aV6043Qp7ZFrLgJr2qB/DAwWOX/CzyPPkqKllfvxyRhKkVCKRbtYxNe TqqR1D2raLosNnrESSfpCM7b5gHoeFYDV/wD+nEWH1uCapHh/SVe0SruKJF2t9C+0x7Y Y3q07TOtrtrgZenIgf71Q3EXX8ol1vhFOZYkXS6QJCjh+7PYoOtKI2Sb3zSdHDWv74xZ AVHA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20230601 header.b=LV1PB1J8; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id 2adb3069b0e04-52cd63b3972si2282306e87.107.2024.06.24.11.51.26; Mon, 24 Jun 2024 11:51:27 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20230601 header.b=LV1PB1J8; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DCE9468D4CF; Mon, 24 Jun 2024 21:51:22 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pf1-f180.google.com (mail-pf1-f180.google.com [209.85.210.180]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 77B1C68D1DA for ; Mon, 24 Jun 2024 21:51:16 +0300 (EEST) Received: by mail-pf1-f180.google.com with SMTP id d2e1a72fcca58-70666ab6434so1820212b3a.1 for ; Mon, 24 Jun 2024 11:51:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1719255074; x=1719859874; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=P3QWpg/qqyzzLTnQKhXxz9wY5oY1Idc9Y5+1c0gGBtE=; b=LV1PB1J8mD2IUjTuKRK39uH9Y4+hrjRS3huy8EiY3fw4tKY2svRIsJZJvhTfihK/Cg oGAufrASBOKiTlc/FPrKz50Qbv+UO2V/DarGTLitfvwA33qzR78HujMo4pOyz7Pe6TXH ykaj0Ro0mBVCSpdTIHmqQYsrVDOkP6P24W++zgrWeMySunwQFBC+NlIpw101Q2S/loZf Hkw4OciG2Cth5CYELUvQQ22JmOi68MnwS3fxCy8vuG5vRqmFOZPJF4cex7PMU0JV5kN/ 8gd8OG2qr2A+ydXtrfVMSjpes9bXIl1bfXFaC89lAHQk137mCKZZ9OJvvWnO5C2jw2oz w3AQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719255074; x=1719859874; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=P3QWpg/qqyzzLTnQKhXxz9wY5oY1Idc9Y5+1c0gGBtE=; b=LBc62rZRN8QLYnX6pzUihfmctZfpb//JyXMqSAXbVhThP0pU17kX262m1AnT52aBp1 yyFzspMp6RWHlAlal5tCsRgFaVtN7dJTEOFB5rqKUgv8FqxHs5Gp0ukQgqoMNFdhEne2 R4ynZ4RgKTjqMplOToSFa7dl7yVs61H0iWkXv8REtYnujN29E9vt6dasJST/GCbAwCTS YkM6ve6XwS9CC/CxP2a7KhmGReTnsJSvAhRwvDTm90b/ccvwAY4FClqfXeN9XOgHXPKB HlDMZon6TW2el90wArq2HD/t37Fmzp2SDwuiYU4E3v1GA9i2IREz3mf7+Phe2uNopMe6 UuKQ== X-Gm-Message-State: AOJu0YyWMjU2tTw4PlWvn31K3xNJ0pYWOSHDRrOgBhIYnsBG5Dgfm+je KoJ+Wv7e79TLRdKG8jo3HUcXDGCtZt1ZfiRtn0zi3rgp/1iPWtZAnddLs+VG X-Received: by 2002:a05:6a00:18a5:b0:706:58a8:f686 with SMTP id d2e1a72fcca58-7067105b523mr6539243b3a.32.1719255074222; Mon, 24 Jun 2024 11:51:14 -0700 (PDT) Received: from cm-ThinkStation-P620.. ([2001:569:7cb3:8e00:def0:6d41:ecaf:16c2]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7067090578dsm3955562b3a.82.2024.06.24.11.51.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 24 Jun 2024 11:51:13 -0700 (PDT) From: Chun-Min Chang To: ffmpeg-devel@ffmpeg.org Date: Mon, 24 Jun 2024 11:50:59 -0700 Message-Id: <20240624185059.16797-1-chun.m.chang@gmail.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] Allow enabling SVC in libaomenc X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Chun-Min Chang Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: cakGLykt5NAH 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 --- 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 #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