tor-browser

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

tpl_model_test.cc (18617B)


      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 <cstdlib>
     13 #include <memory>
     14 #include <new>
     15 #include <vector>
     16 
     17 #include "av1/encoder/cost.h"
     18 #include "av1/encoder/tpl_model.h"
     19 #include "av1/encoder/encoder.h"
     20 #include "gtest/gtest.h"
     21 
     22 namespace {
     23 
     24 #if CONFIG_BITRATE_ACCURACY
     25 constexpr double epsilon = 0.0000001;
     26 #endif
     27 
     28 double laplace_prob(double q_step, double b, double zero_bin_ratio,
     29                    int qcoeff) {
     30  int abs_qcoeff = abs(qcoeff);
     31  double z0 = fmax(exp(-zero_bin_ratio / 2 * q_step / b), TPL_EPSILON);
     32  if (abs_qcoeff == 0) {
     33    double p0 = 1 - z0;
     34    return p0;
     35  } else {
     36    assert(abs_qcoeff > 0);
     37    double z = fmax(exp(-q_step / b), TPL_EPSILON);
     38    double p = z0 / 2 * (1 - z) * pow(z, abs_qcoeff - 1);
     39    return p;
     40  }
     41 }
     42 TEST(TplModelTest, ExponentialEntropyBoundaryTest1) {
     43  double b = 0;
     44  double q_step = 1;
     45  double entropy = av1_exponential_entropy(q_step, b);
     46  EXPECT_NEAR(entropy, 0, 0.00001);
     47 }
     48 
     49 TEST(TplModelTest, TransformCoeffEntropyTest1) {
     50  // Check the consistency between av1_estimate_coeff_entropy() and
     51  // laplace_prob()
     52  double b = 1;
     53  double q_step = 1;
     54  double zero_bin_ratio = 2;
     55  for (int qcoeff = -256; qcoeff < 256; ++qcoeff) {
     56    double rate = av1_estimate_coeff_entropy(q_step, b, zero_bin_ratio, qcoeff);
     57    double prob = laplace_prob(q_step, b, zero_bin_ratio, qcoeff);
     58    double ref_rate = -log2(prob);
     59    EXPECT_DOUBLE_EQ(rate, ref_rate);
     60  }
     61 }
     62 
     63 TEST(TplModelTest, TransformCoeffEntropyTest2) {
     64  // Check the consistency between av1_estimate_coeff_entropy(), laplace_prob()
     65  // and av1_laplace_entropy()
     66  double b = 1;
     67  double q_step = 1;
     68  double zero_bin_ratio = 2;
     69  double est_expected_rate = 0;
     70  for (int qcoeff = -20; qcoeff < 20; ++qcoeff) {
     71    double rate = av1_estimate_coeff_entropy(q_step, b, zero_bin_ratio, qcoeff);
     72    double prob = laplace_prob(q_step, b, zero_bin_ratio, qcoeff);
     73    est_expected_rate += prob * rate;
     74  }
     75  double expected_rate = av1_laplace_entropy(q_step, b, zero_bin_ratio);
     76  EXPECT_NEAR(expected_rate, est_expected_rate, 0.001);
     77 }
     78 
     79 TEST(TplModelTest, InitTplStats1) {
     80  // We use heap allocation instead of stack allocation here to avoid
     81  // -Wstack-usage warning.
     82  std::unique_ptr<TplParams> tpl_data(new (std::nothrow) TplParams);
     83  ASSERT_NE(tpl_data, nullptr);
     84  av1_zero(*tpl_data);
     85  tpl_data->ready = 1;
     86  EXPECT_EQ(sizeof(tpl_data->tpl_stats_buffer),
     87            MAX_LENGTH_TPL_FRAME_STATS * sizeof(tpl_data->tpl_stats_buffer[0]));
     88  for (int i = 0; i < MAX_LENGTH_TPL_FRAME_STATS; ++i) {
     89    // Set it to a random non-zero number
     90    tpl_data->tpl_stats_buffer[i].is_valid = i + 1;
     91  }
     92  av1_init_tpl_stats(tpl_data.get());
     93  EXPECT_EQ(tpl_data->ready, 0);
     94  for (int i = 0; i < MAX_LENGTH_TPL_FRAME_STATS; ++i) {
     95    EXPECT_EQ(tpl_data->tpl_stats_buffer[i].is_valid, 0);
     96  }
     97 }
     98 
     99 TEST(TplModelTest, DeltaRateCostZeroFlow) {
    100  // When srcrf_dist equal to recrf_dist, av1_delta_rate_cost should return 0
    101  int64_t srcrf_dist = 256;
    102  int64_t recrf_dist = 256;
    103  int64_t delta_rate = 512;
    104  int pixel_num = 256;
    105  int64_t rate_cost =
    106      av1_delta_rate_cost(delta_rate, recrf_dist, srcrf_dist, pixel_num);
    107  EXPECT_EQ(rate_cost, 0);
    108 }
    109 
    110 // a reference function of av1_delta_rate_cost() with delta_rate using bit as
    111 // basic unit
    112 double ref_delta_rate_cost(int64_t delta_rate, double src_rec_ratio,
    113                           int pixel_count) {
    114  assert(src_rec_ratio <= 1 && src_rec_ratio >= 0);
    115  double bits_per_pixel = (double)delta_rate / pixel_count;
    116  double p = pow(2, bits_per_pixel);
    117  double flow_rate_per_pixel =
    118      sqrt(p * p / (src_rec_ratio * p * p + (1 - src_rec_ratio)));
    119  double rate_cost = pixel_count * log2(flow_rate_per_pixel);
    120  return rate_cost;
    121 }
    122 
    123 TEST(TplModelTest, DeltaRateCostReference) {
    124  const int64_t scale = TPL_DEP_COST_SCALE_LOG2 + AV1_PROB_COST_SHIFT;
    125  std::vector<int64_t> srcrf_dist_arr = { 256, 257, 312 };
    126  std::vector<int64_t> recrf_dist_arr = { 512, 288, 620 };
    127  std::vector<int64_t> delta_rate_arr = { 10, 278, 100 };
    128  for (size_t t = 0; t < srcrf_dist_arr.size(); ++t) {
    129    int64_t srcrf_dist = srcrf_dist_arr[t];
    130    int64_t recrf_dist = recrf_dist_arr[t];
    131    int64_t delta_rate = delta_rate_arr[t];
    132    int64_t scaled_delta_rate = delta_rate << scale;
    133    int pixel_count = 256;
    134    int64_t rate_cost = av1_delta_rate_cost(scaled_delta_rate, recrf_dist,
    135                                            srcrf_dist, pixel_count);
    136    rate_cost >>= scale;
    137    double src_rec_ratio = (double)srcrf_dist / recrf_dist;
    138    double ref_rate_cost =
    139        ref_delta_rate_cost(delta_rate, src_rec_ratio, pixel_count);
    140    EXPECT_NEAR((double)rate_cost, ref_rate_cost, 1);
    141  }
    142 }
    143 
    144 TEST(TplModelTest, GetOverlapAreaHasOverlap) {
    145  // The block a's area is [10, 17) x [18, 24).
    146  // The block b's area is [8, 15) x [17, 23).
    147  // The overlapping area between block a and block b is [10, 15) x [18, 23).
    148  // Therefore, the size of the area is (15 - 10) * (23 - 18) = 25.
    149  int row_a = 10;
    150  int col_a = 18;
    151  int row_b = 8;
    152  int col_b = 17;
    153  int height = 7;
    154  int width = 6;
    155  int overlap_area =
    156      av1_get_overlap_area(row_a, col_a, row_b, col_b, width, height);
    157  EXPECT_EQ(overlap_area, 25);
    158 }
    159 
    160 TEST(TplModelTest, GetOverlapAreaNoOverlap) {
    161  // The block a's area is [10, 14) x [18, 22).
    162  // The block b's area is [5, 9) x [5, 9).
    163  // Threre is no overlapping area between block a and block b.
    164  // Therefore, the return value should be zero.
    165  int row_a = 10;
    166  int col_a = 18;
    167  int row_b = 5;
    168  int col_b = 5;
    169  int height = 4;
    170  int width = 4;
    171  int overlap_area =
    172      av1_get_overlap_area(row_a, col_a, row_b, col_b, width, height);
    173  EXPECT_EQ(overlap_area, 0);
    174 }
    175 
    176 TEST(TplModelTest, GetQIndexFromQstepRatio) {
    177  const aom_bit_depth_t bit_depth = AOM_BITS_8;
    178  // When qstep_ratio is 1, the output q_index should be equal to leaf_qindex.
    179  double qstep_ratio = 1.0;
    180  for (int leaf_qindex = 1; leaf_qindex <= 255; ++leaf_qindex) {
    181    const int q_index =
    182        av1_get_q_index_from_qstep_ratio(leaf_qindex, qstep_ratio, bit_depth);
    183    EXPECT_EQ(q_index, leaf_qindex);
    184  }
    185 
    186  // When qstep_ratio is very low, the output q_index should be 1.
    187  qstep_ratio = 0.0001;
    188  for (int leaf_qindex = 1; leaf_qindex <= 255; ++leaf_qindex) {
    189    const int q_index =
    190        av1_get_q_index_from_qstep_ratio(leaf_qindex, qstep_ratio, bit_depth);
    191    EXPECT_EQ(q_index, 0);
    192  }
    193 }
    194 
    195 TEST(TplModelTest, TxfmStatsInitTest) {
    196  TplTxfmStats tpl_txfm_stats;
    197  av1_init_tpl_txfm_stats(&tpl_txfm_stats);
    198  EXPECT_EQ(tpl_txfm_stats.coeff_num, 256);
    199  EXPECT_EQ(tpl_txfm_stats.txfm_block_count, 0);
    200  for (int i = 0; i < tpl_txfm_stats.coeff_num; ++i) {
    201    EXPECT_DOUBLE_EQ(tpl_txfm_stats.abs_coeff_sum[i], 0);
    202  }
    203 }
    204 
    205 #if CONFIG_BITRATE_ACCURACY
    206 TEST(TplModelTest, TxfmStatsAccumulateTest) {
    207  TplTxfmStats sub_stats;
    208  av1_init_tpl_txfm_stats(&sub_stats);
    209  sub_stats.txfm_block_count = 17;
    210  for (int i = 0; i < sub_stats.coeff_num; ++i) {
    211    sub_stats.abs_coeff_sum[i] = i;
    212  }
    213 
    214  TplTxfmStats accumulated_stats;
    215  av1_init_tpl_txfm_stats(&accumulated_stats);
    216  accumulated_stats.txfm_block_count = 13;
    217  for (int i = 0; i < accumulated_stats.coeff_num; ++i) {
    218    accumulated_stats.abs_coeff_sum[i] = 5 * i;
    219  }
    220 
    221  av1_accumulate_tpl_txfm_stats(&sub_stats, &accumulated_stats);
    222  EXPECT_DOUBLE_EQ(accumulated_stats.txfm_block_count, 30);
    223  for (int i = 0; i < accumulated_stats.coeff_num; ++i) {
    224    EXPECT_DOUBLE_EQ(accumulated_stats.abs_coeff_sum[i], 6 * i);
    225  }
    226 }
    227 
    228 TEST(TplModelTest, TxfmStatsRecordTest) {
    229  TplTxfmStats stats1;
    230  TplTxfmStats stats2;
    231  av1_init_tpl_txfm_stats(&stats1);
    232  av1_init_tpl_txfm_stats(&stats2);
    233 
    234  tran_low_t coeff[256];
    235  for (int i = 0; i < 256; ++i) {
    236    coeff[i] = i;
    237  }
    238  av1_record_tpl_txfm_block(&stats1, coeff);
    239  EXPECT_EQ(stats1.txfm_block_count, 1);
    240 
    241  // we record the same transform block twice for testing purpose
    242  av1_record_tpl_txfm_block(&stats2, coeff);
    243  av1_record_tpl_txfm_block(&stats2, coeff);
    244  EXPECT_EQ(stats2.txfm_block_count, 2);
    245 
    246  EXPECT_EQ(stats1.coeff_num, 256);
    247  EXPECT_EQ(stats2.coeff_num, 256);
    248  for (int i = 0; i < 256; ++i) {
    249    EXPECT_DOUBLE_EQ(stats2.abs_coeff_sum[i], 2 * stats1.abs_coeff_sum[i]);
    250  }
    251 }
    252 #endif  // CONFIG_BITRATE_ACCURACY
    253 
    254 TEST(TplModelTest, ComputeMVDifferenceTest) {
    255  TplDepFrame tpl_frame_small;
    256  tpl_frame_small.is_valid = true;
    257  tpl_frame_small.mi_rows = 4;
    258  tpl_frame_small.mi_cols = 4;
    259  tpl_frame_small.stride = 1;
    260  uint8_t right_shift_small = 1;
    261  int step_small = 1 << right_shift_small;
    262 
    263  // Test values for motion vectors.
    264  int mv_vals_small[4] = { 1, 2, 3, 4 };
    265  int index = 0;
    266 
    267  // 4x4 blocks means we need to allocate a 4 size array.
    268  // According to av1_tpl_ptr_pos:
    269  // (row >> right_shift) * stride + (col >> right_shift)
    270  // (4 >> 1) * 1 + (4 >> 1) = 4
    271  TplDepStats stats_buf_small[4];
    272  tpl_frame_small.tpl_stats_ptr = stats_buf_small;
    273 
    274  for (int row = 0; row < tpl_frame_small.mi_rows; row += step_small) {
    275    for (int col = 0; col < tpl_frame_small.mi_cols; col += step_small) {
    276      TplDepStats tpl_stats;
    277      tpl_stats.ref_frame_index[0] = 0;
    278      int_mv mv;
    279      mv.as_mv.row = mv_vals_small[index];
    280      mv.as_mv.col = mv_vals_small[index];
    281      index++;
    282      tpl_stats.mv[0] = mv;
    283      tpl_frame_small.tpl_stats_ptr[av1_tpl_ptr_pos(
    284          row, col, tpl_frame_small.stride, right_shift_small)] = tpl_stats;
    285    }
    286  }
    287 
    288  int_mv result_mv =
    289      av1_compute_mv_difference(&tpl_frame_small, 1, 1, step_small,
    290                                tpl_frame_small.stride, right_shift_small);
    291 
    292  // Expect the result to be exactly equal to 1 because this is the difference
    293  // between neighboring motion vectors in this instance.
    294  EXPECT_EQ(result_mv.as_mv.row, 1);
    295  EXPECT_EQ(result_mv.as_mv.col, 1);
    296 }
    297 
    298 TEST(TplModelTest, ComputeMVBitsTest) {
    299  TplDepFrame tpl_frame;
    300  tpl_frame.is_valid = true;
    301  tpl_frame.mi_rows = 16;
    302  tpl_frame.mi_cols = 16;
    303  tpl_frame.stride = 24;
    304  uint8_t right_shift = 2;
    305  int step = 1 << right_shift;
    306  // Test values for motion vectors.
    307  int mv_vals_ordered[16] = { 1, 2,  3,  4,  5,  6,  7,  8,
    308                              9, 10, 11, 12, 13, 14, 15, 16 };
    309  int mv_vals[16] = { 1, 16, 2, 15, 3, 14, 4, 13, 5, 12, 6, 11, 7, 10, 8, 9 };
    310  int index = 0;
    311 
    312  // 16x16 blocks means we need to allocate a 100 size array.
    313  // According to av1_tpl_ptr_pos:
    314  // (row >> right_shift) * stride + (col >> right_shift)
    315  // (16 >> 2) * 24 + (16 >> 2) = 100
    316  TplDepStats stats_buf[100];
    317  tpl_frame.tpl_stats_ptr = stats_buf;
    318 
    319  for (int row = 0; row < tpl_frame.mi_rows; row += step) {
    320    for (int col = 0; col < tpl_frame.mi_cols; col += step) {
    321      TplDepStats tpl_stats;
    322      tpl_stats.ref_frame_index[0] = 0;
    323      int_mv mv;
    324      mv.as_mv.row = mv_vals_ordered[index];
    325      mv.as_mv.col = mv_vals_ordered[index];
    326      index++;
    327      tpl_stats.mv[0] = mv;
    328      tpl_frame.tpl_stats_ptr[av1_tpl_ptr_pos(row, col, tpl_frame.stride,
    329                                              right_shift)] = tpl_stats;
    330    }
    331  }
    332 
    333  double result = av1_tpl_compute_frame_mv_entropy(&tpl_frame, right_shift);
    334 
    335  // Expect the result to be low because the motion vectors are ordered.
    336  // The estimation algorithm takes this into account and reduces the cost.
    337  EXPECT_NEAR(result, 20, 5);
    338 
    339  index = 0;
    340  for (int row = 0; row < tpl_frame.mi_rows; row += step) {
    341    for (int col = 0; col < tpl_frame.mi_cols; col += step) {
    342      TplDepStats tpl_stats;
    343      tpl_stats.ref_frame_index[0] = 0;
    344      int_mv mv;
    345      mv.as_mv.row = mv_vals[index];
    346      mv.as_mv.col = mv_vals[index];
    347      index++;
    348      tpl_stats.mv[0] = mv;
    349      tpl_frame.tpl_stats_ptr[av1_tpl_ptr_pos(row, col, tpl_frame.stride,
    350                                              right_shift)] = tpl_stats;
    351    }
    352  }
    353 
    354  result = av1_tpl_compute_frame_mv_entropy(&tpl_frame, right_shift);
    355 
    356  // Expect the result to be higher because the vectors are not ordered.
    357  // Neighboring vectors will have different values, increasing the cost.
    358  EXPECT_NEAR(result, 70, 5);
    359 }
    360 #if CONFIG_BITRATE_ACCURACY
    361 
    362 TEST(TplModelTest, VbrRcInfoSetGopBitBudget) {
    363  VBR_RATECTRL_INFO vbr_rc_info;
    364  const double total_bit_budget = 2000;
    365  const int show_frame_count = 8;
    366  const int gop_show_frame_count = 4;
    367  av1_vbr_rc_init(&vbr_rc_info, total_bit_budget, show_frame_count);
    368  av1_vbr_rc_set_gop_bit_budget(&vbr_rc_info, gop_show_frame_count);
    369  EXPECT_NEAR(vbr_rc_info.gop_bit_budget, 1000, epsilon);
    370 }
    371 
    372 void init_toy_gf_group(GF_GROUP *gf_group) {
    373  av1_zero(*gf_group);
    374  gf_group->size = 4;
    375  const FRAME_UPDATE_TYPE update_type[4] = { KF_UPDATE, ARF_UPDATE,
    376                                             INTNL_ARF_UPDATE, LF_UPDATE };
    377  for (int i = 0; i < gf_group->size; ++i) {
    378    gf_group->update_type[i] = update_type[i];
    379  }
    380 }
    381 
    382 void init_toy_vbr_rc_info(VBR_RATECTRL_INFO *vbr_rc_info, int gop_size) {
    383  int total_bit_budget = 2000;
    384  int show_frame_count = 8;
    385  av1_vbr_rc_init(vbr_rc_info, total_bit_budget, show_frame_count);
    386 
    387  for (int i = 0; i < gop_size; ++i) {
    388    vbr_rc_info->qstep_ratio_list[i] = 1;
    389  }
    390 }
    391 
    392 void init_toy_tpl_txfm_stats(std::vector<TplTxfmStats> *stats_list) {
    393  for (size_t i = 0; i < stats_list->size(); i++) {
    394    TplTxfmStats *txfm_stats = &stats_list->at(i);
    395    av1_init_tpl_txfm_stats(txfm_stats);
    396    txfm_stats->txfm_block_count = 8;
    397    for (int j = 0; j < txfm_stats->coeff_num; j++) {
    398      txfm_stats->abs_coeff_sum[j] = 1000 + j;
    399    }
    400    av1_tpl_txfm_stats_update_abs_coeff_mean(txfm_stats);
    401  }
    402 }
    403 
    404 /*
    405 * Helper method to brute-force search for the closest q_index
    406 * that achieves the specified bit budget.
    407 */
    408 int find_gop_q_iterative(double bit_budget, aom_bit_depth_t bit_depth,
    409                         const double *update_type_scale_factors,
    410                         int frame_count,
    411                         const FRAME_UPDATE_TYPE *update_type_list,
    412                         const double *qstep_ratio_list,
    413                         const TplTxfmStats *stats_list, int *q_index_list,
    414                         double *estimated_bitrate_byframe) {
    415  int best_q = 255;
    416  double curr_estimate = av1_vbr_rc_info_estimate_gop_bitrate(
    417      best_q, bit_depth, update_type_scale_factors, frame_count,
    418      update_type_list, qstep_ratio_list, stats_list, q_index_list,
    419      estimated_bitrate_byframe);
    420  double min_bits_diff = fabs(curr_estimate - bit_budget);
    421  // Start at q = 254 because we already have an estimate for q = 255.
    422  for (int q = 254; q >= 0; q--) {
    423    curr_estimate = av1_vbr_rc_info_estimate_gop_bitrate(
    424        q, bit_depth, update_type_scale_factors, frame_count, update_type_list,
    425        qstep_ratio_list, stats_list, q_index_list, estimated_bitrate_byframe);
    426    double bits_diff = fabs(curr_estimate - bit_budget);
    427    if (bits_diff <= min_bits_diff) {
    428      min_bits_diff = bits_diff;
    429      best_q = q;
    430    }
    431  }
    432  return best_q;
    433 }
    434 
    435 TEST(TplModelTest, EstimateFrameRateTest) {
    436  GF_GROUP gf_group;
    437  init_toy_gf_group(&gf_group);
    438 
    439  VBR_RATECTRL_INFO vbr_rc_info;
    440  init_toy_vbr_rc_info(&vbr_rc_info, gf_group.size);
    441 
    442  std::vector<TplTxfmStats> stats_list(gf_group.size);
    443  init_toy_tpl_txfm_stats(&stats_list);
    444 
    445  std::vector<double> est_bitrate_list(gf_group.size);
    446  init_toy_tpl_txfm_stats(&stats_list);
    447  const aom_bit_depth_t bit_depth = AOM_BITS_8;
    448 
    449  const int q = 125;
    450 
    451  // Case1: all scale factors are 0
    452  double scale_factors[FRAME_UPDATE_TYPES] = { 0 };
    453  double estimate = av1_vbr_rc_info_estimate_gop_bitrate(
    454      q, bit_depth, scale_factors, gf_group.size, gf_group.update_type,
    455      vbr_rc_info.qstep_ratio_list, stats_list.data(), vbr_rc_info.q_index_list,
    456      est_bitrate_list.data());
    457  EXPECT_NEAR(estimate, 0, epsilon);
    458 
    459  // Case2: all scale factors are 1
    460  for (int i = 0; i < FRAME_UPDATE_TYPES; i++) {
    461    scale_factors[i] = 1;
    462  }
    463  estimate = av1_vbr_rc_info_estimate_gop_bitrate(
    464      q, bit_depth, scale_factors, gf_group.size, gf_group.update_type,
    465      vbr_rc_info.qstep_ratio_list, stats_list.data(), vbr_rc_info.q_index_list,
    466      est_bitrate_list.data());
    467  double ref_estimate = 0;
    468  for (int i = 0; i < gf_group.size; i++) {
    469    ref_estimate += est_bitrate_list[i];
    470  }
    471  EXPECT_NEAR(estimate, ref_estimate, epsilon);
    472 
    473  // Case3: Key frame scale factor is 0 and others are 1
    474  for (int i = 0; i < FRAME_UPDATE_TYPES; i++) {
    475    if (i == KF_UPDATE) {
    476      scale_factors[i] = 0;
    477    } else {
    478      scale_factors[i] = 1;
    479    }
    480  }
    481  estimate = av1_vbr_rc_info_estimate_gop_bitrate(
    482      q, bit_depth, scale_factors, gf_group.size, gf_group.update_type,
    483      vbr_rc_info.qstep_ratio_list, stats_list.data(), vbr_rc_info.q_index_list,
    484      est_bitrate_list.data());
    485  ref_estimate = 0;
    486  for (int i = 0; i < gf_group.size; i++) {
    487    if (gf_group.update_type[i] != KF_UPDATE) {
    488      ref_estimate += est_bitrate_list[i];
    489    }
    490  }
    491  EXPECT_NEAR(estimate, ref_estimate, epsilon);
    492 }
    493 
    494 TEST(TplModelTest, VbrRcInfoEstimateBaseQTest) {
    495  GF_GROUP gf_group;
    496  init_toy_gf_group(&gf_group);
    497 
    498  VBR_RATECTRL_INFO vbr_rc_info;
    499  init_toy_vbr_rc_info(&vbr_rc_info, gf_group.size);
    500 
    501  std::vector<TplTxfmStats> stats_list(gf_group.size);
    502  init_toy_tpl_txfm_stats(&stats_list);
    503  const aom_bit_depth_t bit_depth = AOM_BITS_8;
    504 
    505  // Test multiple bit budgets.
    506  const std::vector<double> bit_budgets = { 0,     2470,  19200,  30750,
    507                                            41315, 65017, DBL_MAX };
    508 
    509  for (double bit_budget : bit_budgets) {
    510    // Binary search method to find the optimal q.
    511    const int base_q = av1_vbr_rc_info_estimate_base_q(
    512        bit_budget, bit_depth, vbr_rc_info.scale_factors, gf_group.size,
    513        gf_group.update_type, vbr_rc_info.qstep_ratio_list, stats_list.data(),
    514        vbr_rc_info.q_index_list, nullptr);
    515    const int ref_base_q = find_gop_q_iterative(
    516        bit_budget, bit_depth, vbr_rc_info.scale_factors, gf_group.size,
    517        gf_group.update_type, vbr_rc_info.qstep_ratio_list, stats_list.data(),
    518        vbr_rc_info.q_index_list, nullptr);
    519    if (bit_budget == 0) {
    520      EXPECT_EQ(base_q, 255);
    521    } else if (bit_budget == DBL_MAX) {
    522      EXPECT_EQ(base_q, 0);
    523    }
    524    EXPECT_EQ(base_q, ref_base_q);
    525  }
    526 }
    527 #endif  // CONFIG_BITRATE_ACCURACY
    528 
    529 }  // namespace