Chromium Code Reviews| 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..138844218a8db70d8b41665be3ab6b5b183ada6a |
| --- /dev/null |
| +++ b/media/filters/vp9_bool_decoder.cc |
| @@ -0,0 +1,157 @@ |
| +// 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 "base/logging.h" |
| +#include "media/base/bit_reader.h" |
| + |
| +namespace media { |
| + |
| +namespace { |
| + |
| +const int kCountToShiftTo128[256] = { |
|
Pawel Osciak
2016/08/04 10:20:18
Please add a comment what this is.
kcwu
2016/08/05 11:38:46
Done.
|
| + 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() : valid_(true) {} |
|
Pawel Osciak
2016/08/04 10:20:17
We could perhaps use class member initialization i
kcwu
2016/08/05 11:38:46
Done.
|
| + |
| +Vp9BoolDecoder::~Vp9BoolDecoder() {} |
| + |
| +// 9.2.1 Initialization process for Boolean decoder |
| +bool Vp9BoolDecoder::Initialize(const uint8_t* data, size_t size) { |
| + DCHECK(data); |
| + reader_.reset(new BitReader(data, size)); |
| + valid_ = true; |
| + |
| + if (size < 1) { |
|
Pawel Osciak
2016/08/04 10:20:17
Perhaps we should check this before BitReader init
kcwu
2016/08/05 11:38:46
Done.
|
| + DVLOG(1) << "input size of bool decoder shall be at least 1"; |
| + valid_ = false; |
| + return false; |
| + } |
| + |
| + bool_value_ = 0; |
| + count_to_fill_ = 8; |
| + bool_range_ = 255; |
| + Fill(); |
|
Pawel Osciak
2016/08/04 10:20:17
I think ReadLiteral() will Fill() by itself, so pe
kcwu
2016/08/05 11:38:46
Done.
|
| + 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. |
| +void Vp9BoolDecoder::Fill() { |
| + DCHECK_GE(count_to_fill_, 0); |
| + |
| + int bits_left = reader_->bits_available(); |
|
Pawel Osciak
2016/08/04 10:20:18
Should all of these be size_t ?
kcwu
2016/08/05 11:38:46
Done.
|
| + if (bits_left < count_to_fill_) { |
| + valid_ = false; |
| + DVLOG(1) << "Vp9BoolDecoder reads beyond the end of stream"; |
| + return; |
| + } |
| + |
| + DCHECK_LE(count_to_fill_, kBoolSize); |
| + int max_bits_to_read = kBigBoolSize - 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; |
| +} |
| + |
| +// 9.2.2 Boolean decoding process |
| +bool Vp9BoolDecoder::ReadBool(int prob) { |
| + DCHECK(reader_); |
| + if (!valid_) |
|
Pawel Osciak
2016/08/04 10:20:18
Should we be checking for valid_ here and in ReadL
kcwu
2016/08/05 11:38:46
This is intended behavior. So the caller doesn't n
|
| + return false; |
| + |
| + if (count_to_fill_ > 0) { |
| + Fill(); |
| + if (!valid_) |
|
Pawel Osciak
2016/08/04 10:20:18
Perhaps Fill() should just return a bool?
kcwu
2016/08/05 11:38:46
Done.
|
| + return false; |
| + } |
| + |
| + unsigned int split = (bool_range_ * prob + (256 - prob)) >> kBoolSize; |
|
Pawel Osciak
2016/08/04 10:20:17
Would it be safer to use a fixed-length type?
kcwu
2016/08/05 11:38:46
|bool_range| is less than 256, thus |split| is les
|
| + BigBool big_split = static_cast<BigBool>(split) << (kBigBoolSize - 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 |
| +int Vp9BoolDecoder::ReadLiteral(int bits) { |
| + DCHECK(reader_); |
| + if (!valid_) |
| + return 0; |
| + |
| + int x = 0; |
|
Pawel Osciak
2016/08/04 10:20:17
Should this be a fixed-size type and also unsigned
kcwu
2016/08/05 11:38:46
I'm not sure what size it should be. Just use arbi
|
| + for (int i = 0; i < bits; i++) |
|
Pawel Osciak
2016/08/04 10:20:17
s/int/size_t/
kcwu
2016/08/05 11:38:47
Acknowledged.
|
| + x = 2 * x + ReadBool(128); |
| + |
| + return x; |
| +} |
| + |
| +bool Vp9BoolDecoder::ConsumePaddingBits() { |
| + DCHECK(reader_); |
| + int data; |
| + |
| + 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 happend |
|
Pawel Osciak
2016/08/04 10:20:17
s/happend/happen./ ?
kcwu
2016/08/05 11:38:46
Done.
|
| + 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 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 |