tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

boolcoder_test.cc (6400B)


      1 /*
      2 * Copyright (c) 2016, 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 <math.h>
     13 #include <stdlib.h>
     14 #include <string.h>
     15 
     16 #include "gtest/gtest.h"
     17 
     18 #include "test/acm_random.h"
     19 #include "aom/aom_integer.h"
     20 #include "aom_dsp/bitreader.h"
     21 #include "aom_dsp/bitwriter.h"
     22 
     23 using libaom_test::ACMRandom;
     24 
     25 namespace {
     26 const int num_tests = 10;
     27 }  // namespace
     28 
     29 TEST(AV1, TestBitIO) {
     30  ACMRandom rnd(ACMRandom::DeterministicSeed());
     31  for (int n = 0; n < num_tests; ++n) {
     32    for (int method = 0; method <= 7; ++method) {  // we generate various proba
     33      const int kBitsToTest = 1000;
     34      uint8_t probas[kBitsToTest];
     35 
     36      for (int i = 0; i < kBitsToTest; ++i) {
     37        const int parity = i & 1;
     38        /* clang-format off */
     39        probas[i] =
     40          (method == 0) ? 0 : (method == 1) ? 255 :
     41          (method == 2) ? 128 :
     42          (method == 3) ? rnd.Rand8() :
     43          (method == 4) ? (parity ? 0 : 255) :
     44            // alternate between low and high proba:
     45            (method == 5) ? (parity ? rnd(128) : 255 - rnd(128)) :
     46            (method == 6) ?
     47            (parity ? rnd(64) : 255 - rnd(64)) :
     48            (parity ? rnd(32) : 255 - rnd(32));
     49        /* clang-format on */
     50      }
     51      for (int bit_method = 0; bit_method <= 3; ++bit_method) {
     52        const int random_seed = 6432;
     53        const int kBufferSize = 10000;
     54        ACMRandom bit_rnd(random_seed);
     55        aom_writer bw;
     56        uint8_t bw_buffer[kBufferSize];
     57        aom_start_encode(&bw, bw_buffer);
     58 
     59        int bit = (bit_method == 0) ? 0 : (bit_method == 1) ? 1 : 0;
     60        for (int i = 0; i < kBitsToTest; ++i) {
     61          if (bit_method == 2) {
     62            bit = (i & 1);
     63          } else if (bit_method == 3) {
     64            bit = bit_rnd(2);
     65          }
     66          aom_write(&bw, bit, static_cast<int>(probas[i]));
     67        }
     68 
     69        GTEST_ASSERT_GE(aom_stop_encode(&bw), 0);
     70 
     71        aom_reader br;
     72        aom_reader_init(&br, bw_buffer, bw.pos);
     73        bit_rnd.Reset(random_seed);
     74        for (int i = 0; i < kBitsToTest; ++i) {
     75          if (bit_method == 2) {
     76            bit = (i & 1);
     77          } else if (bit_method == 3) {
     78            bit = bit_rnd(2);
     79          }
     80          GTEST_ASSERT_EQ(aom_read(&br, probas[i], nullptr), bit)
     81              << "pos: " << i << " / " << kBitsToTest
     82              << " bit_method: " << bit_method << " method: " << method;
     83        }
     84      }
     85    }
     86  }
     87 }
     88 
     89 #define FRAC_DIFF_TOTAL_ERROR 0.18
     90 
     91 TEST(AV1, TestTell) {
     92  const int kBufferSize = 10000;
     93  aom_writer bw;
     94  uint8_t bw_buffer[kBufferSize];
     95  const int kSymbols = 1024;
     96  // Coders are noisier at low probabilities, so we start at p = 4.
     97  for (int p = 4; p < 256; p++) {
     98    double probability = p / 256.;
     99    aom_start_encode(&bw, bw_buffer);
    100    for (int i = 0; i < kSymbols; i++) {
    101      aom_write(&bw, 0, p);
    102    }
    103    GTEST_ASSERT_GE(aom_stop_encode(&bw), 0);
    104    aom_reader br;
    105    aom_reader_init(&br, bw_buffer, bw.pos);
    106    uint32_t last_tell = aom_reader_tell(&br);
    107    uint32_t last_tell_frac = aom_reader_tell_frac(&br);
    108    double frac_diff_total = 0;
    109    GTEST_ASSERT_GE(aom_reader_tell(&br), 0u);
    110    GTEST_ASSERT_LE(aom_reader_tell(&br), 1u);
    111    ASSERT_FALSE(aom_reader_has_overflowed(&br));
    112    for (int i = 0; i < kSymbols; i++) {
    113      aom_read(&br, p, nullptr);
    114      uint32_t tell = aom_reader_tell(&br);
    115      uint32_t tell_frac = aom_reader_tell_frac(&br);
    116      GTEST_ASSERT_GE(tell, last_tell)
    117          << "tell: " << tell << ", last_tell: " << last_tell;
    118      GTEST_ASSERT_GE(tell_frac, last_tell_frac)
    119          << "tell_frac: " << tell_frac
    120          << ", last_tell_frac: " << last_tell_frac;
    121      // Frac tell should round up to tell.
    122      GTEST_ASSERT_EQ(tell, (tell_frac + 7) >> 3);
    123      last_tell = tell;
    124      frac_diff_total +=
    125          fabs(((tell_frac - last_tell_frac) / 8.0) + log2(probability));
    126      last_tell_frac = tell_frac;
    127    }
    128    const uint32_t expected = (uint32_t)(-kSymbols * log2(probability));
    129    // Last tell should be close to the expected value.
    130    GTEST_ASSERT_LE(last_tell, expected + 20) << " last_tell: " << last_tell;
    131    // The average frac_diff error should be pretty small.
    132    GTEST_ASSERT_LE(frac_diff_total / kSymbols, FRAC_DIFF_TOTAL_ERROR)
    133        << " frac_diff_total: " << frac_diff_total;
    134    ASSERT_FALSE(aom_reader_has_overflowed(&br));
    135  }
    136 }
    137 
    138 TEST(AV1, TestHasOverflowed) {
    139  const int kBufferSize = 10000;
    140  aom_writer bw;
    141  uint8_t bw_buffer[kBufferSize];
    142  const int kSymbols = 1024;
    143  // Coders are noisier at low probabilities, so we start at p = 4.
    144  for (int p = 4; p < 256; p++) {
    145    aom_start_encode(&bw, bw_buffer);
    146    for (int i = 0; i < kSymbols; i++) {
    147      aom_write(&bw, 1, p);
    148    }
    149    GTEST_ASSERT_GE(aom_stop_encode(&bw), 0);
    150    aom_reader br;
    151    aom_reader_init(&br, bw_buffer, bw.pos);
    152    ASSERT_FALSE(aom_reader_has_overflowed(&br));
    153    for (int i = 0; i < kSymbols; i++) {
    154      GTEST_ASSERT_EQ(aom_read(&br, p, nullptr), 1);
    155      ASSERT_FALSE(aom_reader_has_overflowed(&br));
    156    }
    157    // In the worst case, the encoder uses just a tiny fraction of the last
    158    // byte in the buffer. So to guarantee that aom_reader_has_overflowed()
    159    // returns true, we have to consume very nearly 8 additional bits of data.
    160    // In the worse case, one of the bits in that byte will be 1, and the rest
    161    // will be zero. Once we are past that 1 bit, when the probability of
    162    // reading zero symbol from aom_read() is high, each additional symbol read
    163    // will consume very little additional data (in the case that p == 255,
    164    // approximately -log_2(255/256) ~= 0.0056 bits). In that case it would
    165    // take around 178 calls to consume more than 8 bits. That is only an upper
    166    // bound. In practice we are not guaranteed to hit the worse case and can
    167    // get away with 174 calls.
    168    for (int i = 0; i < 174; i++) {
    169      aom_read(&br, p, nullptr);
    170    }
    171    ASSERT_TRUE(aom_reader_has_overflowed(&br));
    172  }
    173 }