boolcoder_test.cc 4.76 KB
Newer Older
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
4 5 6 7 8 9 10
 * 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.
*/
11 12 13 14 15 16 17

#include <math.h>
#include <stdlib.h>
#include <string.h>

#include "third_party/googletest/src/include/gtest/gtest.h"

18
#include "test/acm_random.h"
Yaowu Xu's avatar
Yaowu Xu committed
19
#include "aom/aom_integer.h"
20 21
#include "aom_dsp/bitreader.h"
#include "aom_dsp/bitwriter.h"
22

23
using libaom_test::ACMRandom;
24

Daniel Kang's avatar
Daniel Kang committed
25 26
namespace {
const int num_tests = 10;
27 28
}  // namespace

Yaowu Xu's avatar
Yaowu Xu committed
29
TEST(AV1, TestBitIO) {
30 31
  ACMRandom rnd(ACMRandom::DeterministicSeed());
  for (int n = 0; n < num_tests; ++n) {
clang-format's avatar
clang-format committed
32
    for (int method = 0; method <= 7; ++method) {  // we generate various proba
Yaowu Xu's avatar
Yaowu Xu committed
33 34
      const int kBitsToTest = 1000;
      uint8_t probas[kBitsToTest];
35

Yaowu Xu's avatar
Yaowu Xu committed
36
      for (int i = 0; i < kBitsToTest; ++i) {
37
        const int parity = i & 1;
clang-format's avatar
clang-format committed
38
        /* clang-format off */
39
        probas[i] =
John Koleszar's avatar
John Koleszar committed
40 41 42 43
          (method == 0) ? 0 : (method == 1) ? 255 :
          (method == 2) ? 128 :
          (method == 3) ? rnd.Rand8() :
          (method == 4) ? (parity ? 0 : 255) :
44 45 46
            // alternate between low and high proba:
            (method == 5) ? (parity ? rnd(128) : 255 - rnd(128)) :
            (method == 6) ?
John Koleszar's avatar
John Koleszar committed
47 48
            (parity ? rnd(64) : 255 - rnd(64)) :
            (parity ? rnd(32) : 255 - rnd(32));
clang-format's avatar
clang-format committed
49
        /* clang-format on */
50 51 52
      }
      for (int bit_method = 0; bit_method <= 3; ++bit_method) {
        const int random_seed = 6432;
Yaowu Xu's avatar
Yaowu Xu committed
53
        const int kBufferSize = 10000;
54
        ACMRandom bit_rnd(random_seed);
Yaowu Xu's avatar
Yaowu Xu committed
55
        aom_writer bw;
Yaowu Xu's avatar
Yaowu Xu committed
56
        uint8_t bw_buffer[kBufferSize];
Yaowu Xu's avatar
Yaowu Xu committed
57
        aom_start_encode(&bw, bw_buffer);
58 59

        int bit = (bit_method == 0) ? 0 : (bit_method == 1) ? 1 : 0;
Yaowu Xu's avatar
Yaowu Xu committed
60
        for (int i = 0; i < kBitsToTest; ++i) {
61 62 63 64 65
          if (bit_method == 2) {
            bit = (i & 1);
          } else if (bit_method == 3) {
            bit = bit_rnd(2);
          }
Yaowu Xu's avatar
Yaowu Xu committed
66
          aom_write(&bw, bit, static_cast<int>(probas[i]));
67 68
        }

Yaowu Xu's avatar
Yaowu Xu committed
69
        aom_stop_encode(&bw);
70

71 72 73
        // First bit should be zero
        GTEST_ASSERT_EQ(bw_buffer[0] & 0x80, 0);

Yaowu Xu's avatar
Yaowu Xu committed
74 75
        aom_reader br;
        aom_reader_init(&br, bw_buffer, kBufferSize, NULL, NULL);
76
        bit_rnd.Reset(random_seed);
Yaowu Xu's avatar
Yaowu Xu committed
77
        for (int i = 0; i < kBitsToTest; ++i) {
78 79 80 81 82
          if (bit_method == 2) {
            bit = (i & 1);
          } else if (bit_method == 3) {
            bit = bit_rnd(2);
          }
Yaowu Xu's avatar
Yaowu Xu committed
83
          GTEST_ASSERT_EQ(aom_read(&br, probas[i]), bit)
Yaowu Xu's avatar
Yaowu Xu committed
84
              << "pos: " << i << " / " << kBitsToTest
clang-format's avatar
clang-format committed
85
              << " bit_method: " << bit_method << " method: " << method;
86 87 88 89 90
        }
      }
    }
  }
}
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141

#if CONFIG_DAALA_EC
#define FRAC_DIFF_TOTAL_ERROR 0.07
#else
#define FRAC_DIFF_TOTAL_ERROR 0.2
#endif

TEST(AV1, TestTell) {
  const int kBufferSize = 10000;
  aom_writer bw;
  uint8_t bw_buffer[kBufferSize];
  const int kSymbols = 1024;
  // Coders are noisier at low probabilities, so we start at p = 4.
  for (int p = 4; p <= 256; p++) {
    double probability = p / 256.;
    aom_start_encode(&bw, bw_buffer);
    for (int i = 0; i < kSymbols; i++) {
      aom_write(&bw, 0, p);
    }
    aom_stop_encode(&bw);
    aom_reader br;
    aom_reader_init(&br, bw_buffer, kBufferSize, NULL, NULL);
    ptrdiff_t last_tell = aom_reader_tell(&br);
    ptrdiff_t last_tell_frac = aom_reader_tell_frac(&br);
    double frac_diff_total = 0;
    GTEST_ASSERT_GE(aom_reader_tell(&br), 0);
    GTEST_ASSERT_LE(aom_reader_tell(&br), 1);
    for (int i = 0; i < kSymbols; i++) {
      aom_read(&br, p);
      ptrdiff_t tell = aom_reader_tell(&br);
      ptrdiff_t tell_frac = aom_reader_tell_frac(&br);
      GTEST_ASSERT_GE(tell, last_tell) << "tell: " << tell
                                       << ", last_tell: " << last_tell;
      GTEST_ASSERT_GE(tell_frac, last_tell_frac)
          << "tell_frac: " << tell_frac
          << ", last_tell_frac: " << last_tell_frac;
      // Frac tell should round up to tell.
      GTEST_ASSERT_EQ(tell, (tell_frac + 7) >> 3);
      last_tell = tell;
      frac_diff_total +=
          fabs(((tell_frac - last_tell_frac) / 8.0) + log2(probability));
      last_tell_frac = tell_frac;
    }
    const int expected = (int)(-kSymbols * log2(probability));
    // Last tell should be close to the expected value.
    GTEST_ASSERT_LE(last_tell - expected, 20) << " last_tell: " << last_tell;
    // The average frac_diff error should be pretty small.
    GTEST_ASSERT_LE(frac_diff_total / kSymbols, FRAC_DIFF_TOTAL_ERROR)
        << " frac_diff_total: " << frac_diff_total;
  }
}