Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: media/filters/vp9_bool_decoder.cc

Issue 2133993002: Parse VP9 compressed header (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address Pawel's comments Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698