xref: /aosp_15_r20/external/libvpx/vp9/ratectrl_rtc.cc (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2020 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker  *
4*fb1b10abSAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker  */
10*fb1b10abSAndroid Build Coastguard Worker #include "vp9/ratectrl_rtc.h"
11*fb1b10abSAndroid Build Coastguard Worker 
12*fb1b10abSAndroid Build Coastguard Worker #include <new>
13*fb1b10abSAndroid Build Coastguard Worker 
14*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_common.h"
15*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_aq_cyclicrefresh.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encoder.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_picklpf.h"
18*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vp8cx.h"
19*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vpx_codec.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "vpx_mem/vpx_mem.h"
21*fb1b10abSAndroid Build Coastguard Worker 
22*fb1b10abSAndroid Build Coastguard Worker namespace libvpx {
23*fb1b10abSAndroid Build Coastguard Worker 
Create(const VP9RateControlRtcConfig & cfg)24*fb1b10abSAndroid Build Coastguard Worker std::unique_ptr<VP9RateControlRTC> VP9RateControlRTC::Create(
25*fb1b10abSAndroid Build Coastguard Worker     const VP9RateControlRtcConfig &cfg) {
26*fb1b10abSAndroid Build Coastguard Worker   std::unique_ptr<VP9RateControlRTC> rc_api(new (std::nothrow)
27*fb1b10abSAndroid Build Coastguard Worker                                                 VP9RateControlRTC());
28*fb1b10abSAndroid Build Coastguard Worker   if (!rc_api) return nullptr;
29*fb1b10abSAndroid Build Coastguard Worker   rc_api->cpi_ = static_cast<VP9_COMP *>(vpx_memalign(32, sizeof(*cpi_)));
30*fb1b10abSAndroid Build Coastguard Worker   if (!rc_api->cpi_) return nullptr;
31*fb1b10abSAndroid Build Coastguard Worker   vp9_zero(*rc_api->cpi_);
32*fb1b10abSAndroid Build Coastguard Worker 
33*fb1b10abSAndroid Build Coastguard Worker   if (!rc_api->InitRateControl(cfg)) return nullptr;
34*fb1b10abSAndroid Build Coastguard Worker   if (cfg.aq_mode) {
35*fb1b10abSAndroid Build Coastguard Worker     VP9_COMP *const cpi = rc_api->cpi_;
36*fb1b10abSAndroid Build Coastguard Worker     cpi->segmentation_map = static_cast<uint8_t *>(
37*fb1b10abSAndroid Build Coastguard Worker         vpx_calloc(cpi->common.mi_rows * cpi->common.mi_cols,
38*fb1b10abSAndroid Build Coastguard Worker                    sizeof(*cpi->segmentation_map)));
39*fb1b10abSAndroid Build Coastguard Worker     if (!cpi->segmentation_map) return nullptr;
40*fb1b10abSAndroid Build Coastguard Worker     cpi->cyclic_refresh =
41*fb1b10abSAndroid Build Coastguard Worker         vp9_cyclic_refresh_alloc(cpi->common.mi_rows, cpi->common.mi_cols);
42*fb1b10abSAndroid Build Coastguard Worker     cpi->cyclic_refresh->content_mode = 0;
43*fb1b10abSAndroid Build Coastguard Worker   }
44*fb1b10abSAndroid Build Coastguard Worker   return rc_api;
45*fb1b10abSAndroid Build Coastguard Worker }
46*fb1b10abSAndroid Build Coastguard Worker 
~VP9RateControlRTC()47*fb1b10abSAndroid Build Coastguard Worker VP9RateControlRTC::~VP9RateControlRTC() {
48*fb1b10abSAndroid Build Coastguard Worker   if (cpi_) {
49*fb1b10abSAndroid Build Coastguard Worker     if (cpi_->svc.number_spatial_layers > 1 ||
50*fb1b10abSAndroid Build Coastguard Worker         cpi_->svc.number_temporal_layers > 1) {
51*fb1b10abSAndroid Build Coastguard Worker       for (int sl = 0; sl < cpi_->svc.number_spatial_layers; sl++) {
52*fb1b10abSAndroid Build Coastguard Worker         for (int tl = 0; tl < cpi_->svc.number_temporal_layers; tl++) {
53*fb1b10abSAndroid Build Coastguard Worker           int layer = LAYER_IDS_TO_IDX(sl, tl, cpi_->oxcf.ts_number_layers);
54*fb1b10abSAndroid Build Coastguard Worker           LAYER_CONTEXT *const lc = &cpi_->svc.layer_context[layer];
55*fb1b10abSAndroid Build Coastguard Worker           vpx_free(lc->map);
56*fb1b10abSAndroid Build Coastguard Worker           vpx_free(lc->last_coded_q_map);
57*fb1b10abSAndroid Build Coastguard Worker           vpx_free(lc->consec_zero_mv);
58*fb1b10abSAndroid Build Coastguard Worker         }
59*fb1b10abSAndroid Build Coastguard Worker       }
60*fb1b10abSAndroid Build Coastguard Worker     }
61*fb1b10abSAndroid Build Coastguard Worker     if (cpi_->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
62*fb1b10abSAndroid Build Coastguard Worker       vpx_free(cpi_->segmentation_map);
63*fb1b10abSAndroid Build Coastguard Worker       cpi_->segmentation_map = NULL;
64*fb1b10abSAndroid Build Coastguard Worker       vp9_cyclic_refresh_free(cpi_->cyclic_refresh);
65*fb1b10abSAndroid Build Coastguard Worker     }
66*fb1b10abSAndroid Build Coastguard Worker     vpx_free(cpi_);
67*fb1b10abSAndroid Build Coastguard Worker   }
68*fb1b10abSAndroid Build Coastguard Worker }
69*fb1b10abSAndroid Build Coastguard Worker 
InitRateControl(const VP9RateControlRtcConfig & rc_cfg)70*fb1b10abSAndroid Build Coastguard Worker bool VP9RateControlRTC::InitRateControl(const VP9RateControlRtcConfig &rc_cfg) {
71*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *cm = &cpi_->common;
72*fb1b10abSAndroid Build Coastguard Worker   VP9EncoderConfig *oxcf = &cpi_->oxcf;
73*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi_->rc;
74*fb1b10abSAndroid Build Coastguard Worker   cm->profile = PROFILE_0;
75*fb1b10abSAndroid Build Coastguard Worker   cm->bit_depth = VPX_BITS_8;
76*fb1b10abSAndroid Build Coastguard Worker   cm->show_frame = 1;
77*fb1b10abSAndroid Build Coastguard Worker   oxcf->profile = cm->profile;
78*fb1b10abSAndroid Build Coastguard Worker   oxcf->bit_depth = cm->bit_depth;
79*fb1b10abSAndroid Build Coastguard Worker   oxcf->rc_mode = rc_cfg.rc_mode;
80*fb1b10abSAndroid Build Coastguard Worker   oxcf->pass = 0;
81*fb1b10abSAndroid Build Coastguard Worker   oxcf->aq_mode = rc_cfg.aq_mode ? CYCLIC_REFRESH_AQ : NO_AQ;
82*fb1b10abSAndroid Build Coastguard Worker   oxcf->content = VP9E_CONTENT_DEFAULT;
83*fb1b10abSAndroid Build Coastguard Worker   oxcf->drop_frames_water_mark = 0;
84*fb1b10abSAndroid Build Coastguard Worker   cm->current_video_frame = 0;
85*fb1b10abSAndroid Build Coastguard Worker   rc->kf_boost = DEFAULT_KF_BOOST;
86*fb1b10abSAndroid Build Coastguard Worker 
87*fb1b10abSAndroid Build Coastguard Worker   if (!UpdateRateControl(rc_cfg)) return false;
88*fb1b10abSAndroid Build Coastguard Worker   vp9_set_mb_mi(cm, cm->width, cm->height);
89*fb1b10abSAndroid Build Coastguard Worker 
90*fb1b10abSAndroid Build Coastguard Worker   cpi_->use_svc = (cpi_->svc.number_spatial_layers > 1 ||
91*fb1b10abSAndroid Build Coastguard Worker                    cpi_->svc.number_temporal_layers > 1)
92*fb1b10abSAndroid Build Coastguard Worker                       ? 1
93*fb1b10abSAndroid Build Coastguard Worker                       : 0;
94*fb1b10abSAndroid Build Coastguard Worker 
95*fb1b10abSAndroid Build Coastguard Worker   rc->rc_1_frame = 0;
96*fb1b10abSAndroid Build Coastguard Worker   rc->rc_2_frame = 0;
97*fb1b10abSAndroid Build Coastguard Worker   vp9_rc_init_minq_luts();
98*fb1b10abSAndroid Build Coastguard Worker   vp9_rc_init(oxcf, 0, rc);
99*fb1b10abSAndroid Build Coastguard Worker   rc->constrain_gf_key_freq_onepass_vbr = 0;
100*fb1b10abSAndroid Build Coastguard Worker   cpi_->sf.use_nonrd_pick_mode = 1;
101*fb1b10abSAndroid Build Coastguard Worker   return true;
102*fb1b10abSAndroid Build Coastguard Worker }
103*fb1b10abSAndroid Build Coastguard Worker 
UpdateRateControl(const VP9RateControlRtcConfig & rc_cfg)104*fb1b10abSAndroid Build Coastguard Worker bool VP9RateControlRTC::UpdateRateControl(
105*fb1b10abSAndroid Build Coastguard Worker     const VP9RateControlRtcConfig &rc_cfg) {
106*fb1b10abSAndroid Build Coastguard Worker   // Since VPX_MAX_LAYERS (12) is less than the product of VPX_SS_MAX_LAYERS (5)
107*fb1b10abSAndroid Build Coastguard Worker   // and VPX_TS_MAX_LAYERS (5), check all three.
108*fb1b10abSAndroid Build Coastguard Worker   if (rc_cfg.ss_number_layers < 1 ||
109*fb1b10abSAndroid Build Coastguard Worker       rc_cfg.ss_number_layers > VPX_SS_MAX_LAYERS ||
110*fb1b10abSAndroid Build Coastguard Worker       rc_cfg.ts_number_layers < 1 ||
111*fb1b10abSAndroid Build Coastguard Worker       rc_cfg.ts_number_layers > VPX_TS_MAX_LAYERS ||
112*fb1b10abSAndroid Build Coastguard Worker       rc_cfg.ss_number_layers * rc_cfg.ts_number_layers > VPX_MAX_LAYERS) {
113*fb1b10abSAndroid Build Coastguard Worker     return false;
114*fb1b10abSAndroid Build Coastguard Worker   }
115*fb1b10abSAndroid Build Coastguard Worker 
116*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *cm = &cpi_->common;
117*fb1b10abSAndroid Build Coastguard Worker   VP9EncoderConfig *oxcf = &cpi_->oxcf;
118*fb1b10abSAndroid Build Coastguard Worker   RATE_CONTROL *const rc = &cpi_->rc;
119*fb1b10abSAndroid Build Coastguard Worker 
120*fb1b10abSAndroid Build Coastguard Worker   cm->width = rc_cfg.width;
121*fb1b10abSAndroid Build Coastguard Worker   cm->height = rc_cfg.height;
122*fb1b10abSAndroid Build Coastguard Worker   oxcf->width = rc_cfg.width;
123*fb1b10abSAndroid Build Coastguard Worker   oxcf->height = rc_cfg.height;
124*fb1b10abSAndroid Build Coastguard Worker   oxcf->worst_allowed_q = vp9_quantizer_to_qindex(rc_cfg.max_quantizer);
125*fb1b10abSAndroid Build Coastguard Worker   oxcf->best_allowed_q = vp9_quantizer_to_qindex(rc_cfg.min_quantizer);
126*fb1b10abSAndroid Build Coastguard Worker   rc->worst_quality = oxcf->worst_allowed_q;
127*fb1b10abSAndroid Build Coastguard Worker   rc->best_quality = oxcf->best_allowed_q;
128*fb1b10abSAndroid Build Coastguard Worker   oxcf->init_framerate = rc_cfg.framerate;
129*fb1b10abSAndroid Build Coastguard Worker   oxcf->target_bandwidth = 1000 * rc_cfg.target_bandwidth;
130*fb1b10abSAndroid Build Coastguard Worker   oxcf->starting_buffer_level_ms = rc_cfg.buf_initial_sz;
131*fb1b10abSAndroid Build Coastguard Worker   oxcf->optimal_buffer_level_ms = rc_cfg.buf_optimal_sz;
132*fb1b10abSAndroid Build Coastguard Worker   oxcf->maximum_buffer_size_ms = rc_cfg.buf_sz;
133*fb1b10abSAndroid Build Coastguard Worker   oxcf->under_shoot_pct = rc_cfg.undershoot_pct;
134*fb1b10abSAndroid Build Coastguard Worker   oxcf->over_shoot_pct = rc_cfg.overshoot_pct;
135*fb1b10abSAndroid Build Coastguard Worker   oxcf->drop_frames_water_mark = rc_cfg.frame_drop_thresh;
136*fb1b10abSAndroid Build Coastguard Worker   oxcf->content = rc_cfg.is_screen ? VP9E_CONTENT_SCREEN : VP9E_CONTENT_DEFAULT;
137*fb1b10abSAndroid Build Coastguard Worker   oxcf->ss_number_layers = rc_cfg.ss_number_layers;
138*fb1b10abSAndroid Build Coastguard Worker   oxcf->ts_number_layers = rc_cfg.ts_number_layers;
139*fb1b10abSAndroid Build Coastguard Worker   oxcf->temporal_layering_mode =
140*fb1b10abSAndroid Build Coastguard Worker       (VP9E_TEMPORAL_LAYERING_MODE)((rc_cfg.ts_number_layers > 1)
141*fb1b10abSAndroid Build Coastguard Worker                                         ? rc_cfg.ts_number_layers
142*fb1b10abSAndroid Build Coastguard Worker                                         : 0);
143*fb1b10abSAndroid Build Coastguard Worker 
144*fb1b10abSAndroid Build Coastguard Worker   cpi_->oxcf.rc_max_intra_bitrate_pct = rc_cfg.max_intra_bitrate_pct;
145*fb1b10abSAndroid Build Coastguard Worker   cpi_->oxcf.rc_max_inter_bitrate_pct = rc_cfg.max_inter_bitrate_pct;
146*fb1b10abSAndroid Build Coastguard Worker   cpi_->framerate = rc_cfg.framerate;
147*fb1b10abSAndroid Build Coastguard Worker   cpi_->svc.number_spatial_layers = rc_cfg.ss_number_layers;
148*fb1b10abSAndroid Build Coastguard Worker   cpi_->svc.number_temporal_layers = rc_cfg.ts_number_layers;
149*fb1b10abSAndroid Build Coastguard Worker 
150*fb1b10abSAndroid Build Coastguard Worker   vp9_set_mb_mi(cm, cm->width, cm->height);
151*fb1b10abSAndroid Build Coastguard Worker 
152*fb1b10abSAndroid Build Coastguard Worker   if (setjmp(cpi_->common.error.jmp)) {
153*fb1b10abSAndroid Build Coastguard Worker     cpi_->common.error.setjmp = 0;
154*fb1b10abSAndroid Build Coastguard Worker     vpx_clear_system_state();
155*fb1b10abSAndroid Build Coastguard Worker     return false;
156*fb1b10abSAndroid Build Coastguard Worker   }
157*fb1b10abSAndroid Build Coastguard Worker   cpi_->common.error.setjmp = 1;
158*fb1b10abSAndroid Build Coastguard Worker 
159*fb1b10abSAndroid Build Coastguard Worker   for (int tl = 0; tl < cpi_->svc.number_temporal_layers; ++tl) {
160*fb1b10abSAndroid Build Coastguard Worker     oxcf->ts_rate_decimator[tl] = rc_cfg.ts_rate_decimator[tl];
161*fb1b10abSAndroid Build Coastguard Worker   }
162*fb1b10abSAndroid Build Coastguard Worker   for (int sl = 0; sl < cpi_->svc.number_spatial_layers; ++sl) {
163*fb1b10abSAndroid Build Coastguard Worker     for (int tl = 0; tl < cpi_->svc.number_temporal_layers; ++tl) {
164*fb1b10abSAndroid Build Coastguard Worker       const int layer =
165*fb1b10abSAndroid Build Coastguard Worker           LAYER_IDS_TO_IDX(sl, tl, cpi_->svc.number_temporal_layers);
166*fb1b10abSAndroid Build Coastguard Worker       LAYER_CONTEXT *lc = &cpi_->svc.layer_context[layer];
167*fb1b10abSAndroid Build Coastguard Worker       RATE_CONTROL *const lrc = &lc->rc;
168*fb1b10abSAndroid Build Coastguard Worker       oxcf->layer_target_bitrate[layer] =
169*fb1b10abSAndroid Build Coastguard Worker           1000 * rc_cfg.layer_target_bitrate[layer];
170*fb1b10abSAndroid Build Coastguard Worker       lrc->worst_quality =
171*fb1b10abSAndroid Build Coastguard Worker           vp9_quantizer_to_qindex(rc_cfg.max_quantizers[layer]);
172*fb1b10abSAndroid Build Coastguard Worker       lrc->best_quality = vp9_quantizer_to_qindex(rc_cfg.min_quantizers[layer]);
173*fb1b10abSAndroid Build Coastguard Worker       lc->scaling_factor_num = rc_cfg.scaling_factor_num[sl];
174*fb1b10abSAndroid Build Coastguard Worker       lc->scaling_factor_den = rc_cfg.scaling_factor_den[sl];
175*fb1b10abSAndroid Build Coastguard Worker     }
176*fb1b10abSAndroid Build Coastguard Worker   }
177*fb1b10abSAndroid Build Coastguard Worker   vp9_set_rc_buffer_sizes(cpi_);
178*fb1b10abSAndroid Build Coastguard Worker   vp9_new_framerate(cpi_, cpi_->framerate);
179*fb1b10abSAndroid Build Coastguard Worker   if (cpi_->svc.number_temporal_layers > 1 ||
180*fb1b10abSAndroid Build Coastguard Worker       cpi_->svc.number_spatial_layers > 1) {
181*fb1b10abSAndroid Build Coastguard Worker     if (cm->current_video_frame == 0) {
182*fb1b10abSAndroid Build Coastguard Worker       vp9_init_layer_context(cpi_);
183*fb1b10abSAndroid Build Coastguard Worker       // svc->framedrop_mode is not currently exposed, so only allow for
184*fb1b10abSAndroid Build Coastguard Worker       // full superframe drop for now.
185*fb1b10abSAndroid Build Coastguard Worker       cpi_->svc.framedrop_mode = FULL_SUPERFRAME_DROP;
186*fb1b10abSAndroid Build Coastguard Worker     }
187*fb1b10abSAndroid Build Coastguard Worker     vp9_update_layer_context_change_config(cpi_,
188*fb1b10abSAndroid Build Coastguard Worker                                            (int)cpi_->oxcf.target_bandwidth);
189*fb1b10abSAndroid Build Coastguard Worker     cpi_->svc.max_consec_drop = rc_cfg.max_consec_drop;
190*fb1b10abSAndroid Build Coastguard Worker   }
191*fb1b10abSAndroid Build Coastguard Worker   vp9_check_reset_rc_flag(cpi_);
192*fb1b10abSAndroid Build Coastguard Worker 
193*fb1b10abSAndroid Build Coastguard Worker   cpi_->common.error.setjmp = 0;
194*fb1b10abSAndroid Build Coastguard Worker   return true;
195*fb1b10abSAndroid Build Coastguard Worker }
196*fb1b10abSAndroid Build Coastguard Worker 
197*fb1b10abSAndroid Build Coastguard Worker // Compute the QP for the frame. If the frame is dropped this function
198*fb1b10abSAndroid Build Coastguard Worker // returns kDrop, and no QP is computed. If the frame is encoded (not dropped)
199*fb1b10abSAndroid Build Coastguard Worker // the QP is computed and kOk is returned.
ComputeQP(const VP9FrameParamsQpRTC & frame_params)200*fb1b10abSAndroid Build Coastguard Worker FrameDropDecision VP9RateControlRTC::ComputeQP(
201*fb1b10abSAndroid Build Coastguard Worker     const VP9FrameParamsQpRTC &frame_params) {
202*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi_->common;
203*fb1b10abSAndroid Build Coastguard Worker   int width, height;
204*fb1b10abSAndroid Build Coastguard Worker   cpi_->svc.spatial_layer_id = frame_params.spatial_layer_id;
205*fb1b10abSAndroid Build Coastguard Worker   cpi_->svc.temporal_layer_id = frame_params.temporal_layer_id;
206*fb1b10abSAndroid Build Coastguard Worker   if (cpi_->svc.number_spatial_layers > 1) {
207*fb1b10abSAndroid Build Coastguard Worker     const int layer = LAYER_IDS_TO_IDX(cpi_->svc.spatial_layer_id,
208*fb1b10abSAndroid Build Coastguard Worker                                        cpi_->svc.temporal_layer_id,
209*fb1b10abSAndroid Build Coastguard Worker                                        cpi_->svc.number_temporal_layers);
210*fb1b10abSAndroid Build Coastguard Worker     LAYER_CONTEXT *lc = &cpi_->svc.layer_context[layer];
211*fb1b10abSAndroid Build Coastguard Worker     get_layer_resolution(cpi_->oxcf.width, cpi_->oxcf.height,
212*fb1b10abSAndroid Build Coastguard Worker                          lc->scaling_factor_num, lc->scaling_factor_den, &width,
213*fb1b10abSAndroid Build Coastguard Worker                          &height);
214*fb1b10abSAndroid Build Coastguard Worker     cm->width = width;
215*fb1b10abSAndroid Build Coastguard Worker     cm->height = height;
216*fb1b10abSAndroid Build Coastguard Worker   }
217*fb1b10abSAndroid Build Coastguard Worker   vp9_set_mb_mi(cm, cm->width, cm->height);
218*fb1b10abSAndroid Build Coastguard Worker   cm->frame_type = static_cast<FRAME_TYPE>(frame_params.frame_type);
219*fb1b10abSAndroid Build Coastguard Worker   // This is needed to ensure key frame does not get unset in rc_get_svc_params.
220*fb1b10abSAndroid Build Coastguard Worker   cpi_->frame_flags = (cm->frame_type == KEY_FRAME) ? FRAMEFLAGS_KEY : 0;
221*fb1b10abSAndroid Build Coastguard Worker   cpi_->refresh_golden_frame = (cm->frame_type == KEY_FRAME) ? 1 : 0;
222*fb1b10abSAndroid Build Coastguard Worker   cpi_->sf.use_nonrd_pick_mode = 1;
223*fb1b10abSAndroid Build Coastguard Worker   if (cpi_->svc.number_spatial_layers == 1 &&
224*fb1b10abSAndroid Build Coastguard Worker       cpi_->svc.number_temporal_layers == 1) {
225*fb1b10abSAndroid Build Coastguard Worker     int target = 0;
226*fb1b10abSAndroid Build Coastguard Worker     if (cpi_->oxcf.rc_mode == VPX_CBR) {
227*fb1b10abSAndroid Build Coastguard Worker       if (cpi_->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
228*fb1b10abSAndroid Build Coastguard Worker         vp9_cyclic_refresh_update_parameters(cpi_);
229*fb1b10abSAndroid Build Coastguard Worker       if (frame_is_intra_only(cm))
230*fb1b10abSAndroid Build Coastguard Worker         target = vp9_calc_iframe_target_size_one_pass_cbr(cpi_);
231*fb1b10abSAndroid Build Coastguard Worker       else
232*fb1b10abSAndroid Build Coastguard Worker         target = vp9_calc_pframe_target_size_one_pass_cbr(cpi_);
233*fb1b10abSAndroid Build Coastguard Worker     } else if (cpi_->oxcf.rc_mode == VPX_VBR) {
234*fb1b10abSAndroid Build Coastguard Worker       if (cm->frame_type == KEY_FRAME) {
235*fb1b10abSAndroid Build Coastguard Worker         cpi_->rc.this_key_frame_forced = cm->current_video_frame != 0;
236*fb1b10abSAndroid Build Coastguard Worker         cpi_->rc.frames_to_key = cpi_->oxcf.key_freq;
237*fb1b10abSAndroid Build Coastguard Worker       }
238*fb1b10abSAndroid Build Coastguard Worker       vp9_set_gf_update_one_pass_vbr(cpi_);
239*fb1b10abSAndroid Build Coastguard Worker       if (cpi_->oxcf.aq_mode == CYCLIC_REFRESH_AQ)
240*fb1b10abSAndroid Build Coastguard Worker         vp9_cyclic_refresh_update_parameters(cpi_);
241*fb1b10abSAndroid Build Coastguard Worker       if (frame_is_intra_only(cm))
242*fb1b10abSAndroid Build Coastguard Worker         target = vp9_calc_iframe_target_size_one_pass_vbr(cpi_);
243*fb1b10abSAndroid Build Coastguard Worker       else
244*fb1b10abSAndroid Build Coastguard Worker         target = vp9_calc_pframe_target_size_one_pass_vbr(cpi_);
245*fb1b10abSAndroid Build Coastguard Worker     }
246*fb1b10abSAndroid Build Coastguard Worker     vp9_rc_set_frame_target(cpi_, target);
247*fb1b10abSAndroid Build Coastguard Worker     vp9_update_buffer_level_preencode(cpi_);
248*fb1b10abSAndroid Build Coastguard Worker   } else {
249*fb1b10abSAndroid Build Coastguard Worker     vp9_update_temporal_layer_framerate(cpi_);
250*fb1b10abSAndroid Build Coastguard Worker     vp9_restore_layer_context(cpi_);
251*fb1b10abSAndroid Build Coastguard Worker     vp9_rc_get_svc_params(cpi_);
252*fb1b10abSAndroid Build Coastguard Worker   }
253*fb1b10abSAndroid Build Coastguard Worker   if (cpi_->svc.spatial_layer_id == 0) vp9_zero(cpi_->svc.drop_spatial_layer);
254*fb1b10abSAndroid Build Coastguard Worker   // SVC: check for skip encoding of enhancement layer if the
255*fb1b10abSAndroid Build Coastguard Worker   // layer target bandwidth = 0.
256*fb1b10abSAndroid Build Coastguard Worker   if (vp9_svc_check_skip_enhancement_layer(cpi_))
257*fb1b10abSAndroid Build Coastguard Worker     return FrameDropDecision::kDrop;
258*fb1b10abSAndroid Build Coastguard Worker   // Check for dropping this frame based on buffer level.
259*fb1b10abSAndroid Build Coastguard Worker   // Never drop on key frame, or if base layer is key for svc,
260*fb1b10abSAndroid Build Coastguard Worker   if (!frame_is_intra_only(cm) &&
261*fb1b10abSAndroid Build Coastguard Worker       (!cpi_->use_svc ||
262*fb1b10abSAndroid Build Coastguard Worker        !cpi_->svc.layer_context[cpi_->svc.temporal_layer_id].is_key_frame)) {
263*fb1b10abSAndroid Build Coastguard Worker     if (vp9_rc_drop_frame(cpi_)) {
264*fb1b10abSAndroid Build Coastguard Worker       // For FULL_SUPERFRAME_DROP mode (the only mode considered here):
265*fb1b10abSAndroid Build Coastguard Worker       // if the superframe drop is decided we need to save the layer context for
266*fb1b10abSAndroid Build Coastguard Worker       // all spatial layers, and call update_buffer_level and postencode_drop
267*fb1b10abSAndroid Build Coastguard Worker       // for all spatial layers.
268*fb1b10abSAndroid Build Coastguard Worker       if (cpi_->svc.number_spatial_layers > 1 ||
269*fb1b10abSAndroid Build Coastguard Worker           cpi_->svc.number_temporal_layers > 1) {
270*fb1b10abSAndroid Build Coastguard Worker         vp9_save_layer_context(cpi_);
271*fb1b10abSAndroid Build Coastguard Worker         for (int sl = 1; sl < cpi_->svc.number_spatial_layers; sl++) {
272*fb1b10abSAndroid Build Coastguard Worker           cpi_->svc.spatial_layer_id = sl;
273*fb1b10abSAndroid Build Coastguard Worker           vp9_restore_layer_context(cpi_);
274*fb1b10abSAndroid Build Coastguard Worker           vp9_update_buffer_level_svc_preencode(cpi_);
275*fb1b10abSAndroid Build Coastguard Worker           vp9_rc_postencode_update_drop_frame(cpi_);
276*fb1b10abSAndroid Build Coastguard Worker           vp9_save_layer_context(cpi_);
277*fb1b10abSAndroid Build Coastguard Worker         }
278*fb1b10abSAndroid Build Coastguard Worker       }
279*fb1b10abSAndroid Build Coastguard Worker       return FrameDropDecision::kDrop;
280*fb1b10abSAndroid Build Coastguard Worker     }
281*fb1b10abSAndroid Build Coastguard Worker   }
282*fb1b10abSAndroid Build Coastguard Worker   // Compute the QP for the frame.
283*fb1b10abSAndroid Build Coastguard Worker   int bottom_index, top_index;
284*fb1b10abSAndroid Build Coastguard Worker   cpi_->common.base_qindex =
285*fb1b10abSAndroid Build Coastguard Worker       vp9_rc_pick_q_and_bounds(cpi_, &bottom_index, &top_index);
286*fb1b10abSAndroid Build Coastguard Worker 
287*fb1b10abSAndroid Build Coastguard Worker   if (cpi_->oxcf.aq_mode == CYCLIC_REFRESH_AQ) vp9_cyclic_refresh_setup(cpi_);
288*fb1b10abSAndroid Build Coastguard Worker   if (cpi_->svc.number_spatial_layers > 1 ||
289*fb1b10abSAndroid Build Coastguard Worker       cpi_->svc.number_temporal_layers > 1)
290*fb1b10abSAndroid Build Coastguard Worker     vp9_save_layer_context(cpi_);
291*fb1b10abSAndroid Build Coastguard Worker 
292*fb1b10abSAndroid Build Coastguard Worker   cpi_->last_frame_dropped = 0;
293*fb1b10abSAndroid Build Coastguard Worker   cpi_->svc.last_layer_dropped[cpi_->svc.spatial_layer_id] = 0;
294*fb1b10abSAndroid Build Coastguard Worker   if (cpi_->svc.spatial_layer_id == cpi_->svc.number_spatial_layers - 1)
295*fb1b10abSAndroid Build Coastguard Worker     cpi_->svc.num_encoded_top_layer++;
296*fb1b10abSAndroid Build Coastguard Worker 
297*fb1b10abSAndroid Build Coastguard Worker   return FrameDropDecision::kOk;
298*fb1b10abSAndroid Build Coastguard Worker }
299*fb1b10abSAndroid Build Coastguard Worker 
GetQP() const300*fb1b10abSAndroid Build Coastguard Worker int VP9RateControlRTC::GetQP() const { return cpi_->common.base_qindex; }
301*fb1b10abSAndroid Build Coastguard Worker 
GetLoopfilterLevel() const302*fb1b10abSAndroid Build Coastguard Worker int VP9RateControlRTC::GetLoopfilterLevel() const {
303*fb1b10abSAndroid Build Coastguard Worker   struct loopfilter *const lf = &cpi_->common.lf;
304*fb1b10abSAndroid Build Coastguard Worker   vp9_pick_filter_level(nullptr, cpi_, LPF_PICK_FROM_Q);
305*fb1b10abSAndroid Build Coastguard Worker   return lf->filter_level;
306*fb1b10abSAndroid Build Coastguard Worker }
307*fb1b10abSAndroid Build Coastguard Worker 
GetSegmentationData(VP9SegmentationData * segmentation_data) const308*fb1b10abSAndroid Build Coastguard Worker bool VP9RateControlRTC::GetSegmentationData(
309*fb1b10abSAndroid Build Coastguard Worker     VP9SegmentationData *segmentation_data) const {
310*fb1b10abSAndroid Build Coastguard Worker   if (!cpi_->cyclic_refresh || !cpi_->cyclic_refresh->apply_cyclic_refresh) {
311*fb1b10abSAndroid Build Coastguard Worker     return false;
312*fb1b10abSAndroid Build Coastguard Worker   }
313*fb1b10abSAndroid Build Coastguard Worker 
314*fb1b10abSAndroid Build Coastguard Worker   segmentation_data->segmentation_map = cpi_->segmentation_map;
315*fb1b10abSAndroid Build Coastguard Worker   segmentation_data->segmentation_map_size =
316*fb1b10abSAndroid Build Coastguard Worker       cpi_->common.mi_cols * cpi_->common.mi_rows;
317*fb1b10abSAndroid Build Coastguard Worker   segmentation_data->delta_q = cpi_->cyclic_refresh->qindex_delta;
318*fb1b10abSAndroid Build Coastguard Worker   segmentation_data->delta_q_size = 3u;
319*fb1b10abSAndroid Build Coastguard Worker   return true;
320*fb1b10abSAndroid Build Coastguard Worker }
321*fb1b10abSAndroid Build Coastguard Worker 
PostEncodeUpdate(uint64_t encoded_frame_size,const VP9FrameParamsQpRTC & frame_params)322*fb1b10abSAndroid Build Coastguard Worker void VP9RateControlRTC::PostEncodeUpdate(
323*fb1b10abSAndroid Build Coastguard Worker     uint64_t encoded_frame_size, const VP9FrameParamsQpRTC &frame_params) {
324*fb1b10abSAndroid Build Coastguard Worker   cpi_->common.frame_type = static_cast<FRAME_TYPE>(frame_params.frame_type);
325*fb1b10abSAndroid Build Coastguard Worker   cpi_->svc.spatial_layer_id = frame_params.spatial_layer_id;
326*fb1b10abSAndroid Build Coastguard Worker   cpi_->svc.temporal_layer_id = frame_params.temporal_layer_id;
327*fb1b10abSAndroid Build Coastguard Worker   if (cpi_->svc.number_spatial_layers > 1 ||
328*fb1b10abSAndroid Build Coastguard Worker       cpi_->svc.number_temporal_layers > 1) {
329*fb1b10abSAndroid Build Coastguard Worker     vp9_restore_layer_context(cpi_);
330*fb1b10abSAndroid Build Coastguard Worker     const int layer = LAYER_IDS_TO_IDX(cpi_->svc.spatial_layer_id,
331*fb1b10abSAndroid Build Coastguard Worker                                        cpi_->svc.temporal_layer_id,
332*fb1b10abSAndroid Build Coastguard Worker                                        cpi_->svc.number_temporal_layers);
333*fb1b10abSAndroid Build Coastguard Worker     LAYER_CONTEXT *lc = &cpi_->svc.layer_context[layer];
334*fb1b10abSAndroid Build Coastguard Worker     cpi_->common.base_qindex = lc->frame_qp;
335*fb1b10abSAndroid Build Coastguard Worker     cpi_->common.MBs = lc->MBs;
336*fb1b10abSAndroid Build Coastguard Worker     // For spatial-svc, allow cyclic-refresh to be applied on the spatial
337*fb1b10abSAndroid Build Coastguard Worker     // layers, for the base temporal layer.
338*fb1b10abSAndroid Build Coastguard Worker     if (cpi_->oxcf.aq_mode == CYCLIC_REFRESH_AQ &&
339*fb1b10abSAndroid Build Coastguard Worker         cpi_->svc.number_spatial_layers > 1 &&
340*fb1b10abSAndroid Build Coastguard Worker         cpi_->svc.temporal_layer_id == 0) {
341*fb1b10abSAndroid Build Coastguard Worker       CYCLIC_REFRESH *const cr = cpi_->cyclic_refresh;
342*fb1b10abSAndroid Build Coastguard Worker       cr->qindex_delta[0] = lc->qindex_delta[0];
343*fb1b10abSAndroid Build Coastguard Worker       cr->qindex_delta[1] = lc->qindex_delta[1];
344*fb1b10abSAndroid Build Coastguard Worker       cr->qindex_delta[2] = lc->qindex_delta[2];
345*fb1b10abSAndroid Build Coastguard Worker     }
346*fb1b10abSAndroid Build Coastguard Worker   }
347*fb1b10abSAndroid Build Coastguard Worker   vp9_rc_postencode_update(cpi_, encoded_frame_size);
348*fb1b10abSAndroid Build Coastguard Worker   if (cpi_->svc.number_spatial_layers > 1 ||
349*fb1b10abSAndroid Build Coastguard Worker       cpi_->svc.number_temporal_layers > 1)
350*fb1b10abSAndroid Build Coastguard Worker     vp9_save_layer_context(cpi_);
351*fb1b10abSAndroid Build Coastguard Worker   cpi_->common.current_video_frame++;
352*fb1b10abSAndroid Build Coastguard Worker }
353*fb1b10abSAndroid Build Coastguard Worker 
354*fb1b10abSAndroid Build Coastguard Worker }  // namespace libvpx
355