/* * Copyright (c) 2021, Alliance for Open Media. All rights reserved. * * This source code is subject to the terms of the BSD 2 Clause License and * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License * was not distributed with this source code in the LICENSE file, you can * obtain it at www.aomedia.org/license/software. If the Alliance for Open * Media Patent License 1.0 was not distributed with this source code in the * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
*/
TEST(TplModelTest, InitTplStats1) { // We use heap allocation instead of stack allocation here to avoid // -Wstack-usage warning.
std::unique_ptr<TplParams> tpl_data(new (std::nothrow) TplParams);
ASSERT_NE(tpl_data, nullptr);
av1_zero(*tpl_data);
tpl_data->ready = 1;
EXPECT_EQ(sizeof(tpl_data->tpl_stats_buffer),
MAX_LENGTH_TPL_FRAME_STATS * sizeof(tpl_data->tpl_stats_buffer[0])); for (int i = 0; i < MAX_LENGTH_TPL_FRAME_STATS; ++i) { // Set it to a random non-zero number
tpl_data->tpl_stats_buffer[i].is_valid = i + 1;
}
av1_init_tpl_stats(tpl_data.get());
EXPECT_EQ(tpl_data->ready, 0); for (int i = 0; i < MAX_LENGTH_TPL_FRAME_STATS; ++i) {
EXPECT_EQ(tpl_data->tpl_stats_buffer[i].is_valid, 0);
}
}
TEST(TplModelTest, DeltaRateCostZeroFlow) { // When srcrf_dist equal to recrf_dist, av1_delta_rate_cost should return 0
int64_t srcrf_dist = 256;
int64_t recrf_dist = 256;
int64_t delta_rate = 512; int pixel_num = 256;
int64_t rate_cost =
av1_delta_rate_cost(delta_rate, recrf_dist, srcrf_dist, pixel_num);
EXPECT_EQ(rate_cost, 0);
}
// a reference function of av1_delta_rate_cost() with delta_rate using bit as // basic unit double ref_delta_rate_cost(int64_t delta_rate, double src_rec_ratio, int pixel_count) {
assert(src_rec_ratio <= 1 && src_rec_ratio >= 0); double bits_per_pixel = (double)delta_rate / pixel_count; double p = pow(2, bits_per_pixel); double flow_rate_per_pixel =
sqrt(p * p / (src_rec_ratio * p * p + (1 - src_rec_ratio))); double rate_cost = pixel_count * log2(flow_rate_per_pixel); return rate_cost;
}
TEST(TplModelTest, GetOverlapAreaHasOverlap) { // The block a's area is [10, 17) x [18, 24). // The block b's area is [8, 15) x [17, 23). // The overlapping area between block a and block b is [10, 15) x [18, 23). // Therefore, the size of the area is (15 - 10) * (23 - 18) = 25. int row_a = 10; int col_a = 18; int row_b = 8; int col_b = 17; int height = 7; int width = 6; int overlap_area =
av1_get_overlap_area(row_a, col_a, row_b, col_b, width, height);
EXPECT_EQ(overlap_area, 25);
}
TEST(TplModelTest, GetOverlapAreaNoOverlap) { // The block a's area is [10, 14) x [18, 22). // The block b's area is [5, 9) x [5, 9). // Threre is no overlapping area between block a and block b. // Therefore, the return value should be zero. int row_a = 10; int col_a = 18; int row_b = 5; int col_b = 5; int height = 4; int width = 4; int overlap_area =
av1_get_overlap_area(row_a, col_a, row_b, col_b, width, height);
EXPECT_EQ(overlap_area, 0);
}
TEST(TplModelTest, GetQIndexFromQstepRatio) { const aom_bit_depth_t bit_depth = AOM_BITS_8; // When qstep_ratio is 1, the output q_index should be equal to leaf_qindex. double qstep_ratio = 1.0; for (int leaf_qindex = 1; leaf_qindex <= 255; ++leaf_qindex) { constint q_index =
av1_get_q_index_from_qstep_ratio(leaf_qindex, qstep_ratio, bit_depth);
EXPECT_EQ(q_index, leaf_qindex);
}
// When qstep_ratio is very low, the output q_index should be 1.
qstep_ratio = 0.0001; for (int leaf_qindex = 1; leaf_qindex <= 255; ++leaf_qindex) { constint q_index =
av1_get_q_index_from_qstep_ratio(leaf_qindex, qstep_ratio, bit_depth);
EXPECT_EQ(q_index, 0);
}
}
TEST(TplModelTest, TxfmStatsInitTest) {
TplTxfmStats tpl_txfm_stats;
av1_init_tpl_txfm_stats(&tpl_txfm_stats);
EXPECT_EQ(tpl_txfm_stats.coeff_num, 256);
EXPECT_EQ(tpl_txfm_stats.txfm_block_count, 0); for (int i = 0; i < tpl_txfm_stats.coeff_num; ++i) {
EXPECT_DOUBLE_EQ(tpl_txfm_stats.abs_coeff_sum[i], 0);
}
}
#if CONFIG_BITRATE_ACCURACY
TEST(TplModelTest, TxfmStatsAccumulateTest) {
TplTxfmStats sub_stats;
av1_init_tpl_txfm_stats(&sub_stats);
sub_stats.txfm_block_count = 17; for (int i = 0; i < sub_stats.coeff_num; ++i) {
sub_stats.abs_coeff_sum[i] = i;
}
TplTxfmStats accumulated_stats;
av1_init_tpl_txfm_stats(&accumulated_stats);
accumulated_stats.txfm_block_count = 13; for (int i = 0; i < accumulated_stats.coeff_num; ++i) {
accumulated_stats.abs_coeff_sum[i] = 5 * i;
}
av1_accumulate_tpl_txfm_stats(&sub_stats, &accumulated_stats);
EXPECT_DOUBLE_EQ(accumulated_stats.txfm_block_count, 30); for (int i = 0; i < accumulated_stats.coeff_num; ++i) {
EXPECT_DOUBLE_EQ(accumulated_stats.abs_coeff_sum[i], 6 * i);
}
}
tran_low_t coeff[256]; for (int i = 0; i < 256; ++i) {
coeff[i] = i;
}
av1_record_tpl_txfm_block(&stats1, coeff);
EXPECT_EQ(stats1.txfm_block_count, 1);
// we record the same transform block twice for testing purpose
av1_record_tpl_txfm_block(&stats2, coeff);
av1_record_tpl_txfm_block(&stats2, coeff);
EXPECT_EQ(stats2.txfm_block_count, 2);
EXPECT_EQ(stats1.coeff_num, 256);
EXPECT_EQ(stats2.coeff_num, 256); for (int i = 0; i < 256; ++i) {
EXPECT_DOUBLE_EQ(stats2.abs_coeff_sum[i], 2 * stats1.abs_coeff_sum[i]);
}
} #endif// CONFIG_BITRATE_ACCURACY
// Expect the result to be exactly equal to 1 because this is the difference // between neighboring motion vectors in this instance.
EXPECT_EQ(result_mv.as_mv.row, 1);
EXPECT_EQ(result_mv.as_mv.col, 1);
}
// 16x16 blocks means we need to allocate a 100 size array. // According to av1_tpl_ptr_pos: // (row >> right_shift) * stride + (col >> right_shift) // (16 >> 2) * 24 + (16 >> 2) = 100
TplDepStats stats_buf[100];
tpl_frame.tpl_stats_ptr = stats_buf;
for (int row = 0; row < tpl_frame.mi_rows; row += step) { for (int col = 0; col < tpl_frame.mi_cols; col += step) {
TplDepStats tpl_stats;
tpl_stats.ref_frame_index[0] = 0;
int_mv mv;
mv.as_mv.row = mv_vals_ordered[index];
mv.as_mv.col = mv_vals_ordered[index];
index++;
tpl_stats.mv[0] = mv;
tpl_frame.tpl_stats_ptr[av1_tpl_ptr_pos(row, col, tpl_frame.stride,
right_shift)] = tpl_stats;
}
}
double result = av1_tpl_compute_frame_mv_entropy(&tpl_frame, right_shift);
// Expect the result to be low because the motion vectors are ordered. // The estimation algorithm takes this into account and reduces the cost.
EXPECT_NEAR(result, 20, 5);
index = 0; for (int row = 0; row < tpl_frame.mi_rows; row += step) { for (int col = 0; col < tpl_frame.mi_cols; col += step) {
TplDepStats tpl_stats;
tpl_stats.ref_frame_index[0] = 0;
int_mv mv;
mv.as_mv.row = mv_vals[index];
mv.as_mv.col = mv_vals[index];
index++;
tpl_stats.mv[0] = mv;
tpl_frame.tpl_stats_ptr[av1_tpl_ptr_pos(row, col, tpl_frame.stride,
right_shift)] = tpl_stats;
}
}
result = av1_tpl_compute_frame_mv_entropy(&tpl_frame, right_shift);
// Expect the result to be higher because the vectors are not ordered. // Neighboring vectors will have different values, increasing the cost.
EXPECT_NEAR(result, 70, 5);
} #if CONFIG_BITRATE_ACCURACY
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.