xref: /aosp_15_r20/external/libaom/av1/ratectrl_rtc.cc (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker  * Copyright (c) 2021, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker  *
4*77c1e3ccSAndroid Build Coastguard Worker  * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker  * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker  * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker  */
11*77c1e3ccSAndroid Build Coastguard Worker 
12*77c1e3ccSAndroid Build Coastguard Worker #include "av1/ratectrl_rtc.h"
13*77c1e3ccSAndroid Build Coastguard Worker 
14*77c1e3ccSAndroid Build Coastguard Worker #include <memory>
15*77c1e3ccSAndroid Build Coastguard Worker #include <new>
16*77c1e3ccSAndroid Build Coastguard Worker 
17*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aomcx.h"
18*77c1e3ccSAndroid Build Coastguard Worker #include "aom/aom_encoder.h"
19*77c1e3ccSAndroid Build Coastguard Worker #include "aom_mem/aom_mem.h"
20*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/aom_dsp_common.h"
21*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encoder.h"
22*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/encoder_utils.h"
23*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/pickcdef.h"
24*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/picklpf.h"
25*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/ratectrl.h"
26*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/rc_utils.h"
27*77c1e3ccSAndroid Build Coastguard Worker #include "av1/encoder/svc_layercontext.h"
28*77c1e3ccSAndroid Build Coastguard Worker 
29*77c1e3ccSAndroid Build Coastguard Worker namespace aom {
30*77c1e3ccSAndroid Build Coastguard Worker 
AV1RateControlRtcConfig()31*77c1e3ccSAndroid Build Coastguard Worker AV1RateControlRtcConfig::AV1RateControlRtcConfig() {
32*77c1e3ccSAndroid Build Coastguard Worker   width = 1280;
33*77c1e3ccSAndroid Build Coastguard Worker   height = 720;
34*77c1e3ccSAndroid Build Coastguard Worker   max_quantizer = 63;
35*77c1e3ccSAndroid Build Coastguard Worker   min_quantizer = 2;
36*77c1e3ccSAndroid Build Coastguard Worker   target_bandwidth = 1000;
37*77c1e3ccSAndroid Build Coastguard Worker   buf_initial_sz = 600;
38*77c1e3ccSAndroid Build Coastguard Worker   buf_optimal_sz = 600;
39*77c1e3ccSAndroid Build Coastguard Worker   buf_sz = 1000;
40*77c1e3ccSAndroid Build Coastguard Worker   undershoot_pct = overshoot_pct = 50;
41*77c1e3ccSAndroid Build Coastguard Worker   max_intra_bitrate_pct = 50;
42*77c1e3ccSAndroid Build Coastguard Worker   max_inter_bitrate_pct = 0;
43*77c1e3ccSAndroid Build Coastguard Worker   frame_drop_thresh = 0;
44*77c1e3ccSAndroid Build Coastguard Worker   max_consec_drop_ms = 0;
45*77c1e3ccSAndroid Build Coastguard Worker   framerate = 30.0;
46*77c1e3ccSAndroid Build Coastguard Worker   ss_number_layers = 1;
47*77c1e3ccSAndroid Build Coastguard Worker   ts_number_layers = 1;
48*77c1e3ccSAndroid Build Coastguard Worker   aq_mode = 0;
49*77c1e3ccSAndroid Build Coastguard Worker   layer_target_bitrate[0] = static_cast<int>(target_bandwidth);
50*77c1e3ccSAndroid Build Coastguard Worker   ts_rate_decimator[0] = 1;
51*77c1e3ccSAndroid Build Coastguard Worker   av1_zero(max_quantizers);
52*77c1e3ccSAndroid Build Coastguard Worker   av1_zero(min_quantizers);
53*77c1e3ccSAndroid Build Coastguard Worker   av1_zero(scaling_factor_den);
54*77c1e3ccSAndroid Build Coastguard Worker   av1_zero(scaling_factor_num);
55*77c1e3ccSAndroid Build Coastguard Worker   av1_zero(layer_target_bitrate);
56*77c1e3ccSAndroid Build Coastguard Worker   av1_zero(ts_rate_decimator);
57*77c1e3ccSAndroid Build Coastguard Worker   scaling_factor_num[0] = 1;
58*77c1e3ccSAndroid Build Coastguard Worker   scaling_factor_den[0] = 1;
59*77c1e3ccSAndroid Build Coastguard Worker   max_quantizers[0] = max_quantizer;
60*77c1e3ccSAndroid Build Coastguard Worker   min_quantizers[0] = min_quantizer;
61*77c1e3ccSAndroid Build Coastguard Worker }
62*77c1e3ccSAndroid Build Coastguard Worker 
Create(const AV1RateControlRtcConfig & cfg)63*77c1e3ccSAndroid Build Coastguard Worker std::unique_ptr<AV1RateControlRTC> AV1RateControlRTC::Create(
64*77c1e3ccSAndroid Build Coastguard Worker     const AV1RateControlRtcConfig &cfg) {
65*77c1e3ccSAndroid Build Coastguard Worker   std::unique_ptr<AV1RateControlRTC> rc_api(new (std::nothrow)
66*77c1e3ccSAndroid Build Coastguard Worker                                                 AV1RateControlRTC());
67*77c1e3ccSAndroid Build Coastguard Worker   if (!rc_api) return nullptr;
68*77c1e3ccSAndroid Build Coastguard Worker   rc_api->cpi_ = static_cast<AV1_COMP *>(aom_memalign(32, sizeof(*cpi_)));
69*77c1e3ccSAndroid Build Coastguard Worker   if (!rc_api->cpi_) return nullptr;
70*77c1e3ccSAndroid Build Coastguard Worker   av1_zero(*rc_api->cpi_);
71*77c1e3ccSAndroid Build Coastguard Worker   rc_api->cpi_->ppi =
72*77c1e3ccSAndroid Build Coastguard Worker       static_cast<AV1_PRIMARY *>(aom_memalign(32, sizeof(AV1_PRIMARY)));
73*77c1e3ccSAndroid Build Coastguard Worker   if (!rc_api->cpi_->ppi) return nullptr;
74*77c1e3ccSAndroid Build Coastguard Worker   av1_zero(*rc_api->cpi_->ppi);
75*77c1e3ccSAndroid Build Coastguard Worker   rc_api->cpi_->common.seq_params = &rc_api->cpi_->ppi->seq_params;
76*77c1e3ccSAndroid Build Coastguard Worker   av1_zero(*rc_api->cpi_->common.seq_params);
77*77c1e3ccSAndroid Build Coastguard Worker   if (!rc_api->InitRateControl(cfg)) return nullptr;
78*77c1e3ccSAndroid Build Coastguard Worker   if (cfg.aq_mode) {
79*77c1e3ccSAndroid Build Coastguard Worker     AV1_COMP *const cpi = rc_api->cpi_;
80*77c1e3ccSAndroid Build Coastguard Worker     cpi->enc_seg.map = static_cast<uint8_t *>(aom_calloc(
81*77c1e3ccSAndroid Build Coastguard Worker         cpi->common.mi_params.mi_rows * cpi->common.mi_params.mi_cols,
82*77c1e3ccSAndroid Build Coastguard Worker         sizeof(*cpi->enc_seg.map)));
83*77c1e3ccSAndroid Build Coastguard Worker     if (!cpi->enc_seg.map) return nullptr;
84*77c1e3ccSAndroid Build Coastguard Worker     cpi->cyclic_refresh = av1_cyclic_refresh_alloc(
85*77c1e3ccSAndroid Build Coastguard Worker         cpi->common.mi_params.mi_rows, cpi->common.mi_params.mi_cols);
86*77c1e3ccSAndroid Build Coastguard Worker     if (!cpi->cyclic_refresh) return nullptr;
87*77c1e3ccSAndroid Build Coastguard Worker   }
88*77c1e3ccSAndroid Build Coastguard Worker   return rc_api;
89*77c1e3ccSAndroid Build Coastguard Worker }
90*77c1e3ccSAndroid Build Coastguard Worker 
~AV1RateControlRTC()91*77c1e3ccSAndroid Build Coastguard Worker AV1RateControlRTC::~AV1RateControlRTC() {
92*77c1e3ccSAndroid Build Coastguard Worker   if (cpi_) {
93*77c1e3ccSAndroid Build Coastguard Worker     if (cpi_->svc.number_spatial_layers > 1 ||
94*77c1e3ccSAndroid Build Coastguard Worker         cpi_->svc.number_temporal_layers > 1) {
95*77c1e3ccSAndroid Build Coastguard Worker       for (int sl = 0; sl < cpi_->svc.number_spatial_layers; sl++) {
96*77c1e3ccSAndroid Build Coastguard Worker         for (int tl = 0; tl < cpi_->svc.number_temporal_layers; tl++) {
97*77c1e3ccSAndroid Build Coastguard Worker           int layer =
98*77c1e3ccSAndroid Build Coastguard Worker               LAYER_IDS_TO_IDX(sl, tl, cpi_->svc.number_temporal_layers);
99*77c1e3ccSAndroid Build Coastguard Worker           LAYER_CONTEXT *const lc = &cpi_->svc.layer_context[layer];
100*77c1e3ccSAndroid Build Coastguard Worker           aom_free(lc->map);
101*77c1e3ccSAndroid Build Coastguard Worker         }
102*77c1e3ccSAndroid Build Coastguard Worker       }
103*77c1e3ccSAndroid Build Coastguard Worker     }
104*77c1e3ccSAndroid Build Coastguard Worker     aom_free(cpi_->svc.layer_context);
105*77c1e3ccSAndroid Build Coastguard Worker     cpi_->svc.layer_context = nullptr;
106*77c1e3ccSAndroid Build Coastguard Worker 
107*77c1e3ccSAndroid Build Coastguard Worker     if (cpi_->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ) {
108*77c1e3ccSAndroid Build Coastguard Worker       aom_free(cpi_->enc_seg.map);
109*77c1e3ccSAndroid Build Coastguard Worker       cpi_->enc_seg.map = nullptr;
110*77c1e3ccSAndroid Build Coastguard Worker       av1_cyclic_refresh_free(cpi_->cyclic_refresh);
111*77c1e3ccSAndroid Build Coastguard Worker     }
112*77c1e3ccSAndroid Build Coastguard Worker     aom_free(cpi_->ppi);
113*77c1e3ccSAndroid Build Coastguard Worker     aom_free(cpi_);
114*77c1e3ccSAndroid Build Coastguard Worker   }
115*77c1e3ccSAndroid Build Coastguard Worker }
116*77c1e3ccSAndroid Build Coastguard Worker 
InitRateControl(const AV1RateControlRtcConfig & rc_cfg)117*77c1e3ccSAndroid Build Coastguard Worker bool AV1RateControlRTC::InitRateControl(const AV1RateControlRtcConfig &rc_cfg) {
118*77c1e3ccSAndroid Build Coastguard Worker   AV1_COMMON *cm = &cpi_->common;
119*77c1e3ccSAndroid Build Coastguard Worker   AV1EncoderConfig *oxcf = &cpi_->oxcf;
120*77c1e3ccSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi_->rc;
121*77c1e3ccSAndroid Build Coastguard Worker   cm->seq_params->profile = PROFILE_0;
122*77c1e3ccSAndroid Build Coastguard Worker   cm->seq_params->bit_depth = AOM_BITS_8;
123*77c1e3ccSAndroid Build Coastguard Worker   cm->show_frame = 1;
124*77c1e3ccSAndroid Build Coastguard Worker   oxcf->profile = cm->seq_params->profile;
125*77c1e3ccSAndroid Build Coastguard Worker   oxcf->mode = REALTIME;
126*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.mode = AOM_CBR;
127*77c1e3ccSAndroid Build Coastguard Worker   oxcf->pass = AOM_RC_ONE_PASS;
128*77c1e3ccSAndroid Build Coastguard Worker   oxcf->q_cfg.aq_mode = rc_cfg.aq_mode ? CYCLIC_REFRESH_AQ : NO_AQ;
129*77c1e3ccSAndroid Build Coastguard Worker   oxcf->tune_cfg.content = AOM_CONTENT_DEFAULT;
130*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.drop_frames_water_mark = rc_cfg.frame_drop_thresh;
131*77c1e3ccSAndroid Build Coastguard Worker   if (rc_cfg.max_consec_drop_ms > 0) {
132*77c1e3ccSAndroid Build Coastguard Worker     rc->max_consec_drop = saturate_cast_double_to_int(
133*77c1e3ccSAndroid Build Coastguard Worker         ceil(cpi_->framerate * rc_cfg.max_consec_drop_ms / 1000));
134*77c1e3ccSAndroid Build Coastguard Worker   }
135*77c1e3ccSAndroid Build Coastguard Worker   cpi_->svc.framedrop_mode = AOM_FULL_SUPERFRAME_DROP;
136*77c1e3ccSAndroid Build Coastguard Worker   oxcf->tool_cfg.bit_depth = AOM_BITS_8;
137*77c1e3ccSAndroid Build Coastguard Worker   oxcf->tool_cfg.superblock_size = AOM_SUPERBLOCK_SIZE_DYNAMIC;
138*77c1e3ccSAndroid Build Coastguard Worker   oxcf->algo_cfg.loopfilter_control = LOOPFILTER_ALL;
139*77c1e3ccSAndroid Build Coastguard Worker   cm->current_frame.frame_number = 0;
140*77c1e3ccSAndroid Build Coastguard Worker   cpi_->ppi->p_rc.kf_boost = DEFAULT_KF_BOOST_RT;
141*77c1e3ccSAndroid Build Coastguard Worker   for (auto &lvl_idx : oxcf->target_seq_level_idx) lvl_idx = SEQ_LEVEL_MAX;
142*77c1e3ccSAndroid Build Coastguard Worker 
143*77c1e3ccSAndroid Build Coastguard Worker   memcpy(cpi_->ppi->level_params.target_seq_level_idx,
144*77c1e3ccSAndroid Build Coastguard Worker          oxcf->target_seq_level_idx, sizeof(oxcf->target_seq_level_idx));
145*77c1e3ccSAndroid Build Coastguard Worker   if (!UpdateRateControl(rc_cfg)) return false;
146*77c1e3ccSAndroid Build Coastguard Worker   set_sb_size(cm->seq_params,
147*77c1e3ccSAndroid Build Coastguard Worker               av1_select_sb_size(oxcf, cm->width, cm->height,
148*77c1e3ccSAndroid Build Coastguard Worker                                  cpi_->svc.number_spatial_layers));
149*77c1e3ccSAndroid Build Coastguard Worker   cpi_->ppi->use_svc = cpi_->svc.number_spatial_layers > 1 ||
150*77c1e3ccSAndroid Build Coastguard Worker                        cpi_->svc.number_temporal_layers > 1;
151*77c1e3ccSAndroid Build Coastguard Worker   av1_primary_rc_init(oxcf, &cpi_->ppi->p_rc);
152*77c1e3ccSAndroid Build Coastguard Worker   rc->rc_1_frame = 0;
153*77c1e3ccSAndroid Build Coastguard Worker   rc->rc_2_frame = 0;
154*77c1e3ccSAndroid Build Coastguard Worker   av1_rc_init_minq_luts();
155*77c1e3ccSAndroid Build Coastguard Worker   av1_rc_init(oxcf, rc);
156*77c1e3ccSAndroid Build Coastguard Worker   // Enable external rate control.
157*77c1e3ccSAndroid Build Coastguard Worker   cpi_->rc.rtc_external_ratectrl = 1;
158*77c1e3ccSAndroid Build Coastguard Worker   cpi_->sf.rt_sf.use_nonrd_pick_mode = 1;
159*77c1e3ccSAndroid Build Coastguard Worker   return true;
160*77c1e3ccSAndroid Build Coastguard Worker }
161*77c1e3ccSAndroid Build Coastguard Worker 
UpdateRateControl(const AV1RateControlRtcConfig & rc_cfg)162*77c1e3ccSAndroid Build Coastguard Worker bool AV1RateControlRTC::UpdateRateControl(
163*77c1e3ccSAndroid Build Coastguard Worker     const AV1RateControlRtcConfig &rc_cfg) {
164*77c1e3ccSAndroid Build Coastguard Worker   if (rc_cfg.ss_number_layers < 1 ||
165*77c1e3ccSAndroid Build Coastguard Worker       rc_cfg.ss_number_layers > AOM_MAX_SS_LAYERS ||
166*77c1e3ccSAndroid Build Coastguard Worker       rc_cfg.ts_number_layers < 1 ||
167*77c1e3ccSAndroid Build Coastguard Worker       rc_cfg.ts_number_layers > AOM_MAX_TS_LAYERS) {
168*77c1e3ccSAndroid Build Coastguard Worker     return false;
169*77c1e3ccSAndroid Build Coastguard Worker   }
170*77c1e3ccSAndroid Build Coastguard Worker   const int num_layers = rc_cfg.ss_number_layers * rc_cfg.ts_number_layers;
171*77c1e3ccSAndroid Build Coastguard Worker   if (num_layers > 1 && !av1_alloc_layer_context(cpi_, num_layers)) {
172*77c1e3ccSAndroid Build Coastguard Worker     return false;
173*77c1e3ccSAndroid Build Coastguard Worker   }
174*77c1e3ccSAndroid Build Coastguard Worker   AV1_COMMON *cm = &cpi_->common;
175*77c1e3ccSAndroid Build Coastguard Worker   AV1EncoderConfig *oxcf = &cpi_->oxcf;
176*77c1e3ccSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi_->rc;
177*77c1e3ccSAndroid Build Coastguard Worker   initial_width_ = rc_cfg.width;
178*77c1e3ccSAndroid Build Coastguard Worker   initial_height_ = rc_cfg.height;
179*77c1e3ccSAndroid Build Coastguard Worker   cm->width = rc_cfg.width;
180*77c1e3ccSAndroid Build Coastguard Worker   cm->height = rc_cfg.height;
181*77c1e3ccSAndroid Build Coastguard Worker   oxcf->frm_dim_cfg.width = rc_cfg.width;
182*77c1e3ccSAndroid Build Coastguard Worker   oxcf->frm_dim_cfg.height = rc_cfg.height;
183*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.worst_allowed_q = av1_quantizer_to_qindex(rc_cfg.max_quantizer);
184*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.best_allowed_q = av1_quantizer_to_qindex(rc_cfg.min_quantizer);
185*77c1e3ccSAndroid Build Coastguard Worker   rc->worst_quality = oxcf->rc_cfg.worst_allowed_q;
186*77c1e3ccSAndroid Build Coastguard Worker   rc->best_quality = oxcf->rc_cfg.best_allowed_q;
187*77c1e3ccSAndroid Build Coastguard Worker   oxcf->input_cfg.init_framerate = rc_cfg.framerate;
188*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.target_bandwidth = rc_cfg.target_bandwidth > INT64_MAX / 1000
189*77c1e3ccSAndroid Build Coastguard Worker                                       ? INT64_MAX
190*77c1e3ccSAndroid Build Coastguard Worker                                       : 1000 * rc_cfg.target_bandwidth;
191*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.starting_buffer_level_ms = rc_cfg.buf_initial_sz;
192*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.optimal_buffer_level_ms = rc_cfg.buf_optimal_sz;
193*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.maximum_buffer_size_ms = rc_cfg.buf_sz;
194*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.under_shoot_pct = rc_cfg.undershoot_pct;
195*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.over_shoot_pct = rc_cfg.overshoot_pct;
196*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.drop_frames_water_mark = rc_cfg.frame_drop_thresh;
197*77c1e3ccSAndroid Build Coastguard Worker   if (rc_cfg.max_consec_drop_ms > 0) {
198*77c1e3ccSAndroid Build Coastguard Worker     rc->max_consec_drop = saturate_cast_double_to_int(
199*77c1e3ccSAndroid Build Coastguard Worker         ceil(cpi_->framerate * rc_cfg.max_consec_drop_ms / 1000));
200*77c1e3ccSAndroid Build Coastguard Worker   }
201*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.max_intra_bitrate_pct = rc_cfg.max_intra_bitrate_pct;
202*77c1e3ccSAndroid Build Coastguard Worker   oxcf->rc_cfg.max_inter_bitrate_pct = rc_cfg.max_inter_bitrate_pct;
203*77c1e3ccSAndroid Build Coastguard Worker   cpi_->framerate = rc_cfg.framerate;
204*77c1e3ccSAndroid Build Coastguard Worker   if (rc_cfg.is_screen) {
205*77c1e3ccSAndroid Build Coastguard Worker     cpi_->oxcf.tune_cfg.content = AOM_CONTENT_SCREEN;
206*77c1e3ccSAndroid Build Coastguard Worker     cpi_->is_screen_content_type = 1;
207*77c1e3ccSAndroid Build Coastguard Worker   }
208*77c1e3ccSAndroid Build Coastguard Worker   cpi_->svc.number_spatial_layers = rc_cfg.ss_number_layers;
209*77c1e3ccSAndroid Build Coastguard Worker   cpi_->svc.number_temporal_layers = rc_cfg.ts_number_layers;
210*77c1e3ccSAndroid Build Coastguard Worker   set_primary_rc_buffer_sizes(oxcf, cpi_->ppi);
211*77c1e3ccSAndroid Build Coastguard Worker   enc_set_mb_mi(&cm->mi_params, cm->width, cm->height, BLOCK_8X8);
212*77c1e3ccSAndroid Build Coastguard Worker   av1_new_framerate(cpi_, cpi_->framerate);
213*77c1e3ccSAndroid Build Coastguard Worker   if (cpi_->svc.number_temporal_layers > 1 ||
214*77c1e3ccSAndroid Build Coastguard Worker       cpi_->svc.number_spatial_layers > 1) {
215*77c1e3ccSAndroid Build Coastguard Worker     int64_t target_bandwidth_svc = 0;
216*77c1e3ccSAndroid Build Coastguard Worker     for (int sl = 0; sl < cpi_->svc.number_spatial_layers; ++sl) {
217*77c1e3ccSAndroid Build Coastguard Worker       for (int tl = 0; tl < cpi_->svc.number_temporal_layers; ++tl) {
218*77c1e3ccSAndroid Build Coastguard Worker         const int layer =
219*77c1e3ccSAndroid Build Coastguard Worker             LAYER_IDS_TO_IDX(sl, tl, cpi_->svc.number_temporal_layers);
220*77c1e3ccSAndroid Build Coastguard Worker         LAYER_CONTEXT *lc = &cpi_->svc.layer_context[layer];
221*77c1e3ccSAndroid Build Coastguard Worker         RATE_CONTROL *const lrc = &lc->rc;
222*77c1e3ccSAndroid Build Coastguard Worker         lc->layer_target_bitrate = 1000 * rc_cfg.layer_target_bitrate[layer];
223*77c1e3ccSAndroid Build Coastguard Worker         lc->max_q = rc_cfg.max_quantizers[layer];
224*77c1e3ccSAndroid Build Coastguard Worker         lc->min_q = rc_cfg.min_quantizers[layer];
225*77c1e3ccSAndroid Build Coastguard Worker         lrc->worst_quality =
226*77c1e3ccSAndroid Build Coastguard Worker             av1_quantizer_to_qindex(rc_cfg.max_quantizers[layer]);
227*77c1e3ccSAndroid Build Coastguard Worker         lrc->best_quality =
228*77c1e3ccSAndroid Build Coastguard Worker             av1_quantizer_to_qindex(rc_cfg.min_quantizers[layer]);
229*77c1e3ccSAndroid Build Coastguard Worker         lc->scaling_factor_num = rc_cfg.scaling_factor_num[sl];
230*77c1e3ccSAndroid Build Coastguard Worker         lc->scaling_factor_den = rc_cfg.scaling_factor_den[sl];
231*77c1e3ccSAndroid Build Coastguard Worker         lc->framerate_factor = rc_cfg.ts_rate_decimator[tl];
232*77c1e3ccSAndroid Build Coastguard Worker         if (tl == cpi_->svc.number_temporal_layers - 1)
233*77c1e3ccSAndroid Build Coastguard Worker           target_bandwidth_svc += lc->layer_target_bitrate;
234*77c1e3ccSAndroid Build Coastguard Worker       }
235*77c1e3ccSAndroid Build Coastguard Worker     }
236*77c1e3ccSAndroid Build Coastguard Worker 
237*77c1e3ccSAndroid Build Coastguard Worker     if (cm->current_frame.frame_number == 0) av1_init_layer_context(cpi_);
238*77c1e3ccSAndroid Build Coastguard Worker     // This is needed to initialize external RC flag in layer context structure.
239*77c1e3ccSAndroid Build Coastguard Worker     cpi_->rc.rtc_external_ratectrl = 1;
240*77c1e3ccSAndroid Build Coastguard Worker     av1_update_layer_context_change_config(cpi_, target_bandwidth_svc);
241*77c1e3ccSAndroid Build Coastguard Worker   }
242*77c1e3ccSAndroid Build Coastguard Worker   check_reset_rc_flag(cpi_);
243*77c1e3ccSAndroid Build Coastguard Worker   return true;
244*77c1e3ccSAndroid Build Coastguard Worker }
245*77c1e3ccSAndroid Build Coastguard Worker 
ComputeQP(const AV1FrameParamsRTC & frame_params)246*77c1e3ccSAndroid Build Coastguard Worker FrameDropDecision AV1RateControlRTC::ComputeQP(
247*77c1e3ccSAndroid Build Coastguard Worker     const AV1FrameParamsRTC &frame_params) {
248*77c1e3ccSAndroid Build Coastguard Worker   AV1_COMMON *const cm = &cpi_->common;
249*77c1e3ccSAndroid Build Coastguard Worker   int width, height;
250*77c1e3ccSAndroid Build Coastguard Worker   GF_GROUP *const gf_group = &cpi_->ppi->gf_group;
251*77c1e3ccSAndroid Build Coastguard Worker   cpi_->svc.spatial_layer_id = frame_params.spatial_layer_id;
252*77c1e3ccSAndroid Build Coastguard Worker   cpi_->svc.temporal_layer_id = frame_params.temporal_layer_id;
253*77c1e3ccSAndroid Build Coastguard Worker   if (cpi_->svc.number_spatial_layers > 1) {
254*77c1e3ccSAndroid Build Coastguard Worker     const int layer = LAYER_IDS_TO_IDX(cpi_->svc.spatial_layer_id,
255*77c1e3ccSAndroid Build Coastguard Worker                                        cpi_->svc.temporal_layer_id,
256*77c1e3ccSAndroid Build Coastguard Worker                                        cpi_->svc.number_temporal_layers);
257*77c1e3ccSAndroid Build Coastguard Worker     LAYER_CONTEXT *lc = &cpi_->svc.layer_context[layer];
258*77c1e3ccSAndroid Build Coastguard Worker     av1_get_layer_resolution(initial_width_, initial_height_,
259*77c1e3ccSAndroid Build Coastguard Worker                              lc->scaling_factor_num, lc->scaling_factor_den,
260*77c1e3ccSAndroid Build Coastguard Worker                              &width, &height);
261*77c1e3ccSAndroid Build Coastguard Worker     cm->width = width;
262*77c1e3ccSAndroid Build Coastguard Worker     cm->height = height;
263*77c1e3ccSAndroid Build Coastguard Worker   }
264*77c1e3ccSAndroid Build Coastguard Worker   enc_set_mb_mi(&cm->mi_params, cm->width, cm->height, BLOCK_8X8);
265*77c1e3ccSAndroid Build Coastguard Worker   cm->current_frame.frame_type = frame_params.frame_type;
266*77c1e3ccSAndroid Build Coastguard Worker   cpi_->refresh_frame.golden_frame =
267*77c1e3ccSAndroid Build Coastguard Worker       (cm->current_frame.frame_type == KEY_FRAME) ? 1 : 0;
268*77c1e3ccSAndroid Build Coastguard Worker   cpi_->sf.rt_sf.use_nonrd_pick_mode = 1;
269*77c1e3ccSAndroid Build Coastguard Worker 
270*77c1e3ccSAndroid Build Coastguard Worker   if (frame_params.frame_type == kKeyFrame) {
271*77c1e3ccSAndroid Build Coastguard Worker     gf_group->update_type[cpi_->gf_frame_index] = KF_UPDATE;
272*77c1e3ccSAndroid Build Coastguard Worker     gf_group->frame_type[cpi_->gf_frame_index] = KEY_FRAME;
273*77c1e3ccSAndroid Build Coastguard Worker     gf_group->refbuf_state[cpi_->gf_frame_index] = REFBUF_RESET;
274*77c1e3ccSAndroid Build Coastguard Worker     if (cpi_->ppi->use_svc) {
275*77c1e3ccSAndroid Build Coastguard Worker       const int layer = LAYER_IDS_TO_IDX(cpi_->svc.spatial_layer_id,
276*77c1e3ccSAndroid Build Coastguard Worker                                          cpi_->svc.temporal_layer_id,
277*77c1e3ccSAndroid Build Coastguard Worker                                          cpi_->svc.number_temporal_layers);
278*77c1e3ccSAndroid Build Coastguard Worker       if (cm->current_frame.frame_number > 0)
279*77c1e3ccSAndroid Build Coastguard Worker         av1_svc_reset_temporal_layers(cpi_, 1);
280*77c1e3ccSAndroid Build Coastguard Worker       cpi_->svc.layer_context[layer].is_key_frame = 1;
281*77c1e3ccSAndroid Build Coastguard Worker     }
282*77c1e3ccSAndroid Build Coastguard Worker   } else {
283*77c1e3ccSAndroid Build Coastguard Worker     gf_group->update_type[cpi_->gf_frame_index] = LF_UPDATE;
284*77c1e3ccSAndroid Build Coastguard Worker     gf_group->frame_type[cpi_->gf_frame_index] = INTER_FRAME;
285*77c1e3ccSAndroid Build Coastguard Worker     gf_group->refbuf_state[cpi_->gf_frame_index] = REFBUF_UPDATE;
286*77c1e3ccSAndroid Build Coastguard Worker     if (cpi_->ppi->use_svc) {
287*77c1e3ccSAndroid Build Coastguard Worker       const int layer = LAYER_IDS_TO_IDX(cpi_->svc.spatial_layer_id,
288*77c1e3ccSAndroid Build Coastguard Worker                                          cpi_->svc.temporal_layer_id,
289*77c1e3ccSAndroid Build Coastguard Worker                                          cpi_->svc.number_temporal_layers);
290*77c1e3ccSAndroid Build Coastguard Worker       cpi_->svc.layer_context[layer].is_key_frame = 0;
291*77c1e3ccSAndroid Build Coastguard Worker     }
292*77c1e3ccSAndroid Build Coastguard Worker   }
293*77c1e3ccSAndroid Build Coastguard Worker   if (cpi_->svc.number_spatial_layers > 1 ||
294*77c1e3ccSAndroid Build Coastguard Worker       cpi_->svc.number_temporal_layers > 1) {
295*77c1e3ccSAndroid Build Coastguard Worker     av1_update_temporal_layer_framerate(cpi_);
296*77c1e3ccSAndroid Build Coastguard Worker     av1_restore_layer_context(cpi_);
297*77c1e3ccSAndroid Build Coastguard Worker   }
298*77c1e3ccSAndroid Build Coastguard Worker   int target = 0;
299*77c1e3ccSAndroid Build Coastguard Worker   if (cpi_->oxcf.rc_cfg.mode == AOM_CBR) {
300*77c1e3ccSAndroid Build Coastguard Worker     if (cpi_->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ)
301*77c1e3ccSAndroid Build Coastguard Worker       av1_cyclic_refresh_update_parameters(cpi_);
302*77c1e3ccSAndroid Build Coastguard Worker     if (frame_is_intra_only(cm)) {
303*77c1e3ccSAndroid Build Coastguard Worker       target = av1_calc_iframe_target_size_one_pass_cbr(cpi_);
304*77c1e3ccSAndroid Build Coastguard Worker       cpi_->common.current_frame.frame_number = 0;
305*77c1e3ccSAndroid Build Coastguard Worker     } else {
306*77c1e3ccSAndroid Build Coastguard Worker       target = av1_calc_pframe_target_size_one_pass_cbr(
307*77c1e3ccSAndroid Build Coastguard Worker           cpi_, gf_group->update_type[cpi_->gf_frame_index]);
308*77c1e3ccSAndroid Build Coastguard Worker     }
309*77c1e3ccSAndroid Build Coastguard Worker   }
310*77c1e3ccSAndroid Build Coastguard Worker   av1_rc_set_frame_target(cpi_, target, cm->width, cm->height);
311*77c1e3ccSAndroid Build Coastguard Worker   // Always drop for spatial enhancement layer if layer bandwidth is 0.
312*77c1e3ccSAndroid Build Coastguard Worker   // Otherwise check for frame-dropping based on buffer level in
313*77c1e3ccSAndroid Build Coastguard Worker   // av1_rc_drop_frame().
314*77c1e3ccSAndroid Build Coastguard Worker   if ((cpi_->svc.spatial_layer_id > 0 &&
315*77c1e3ccSAndroid Build Coastguard Worker        cpi_->oxcf.rc_cfg.target_bandwidth == 0) ||
316*77c1e3ccSAndroid Build Coastguard Worker       av1_rc_drop_frame(cpi_)) {
317*77c1e3ccSAndroid Build Coastguard Worker     cpi_->is_dropped_frame = true;
318*77c1e3ccSAndroid Build Coastguard Worker     av1_rc_postencode_update_drop_frame(cpi_);
319*77c1e3ccSAndroid Build Coastguard Worker     if (cpi_->svc.spatial_layer_id == cpi_->svc.number_spatial_layers - 1)
320*77c1e3ccSAndroid Build Coastguard Worker       cpi_->rc.frames_since_key++;
321*77c1e3ccSAndroid Build Coastguard Worker     cpi_->frame_index_set.show_frame_count++;
322*77c1e3ccSAndroid Build Coastguard Worker     cpi_->common.current_frame.frame_number++;
323*77c1e3ccSAndroid Build Coastguard Worker     return FrameDropDecision::kDrop;
324*77c1e3ccSAndroid Build Coastguard Worker   }
325*77c1e3ccSAndroid Build Coastguard Worker   int bottom_index = 0, top_index = 0;
326*77c1e3ccSAndroid Build Coastguard Worker   cpi_->common.quant_params.base_qindex =
327*77c1e3ccSAndroid Build Coastguard Worker       av1_rc_pick_q_and_bounds(cpi_, cm->width, cm->height,
328*77c1e3ccSAndroid Build Coastguard Worker                                cpi_->gf_frame_index, &bottom_index, &top_index);
329*77c1e3ccSAndroid Build Coastguard Worker   if (cpi_->oxcf.q_cfg.aq_mode == CYCLIC_REFRESH_AQ)
330*77c1e3ccSAndroid Build Coastguard Worker     av1_cyclic_refresh_setup(cpi_);
331*77c1e3ccSAndroid Build Coastguard Worker   return FrameDropDecision::kOk;
332*77c1e3ccSAndroid Build Coastguard Worker }
333*77c1e3ccSAndroid Build Coastguard Worker 
GetQP() const334*77c1e3ccSAndroid Build Coastguard Worker int AV1RateControlRTC::GetQP() const {
335*77c1e3ccSAndroid Build Coastguard Worker   return cpi_->common.quant_params.base_qindex;
336*77c1e3ccSAndroid Build Coastguard Worker }
337*77c1e3ccSAndroid Build Coastguard Worker 
GetLoopfilterLevel() const338*77c1e3ccSAndroid Build Coastguard Worker AV1LoopfilterLevel AV1RateControlRTC::GetLoopfilterLevel() const {
339*77c1e3ccSAndroid Build Coastguard Worker   av1_pick_filter_level(nullptr, cpi_, LPF_PICK_FROM_Q);
340*77c1e3ccSAndroid Build Coastguard Worker   AV1LoopfilterLevel lpf_level;
341*77c1e3ccSAndroid Build Coastguard Worker   lpf_level.filter_level[0] = cpi_->common.lf.filter_level[0];
342*77c1e3ccSAndroid Build Coastguard Worker   lpf_level.filter_level[1] = cpi_->common.lf.filter_level[1];
343*77c1e3ccSAndroid Build Coastguard Worker   lpf_level.filter_level_u = cpi_->common.lf.filter_level_u;
344*77c1e3ccSAndroid Build Coastguard Worker   lpf_level.filter_level_v = cpi_->common.lf.filter_level_v;
345*77c1e3ccSAndroid Build Coastguard Worker 
346*77c1e3ccSAndroid Build Coastguard Worker   return lpf_level;
347*77c1e3ccSAndroid Build Coastguard Worker }
348*77c1e3ccSAndroid Build Coastguard Worker 
GetCdefInfo() const349*77c1e3ccSAndroid Build Coastguard Worker AV1CdefInfo AV1RateControlRTC::GetCdefInfo() const {
350*77c1e3ccSAndroid Build Coastguard Worker   av1_pick_cdef_from_qp(&cpi_->common, 0, 0);
351*77c1e3ccSAndroid Build Coastguard Worker   AV1CdefInfo cdef_level;
352*77c1e3ccSAndroid Build Coastguard Worker   cdef_level.cdef_strength_y = cpi_->common.cdef_info.cdef_strengths[0];
353*77c1e3ccSAndroid Build Coastguard Worker   cdef_level.cdef_strength_uv = cpi_->common.cdef_info.cdef_uv_strengths[0];
354*77c1e3ccSAndroid Build Coastguard Worker   cdef_level.damping = cpi_->common.cdef_info.cdef_damping;
355*77c1e3ccSAndroid Build Coastguard Worker 
356*77c1e3ccSAndroid Build Coastguard Worker   return cdef_level;
357*77c1e3ccSAndroid Build Coastguard Worker }
358*77c1e3ccSAndroid Build Coastguard Worker 
GetSegmentationData(AV1SegmentationData * segmentation_data) const359*77c1e3ccSAndroid Build Coastguard Worker bool AV1RateControlRTC::GetSegmentationData(
360*77c1e3ccSAndroid Build Coastguard Worker     AV1SegmentationData *segmentation_data) const {
361*77c1e3ccSAndroid Build Coastguard Worker   if (cpi_->oxcf.q_cfg.aq_mode == 0) {
362*77c1e3ccSAndroid Build Coastguard Worker     return false;
363*77c1e3ccSAndroid Build Coastguard Worker   }
364*77c1e3ccSAndroid Build Coastguard Worker   segmentation_data->segmentation_map = cpi_->enc_seg.map;
365*77c1e3ccSAndroid Build Coastguard Worker   segmentation_data->segmentation_map_size =
366*77c1e3ccSAndroid Build Coastguard Worker       cpi_->common.mi_params.mi_rows * cpi_->common.mi_params.mi_cols;
367*77c1e3ccSAndroid Build Coastguard Worker   segmentation_data->delta_q = cpi_->cyclic_refresh->qindex_delta;
368*77c1e3ccSAndroid Build Coastguard Worker   segmentation_data->delta_q_size = 3u;
369*77c1e3ccSAndroid Build Coastguard Worker   return true;
370*77c1e3ccSAndroid Build Coastguard Worker }
371*77c1e3ccSAndroid Build Coastguard Worker 
PostEncodeUpdate(uint64_t encoded_frame_size)372*77c1e3ccSAndroid Build Coastguard Worker void AV1RateControlRTC::PostEncodeUpdate(uint64_t encoded_frame_size) {
373*77c1e3ccSAndroid Build Coastguard Worker   cpi_->common.current_frame.frame_number++;
374*77c1e3ccSAndroid Build Coastguard Worker   av1_rc_postencode_update(cpi_, encoded_frame_size);
375*77c1e3ccSAndroid Build Coastguard Worker   if (cpi_->svc.spatial_layer_id == cpi_->svc.number_spatial_layers - 1) {
376*77c1e3ccSAndroid Build Coastguard Worker     cpi_->svc.prev_number_spatial_layers = cpi_->svc.number_spatial_layers;
377*77c1e3ccSAndroid Build Coastguard Worker     cpi_->rc.frames_since_key++;
378*77c1e3ccSAndroid Build Coastguard Worker   }
379*77c1e3ccSAndroid Build Coastguard Worker   if (cpi_->svc.number_spatial_layers > 1 ||
380*77c1e3ccSAndroid Build Coastguard Worker       cpi_->svc.number_temporal_layers > 1)
381*77c1e3ccSAndroid Build Coastguard Worker     av1_save_layer_context(cpi_);
382*77c1e3ccSAndroid Build Coastguard Worker }
383*77c1e3ccSAndroid Build Coastguard Worker 
384*77c1e3ccSAndroid Build Coastguard Worker }  // namespace aom
385