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"