1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
|
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/filters/vp9_bool_decoder.h"
#include <algorithm>
#include "base/logging.h"
#include "media/base/bit_reader.h"
namespace media {
namespace {
// This is an optimization lookup table for the loop in spec 9.2.2.
// while BoolRange <= 128:
// read 1 bit
// BoolRange *= 2
// This table indicates how many iterations to run for a given BoolRange. So
// the loop could be reduced to
// read (kCountToShiftTo128[BoolRange]) bits
const int kCountToShiftTo128[256] = {
0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
} // namespace
Vp9BoolDecoder::Vp9BoolDecoder() = default;
Vp9BoolDecoder::~Vp9BoolDecoder() = default;
// 9.2.1 Initialization process for Boolean decoder
bool Vp9BoolDecoder::Initialize(const uint8_t* data, size_t size) {
DCHECK(data);
if (size < 1) {
DVLOG(1) << "input size of bool decoder shall be at least 1";
valid_ = false;
return false;
}
reader_.reset(new BitReader(data, size));
valid_ = true;
bool_value_ = 0;
count_to_fill_ = 8;
bool_range_ = 255;
if (ReadLiteral(1) != 0) {
DVLOG(1) << "marker bit should be 0";
valid_ = false;
return false;
}
return true;
}
// Fill at least |count_to_fill_| bits and prefill remain bits of |bool_value_|
// if data is enough.
bool Vp9BoolDecoder::Fill() {
DCHECK_GE(count_to_fill_, 0);
int bits_left = reader_->bits_available();
if (bits_left < count_to_fill_) {
valid_ = false;
DVLOG(1) << "Vp9BoolDecoder reads beyond the end of stream";
return false;
}
DCHECK_LE(count_to_fill_, kBoolSize);
int max_bits_to_read = kBigBoolBitSize - kBoolSize + count_to_fill_;
int bits_to_read = std::min(max_bits_to_read, bits_left);
BigBool data;
reader_->ReadBits(bits_to_read, &data);
bool_value_ |= data << (max_bits_to_read - bits_to_read);
count_to_fill_ -= bits_to_read;
return true;
}
// 9.2.2 Boolean decoding process
bool Vp9BoolDecoder::ReadBool(int prob) {
DCHECK(reader_);
if (count_to_fill_ > 0) {
if (!Fill())
return false;
}
unsigned int split = (bool_range_ * prob + (256 - prob)) >> kBoolSize;
BigBool big_split = static_cast<BigBool>(split)
<< (kBigBoolBitSize - kBoolSize);
bool bit;
if (bool_value_ < big_split) {
bool_range_ = split;
bit = false;
} else {
bool_range_ -= split;
bool_value_ -= big_split;
bit = true;
}
// Need to fill |count| bits next time in order to make |bool_range_| >=
// 128.
DCHECK_LT(bool_range_, arraysize(kCountToShiftTo128));
DCHECK_GT(bool_range_, 0u);
int count = kCountToShiftTo128[bool_range_];
bool_range_ <<= count;
bool_value_ <<= count;
count_to_fill_ += count;
return bit;
}
// 9.2.4 Parsing process for read_literal
uint8_t Vp9BoolDecoder::ReadLiteral(int bits) {
DCHECK_LT(static_cast<size_t>(bits), sizeof(uint8_t) * 8);
DCHECK(reader_);
uint8_t x = 0;
for (int i = 0; i < bits; i++)
x = 2 * x + ReadBool(128);
return x;
}
bool Vp9BoolDecoder::ConsumePaddingBits() {
DCHECK(reader_);
if (count_to_fill_ > reader_->bits_available()) {
// 9.2.2 Boolean decoding process
// Although we actually don't used the value, spec says the bitstream
// should have enough bits to fill bool range, this should never happen.
DVLOG(2) << "not enough bits in bitstream to fill bool range";
return false;
}
if (bool_value_ != 0) {
DVLOG(1) << "prefilled padding bits are not zero";
return false;
}
while (reader_->bits_available() > 0) {
int data;
int size_to_read =
std::min(reader_->bits_available(), static_cast<int>(sizeof(data) * 8));
reader_->ReadBits(size_to_read, &data);
if (data != 0) {
DVLOG(1) << "padding bits are not zero";
return false;
}
}
return true;
}
} // namespace media
|