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 |