tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ratectrl_rtc.cc (18783B)


      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 
     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 
     69 AomAV1RateControlRtcConfig::AomAV1RateControlRtcConfig() {
     70  AomAV1RateControlRtcConfigInitDefault(this);
     71 }
     72 
     73 namespace aom {
     74 
     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 
    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 
    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 
    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 
    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 
    350 int AV1RateControlRTC::GetQP() const {
    351  return cpi_->common.quant_params.base_qindex;
    352 }
    353 
    354 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 
    364 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 
    373 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 
    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 
    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 
    412 void av1_ratecontrol_rtc_destroy(AomAV1RateControlRTC *controller) {
    413  delete reinterpret_cast<aom::AV1RateControlRTC *>(controller);
    414 }
    415 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    473 void av1_ratecontrol_rtc_init_ratecontrol_config(
    474    AomAV1RateControlRtcConfig *config) {
    475  AomAV1RateControlRtcConfigInitDefault(config);
    476 }
    477 
    478 }  // extern "C"