| Index: media/filters/vp9_bool_decoder.cc
|
| diff --git a/media/filters/vp9_bool_decoder.cc b/media/filters/vp9_bool_decoder.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e8d50b12da7b7c71908a86337b4c63a75b0487e8
|
| --- /dev/null
|
| +++ b/media/filters/vp9_bool_decoder.cc
|
| @@ -0,0 +1,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() {}
|
| +
|
| +Vp9BoolDecoder::~Vp9BoolDecoder() {}
|
| +
|
| +// 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
|
|
|