libaomenc-svc.patch (6806B)
1 diff --git a/media/ffvpx/libavcodec/libaomenc.c b/media/ffvpx/libavcodec/libaomenc.c 2 index 0f7571ee7a1ba..a116989b1f4bc 100644 3 --- a/media/ffvpx/libavcodec/libaomenc.c 4 +++ b/media/ffvpx/libavcodec/libaomenc.c 5 @@ -30,6 +30,7 @@ 6 #include <aom/aomcx.h> 7 8 #include "libavutil/avassert.h" 9 +#include "libavutil/avstring.h" 10 #include "libavutil/base64.h" 11 #include "libavutil/common.h" 12 #include "libavutil/cpu.h" 13 @@ -137,6 +138,7 @@ typedef struct AOMEncoderContext { 14 int enable_diff_wtd_comp; 15 int enable_dist_wtd_comp; 16 int enable_dual_filter; 17 + AVDictionary *svc_parameters; 18 AVDictionary *aom_params; 19 } AOMContext; 20 21 @@ -201,6 +203,7 @@ static const char *const ctlidstr[] = { 22 [AV1E_GET_TARGET_SEQ_LEVEL_IDX] = "AV1E_GET_TARGET_SEQ_LEVEL_IDX", 23 #endif 24 [AV1_GET_NEW_FRAME_IMAGE] = "AV1_GET_NEW_FRAME_IMAGE", 25 + [AV1E_SET_SVC_PARAMS] = "AV1E_SET_SVC_PARAMS", 26 }; 27 28 static av_cold void log_encoder_error(AVCodecContext *avctx, const char *desc) 29 @@ -382,6 +385,31 @@ static av_cold int codecctl_imgp(AVCodecContext *avctx, 30 return 0; 31 } 32 33 +static av_cold int codecctl_svcp(AVCodecContext *avctx, 34 +#ifdef UENUM1BYTE 35 + aome_enc_control_id id, 36 +#else 37 + enum aome_enc_control_id id, 38 +#endif 39 + aom_svc_params_t *svc_params) 40 +{ 41 + AOMContext *ctx = avctx->priv_data; 42 + char buf[80]; 43 + int res; 44 + 45 + snprintf(buf, sizeof(buf), "%s:", ctlidstr[id]); 46 + 47 + res = aom_codec_control(&ctx->encoder, id, svc_params); 48 + if (res != AOM_CODEC_OK) { 49 + snprintf(buf, sizeof(buf), "Failed to get %s codec control", 50 + ctlidstr[id]); 51 + log_encoder_error(avctx, buf); 52 + return AVERROR(EINVAL); 53 + } 54 + 55 + return 0; 56 +} 57 + 58 static av_cold int aom_free(AVCodecContext *avctx) 59 { 60 AOMContext *ctx = avctx->priv_data; 61 @@ -428,6 +456,18 @@ static av_cold int aom_free(AVCodecContext *avctx) 62 return 0; 63 } 64 65 +static void aom_svc_parse_int_array(int *dest, char *value, int max_entries) 66 +{ 67 + int dest_idx = 0; 68 + char *saveptr = NULL; 69 + char *token = av_strtok(value, ",", &saveptr); 70 + 71 + while (token && dest_idx < max_entries) { 72 + dest[dest_idx++] = strtoul(token, NULL, 10); 73 + token = av_strtok(NULL, ",", &saveptr); 74 + } 75 +} 76 + 77 static int set_pix_fmt(AVCodecContext *avctx, aom_codec_caps_t codec_caps, 78 struct aom_codec_enc_cfg *enccfg, aom_codec_flags_t *flags, 79 aom_img_fmt_t *img_fmt) 80 @@ -968,6 +1008,41 @@ static av_cold int aom_init(AVCodecContext *avctx, 81 if (ctx->enable_intrabc >= 0) 82 codecctl_int(avctx, AV1E_SET_ENABLE_INTRABC, ctx->enable_intrabc); 83 84 + if (enccfg.rc_end_usage == AOM_CBR) { 85 + aom_svc_params_t svc_params = {}; 86 + svc_params.framerate_factor[0] = 1; 87 + svc_params.number_spatial_layers = 1; 88 + svc_params.number_temporal_layers = 1; 89 + 90 + AVDictionaryEntry *en = NULL; 91 + while ((en = av_dict_get(ctx->svc_parameters, "", en, AV_DICT_IGNORE_SUFFIX))) { 92 + if (!strlen(en->value)) 93 + return AVERROR(EINVAL); 94 + 95 + if (!strcmp(en->key, "number_spatial_layers")) 96 + svc_params.number_spatial_layers = strtoul(en->value, NULL, 10); 97 + else if (!strcmp(en->key, "number_temporal_layers")) 98 + svc_params.number_temporal_layers = strtoul(en->value, NULL, 10); 99 + else if (!strcmp(en->key, "max_quantizers")) 100 + aom_svc_parse_int_array(svc_params.max_quantizers, en->value, AOM_MAX_LAYERS); 101 + else if (!strcmp(en->key, "min_quantizers")) 102 + aom_svc_parse_int_array(svc_params.min_quantizers, en->value, AOM_MAX_LAYERS); 103 + else if (!strcmp(en->key, "scaling_factor_num")) 104 + aom_svc_parse_int_array(svc_params.scaling_factor_num, en->value, AOM_MAX_SS_LAYERS); 105 + else if (!strcmp(en->key, "scaling_factor_den")) 106 + aom_svc_parse_int_array(svc_params.scaling_factor_den, en->value, AOM_MAX_SS_LAYERS); 107 + else if (!strcmp(en->key, "layer_target_bitrate")) 108 + aom_svc_parse_int_array(svc_params.layer_target_bitrate, en->value, AOM_MAX_LAYERS); 109 + else if (!strcmp(en->key, "framerate_factor")) 110 + aom_svc_parse_int_array(svc_params.framerate_factor, en->value, AOM_MAX_TS_LAYERS); 111 + } 112 + 113 + res = codecctl_svcp(avctx, AV1E_SET_SVC_PARAMS, &svc_params); 114 + if (res < 0) 115 + return res; 116 + } 117 + 118 + 119 #if AOM_ENCODER_ABI_VERSION >= 23 120 { 121 const AVDictionaryEntry *en = NULL; 122 @@ -1310,6 +1385,25 @@ FF_ENABLE_DEPRECATION_WARNINGS 123 124 if (frame->pict_type == AV_PICTURE_TYPE_I) 125 flags |= AOM_EFLAG_FORCE_KF; 126 + 127 + AVDictionaryEntry* en = av_dict_get(frame->metadata, "temporal_id", NULL, 0); 128 + if (en) { 129 + aom_svc_layer_id_t layer_id = {}; 130 + layer_id.temporal_layer_id = strtoul(en->value, NULL, 10); 131 + av_log(avctx, AV_LOG_DEBUG, "Frame pts % " PRId64 " temporal layer id %d", 132 + frame->pts, layer_id.temporal_layer_id); 133 + if (!ctx->svc_parameters) { 134 + av_log(avctx, AV_LOG_WARNING, 135 + "Temporal SVC not enabled, but temporal layer id received."); 136 + } 137 + res = aom_codec_control(&ctx->encoder, AV1E_SET_SVC_LAYER_ID, &layer_id); 138 + if (res != AOM_CODEC_OK) { 139 + av_log(avctx, AV_LOG_ERROR, 140 + "Error setting temporal layer id %d on frame pts % " PRId64 "\n", 141 + layer_id.temporal_layer_id, frame->pts); 142 + return res; 143 + } 144 + } 145 } 146 147 res = aom_codec_encode(&ctx->encoder, rawimg, timestamp, duration, flags); 148 @@ -1538,6 +1632,7 @@ static const AVOption options[] = { 149 { "enable-masked-comp", "Enable masked compound", OFFSET(enable_masked_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, 150 { "enable-interintra-comp", "Enable interintra compound", OFFSET(enable_interintra_comp), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, 151 { "enable-smooth-interintra", "Enable smooth interintra mode", OFFSET(enable_smooth_interintra), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, VE}, 152 + { "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}, 153 #if AOM_ENCODER_ABI_VERSION >= 23 154 { "aom-params", "Set libaom options using a :-separated list of key=value pairs", OFFSET(aom_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, 155 #endif