xref: /aosp_15_r20/external/libaom/test/ec_test.cc (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1*77c1e3ccSAndroid Build Coastguard Worker /*
2*77c1e3ccSAndroid Build Coastguard Worker  * Copyright (c) 2017, Alliance for Open Media. All rights reserved.
3*77c1e3ccSAndroid Build Coastguard Worker  *
4*77c1e3ccSAndroid Build Coastguard Worker  * This source code is subject to the terms of the BSD 2 Clause License and
5*77c1e3ccSAndroid Build Coastguard Worker  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6*77c1e3ccSAndroid Build Coastguard Worker  * was not distributed with this source code in the LICENSE file, you can
7*77c1e3ccSAndroid Build Coastguard Worker  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8*77c1e3ccSAndroid Build Coastguard Worker  * Media Patent License 1.0 was not distributed with this source code in the
9*77c1e3ccSAndroid Build Coastguard Worker  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10*77c1e3ccSAndroid Build Coastguard Worker  */
11*77c1e3ccSAndroid Build Coastguard Worker 
12*77c1e3ccSAndroid Build Coastguard Worker #include "gtest/gtest.h"
13*77c1e3ccSAndroid Build Coastguard Worker 
14*77c1e3ccSAndroid Build Coastguard Worker #include <cstdlib>
15*77c1e3ccSAndroid Build Coastguard Worker #include <memory>
16*77c1e3ccSAndroid Build Coastguard Worker #include <new>
17*77c1e3ccSAndroid Build Coastguard Worker 
18*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/entenc.h"
19*77c1e3ccSAndroid Build Coastguard Worker #include "aom_dsp/entdec.h"
20*77c1e3ccSAndroid Build Coastguard Worker 
TEST(EC_TEST,random_ec_test)21*77c1e3ccSAndroid Build Coastguard Worker TEST(EC_TEST, random_ec_test) {
22*77c1e3ccSAndroid Build Coastguard Worker   od_ec_enc enc;
23*77c1e3ccSAndroid Build Coastguard Worker   od_ec_dec dec;
24*77c1e3ccSAndroid Build Coastguard Worker   int sz;
25*77c1e3ccSAndroid Build Coastguard Worker   int i;
26*77c1e3ccSAndroid Build Coastguard Worker   int ret;
27*77c1e3ccSAndroid Build Coastguard Worker   unsigned int seed;
28*77c1e3ccSAndroid Build Coastguard Worker   unsigned char *ptr;
29*77c1e3ccSAndroid Build Coastguard Worker   uint32_t ptr_sz;
30*77c1e3ccSAndroid Build Coastguard Worker   char *seed_str;
31*77c1e3ccSAndroid Build Coastguard Worker   ret = 0;
32*77c1e3ccSAndroid Build Coastguard Worker   seed_str = getenv("EC_TEST_SEED");
33*77c1e3ccSAndroid Build Coastguard Worker   if (seed_str) {
34*77c1e3ccSAndroid Build Coastguard Worker     seed = atoi(seed_str);
35*77c1e3ccSAndroid Build Coastguard Worker   } else {
36*77c1e3ccSAndroid Build Coastguard Worker     seed = 0xdaa1a;
37*77c1e3ccSAndroid Build Coastguard Worker   }
38*77c1e3ccSAndroid Build Coastguard Worker   srand(seed);
39*77c1e3ccSAndroid Build Coastguard Worker   od_ec_enc_init(&enc, 1);
40*77c1e3ccSAndroid Build Coastguard Worker   /*Test compatibility between multiple different encode/decode routines.*/
41*77c1e3ccSAndroid Build Coastguard Worker   for (i = 0; i < 409600; i++) {
42*77c1e3ccSAndroid Build Coastguard Worker     int j;
43*77c1e3ccSAndroid Build Coastguard Worker     sz = rand() / ((RAND_MAX >> (rand() % 9U)) + 1U);
44*77c1e3ccSAndroid Build Coastguard Worker     std::unique_ptr<unsigned[]> fz(new (std::nothrow) unsigned[sz]);
45*77c1e3ccSAndroid Build Coastguard Worker     ASSERT_NE(fz, nullptr);
46*77c1e3ccSAndroid Build Coastguard Worker     std::unique_ptr<unsigned[]> fts(new (std::nothrow) unsigned[sz]);
47*77c1e3ccSAndroid Build Coastguard Worker     ASSERT_NE(fts, nullptr);
48*77c1e3ccSAndroid Build Coastguard Worker     std::unique_ptr<unsigned[]> data(new (std::nothrow) unsigned[sz]);
49*77c1e3ccSAndroid Build Coastguard Worker     ASSERT_NE(data, nullptr);
50*77c1e3ccSAndroid Build Coastguard Worker     std::unique_ptr<unsigned[]> tell(new (std::nothrow) unsigned[sz + 1]);
51*77c1e3ccSAndroid Build Coastguard Worker     ASSERT_NE(tell, nullptr);
52*77c1e3ccSAndroid Build Coastguard Worker     std::unique_ptr<unsigned[]> enc_method(new (std::nothrow) unsigned[sz]);
53*77c1e3ccSAndroid Build Coastguard Worker     ASSERT_NE(enc_method, nullptr);
54*77c1e3ccSAndroid Build Coastguard Worker     od_ec_enc_reset(&enc);
55*77c1e3ccSAndroid Build Coastguard Worker     tell[0] = od_ec_enc_tell_frac(&enc);
56*77c1e3ccSAndroid Build Coastguard Worker     for (j = 0; j < sz; j++) {
57*77c1e3ccSAndroid Build Coastguard Worker       data[j] = rand() / ((RAND_MAX >> 1) + 1);
58*77c1e3ccSAndroid Build Coastguard Worker 
59*77c1e3ccSAndroid Build Coastguard Worker       fts[j] = CDF_PROB_BITS;
60*77c1e3ccSAndroid Build Coastguard Worker       fz[j] = (rand() % (CDF_PROB_TOP - 2)) >> (CDF_PROB_BITS - fts[j]);
61*77c1e3ccSAndroid Build Coastguard Worker       fz[j] = OD_MAXI(fz[j], 1);
62*77c1e3ccSAndroid Build Coastguard Worker       enc_method[j] = 3 + (rand() & 1);
63*77c1e3ccSAndroid Build Coastguard Worker       switch (enc_method[j]) {
64*77c1e3ccSAndroid Build Coastguard Worker         case 3: {
65*77c1e3ccSAndroid Build Coastguard Worker           od_ec_encode_bool_q15(&enc, data[j],
66*77c1e3ccSAndroid Build Coastguard Worker                                 OD_ICDF(fz[j] << (CDF_PROB_BITS - fts[j])));
67*77c1e3ccSAndroid Build Coastguard Worker           break;
68*77c1e3ccSAndroid Build Coastguard Worker         }
69*77c1e3ccSAndroid Build Coastguard Worker         case 4: {
70*77c1e3ccSAndroid Build Coastguard Worker           uint16_t cdf[2];
71*77c1e3ccSAndroid Build Coastguard Worker           cdf[0] = OD_ICDF(fz[j]);
72*77c1e3ccSAndroid Build Coastguard Worker           cdf[1] = OD_ICDF(1U << fts[j]);
73*77c1e3ccSAndroid Build Coastguard Worker           od_ec_encode_cdf_q15(&enc, data[j], cdf, 2);
74*77c1e3ccSAndroid Build Coastguard Worker           break;
75*77c1e3ccSAndroid Build Coastguard Worker         }
76*77c1e3ccSAndroid Build Coastguard Worker       }
77*77c1e3ccSAndroid Build Coastguard Worker 
78*77c1e3ccSAndroid Build Coastguard Worker       tell[j + 1] = od_ec_enc_tell_frac(&enc);
79*77c1e3ccSAndroid Build Coastguard Worker     }
80*77c1e3ccSAndroid Build Coastguard Worker     ptr = od_ec_enc_done(&enc, &ptr_sz);
81*77c1e3ccSAndroid Build Coastguard Worker     ASSERT_NE(ptr, nullptr);
82*77c1e3ccSAndroid Build Coastguard Worker     EXPECT_GE(((od_ec_enc_tell(&enc) + 7U) >> 3), ptr_sz)
83*77c1e3ccSAndroid Build Coastguard Worker         << "od_ec_enc_tell() lied: "
84*77c1e3ccSAndroid Build Coastguard Worker            "there's "
85*77c1e3ccSAndroid Build Coastguard Worker         << ptr_sz << " bytes instead of " << ((od_ec_enc_tell(&enc) + 7) >> 3)
86*77c1e3ccSAndroid Build Coastguard Worker         << " (Random seed: " << seed << ")\n";
87*77c1e3ccSAndroid Build Coastguard Worker     od_ec_dec_init(&dec, ptr, ptr_sz);
88*77c1e3ccSAndroid Build Coastguard Worker     EXPECT_EQ(od_ec_dec_tell_frac(&dec), tell[0])
89*77c1e3ccSAndroid Build Coastguard Worker         << "od_ec_dec_tell() mismatch between encoder and decoder "
90*77c1e3ccSAndroid Build Coastguard Worker            "at symbol 0: "
91*77c1e3ccSAndroid Build Coastguard Worker         << (unsigned)od_ec_dec_tell_frac(&dec) << " instead of " << tell[0]
92*77c1e3ccSAndroid Build Coastguard Worker         << " (Random seed: " << seed << ").\n";
93*77c1e3ccSAndroid Build Coastguard Worker     for (j = 0; j < sz; j++) {
94*77c1e3ccSAndroid Build Coastguard Worker       int dec_method;
95*77c1e3ccSAndroid Build Coastguard Worker       unsigned int sym = data[j] + 1;  // Initialize sym to an invalid value.
96*77c1e3ccSAndroid Build Coastguard Worker 
97*77c1e3ccSAndroid Build Coastguard Worker       dec_method = 3 + (rand() & 1);
98*77c1e3ccSAndroid Build Coastguard Worker 
99*77c1e3ccSAndroid Build Coastguard Worker       switch (dec_method) {
100*77c1e3ccSAndroid Build Coastguard Worker         case 3: {
101*77c1e3ccSAndroid Build Coastguard Worker           sym = od_ec_decode_bool_q15(
102*77c1e3ccSAndroid Build Coastguard Worker               &dec, OD_ICDF(fz[j] << (CDF_PROB_BITS - fts[j])));
103*77c1e3ccSAndroid Build Coastguard Worker           break;
104*77c1e3ccSAndroid Build Coastguard Worker         }
105*77c1e3ccSAndroid Build Coastguard Worker         case 4: {
106*77c1e3ccSAndroid Build Coastguard Worker           uint16_t cdf[2];
107*77c1e3ccSAndroid Build Coastguard Worker           cdf[0] = OD_ICDF(fz[j]);
108*77c1e3ccSAndroid Build Coastguard Worker           cdf[1] = OD_ICDF(1U << fts[j]);
109*77c1e3ccSAndroid Build Coastguard Worker           sym = od_ec_decode_cdf_q15(&dec, cdf, 2);
110*77c1e3ccSAndroid Build Coastguard Worker           break;
111*77c1e3ccSAndroid Build Coastguard Worker         }
112*77c1e3ccSAndroid Build Coastguard Worker       }
113*77c1e3ccSAndroid Build Coastguard Worker 
114*77c1e3ccSAndroid Build Coastguard Worker       EXPECT_EQ(sym, data[j])
115*77c1e3ccSAndroid Build Coastguard Worker           << "Decoded " << sym << " instead of " << data[j]
116*77c1e3ccSAndroid Build Coastguard Worker           << " with fz=" << fz[j] << " and ftb=" << fts[j] << "at position "
117*77c1e3ccSAndroid Build Coastguard Worker           << j << " of " << sz << " (Random seed: " << seed << ").\n"
118*77c1e3ccSAndroid Build Coastguard Worker           << "Encoding method: " << enc_method[j]
119*77c1e3ccSAndroid Build Coastguard Worker           << " decoding method: " << dec_method << "\n";
120*77c1e3ccSAndroid Build Coastguard Worker       EXPECT_EQ(od_ec_dec_tell_frac(&dec), tell[j + 1])
121*77c1e3ccSAndroid Build Coastguard Worker           << "od_ec_dec_tell() mismatch between encoder and "
122*77c1e3ccSAndroid Build Coastguard Worker              "decoder at symbol "
123*77c1e3ccSAndroid Build Coastguard Worker           << j + 1 << ": " << (unsigned)od_ec_dec_tell_frac(&dec)
124*77c1e3ccSAndroid Build Coastguard Worker           << " instead of " << tell[j + 1] << " (Random seed: " << seed
125*77c1e3ccSAndroid Build Coastguard Worker           << ").\n";
126*77c1e3ccSAndroid Build Coastguard Worker     }
127*77c1e3ccSAndroid Build Coastguard Worker   }
128*77c1e3ccSAndroid Build Coastguard Worker   od_ec_enc_reset(&enc);
129*77c1e3ccSAndroid Build Coastguard Worker   od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
130*77c1e3ccSAndroid Build Coastguard Worker   od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
131*77c1e3ccSAndroid Build Coastguard Worker   od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
132*77c1e3ccSAndroid Build Coastguard Worker   od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
133*77c1e3ccSAndroid Build Coastguard Worker   od_ec_encode_bool_q15(&enc, 0, OD_ICDF(24576));
134*77c1e3ccSAndroid Build Coastguard Worker   od_ec_enc_patch_initial_bits(&enc, 3, 2);
135*77c1e3ccSAndroid Build Coastguard Worker   EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n";
136*77c1e3ccSAndroid Build Coastguard Worker   od_ec_enc_patch_initial_bits(&enc, 0, 5);
137*77c1e3ccSAndroid Build Coastguard Worker   EXPECT_TRUE(enc.error)
138*77c1e3ccSAndroid Build Coastguard Worker       << "od_ec_enc_patch_initial_bits() didn't fail when it should have.\n";
139*77c1e3ccSAndroid Build Coastguard Worker   od_ec_enc_reset(&enc);
140*77c1e3ccSAndroid Build Coastguard Worker   od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
141*77c1e3ccSAndroid Build Coastguard Worker   od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
142*77c1e3ccSAndroid Build Coastguard Worker   od_ec_encode_bool_q15(&enc, 1, OD_ICDF(32256));
143*77c1e3ccSAndroid Build Coastguard Worker   od_ec_encode_bool_q15(&enc, 0, OD_ICDF(24576));
144*77c1e3ccSAndroid Build Coastguard Worker   od_ec_enc_patch_initial_bits(&enc, 0, 2);
145*77c1e3ccSAndroid Build Coastguard Worker   EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n";
146*77c1e3ccSAndroid Build Coastguard Worker   ptr = od_ec_enc_done(&enc, &ptr_sz);
147*77c1e3ccSAndroid Build Coastguard Worker   ASSERT_NE(ptr, nullptr);
148*77c1e3ccSAndroid Build Coastguard Worker   EXPECT_EQ(ptr_sz, 2u);
149*77c1e3ccSAndroid Build Coastguard Worker   EXPECT_EQ(ptr[0], 63)
150*77c1e3ccSAndroid Build Coastguard Worker       << "Got " << ptr[0]
151*77c1e3ccSAndroid Build Coastguard Worker       << " when expecting 63 for od_ec_enc_patch_initial_bits().\n";
152*77c1e3ccSAndroid Build Coastguard Worker   od_ec_enc_clear(&enc);
153*77c1e3ccSAndroid Build Coastguard Worker   EXPECT_EQ(ret, 0);
154*77c1e3ccSAndroid Build Coastguard Worker }
155