blob: 8d5edcd3392cc61a17ba1f70cd3725f4d0e783b1 [file] [log] [blame]
 /* * 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. */ #include #include #include "av1/encoder/cost.h" #include "av1/encoder/tpl_model.h" #include "third_party/googletest/src/googletest/include/gtest/gtest.h" namespace { double laplace_prob(double q_step, double b, double zero_bin_ratio, int qcoeff) { int abs_qcoeff = abs(qcoeff); double z0 = fmax(exp(-zero_bin_ratio / 2 * q_step / b), TPL_EPSILON); if (abs_qcoeff == 0) { double p0 = 1 - z0; return p0; } else { assert(abs_qcoeff > 0); double z = fmax(exp(-q_step / b), TPL_EPSILON); double p = z0 / 2 * (1 - z) * pow(z, abs_qcoeff - 1); return p; } } TEST(TplModelTest, TransformCoeffEntropyTest1) { // Check the consistency between av1_estimate_coeff_entropy() and // laplace_prob() double b = 1; double q_step = 1; double zero_bin_ratio = 2; for (int qcoeff = -256; qcoeff < 256; ++qcoeff) { double rate = av1_estimate_coeff_entropy(q_step, b, zero_bin_ratio, qcoeff); double prob = laplace_prob(q_step, b, zero_bin_ratio, qcoeff); double ref_rate = -log2(prob); EXPECT_DOUBLE_EQ(rate, ref_rate); } } TEST(TplModelTest, TransformCoeffEntropyTest2) { // Check the consistency between av1_estimate_coeff_entropy(), laplace_prob() // and av1_laplace_entropy() double b = 1; double q_step = 1; double zero_bin_ratio = 2; double est_expected_rate = 0; for (int qcoeff = -20; qcoeff < 20; ++qcoeff) { double rate = av1_estimate_coeff_entropy(q_step, b, zero_bin_ratio, qcoeff); double prob = laplace_prob(q_step, b, zero_bin_ratio, qcoeff); est_expected_rate += prob * rate; } double expected_rate = av1_laplace_entropy(q_step, b, zero_bin_ratio); EXPECT_NEAR(expected_rate, est_expected_rate, 0.001); } 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, DeltaRateCostReference) { const int64_t scale = TPL_DEP_COST_SCALE_LOG2 + AV1_PROB_COST_SHIFT; std::vector srcrf_dist_arr = { 256, 257, 312 }; std::vector recrf_dist_arr = { 512, 288, 620 }; std::vector delta_rate_arr = { 10, 278, 100 }; for (size_t t = 0; t < srcrf_dist_arr.size(); ++t) { int64_t srcrf_dist = srcrf_dist_arr[t]; int64_t recrf_dist = recrf_dist_arr[t]; int64_t delta_rate = delta_rate_arr[t]; int64_t scaled_delta_rate = delta_rate << scale; int pixel_count = 256; int64_t rate_cost = av1_delta_rate_cost(scaled_delta_rate, recrf_dist, srcrf_dist, pixel_count); rate_cost >>= scale; double src_rec_ratio = (double)srcrf_dist / recrf_dist; double ref_rate_cost = ref_delta_rate_cost(delta_rate, src_rec_ratio, pixel_count); EXPECT_NEAR((double)rate_cost, ref_rate_cost, 1); } } 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); } } // namespace