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