blob: d89c991e7e7e4684d120eba893c90a7f171a2239 [file] [log] [blame]
/*
* Copyright (c) 2021, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 3-Clause Clear License
* and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
* License was not distributed with this source code in the LICENSE file, you
* can obtain it at aomedia.org/license/software-license/bsd-3-c-c/. 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
* aomedia.org/license/patent-license/.
*/
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include <cstdlib>
#include "aom_dsp/entenc.h"
#include "aom_dsp/entdec.h"
TEST(EC_TEST, random_ec_test_Large) {
od_ec_enc enc;
od_ec_dec dec;
int sz;
int i;
int ret;
unsigned int seed;
unsigned char *ptr;
uint32_t ptr_sz;
char *seed_str;
ret = 0;
seed_str = getenv("EC_TEST_SEED");
if (seed_str) {
seed = atoi(seed_str);
} else {
seed = 0xdaa1a;
}
srand(seed);
od_ec_enc_init(&enc, 1);
/*Test compatibility between multiple different encode/decode routines.*/
for (i = 0; i < 409600; i++) {
unsigned *fz;
unsigned *fts;
unsigned *data;
#if CONFIG_BYPASS_IMPROVEMENT
unsigned *mode;
#endif // CONFIG_BYPASS_IMPROVEMENT
unsigned *tell;
unsigned *enc_method;
int j;
sz = rand() / ((RAND_MAX >> (rand() % 9U)) + 1U);
fz = (unsigned *)malloc(sz * sizeof(*fz));
fts = (unsigned *)malloc(sz * sizeof(*fts));
data = (unsigned *)malloc(sz * sizeof(*data));
#if CONFIG_BYPASS_IMPROVEMENT
mode = (unsigned *)malloc(sz * sizeof(*mode));
#endif // CONFIG_BYPASS_IMPROVEMENT
tell = (unsigned *)malloc((sz + 1) * sizeof(*tell));
enc_method = (unsigned *)malloc(sz * sizeof(*enc_method));
od_ec_enc_reset(&enc);
tell[0] = od_ec_enc_tell_frac(&enc);
for (j = 0; j < sz; j++) {
#if CONFIG_BYPASS_IMPROVEMENT
data[j] = rand();
mode[j] = rand();
#else
data[j] = rand() / ((RAND_MAX >> 1) + 1);
#endif // CONFIG_BYPASS_IMPROVEMENT
fts[j] = CDF_PROB_BITS;
fz[j] = (rand() % (CDF_PROB_TOP - 2)) >> (CDF_PROB_BITS - fts[j]);
#if CONFIG_BYPASS_IMPROVEMENT
fz[j] = OD_MAXI(fz[j] & ~1, 2);
enc_method[j] = 1 + (rand() & 3);
#else
fz[j] = OD_MAXI(fz[j], 1);
enc_method[j] = 3 + (rand() & 1);
#endif // CONFIG_BYPASS_IMPROVEMENT
switch (enc_method[j]) {
#if CONFIG_BYPASS_IMPROVEMENT
case 1: {
// Write literal in smaller pieces; read back in single call.
int bits = (mode[j] & 7) + 1;
data[j] &= ((1 << bits) - 1);
int chunk = ((mode[j] >> 4) & 7) + 1;
int d = data[j];
while (bits > 0) {
int n = bits > chunk ? chunk : bits;
od_ec_encode_literal_bypass(&enc, (d >> (bits - n)), n);
bits -= n;
d &= ((1 << bits) - 1);
}
break;
}
case 2: {
// Write literal in single call; read back in smaller pieces.
int bits = (mode[j] & 7) + 1;
data[j] &= ((1 << bits) - 1);
od_ec_encode_literal_bypass(&enc, data[j], bits);
break;
}
case 3: {
data[j] &= 1;
od_ec_encode_bool_bypass(&enc, data[j]);
break;
}
case 4: {
data[j] &= 1;
uint16_t cdf[2];
cdf[0] = OD_ICDF(fz[j]);
cdf[1] = OD_ICDF(1U << fts[j]);
od_ec_encode_cdf_q15(&enc, data[j], cdf, 2);
break;
}
#else
case 3: {
od_ec_encode_bool_q15(&enc, data[j],
OD_ICDF(fz[j] << (CDF_PROB_BITS - fts[j])));
break;
}
case 4: {
uint16_t cdf[2];
cdf[0] = OD_ICDF(fz[j]);
cdf[1] = OD_ICDF(1U << fts[j]);
od_ec_encode_cdf_q15(&enc, data[j], cdf, 2);
break;
}
#endif // CONFIG_BYPASS_IMPROVEMENT
}
tell[j + 1] = od_ec_enc_tell_frac(&enc);
}
ptr = od_ec_enc_done(&enc, &ptr_sz);
EXPECT_GE(((od_ec_enc_tell(&enc) + 7U) >> 3), ptr_sz)
<< "od_ec_enc_tell() lied: "
"there's "
<< ptr_sz << " bytes instead of " << ((od_ec_enc_tell(&enc) + 7) >> 3)
<< " (Random seed: " << seed << ")\n";
od_ec_dec_init(&dec, ptr, ptr_sz);
EXPECT_EQ(od_ec_dec_tell_frac(&dec), tell[0])
<< "od_ec_dec_tell() mismatch between encoder and decoder "
"at symbol 0: "
<< (unsigned)od_ec_dec_tell_frac(&dec) << " instead of " << tell[0]
<< " (Random seed: " << seed << ").\n";
for (j = 0; j < sz; j++) {
int dec_method;
unsigned int sym = data[j] + 1; // Initialize sym to an invalid value.
#if CONFIG_BYPASS_IMPROVEMENT
dec_method = enc_method[j];
switch (dec_method) {
case 1: {
int bits = (mode[j] & 7) + 1;
sym = od_ec_decode_literal_bypass(&dec, bits);
break;
}
case 2: {
int bits = (mode[j] & 7) + 1;
int chunk = ((mode[j] >> 4) & 7) + 1;
sym = 0;
while (bits > 0) {
int n = bits > chunk ? chunk : bits;
sym <<= n;
sym += od_ec_decode_literal_bypass(&dec, n);
bits -= n;
}
break;
}
case 3: {
sym = od_ec_decode_bool_bypass(&dec);
break;
}
case 4: {
uint16_t cdf[2];
cdf[0] = OD_ICDF(fz[j]);
cdf[1] = OD_ICDF(1U << fts[j]);
sym = od_ec_decode_cdf_q15(&dec, cdf, 2);
break;
}
}
#else
if (CDF_SHIFT == 0) {
dec_method = 3 + (rand() & 1);
} else {
dec_method = enc_method[j];
}
switch (dec_method) {
case 3: {
sym = od_ec_decode_bool_q15(
&dec, OD_ICDF(fz[j] << (CDF_PROB_BITS - fts[j])));
break;
}
case 4: {
uint16_t cdf[2];
cdf[0] = OD_ICDF(fz[j]);
cdf[1] = OD_ICDF(1U << fts[j]);
sym = od_ec_decode_cdf_q15(&dec, cdf, 2);
break;
}
}
#endif // CONFIG_BYPASS_IMPROVEMENT
EXPECT_EQ(sym, data[j])
<< "Decoded " << sym << " instead of " << data[j]
<< " with fz=" << fz[j] << " and ftb=" << fts[j] << "at position "
<< j << " of " << sz << " (Random seed: " << seed << ").\n"
<< "Encoding method: " << enc_method[j]
<< " decoding method: " << dec_method << "\n";
EXPECT_EQ(od_ec_dec_tell_frac(&dec), tell[j + 1])
<< "od_ec_dec_tell() mismatch between encoder and "
"decoder at symbol "
<< j + 1 << ": " << (unsigned)od_ec_dec_tell_frac(&dec)
<< " instead of " << tell[j + 1] << " (Random seed: " << seed
<< ").\n";
}
free(enc_method);
free(tell);
#if CONFIG_BYPASS_IMPROVEMENT
free(mode);
#endif // CONFIG_BYPASS_IMPROVEMENT
free(data);
free(fts);
free(fz);
}
od_ec_enc_reset(&enc);
if (CDF_SHIFT == 0) {
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(24576));
od_ec_enc_patch_initial_bits(&enc, 3, 2);
EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n";
od_ec_enc_patch_initial_bits(&enc, 0, 5);
EXPECT_TRUE(enc.error)
<< "od_ec_enc_patch_initial_bits() didn't fail when it should have.\n";
od_ec_enc_reset(&enc);
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(16384));
od_ec_encode_bool_q15(&enc, 1, OD_ICDF(32256));
od_ec_encode_bool_q15(&enc, 0, OD_ICDF(24576));
od_ec_enc_patch_initial_bits(&enc, 0, 2);
EXPECT_FALSE(enc.error) << "od_ec_enc_patch_initial_bits() failed.\n";
ptr = od_ec_enc_done(&enc, &ptr_sz);
EXPECT_EQ(ptr_sz, 2u);
EXPECT_EQ(ptr[0], 63)
<< "Got " << ptr[0]
<< " when expecting 63 for od_ec_enc_patch_initial_bits().\n";
}
od_ec_enc_clear(&enc);
EXPECT_EQ(ret, 0);
}