OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "media/filters/vp9_bool_decoder.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "media/base/bit_reader.h" | |
9 | |
10 namespace media { | |
11 | |
12 namespace { | |
13 | |
14 // This is an optimization lookup table for the loop in spec 9.2.2. | |
15 // while BoolRange <= 128: | |
16 // read 1 bit | |
17 // BoolRange *= 2 | |
18 // This table indicates how many iterations to run for a given BoolRange. So | |
19 // the loop could be reduced to | |
20 // read (kCountToShiftTo128[BoolRange]) bits | |
21 const int kCountToShiftTo128[256] = { | |
22 0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, | |
23 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, | |
24 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, | |
25 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
26 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |
27 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
28 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
29 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
30 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
33 }; | |
34 } // namespace | |
35 | |
36 Vp9BoolDecoder::Vp9BoolDecoder() {} | |
37 | |
38 Vp9BoolDecoder::~Vp9BoolDecoder() {} | |
39 | |
40 // 9.2.1 Initialization process for Boolean decoder | |
41 bool Vp9BoolDecoder::Initialize(const uint8_t* data, size_t size) { | |
42 DCHECK(data); | |
43 if (size < 1) { | |
44 DVLOG(1) << "input size of bool decoder shall be at least 1"; | |
45 valid_ = false; | |
46 return false; | |
47 } | |
48 | |
49 reader_.reset(new BitReader(data, size)); | |
50 valid_ = true; | |
51 | |
52 bool_value_ = 0; | |
53 count_to_fill_ = 8; | |
54 bool_range_ = 255; | |
55 if (ReadLiteral(1) != 0) { | |
56 DVLOG(1) << "marker bit should be 0"; | |
57 valid_ = false; | |
58 return false; | |
59 } | |
60 return true; | |
61 } | |
62 | |
63 // Fill at least |count_to_fill_| bits and prefill remain bits of |bool_value_| | |
64 // if data is enough. | |
65 bool Vp9BoolDecoder::Fill() { | |
66 DCHECK_GE(count_to_fill_, 0); | |
67 | |
68 size_t bits_left = reader_->bits_available(); | |
69 if (bits_left < static_cast<size_t>(count_to_fill_)) { | |
Pawel Osciak
2016/08/08 08:13:37
Hmm, ok, I admit I'm not seeing any good ways to a
kcwu
2016/08/09 04:29:43
Done.
| |
70 valid_ = false; | |
71 DVLOG(1) << "Vp9BoolDecoder reads beyond the end of stream"; | |
72 return false; | |
73 } | |
74 | |
75 DCHECK_LE(static_cast<size_t>(count_to_fill_), kBoolSize); | |
76 size_t max_bits_to_read = kBigBoolBitSize - kBoolSize + count_to_fill_; | |
77 size_t bits_to_read = std::min(max_bits_to_read, bits_left); | |
78 | |
79 BigBool data; | |
80 reader_->ReadBits(bits_to_read, &data); | |
81 bool_value_ |= data << (max_bits_to_read - bits_to_read); | |
82 count_to_fill_ -= bits_to_read; | |
83 | |
84 return true; | |
85 } | |
86 | |
87 // 9.2.2 Boolean decoding process | |
88 bool Vp9BoolDecoder::ReadBool(int prob) { | |
89 DCHECK(reader_); | |
90 | |
91 if (count_to_fill_ > 0) { | |
92 if (!Fill()) | |
93 return false; | |
94 } | |
95 | |
96 unsigned int split = (bool_range_ * prob + (256 - prob)) >> kBoolSize; | |
97 BigBool big_split = static_cast<BigBool>(split) | |
98 << (kBigBoolBitSize - kBoolSize); | |
99 | |
100 bool bit; | |
101 if (bool_value_ < big_split) { | |
102 bool_range_ = split; | |
103 bit = false; | |
104 } else { | |
105 bool_range_ -= split; | |
106 bool_value_ -= big_split; | |
107 bit = true; | |
108 } | |
109 | |
110 // Need to fill |count| bits next time in order to make |bool_range_| >= | |
111 // 128. | |
112 DCHECK_LT(bool_range_, arraysize(kCountToShiftTo128)); | |
113 DCHECK_GT(bool_range_, 0u); | |
114 int count = kCountToShiftTo128[bool_range_]; | |
115 bool_range_ <<= count; | |
116 bool_value_ <<= count; | |
117 count_to_fill_ += count; | |
118 | |
119 return bit; | |
120 } | |
121 | |
122 // 9.2.4 Parsing process for read_literal | |
123 uint8_t Vp9BoolDecoder::ReadLiteral(int bits) { | |
124 DCHECK_LT(static_cast<size_t>(bits), sizeof(uint8_t) * 8); | |
125 DCHECK(reader_); | |
126 | |
127 uint8_t x = 0; | |
128 for (int i = 0; i < bits; i++) | |
129 x = 2 * x + ReadBool(128); | |
130 | |
131 return x; | |
132 } | |
133 | |
134 bool Vp9BoolDecoder::ConsumePaddingBits() { | |
135 DCHECK(reader_); | |
136 int data; | |
137 | |
138 if (count_to_fill_ > reader_->bits_available()) { | |
139 // 9.2.2 Boolean decoding process | |
140 // Although we actually don't used the value, spec says the bitstream | |
141 // should have enough bits to fill bool range, this should never happen. | |
142 DVLOG(2) << "not enough bits in bitstream to fill bool range"; | |
143 return false; | |
144 } | |
145 | |
146 if (bool_value_ != 0) { | |
147 DVLOG(1) << "prefilled padding bits are not zero"; | |
148 return false; | |
149 } | |
150 while (reader_->bits_available() > 0) { | |
151 int size_to_read = | |
152 std::min(reader_->bits_available(), static_cast<int>(sizeof(data) * 8)); | |
153 reader_->ReadBits(size_to_read, &data); | |
154 if (data != 0) { | |
155 DVLOG(1) << "padding bits are not zero"; | |
156 return false; | |
157 } | |
158 } | |
159 return true; | |
160 } | |
161 | |
162 } // namespace media | |
OLD | NEW |