1 /* 2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 12 #include <math.h> 13 #include <stddef.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <sys/types.h> 18 19 #include "test/acm_random.h" 20 #include "third_party/googletest/src/include/gtest/gtest.h" 21 #include "vpx/vpx_integer.h" 22 23 extern "C" { 24 #include "vp8/encoder/boolhuff.h" 25 #include "vp8/decoder/dboolhuff.h" 26 } 27 28 namespace { 29 const int num_tests = 10; 30 31 // In a real use the 'decrypt_state' parameter will be a pointer to a struct 32 // with whatever internal state the decryptor uses. For testing we'll just 33 // xor with a constant key, and decrypt_state will point to the start of 34 // the original buffer. 35 const uint8_t secret_key[16] = { 36 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 37 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0 38 }; 39 40 void encrypt_buffer(uint8_t *buffer, int size) { 41 for (int i = 0; i < size; ++i) { 42 buffer[i] ^= secret_key[i & 15]; 43 } 44 } 45 46 void test_decrypt_cb(void *decrypt_state, const uint8_t *input, 47 uint8_t *output, int count) { 48 int offset = input - reinterpret_cast<uint8_t *>(decrypt_state); 49 for (int i = 0; i < count; i++) { 50 output[i] = input[i] ^ secret_key[(offset + i) & 15]; 51 } 52 } 53 54 } // namespace 55 56 using libvpx_test::ACMRandom; 57 58 TEST(VP8, TestBitIO) { 59 ACMRandom rnd(ACMRandom::DeterministicSeed()); 60 for (int n = 0; n < num_tests; ++n) { 61 for (int method = 0; method <= 7; ++method) { // we generate various proba 62 const int kBitsToTest = 1000; 63 uint8_t probas[kBitsToTest]; 64 65 for (int i = 0; i < kBitsToTest; ++i) { 66 const int parity = i & 1; 67 probas[i] = 68 (method == 0) ? 0 : (method == 1) ? 255 : 69 (method == 2) ? 128 : 70 (method == 3) ? rnd.Rand8() : 71 (method == 4) ? (parity ? 0 : 255) : 72 // alternate between low and high proba: 73 (method == 5) ? (parity ? rnd(128) : 255 - rnd(128)) : 74 (method == 6) ? 75 (parity ? rnd(64) : 255 - rnd(64)) : 76 (parity ? rnd(32) : 255 - rnd(32)); 77 } 78 for (int bit_method = 0; bit_method <= 3; ++bit_method) { 79 const int random_seed = 6432; 80 const int kBufferSize = 10000; 81 ACMRandom bit_rnd(random_seed); 82 BOOL_CODER bw; 83 uint8_t bw_buffer[kBufferSize]; 84 vp8_start_encode(&bw, bw_buffer, bw_buffer + kBufferSize); 85 86 int bit = (bit_method == 0) ? 0 : (bit_method == 1) ? 1 : 0; 87 for (int i = 0; i < kBitsToTest; ++i) { 88 if (bit_method == 2) { 89 bit = (i & 1); 90 } else if (bit_method == 3) { 91 bit = bit_rnd(2); 92 } 93 vp8_encode_bool(&bw, bit, static_cast<int>(probas[i])); 94 } 95 96 vp8_stop_encode(&bw); 97 98 BOOL_DECODER br; 99 #if CONFIG_DECRYPT 100 encrypt_buffer(bw_buffer, buffer_size); 101 vp8dx_start_decode(&br, bw_buffer, buffer_size, 102 test_decrypt_cb, 103 reinterpret_cast<void *>(bw_buffer)); 104 #else 105 vp8dx_start_decode(&br, bw_buffer, kBufferSize, NULL, NULL); 106 #endif 107 bit_rnd.Reset(random_seed); 108 for (int i = 0; i < kBitsToTest; ++i) { 109 if (bit_method == 2) { 110 bit = (i & 1); 111 } else if (bit_method == 3) { 112 bit = bit_rnd(2); 113 } 114 GTEST_ASSERT_EQ(vp8dx_decode_bool(&br, probas[i]), bit) 115 << "pos: "<< i << " / " << kBitsToTest 116 << " bit_method: " << bit_method 117 << " method: " << method; 118 } 119 } 120 } 121 } 122 } 123