1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2021 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
11*fb1b10abSAndroid Build Coastguard Worker #include "vp8/vp8_ratectrl_rtc.h"
12*fb1b10abSAndroid Build Coastguard Worker
13*fb1b10abSAndroid Build Coastguard Worker #include <math.h>
14*fb1b10abSAndroid Build Coastguard Worker
15*fb1b10abSAndroid Build Coastguard Worker #include <new>
16*fb1b10abSAndroid Build Coastguard Worker
17*fb1b10abSAndroid Build Coastguard Worker #include "vp8/common/common.h"
18*fb1b10abSAndroid Build Coastguard Worker #include "vp8/encoder/onyx_int.h"
19*fb1b10abSAndroid Build Coastguard Worker #include "vp8/encoder/ratectrl.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/system_state.h"
21*fb1b10abSAndroid Build Coastguard Worker
22*fb1b10abSAndroid Build Coastguard Worker namespace libvpx {
23*fb1b10abSAndroid Build Coastguard Worker /* Quant MOD */
24*fb1b10abSAndroid Build Coastguard Worker static const int kQTrans[] = {
25*fb1b10abSAndroid Build Coastguard Worker 0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19,
26*fb1b10abSAndroid Build Coastguard Worker 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 35, 37, 39, 41,
27*fb1b10abSAndroid Build Coastguard Worker 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 64, 67, 70, 73, 76, 79,
28*fb1b10abSAndroid Build Coastguard Worker 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 115, 118, 121, 124, 127,
29*fb1b10abSAndroid Build Coastguard Worker };
30*fb1b10abSAndroid Build Coastguard Worker
31*fb1b10abSAndroid Build Coastguard Worker static const unsigned char kf_high_motion_minq[QINDEX_RANGE] = {
32*fb1b10abSAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33*fb1b10abSAndroid Build Coastguard Worker 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,
34*fb1b10abSAndroid Build Coastguard Worker 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5,
35*fb1b10abSAndroid Build Coastguard Worker 5, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 8, 8, 8, 8, 9, 9, 10, 10,
36*fb1b10abSAndroid Build Coastguard Worker 10, 10, 11, 11, 11, 11, 12, 12, 13, 13, 13, 13, 14, 14, 15, 15, 15, 15, 16,
37*fb1b10abSAndroid Build Coastguard Worker 16, 16, 16, 17, 17, 18, 18, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21,
38*fb1b10abSAndroid Build Coastguard Worker 22, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, 29, 30
39*fb1b10abSAndroid Build Coastguard Worker };
40*fb1b10abSAndroid Build Coastguard Worker
41*fb1b10abSAndroid Build Coastguard Worker static const unsigned char inter_minq[QINDEX_RANGE] = {
42*fb1b10abSAndroid Build Coastguard Worker 0, 0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 9, 10, 11,
43*fb1b10abSAndroid Build Coastguard Worker 11, 12, 13, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 20, 21, 22, 22, 23, 24,
44*fb1b10abSAndroid Build Coastguard Worker 24, 25, 26, 27, 27, 28, 29, 30, 30, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38,
45*fb1b10abSAndroid Build Coastguard Worker 39, 39, 40, 41, 42, 42, 43, 44, 45, 46, 46, 47, 48, 49, 50, 50, 51, 52, 53,
46*fb1b10abSAndroid Build Coastguard Worker 54, 55, 55, 56, 57, 58, 59, 60, 60, 61, 62, 63, 64, 65, 66, 67, 67, 68, 69,
47*fb1b10abSAndroid Build Coastguard Worker 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 86,
48*fb1b10abSAndroid Build Coastguard Worker 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100
49*fb1b10abSAndroid Build Coastguard Worker };
50*fb1b10abSAndroid Build Coastguard Worker
rescale(int val,int num,int denom)51*fb1b10abSAndroid Build Coastguard Worker static int rescale(int val, int num, int denom) {
52*fb1b10abSAndroid Build Coastguard Worker int64_t llnum = num;
53*fb1b10abSAndroid Build Coastguard Worker int64_t llden = denom;
54*fb1b10abSAndroid Build Coastguard Worker int64_t llval = val;
55*fb1b10abSAndroid Build Coastguard Worker
56*fb1b10abSAndroid Build Coastguard Worker return (int)(llval * llnum / llden);
57*fb1b10abSAndroid Build Coastguard Worker }
58*fb1b10abSAndroid Build Coastguard Worker
Create(const VP8RateControlRtcConfig & cfg)59*fb1b10abSAndroid Build Coastguard Worker std::unique_ptr<VP8RateControlRTC> VP8RateControlRTC::Create(
60*fb1b10abSAndroid Build Coastguard Worker const VP8RateControlRtcConfig &cfg) {
61*fb1b10abSAndroid Build Coastguard Worker std::unique_ptr<VP8RateControlRTC> rc_api(new (std::nothrow)
62*fb1b10abSAndroid Build Coastguard Worker VP8RateControlRTC());
63*fb1b10abSAndroid Build Coastguard Worker if (!rc_api) return nullptr;
64*fb1b10abSAndroid Build Coastguard Worker rc_api->cpi_ = static_cast<VP8_COMP *>(vpx_memalign(32, sizeof(*cpi_)));
65*fb1b10abSAndroid Build Coastguard Worker if (!rc_api->cpi_) return nullptr;
66*fb1b10abSAndroid Build Coastguard Worker vp8_zero(*rc_api->cpi_);
67*fb1b10abSAndroid Build Coastguard Worker
68*fb1b10abSAndroid Build Coastguard Worker if (!rc_api->InitRateControl(cfg)) return nullptr;
69*fb1b10abSAndroid Build Coastguard Worker
70*fb1b10abSAndroid Build Coastguard Worker return rc_api;
71*fb1b10abSAndroid Build Coastguard Worker }
72*fb1b10abSAndroid Build Coastguard Worker
~VP8RateControlRTC()73*fb1b10abSAndroid Build Coastguard Worker VP8RateControlRTC::~VP8RateControlRTC() {
74*fb1b10abSAndroid Build Coastguard Worker if (cpi_) {
75*fb1b10abSAndroid Build Coastguard Worker vpx_free(cpi_->gf_active_flags);
76*fb1b10abSAndroid Build Coastguard Worker vpx_free(cpi_);
77*fb1b10abSAndroid Build Coastguard Worker }
78*fb1b10abSAndroid Build Coastguard Worker }
79*fb1b10abSAndroid Build Coastguard Worker
InitRateControl(const VP8RateControlRtcConfig & rc_cfg)80*fb1b10abSAndroid Build Coastguard Worker bool VP8RateControlRTC::InitRateControl(const VP8RateControlRtcConfig &rc_cfg) {
81*fb1b10abSAndroid Build Coastguard Worker VP8_COMMON *cm = &cpi_->common;
82*fb1b10abSAndroid Build Coastguard Worker VP8_CONFIG *oxcf = &cpi_->oxcf;
83*fb1b10abSAndroid Build Coastguard Worker oxcf->end_usage = USAGE_STREAM_FROM_SERVER;
84*fb1b10abSAndroid Build Coastguard Worker cpi_->pass = 0;
85*fb1b10abSAndroid Build Coastguard Worker cm->show_frame = 1;
86*fb1b10abSAndroid Build Coastguard Worker oxcf->drop_frames_water_mark = 0;
87*fb1b10abSAndroid Build Coastguard Worker cm->current_video_frame = 0;
88*fb1b10abSAndroid Build Coastguard Worker cpi_->auto_gold = 1;
89*fb1b10abSAndroid Build Coastguard Worker cpi_->key_frame_count = 1;
90*fb1b10abSAndroid Build Coastguard Worker cpi_->rate_correction_factor = 1.0;
91*fb1b10abSAndroid Build Coastguard Worker cpi_->key_frame_rate_correction_factor = 1.0;
92*fb1b10abSAndroid Build Coastguard Worker cpi_->cyclic_refresh_mode_enabled = 0;
93*fb1b10abSAndroid Build Coastguard Worker cpi_->auto_worst_q = 1;
94*fb1b10abSAndroid Build Coastguard Worker cpi_->kf_overspend_bits = 0;
95*fb1b10abSAndroid Build Coastguard Worker cpi_->kf_bitrate_adjustment = 0;
96*fb1b10abSAndroid Build Coastguard Worker cpi_->gf_overspend_bits = 0;
97*fb1b10abSAndroid Build Coastguard Worker cpi_->non_gf_bitrate_adjustment = 0;
98*fb1b10abSAndroid Build Coastguard Worker if (!UpdateRateControl(rc_cfg)) return false;
99*fb1b10abSAndroid Build Coastguard Worker cpi_->buffer_level = oxcf->starting_buffer_level;
100*fb1b10abSAndroid Build Coastguard Worker cpi_->bits_off_target = oxcf->starting_buffer_level;
101*fb1b10abSAndroid Build Coastguard Worker return true;
102*fb1b10abSAndroid Build Coastguard Worker }
103*fb1b10abSAndroid Build Coastguard Worker
UpdateRateControl(const VP8RateControlRtcConfig & rc_cfg)104*fb1b10abSAndroid Build Coastguard Worker bool VP8RateControlRTC::UpdateRateControl(
105*fb1b10abSAndroid Build Coastguard Worker const VP8RateControlRtcConfig &rc_cfg) {
106*fb1b10abSAndroid Build Coastguard Worker if (rc_cfg.ts_number_layers < 1 ||
107*fb1b10abSAndroid Build Coastguard Worker rc_cfg.ts_number_layers > VPX_TS_MAX_LAYERS) {
108*fb1b10abSAndroid Build Coastguard Worker return false;
109*fb1b10abSAndroid Build Coastguard Worker }
110*fb1b10abSAndroid Build Coastguard Worker
111*fb1b10abSAndroid Build Coastguard Worker VP8_COMMON *cm = &cpi_->common;
112*fb1b10abSAndroid Build Coastguard Worker VP8_CONFIG *oxcf = &cpi_->oxcf;
113*fb1b10abSAndroid Build Coastguard Worker const unsigned int prev_number_of_layers = oxcf->number_of_layers;
114*fb1b10abSAndroid Build Coastguard Worker vpx_clear_system_state();
115*fb1b10abSAndroid Build Coastguard Worker cm->Width = rc_cfg.width;
116*fb1b10abSAndroid Build Coastguard Worker cm->Height = rc_cfg.height;
117*fb1b10abSAndroid Build Coastguard Worker oxcf->Width = rc_cfg.width;
118*fb1b10abSAndroid Build Coastguard Worker oxcf->Height = rc_cfg.height;
119*fb1b10abSAndroid Build Coastguard Worker oxcf->worst_allowed_q = kQTrans[rc_cfg.max_quantizer];
120*fb1b10abSAndroid Build Coastguard Worker oxcf->best_allowed_q = kQTrans[rc_cfg.min_quantizer];
121*fb1b10abSAndroid Build Coastguard Worker cpi_->worst_quality = oxcf->worst_allowed_q;
122*fb1b10abSAndroid Build Coastguard Worker cpi_->best_quality = oxcf->best_allowed_q;
123*fb1b10abSAndroid Build Coastguard Worker cpi_->output_framerate = rc_cfg.framerate;
124*fb1b10abSAndroid Build Coastguard Worker oxcf->target_bandwidth =
125*fb1b10abSAndroid Build Coastguard Worker static_cast<unsigned int>(1000 * rc_cfg.target_bandwidth);
126*fb1b10abSAndroid Build Coastguard Worker cpi_->ref_framerate = cpi_->output_framerate;
127*fb1b10abSAndroid Build Coastguard Worker oxcf->fixed_q = -1;
128*fb1b10abSAndroid Build Coastguard Worker oxcf->error_resilient_mode = 1;
129*fb1b10abSAndroid Build Coastguard Worker oxcf->starting_buffer_level_in_ms = rc_cfg.buf_initial_sz;
130*fb1b10abSAndroid Build Coastguard Worker oxcf->optimal_buffer_level_in_ms = rc_cfg.buf_optimal_sz;
131*fb1b10abSAndroid Build Coastguard Worker oxcf->maximum_buffer_size_in_ms = rc_cfg.buf_sz;
132*fb1b10abSAndroid Build Coastguard Worker oxcf->starting_buffer_level = rc_cfg.buf_initial_sz;
133*fb1b10abSAndroid Build Coastguard Worker oxcf->optimal_buffer_level = rc_cfg.buf_optimal_sz;
134*fb1b10abSAndroid Build Coastguard Worker oxcf->maximum_buffer_size = rc_cfg.buf_sz;
135*fb1b10abSAndroid Build Coastguard Worker oxcf->number_of_layers = rc_cfg.ts_number_layers;
136*fb1b10abSAndroid Build Coastguard Worker cpi_->buffered_mode = oxcf->optimal_buffer_level > 0;
137*fb1b10abSAndroid Build Coastguard Worker oxcf->under_shoot_pct = rc_cfg.undershoot_pct;
138*fb1b10abSAndroid Build Coastguard Worker oxcf->over_shoot_pct = rc_cfg.overshoot_pct;
139*fb1b10abSAndroid Build Coastguard Worker oxcf->drop_frames_water_mark = rc_cfg.frame_drop_thresh;
140*fb1b10abSAndroid Build Coastguard Worker if (oxcf->drop_frames_water_mark > 0) cpi_->drop_frames_allowed = 1;
141*fb1b10abSAndroid Build Coastguard Worker cpi_->oxcf.rc_max_intra_bitrate_pct = rc_cfg.max_intra_bitrate_pct;
142*fb1b10abSAndroid Build Coastguard Worker cpi_->framerate = rc_cfg.framerate;
143*fb1b10abSAndroid Build Coastguard Worker for (int i = 0; i < KEY_FRAME_CONTEXT; ++i) {
144*fb1b10abSAndroid Build Coastguard Worker cpi_->prior_key_frame_distance[i] =
145*fb1b10abSAndroid Build Coastguard Worker static_cast<int>(cpi_->output_framerate);
146*fb1b10abSAndroid Build Coastguard Worker }
147*fb1b10abSAndroid Build Coastguard Worker oxcf->screen_content_mode = rc_cfg.is_screen;
148*fb1b10abSAndroid Build Coastguard Worker if (oxcf->number_of_layers > 1 || prev_number_of_layers > 1) {
149*fb1b10abSAndroid Build Coastguard Worker memcpy(oxcf->target_bitrate, rc_cfg.layer_target_bitrate,
150*fb1b10abSAndroid Build Coastguard Worker sizeof(rc_cfg.layer_target_bitrate));
151*fb1b10abSAndroid Build Coastguard Worker memcpy(oxcf->rate_decimator, rc_cfg.ts_rate_decimator,
152*fb1b10abSAndroid Build Coastguard Worker sizeof(rc_cfg.ts_rate_decimator));
153*fb1b10abSAndroid Build Coastguard Worker if (cm->current_video_frame == 0) {
154*fb1b10abSAndroid Build Coastguard Worker double prev_layer_framerate = 0;
155*fb1b10abSAndroid Build Coastguard Worker for (unsigned int i = 0; i < oxcf->number_of_layers; ++i) {
156*fb1b10abSAndroid Build Coastguard Worker vp8_init_temporal_layer_context(cpi_, oxcf, i, prev_layer_framerate);
157*fb1b10abSAndroid Build Coastguard Worker prev_layer_framerate = cpi_->output_framerate / oxcf->rate_decimator[i];
158*fb1b10abSAndroid Build Coastguard Worker }
159*fb1b10abSAndroid Build Coastguard Worker } else if (oxcf->number_of_layers != prev_number_of_layers) {
160*fb1b10abSAndroid Build Coastguard Worker // The number of temporal layers has changed, so reset/initialize the
161*fb1b10abSAndroid Build Coastguard Worker // temporal layer context for the new layer configuration: this means
162*fb1b10abSAndroid Build Coastguard Worker // calling vp8_reset_temporal_layer_change() below.
163*fb1b10abSAndroid Build Coastguard Worker
164*fb1b10abSAndroid Build Coastguard Worker // Start at the base of the pattern cycle, so set the layer id to 0 and
165*fb1b10abSAndroid Build Coastguard Worker // reset the temporal pattern counter.
166*fb1b10abSAndroid Build Coastguard Worker // TODO(marpan/jianj): don't think lines 148-151 are needed (user controls
167*fb1b10abSAndroid Build Coastguard Worker // the layer_id) so remove.
168*fb1b10abSAndroid Build Coastguard Worker if (cpi_->temporal_layer_id > 0) {
169*fb1b10abSAndroid Build Coastguard Worker cpi_->temporal_layer_id = 0;
170*fb1b10abSAndroid Build Coastguard Worker }
171*fb1b10abSAndroid Build Coastguard Worker cpi_->temporal_pattern_counter = 0;
172*fb1b10abSAndroid Build Coastguard Worker
173*fb1b10abSAndroid Build Coastguard Worker vp8_reset_temporal_layer_change(cpi_, oxcf,
174*fb1b10abSAndroid Build Coastguard Worker static_cast<int>(prev_number_of_layers));
175*fb1b10abSAndroid Build Coastguard Worker }
176*fb1b10abSAndroid Build Coastguard Worker }
177*fb1b10abSAndroid Build Coastguard Worker
178*fb1b10abSAndroid Build Coastguard Worker cpi_->total_actual_bits = 0;
179*fb1b10abSAndroid Build Coastguard Worker cpi_->total_target_vs_actual = 0;
180*fb1b10abSAndroid Build Coastguard Worker
181*fb1b10abSAndroid Build Coastguard Worker cm->mb_rows = cm->Height >> 4;
182*fb1b10abSAndroid Build Coastguard Worker cm->mb_cols = cm->Width >> 4;
183*fb1b10abSAndroid Build Coastguard Worker cm->MBs = cm->mb_rows * cm->mb_cols;
184*fb1b10abSAndroid Build Coastguard Worker cm->mode_info_stride = cm->mb_cols + 1;
185*fb1b10abSAndroid Build Coastguard Worker
186*fb1b10abSAndroid Build Coastguard Worker // For temporal layers: starting/maximum/optimal_buffer_level is already set
187*fb1b10abSAndroid Build Coastguard Worker // via vp8_init_temporal_layer_context() or vp8_reset_temporal_layer_change().
188*fb1b10abSAndroid Build Coastguard Worker if (oxcf->number_of_layers <= 1 && prev_number_of_layers <= 1) {
189*fb1b10abSAndroid Build Coastguard Worker oxcf->starting_buffer_level =
190*fb1b10abSAndroid Build Coastguard Worker rescale((int)oxcf->starting_buffer_level, oxcf->target_bandwidth, 1000);
191*fb1b10abSAndroid Build Coastguard Worker /* Set or reset optimal and maximum buffer levels. */
192*fb1b10abSAndroid Build Coastguard Worker if (oxcf->optimal_buffer_level == 0) {
193*fb1b10abSAndroid Build Coastguard Worker oxcf->optimal_buffer_level = oxcf->target_bandwidth / 8;
194*fb1b10abSAndroid Build Coastguard Worker } else {
195*fb1b10abSAndroid Build Coastguard Worker oxcf->optimal_buffer_level = rescale((int)oxcf->optimal_buffer_level,
196*fb1b10abSAndroid Build Coastguard Worker oxcf->target_bandwidth, 1000);
197*fb1b10abSAndroid Build Coastguard Worker }
198*fb1b10abSAndroid Build Coastguard Worker if (oxcf->maximum_buffer_size == 0) {
199*fb1b10abSAndroid Build Coastguard Worker oxcf->maximum_buffer_size = oxcf->target_bandwidth / 8;
200*fb1b10abSAndroid Build Coastguard Worker } else {
201*fb1b10abSAndroid Build Coastguard Worker oxcf->maximum_buffer_size =
202*fb1b10abSAndroid Build Coastguard Worker rescale((int)oxcf->maximum_buffer_size, oxcf->target_bandwidth, 1000);
203*fb1b10abSAndroid Build Coastguard Worker }
204*fb1b10abSAndroid Build Coastguard Worker }
205*fb1b10abSAndroid Build Coastguard Worker
206*fb1b10abSAndroid Build Coastguard Worker if (cpi_->bits_off_target > oxcf->maximum_buffer_size) {
207*fb1b10abSAndroid Build Coastguard Worker cpi_->bits_off_target = oxcf->maximum_buffer_size;
208*fb1b10abSAndroid Build Coastguard Worker cpi_->buffer_level = cpi_->bits_off_target;
209*fb1b10abSAndroid Build Coastguard Worker }
210*fb1b10abSAndroid Build Coastguard Worker
211*fb1b10abSAndroid Build Coastguard Worker vp8_new_framerate(cpi_, cpi_->framerate);
212*fb1b10abSAndroid Build Coastguard Worker vpx_clear_system_state();
213*fb1b10abSAndroid Build Coastguard Worker return true;
214*fb1b10abSAndroid Build Coastguard Worker }
215*fb1b10abSAndroid Build Coastguard Worker
ComputeQP(const VP8FrameParamsQpRTC & frame_params)216*fb1b10abSAndroid Build Coastguard Worker FrameDropDecision VP8RateControlRTC::ComputeQP(
217*fb1b10abSAndroid Build Coastguard Worker const VP8FrameParamsQpRTC &frame_params) {
218*fb1b10abSAndroid Build Coastguard Worker VP8_COMMON *const cm = &cpi_->common;
219*fb1b10abSAndroid Build Coastguard Worker vpx_clear_system_state();
220*fb1b10abSAndroid Build Coastguard Worker if (cpi_->oxcf.number_of_layers > 1) {
221*fb1b10abSAndroid Build Coastguard Worker cpi_->temporal_layer_id = frame_params.temporal_layer_id;
222*fb1b10abSAndroid Build Coastguard Worker const int layer = frame_params.temporal_layer_id;
223*fb1b10abSAndroid Build Coastguard Worker vp8_update_layer_contexts(cpi_);
224*fb1b10abSAndroid Build Coastguard Worker /* Restore layer specific context & set frame rate */
225*fb1b10abSAndroid Build Coastguard Worker vp8_restore_layer_context(cpi_, layer);
226*fb1b10abSAndroid Build Coastguard Worker vp8_new_framerate(cpi_, cpi_->layer_context[layer].framerate);
227*fb1b10abSAndroid Build Coastguard Worker }
228*fb1b10abSAndroid Build Coastguard Worker cm->frame_type = static_cast<FRAME_TYPE>(frame_params.frame_type);
229*fb1b10abSAndroid Build Coastguard Worker cm->refresh_golden_frame = (cm->frame_type == KEY_FRAME) ? 1 : 0;
230*fb1b10abSAndroid Build Coastguard Worker cm->refresh_alt_ref_frame = (cm->frame_type == KEY_FRAME) ? 1 : 0;
231*fb1b10abSAndroid Build Coastguard Worker if (cm->frame_type == KEY_FRAME && cpi_->common.current_video_frame > 0) {
232*fb1b10abSAndroid Build Coastguard Worker cpi_->common.frame_flags |= FRAMEFLAGS_KEY;
233*fb1b10abSAndroid Build Coastguard Worker }
234*fb1b10abSAndroid Build Coastguard Worker
235*fb1b10abSAndroid Build Coastguard Worker cpi_->per_frame_bandwidth = static_cast<int>(
236*fb1b10abSAndroid Build Coastguard Worker round(cpi_->oxcf.target_bandwidth / cpi_->output_framerate));
237*fb1b10abSAndroid Build Coastguard Worker if (vp8_check_drop_buffer(cpi_)) {
238*fb1b10abSAndroid Build Coastguard Worker if (cpi_->oxcf.number_of_layers > 1) vp8_save_layer_context(cpi_);
239*fb1b10abSAndroid Build Coastguard Worker return FrameDropDecision::kDrop;
240*fb1b10abSAndroid Build Coastguard Worker }
241*fb1b10abSAndroid Build Coastguard Worker
242*fb1b10abSAndroid Build Coastguard Worker if (!vp8_pick_frame_size(cpi_)) {
243*fb1b10abSAndroid Build Coastguard Worker cm->current_video_frame++;
244*fb1b10abSAndroid Build Coastguard Worker cpi_->frames_since_key++;
245*fb1b10abSAndroid Build Coastguard Worker cpi_->ext_refresh_frame_flags_pending = 0;
246*fb1b10abSAndroid Build Coastguard Worker if (cpi_->oxcf.number_of_layers > 1) vp8_save_layer_context(cpi_);
247*fb1b10abSAndroid Build Coastguard Worker return FrameDropDecision::kDrop;
248*fb1b10abSAndroid Build Coastguard Worker }
249*fb1b10abSAndroid Build Coastguard Worker
250*fb1b10abSAndroid Build Coastguard Worker if (cpi_->buffer_level >= cpi_->oxcf.optimal_buffer_level &&
251*fb1b10abSAndroid Build Coastguard Worker cpi_->buffered_mode) {
252*fb1b10abSAndroid Build Coastguard Worker /* Max adjustment is 1/4 */
253*fb1b10abSAndroid Build Coastguard Worker int Adjustment = cpi_->active_worst_quality / 4;
254*fb1b10abSAndroid Build Coastguard Worker if (Adjustment) {
255*fb1b10abSAndroid Build Coastguard Worker int buff_lvl_step;
256*fb1b10abSAndroid Build Coastguard Worker if (cpi_->buffer_level < cpi_->oxcf.maximum_buffer_size) {
257*fb1b10abSAndroid Build Coastguard Worker buff_lvl_step = (int)((cpi_->oxcf.maximum_buffer_size -
258*fb1b10abSAndroid Build Coastguard Worker cpi_->oxcf.optimal_buffer_level) /
259*fb1b10abSAndroid Build Coastguard Worker Adjustment);
260*fb1b10abSAndroid Build Coastguard Worker if (buff_lvl_step) {
261*fb1b10abSAndroid Build Coastguard Worker Adjustment =
262*fb1b10abSAndroid Build Coastguard Worker (int)((cpi_->buffer_level - cpi_->oxcf.optimal_buffer_level) /
263*fb1b10abSAndroid Build Coastguard Worker buff_lvl_step);
264*fb1b10abSAndroid Build Coastguard Worker } else {
265*fb1b10abSAndroid Build Coastguard Worker Adjustment = 0;
266*fb1b10abSAndroid Build Coastguard Worker }
267*fb1b10abSAndroid Build Coastguard Worker }
268*fb1b10abSAndroid Build Coastguard Worker cpi_->active_worst_quality -= Adjustment;
269*fb1b10abSAndroid Build Coastguard Worker if (cpi_->active_worst_quality < cpi_->active_best_quality) {
270*fb1b10abSAndroid Build Coastguard Worker cpi_->active_worst_quality = cpi_->active_best_quality;
271*fb1b10abSAndroid Build Coastguard Worker }
272*fb1b10abSAndroid Build Coastguard Worker }
273*fb1b10abSAndroid Build Coastguard Worker }
274*fb1b10abSAndroid Build Coastguard Worker
275*fb1b10abSAndroid Build Coastguard Worker if (cpi_->ni_frames > 150) {
276*fb1b10abSAndroid Build Coastguard Worker int q = cpi_->active_worst_quality;
277*fb1b10abSAndroid Build Coastguard Worker if (cm->frame_type == KEY_FRAME) {
278*fb1b10abSAndroid Build Coastguard Worker cpi_->active_best_quality = kf_high_motion_minq[q];
279*fb1b10abSAndroid Build Coastguard Worker } else {
280*fb1b10abSAndroid Build Coastguard Worker cpi_->active_best_quality = inter_minq[q];
281*fb1b10abSAndroid Build Coastguard Worker }
282*fb1b10abSAndroid Build Coastguard Worker
283*fb1b10abSAndroid Build Coastguard Worker if (cpi_->buffer_level >= cpi_->oxcf.maximum_buffer_size) {
284*fb1b10abSAndroid Build Coastguard Worker cpi_->active_best_quality = cpi_->best_quality;
285*fb1b10abSAndroid Build Coastguard Worker
286*fb1b10abSAndroid Build Coastguard Worker } else if (cpi_->buffer_level > cpi_->oxcf.optimal_buffer_level) {
287*fb1b10abSAndroid Build Coastguard Worker int Fraction =
288*fb1b10abSAndroid Build Coastguard Worker (int)(((cpi_->buffer_level - cpi_->oxcf.optimal_buffer_level) * 128) /
289*fb1b10abSAndroid Build Coastguard Worker (cpi_->oxcf.maximum_buffer_size -
290*fb1b10abSAndroid Build Coastguard Worker cpi_->oxcf.optimal_buffer_level));
291*fb1b10abSAndroid Build Coastguard Worker int min_qadjustment =
292*fb1b10abSAndroid Build Coastguard Worker ((cpi_->active_best_quality - cpi_->best_quality) * Fraction) / 128;
293*fb1b10abSAndroid Build Coastguard Worker
294*fb1b10abSAndroid Build Coastguard Worker cpi_->active_best_quality -= min_qadjustment;
295*fb1b10abSAndroid Build Coastguard Worker }
296*fb1b10abSAndroid Build Coastguard Worker }
297*fb1b10abSAndroid Build Coastguard Worker
298*fb1b10abSAndroid Build Coastguard Worker /* Clip the active best and worst quality values to limits */
299*fb1b10abSAndroid Build Coastguard Worker if (cpi_->active_worst_quality > cpi_->worst_quality) {
300*fb1b10abSAndroid Build Coastguard Worker cpi_->active_worst_quality = cpi_->worst_quality;
301*fb1b10abSAndroid Build Coastguard Worker }
302*fb1b10abSAndroid Build Coastguard Worker if (cpi_->active_best_quality < cpi_->best_quality) {
303*fb1b10abSAndroid Build Coastguard Worker cpi_->active_best_quality = cpi_->best_quality;
304*fb1b10abSAndroid Build Coastguard Worker }
305*fb1b10abSAndroid Build Coastguard Worker if (cpi_->active_worst_quality < cpi_->active_best_quality) {
306*fb1b10abSAndroid Build Coastguard Worker cpi_->active_worst_quality = cpi_->active_best_quality;
307*fb1b10abSAndroid Build Coastguard Worker }
308*fb1b10abSAndroid Build Coastguard Worker
309*fb1b10abSAndroid Build Coastguard Worker q_ = vp8_regulate_q(cpi_, cpi_->this_frame_target);
310*fb1b10abSAndroid Build Coastguard Worker vp8_set_quantizer(cpi_, q_);
311*fb1b10abSAndroid Build Coastguard Worker vpx_clear_system_state();
312*fb1b10abSAndroid Build Coastguard Worker return FrameDropDecision::kOk;
313*fb1b10abSAndroid Build Coastguard Worker }
314*fb1b10abSAndroid Build Coastguard Worker
GetQP() const315*fb1b10abSAndroid Build Coastguard Worker int VP8RateControlRTC::GetQP() const { return q_; }
316*fb1b10abSAndroid Build Coastguard Worker
GetUVDeltaQP() const317*fb1b10abSAndroid Build Coastguard Worker UVDeltaQP VP8RateControlRTC::GetUVDeltaQP() const {
318*fb1b10abSAndroid Build Coastguard Worker VP8_COMMON *cm = &cpi_->common;
319*fb1b10abSAndroid Build Coastguard Worker UVDeltaQP uv_delta_q;
320*fb1b10abSAndroid Build Coastguard Worker uv_delta_q.uvdc_delta_q = cm->uvdc_delta_q;
321*fb1b10abSAndroid Build Coastguard Worker uv_delta_q.uvac_delta_q = cm->uvac_delta_q;
322*fb1b10abSAndroid Build Coastguard Worker return uv_delta_q;
323*fb1b10abSAndroid Build Coastguard Worker }
324*fb1b10abSAndroid Build Coastguard Worker
GetLoopfilterLevel() const325*fb1b10abSAndroid Build Coastguard Worker int VP8RateControlRTC::GetLoopfilterLevel() const {
326*fb1b10abSAndroid Build Coastguard Worker VP8_COMMON *cm = &cpi_->common;
327*fb1b10abSAndroid Build Coastguard Worker const double qp = q_;
328*fb1b10abSAndroid Build Coastguard Worker
329*fb1b10abSAndroid Build Coastguard Worker // This model is from linear regression
330*fb1b10abSAndroid Build Coastguard Worker if (cm->Width * cm->Height <= 320 * 240) {
331*fb1b10abSAndroid Build Coastguard Worker cm->filter_level = static_cast<int>(0.352685 * qp + 2.957774);
332*fb1b10abSAndroid Build Coastguard Worker } else if (cm->Width * cm->Height <= 640 * 480) {
333*fb1b10abSAndroid Build Coastguard Worker cm->filter_level = static_cast<int>(0.485069 * qp - 0.534462);
334*fb1b10abSAndroid Build Coastguard Worker } else {
335*fb1b10abSAndroid Build Coastguard Worker cm->filter_level = static_cast<int>(0.314875 * qp + 7.959003);
336*fb1b10abSAndroid Build Coastguard Worker }
337*fb1b10abSAndroid Build Coastguard Worker
338*fb1b10abSAndroid Build Coastguard Worker int min_filter_level = 0;
339*fb1b10abSAndroid Build Coastguard Worker // This logic is from get_min_filter_level() in picklpf.c
340*fb1b10abSAndroid Build Coastguard Worker if (q_ > 6 && q_ <= 16) {
341*fb1b10abSAndroid Build Coastguard Worker min_filter_level = 1;
342*fb1b10abSAndroid Build Coastguard Worker } else {
343*fb1b10abSAndroid Build Coastguard Worker min_filter_level = (q_ / 8);
344*fb1b10abSAndroid Build Coastguard Worker }
345*fb1b10abSAndroid Build Coastguard Worker
346*fb1b10abSAndroid Build Coastguard Worker const int max_filter_level = 63;
347*fb1b10abSAndroid Build Coastguard Worker if (cm->filter_level < min_filter_level) cm->filter_level = min_filter_level;
348*fb1b10abSAndroid Build Coastguard Worker if (cm->filter_level > max_filter_level) cm->filter_level = max_filter_level;
349*fb1b10abSAndroid Build Coastguard Worker
350*fb1b10abSAndroid Build Coastguard Worker return cm->filter_level;
351*fb1b10abSAndroid Build Coastguard Worker }
352*fb1b10abSAndroid Build Coastguard Worker
PostEncodeUpdate(uint64_t encoded_frame_size)353*fb1b10abSAndroid Build Coastguard Worker void VP8RateControlRTC::PostEncodeUpdate(uint64_t encoded_frame_size) {
354*fb1b10abSAndroid Build Coastguard Worker VP8_COMMON *const cm = &cpi_->common;
355*fb1b10abSAndroid Build Coastguard Worker vpx_clear_system_state();
356*fb1b10abSAndroid Build Coastguard Worker cpi_->total_byte_count += encoded_frame_size;
357*fb1b10abSAndroid Build Coastguard Worker cpi_->projected_frame_size = static_cast<int>(encoded_frame_size << 3);
358*fb1b10abSAndroid Build Coastguard Worker if (cpi_->oxcf.number_of_layers > 1) {
359*fb1b10abSAndroid Build Coastguard Worker for (unsigned int i = cpi_->current_layer + 1;
360*fb1b10abSAndroid Build Coastguard Worker i < cpi_->oxcf.number_of_layers; ++i) {
361*fb1b10abSAndroid Build Coastguard Worker cpi_->layer_context[i].total_byte_count += encoded_frame_size;
362*fb1b10abSAndroid Build Coastguard Worker }
363*fb1b10abSAndroid Build Coastguard Worker }
364*fb1b10abSAndroid Build Coastguard Worker
365*fb1b10abSAndroid Build Coastguard Worker vp8_update_rate_correction_factors(cpi_, 2);
366*fb1b10abSAndroid Build Coastguard Worker
367*fb1b10abSAndroid Build Coastguard Worker cpi_->last_q[cm->frame_type] = cm->base_qindex;
368*fb1b10abSAndroid Build Coastguard Worker
369*fb1b10abSAndroid Build Coastguard Worker if (cm->frame_type == KEY_FRAME) {
370*fb1b10abSAndroid Build Coastguard Worker vp8_adjust_key_frame_context(cpi_);
371*fb1b10abSAndroid Build Coastguard Worker }
372*fb1b10abSAndroid Build Coastguard Worker
373*fb1b10abSAndroid Build Coastguard Worker /* Keep a record of ambient average Q. */
374*fb1b10abSAndroid Build Coastguard Worker if (cm->frame_type != KEY_FRAME) {
375*fb1b10abSAndroid Build Coastguard Worker cpi_->avg_frame_qindex =
376*fb1b10abSAndroid Build Coastguard Worker (2 + 3 * cpi_->avg_frame_qindex + cm->base_qindex) >> 2;
377*fb1b10abSAndroid Build Coastguard Worker }
378*fb1b10abSAndroid Build Coastguard Worker /* Keep a record from which we can calculate the average Q excluding
379*fb1b10abSAndroid Build Coastguard Worker * key frames.
380*fb1b10abSAndroid Build Coastguard Worker */
381*fb1b10abSAndroid Build Coastguard Worker if (cm->frame_type != KEY_FRAME) {
382*fb1b10abSAndroid Build Coastguard Worker cpi_->ni_frames++;
383*fb1b10abSAndroid Build Coastguard Worker /* Damp value for first few frames */
384*fb1b10abSAndroid Build Coastguard Worker if (cpi_->ni_frames > 150) {
385*fb1b10abSAndroid Build Coastguard Worker cpi_->ni_tot_qi += q_;
386*fb1b10abSAndroid Build Coastguard Worker cpi_->ni_av_qi = (cpi_->ni_tot_qi / cpi_->ni_frames);
387*fb1b10abSAndroid Build Coastguard Worker } else {
388*fb1b10abSAndroid Build Coastguard Worker cpi_->ni_tot_qi += q_;
389*fb1b10abSAndroid Build Coastguard Worker cpi_->ni_av_qi =
390*fb1b10abSAndroid Build Coastguard Worker ((cpi_->ni_tot_qi / cpi_->ni_frames) + cpi_->worst_quality + 1) / 2;
391*fb1b10abSAndroid Build Coastguard Worker }
392*fb1b10abSAndroid Build Coastguard Worker
393*fb1b10abSAndroid Build Coastguard Worker /* If the average Q is higher than what was used in the last
394*fb1b10abSAndroid Build Coastguard Worker * frame (after going through the recode loop to keep the frame
395*fb1b10abSAndroid Build Coastguard Worker * size within range) then use the last frame value - 1. The -1
396*fb1b10abSAndroid Build Coastguard Worker * is designed to stop Q and hence the data rate, from
397*fb1b10abSAndroid Build Coastguard Worker * progressively falling away during difficult sections, but at
398*fb1b10abSAndroid Build Coastguard Worker * the same time reduce the number of itterations around the
399*fb1b10abSAndroid Build Coastguard Worker * recode loop.
400*fb1b10abSAndroid Build Coastguard Worker */
401*fb1b10abSAndroid Build Coastguard Worker if (q_ > cpi_->ni_av_qi) cpi_->ni_av_qi = q_ - 1;
402*fb1b10abSAndroid Build Coastguard Worker }
403*fb1b10abSAndroid Build Coastguard Worker
404*fb1b10abSAndroid Build Coastguard Worker cpi_->bits_off_target +=
405*fb1b10abSAndroid Build Coastguard Worker cpi_->av_per_frame_bandwidth - cpi_->projected_frame_size;
406*fb1b10abSAndroid Build Coastguard Worker if (cpi_->bits_off_target > cpi_->oxcf.maximum_buffer_size) {
407*fb1b10abSAndroid Build Coastguard Worker cpi_->bits_off_target = cpi_->oxcf.maximum_buffer_size;
408*fb1b10abSAndroid Build Coastguard Worker }
409*fb1b10abSAndroid Build Coastguard Worker
410*fb1b10abSAndroid Build Coastguard Worker cpi_->total_actual_bits += cpi_->projected_frame_size;
411*fb1b10abSAndroid Build Coastguard Worker cpi_->buffer_level = cpi_->bits_off_target;
412*fb1b10abSAndroid Build Coastguard Worker
413*fb1b10abSAndroid Build Coastguard Worker /* Propagate values to higher temporal layers */
414*fb1b10abSAndroid Build Coastguard Worker if (cpi_->oxcf.number_of_layers > 1) {
415*fb1b10abSAndroid Build Coastguard Worker for (unsigned int i = cpi_->current_layer + 1;
416*fb1b10abSAndroid Build Coastguard Worker i < cpi_->oxcf.number_of_layers; ++i) {
417*fb1b10abSAndroid Build Coastguard Worker LAYER_CONTEXT *lc = &cpi_->layer_context[i];
418*fb1b10abSAndroid Build Coastguard Worker int bits_off_for_this_layer = (int)round(
419*fb1b10abSAndroid Build Coastguard Worker lc->target_bandwidth / lc->framerate - cpi_->projected_frame_size);
420*fb1b10abSAndroid Build Coastguard Worker
421*fb1b10abSAndroid Build Coastguard Worker lc->bits_off_target += bits_off_for_this_layer;
422*fb1b10abSAndroid Build Coastguard Worker
423*fb1b10abSAndroid Build Coastguard Worker /* Clip buffer level to maximum buffer size for the layer */
424*fb1b10abSAndroid Build Coastguard Worker if (lc->bits_off_target > lc->maximum_buffer_size) {
425*fb1b10abSAndroid Build Coastguard Worker lc->bits_off_target = lc->maximum_buffer_size;
426*fb1b10abSAndroid Build Coastguard Worker }
427*fb1b10abSAndroid Build Coastguard Worker
428*fb1b10abSAndroid Build Coastguard Worker lc->total_actual_bits += cpi_->projected_frame_size;
429*fb1b10abSAndroid Build Coastguard Worker lc->total_target_vs_actual += bits_off_for_this_layer;
430*fb1b10abSAndroid Build Coastguard Worker lc->buffer_level = lc->bits_off_target;
431*fb1b10abSAndroid Build Coastguard Worker }
432*fb1b10abSAndroid Build Coastguard Worker }
433*fb1b10abSAndroid Build Coastguard Worker
434*fb1b10abSAndroid Build Coastguard Worker cpi_->common.current_video_frame++;
435*fb1b10abSAndroid Build Coastguard Worker cpi_->frames_since_key++;
436*fb1b10abSAndroid Build Coastguard Worker
437*fb1b10abSAndroid Build Coastguard Worker if (cpi_->oxcf.number_of_layers > 1) vp8_save_layer_context(cpi_);
438*fb1b10abSAndroid Build Coastguard Worker vpx_clear_system_state();
439*fb1b10abSAndroid Build Coastguard Worker }
440*fb1b10abSAndroid Build Coastguard Worker } // namespace libvpx
441