• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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