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