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 // Note: ported from Chromium commit head: 2de6929
5
6 #include "vp9_compressed_header_parser.h"
7
8 #include "base/logging.h"
9
10 namespace media {
11
12 namespace {
13
14 // 6.3.6 Inv recenter noneg syntax, inv_recenter_nonneg().
InvRecenterNonneg(int v,int m)15 int InvRecenterNonneg(int v, int m) {
16 DCHECK_LE(m, kVp9MaxProb / 2);
17 if (v > 2 * m)
18 return v;
19
20 if (v & 1)
21 return m - ((v + 1) >> 1);
22 return m + (v >> 1);
23 }
24
25 // 6.3.5 Inv remap prob syntax, inv_remap_prob().
InvRemapProb(uint8_t delta_prob,uint8_t prob)26 Vp9Prob InvRemapProb(uint8_t delta_prob, uint8_t prob) {
27 static uint8_t inv_map_table[kVp9MaxProb] = {
28 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176,
29 189, 202, 215, 228, 241, 254, 1, 2, 3, 4, 5, 6, 8, 9,
30 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24,
31 25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 39,
32 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 52, 53, 54,
33 55, 56, 57, 58, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
34 70, 71, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
35 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 99, 100,
36 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 112, 113, 114, 115,
37 116, 117, 118, 119, 120, 121, 122, 123, 125, 126, 127, 128, 129, 130,
38 131, 132, 133, 134, 135, 136, 138, 139, 140, 141, 142, 143, 144, 145,
39 146, 147, 148, 149, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
40 161, 162, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
41 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 190, 191,
42 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 203, 204, 205, 206,
43 207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221,
44 222, 223, 224, 225, 226, 227, 229, 230, 231, 232, 233, 234, 235, 236,
45 237, 238, 239, 240, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251,
46 252, 253, 253};
47 uint8_t m = prob;
48 uint8_t v = delta_prob;
49 DCHECK_GE(m, 1);
50 DCHECK_LE(m, kVp9MaxProb);
51 DCHECK_LT(v, arraysize(inv_map_table));
52 v = inv_map_table[v];
53 m--;
54 if ((m << 1) <= kVp9MaxProb) {
55 return 1 + InvRecenterNonneg(v, m);
56 } else {
57 return kVp9MaxProb - InvRecenterNonneg(v, kVp9MaxProb - 1 - m);
58 }
59 }
60
61 } // namespace
62
63 Vp9CompressedHeaderParser::Vp9CompressedHeaderParser() = default;
64
65 // 6.3.1 Tx mode syntax
ReadTxMode(Vp9FrameHeader * fhdr)66 void Vp9CompressedHeaderParser::ReadTxMode(Vp9FrameHeader* fhdr) {
67 int tx_mode;
68 if (fhdr->quant_params.IsLossless()) {
69 tx_mode = Vp9CompressedHeader::ONLY_4X4;
70 } else {
71 tx_mode = reader_.ReadLiteral(2);
72 if (tx_mode == Vp9CompressedHeader::ALLOW_32X32)
73 tx_mode += reader_.ReadLiteral(1);
74 }
75 fhdr->compressed_header.tx_mode =
76 static_cast<Vp9CompressedHeader::Vp9TxMode>(tx_mode);
77 }
78
79 // 6.3.4 Decode term subexp syntax
DecodeTermSubexp()80 uint8_t Vp9CompressedHeaderParser::DecodeTermSubexp() {
81 if (reader_.ReadLiteral(1) == 0)
82 return reader_.ReadLiteral(4);
83 if (reader_.ReadLiteral(1) == 0)
84 return reader_.ReadLiteral(4) + 16;
85 if (reader_.ReadLiteral(1) == 0)
86 return reader_.ReadLiteral(5) + 32;
87 uint8_t v = reader_.ReadLiteral(7);
88 if (v < 65)
89 return v + 64;
90 return (v << 1) - 1 + reader_.ReadLiteral(1);
91 }
92
93 // 6.3.3 Diff update prob syntax
DiffUpdateProb(Vp9Prob * prob)94 void Vp9CompressedHeaderParser::DiffUpdateProb(Vp9Prob* prob) {
95 const Vp9Prob kUpdateProb = 252;
96 if (reader_.ReadBool(kUpdateProb)) {
97 uint8_t delta_prob = DecodeTermSubexp();
98 *prob = InvRemapProb(delta_prob, *prob);
99 }
100 }
101
102 // Helper function to DiffUpdateProb an array of probs.
103 template <int N>
DiffUpdateProbArray(Vp9Prob (& prob_array)[N])104 void Vp9CompressedHeaderParser::DiffUpdateProbArray(Vp9Prob (&prob_array)[N]) {
105 for (auto& x : prob_array) {
106 DiffUpdateProb(&x);
107 }
108 }
109
110 // 6.3.2 Tx mode probs syntax
ReadTxModeProbs(Vp9FrameContext * frame_context)111 void Vp9CompressedHeaderParser::ReadTxModeProbs(
112 Vp9FrameContext* frame_context) {
113 for (auto& a : frame_context->tx_probs_8x8) {
114 DiffUpdateProbArray(a);
115 }
116 for (auto& a : frame_context->tx_probs_16x16) {
117 DiffUpdateProbArray(a);
118 }
119 for (auto& a : frame_context->tx_probs_32x32) {
120 DiffUpdateProbArray(a);
121 }
122 }
123
124 // 6.3.7 Coef probs syntax
ReadCoefProbs(Vp9FrameHeader * fhdr)125 void Vp9CompressedHeaderParser::ReadCoefProbs(Vp9FrameHeader* fhdr) {
126 const int tx_mode_to_biggest_tx_size[Vp9CompressedHeader::TX_MODES] = {
127 0, 1, 2, 3, 3,
128 };
129 const int max_tx_size =
130 tx_mode_to_biggest_tx_size[fhdr->compressed_header.tx_mode];
131 for (int tx_size = 0; tx_size <= max_tx_size; tx_size++) {
132 if (reader_.ReadLiteral(1) == 0)
133 continue;
134
135 for (auto& ai : fhdr->frame_context.coef_probs[tx_size]) {
136 for (auto& aj : ai) {
137 for (auto& ak : aj) {
138 int max_l = (ak == aj[0]) ? 3 : 6;
139 for (int l = 0; l < max_l; l++) {
140 DiffUpdateProbArray(ak[l]);
141 }
142 }
143 }
144 }
145 }
146 }
147
148 // 6.3.8 Skip probs syntax
ReadSkipProb(Vp9FrameContext * frame_context)149 void Vp9CompressedHeaderParser::ReadSkipProb(Vp9FrameContext* frame_context) {
150 DiffUpdateProbArray(frame_context->skip_prob);
151 }
152
153 // 6.3.9 Inter mode probs syntax
ReadInterModeProbs(Vp9FrameContext * frame_context)154 void Vp9CompressedHeaderParser::ReadInterModeProbs(
155 Vp9FrameContext* frame_context) {
156 for (auto& a : frame_context->inter_mode_probs)
157 DiffUpdateProbArray(a);
158 }
159
160 // 6.3.10 Interp filter probs syntax
ReadInterpFilterProbs(Vp9FrameContext * frame_context)161 void Vp9CompressedHeaderParser::ReadInterpFilterProbs(
162 Vp9FrameContext* frame_context) {
163 for (auto& a : frame_context->interp_filter_probs)
164 DiffUpdateProbArray(a);
165 }
166
167 // 6.3.11 Intra inter probs syntax
ReadIsInterProbs(Vp9FrameContext * frame_context)168 void Vp9CompressedHeaderParser::ReadIsInterProbs(
169 Vp9FrameContext* frame_context) {
170 DiffUpdateProbArray(frame_context->is_inter_prob);
171 }
172
173 // 6.3.12 Frame reference mode syntax
ReadFrameReferenceMode(Vp9FrameHeader * fhdr)174 void Vp9CompressedHeaderParser::ReadFrameReferenceMode(Vp9FrameHeader* fhdr) {
175 bool compound_reference_allowed = false;
176 for (int i = VP9_FRAME_LAST + 1; i < VP9_FRAME_MAX; i++)
177 if (fhdr->ref_frame_sign_bias[i] != fhdr->ref_frame_sign_bias[1])
178 compound_reference_allowed = true;
179
180 if (compound_reference_allowed && reader_.ReadLiteral(1)) {
181 fhdr->compressed_header.reference_mode =
182 reader_.ReadLiteral(1) ? REFERENCE_MODE_SELECT : COMPOUND_REFERENCE;
183 } else {
184 fhdr->compressed_header.reference_mode = SINGLE_REFERENCE;
185 }
186 }
187
188 // 6.3.13 Frame reference mode probs syntax
ReadFrameReferenceModeProbs(Vp9FrameHeader * fhdr)189 void Vp9CompressedHeaderParser::ReadFrameReferenceModeProbs(
190 Vp9FrameHeader* fhdr) {
191 Vp9FrameContext* frame_context = &fhdr->frame_context;
192 if (fhdr->compressed_header.reference_mode == REFERENCE_MODE_SELECT)
193 DiffUpdateProbArray(frame_context->comp_mode_prob);
194
195 if (fhdr->compressed_header.reference_mode != COMPOUND_REFERENCE)
196 for (auto& a : frame_context->single_ref_prob)
197 DiffUpdateProbArray(a);
198
199 if (fhdr->compressed_header.reference_mode != SINGLE_REFERENCE)
200 DiffUpdateProbArray(frame_context->comp_ref_prob);
201 }
202
203 // 6.3.14 Y mode probs syntax
ReadYModeProbs(Vp9FrameContext * frame_context)204 void Vp9CompressedHeaderParser::ReadYModeProbs(Vp9FrameContext* frame_context) {
205 for (auto& a : frame_context->y_mode_probs)
206 DiffUpdateProbArray(a);
207 }
208
209 // 6.3.15 Partition probs syntax
ReadPartitionProbs(Vp9FrameContext * frame_context)210 void Vp9CompressedHeaderParser::ReadPartitionProbs(
211 Vp9FrameContext* frame_context) {
212 for (auto& a : frame_context->partition_probs)
213 DiffUpdateProbArray(a);
214 }
215
216 // 6.3.16 MV probs syntax
ReadMvProbs(bool allow_high_precision_mv,Vp9FrameContext * frame_context)217 void Vp9CompressedHeaderParser::ReadMvProbs(bool allow_high_precision_mv,
218 Vp9FrameContext* frame_context) {
219 UpdateMvProbArray(frame_context->mv_joint_probs);
220
221 for (int i = 0; i < 2; i++) {
222 UpdateMvProb(&frame_context->mv_sign_prob[i]);
223 UpdateMvProbArray(frame_context->mv_class_probs[i]);
224 UpdateMvProb(&frame_context->mv_class0_bit_prob[i]);
225 UpdateMvProbArray(frame_context->mv_bits_prob[i]);
226 }
227
228 for (int i = 0; i < 2; i++) {
229 for (auto& a : frame_context->mv_class0_fr_probs[i])
230 UpdateMvProbArray(a);
231 UpdateMvProbArray(frame_context->mv_fr_probs[i]);
232 }
233
234 if (allow_high_precision_mv) {
235 for (int i = 0; i < 2; i++) {
236 UpdateMvProb(&frame_context->mv_class0_hp_prob[i]);
237 UpdateMvProb(&frame_context->mv_hp_prob[i]);
238 }
239 }
240 }
241
242 // 6.3.17 Update mv prob syntax
UpdateMvProb(Vp9Prob * prob)243 void Vp9CompressedHeaderParser::UpdateMvProb(Vp9Prob* prob) {
244 if (reader_.ReadBool(252))
245 *prob = reader_.ReadLiteral(7) << 1 | 1;
246 }
247
248 // Helper function to UpdateMvProb an array of probs.
249 template <int N>
UpdateMvProbArray(Vp9Prob (& prob_array)[N])250 void Vp9CompressedHeaderParser::UpdateMvProbArray(Vp9Prob (&prob_array)[N]) {
251 for (auto& x : prob_array) {
252 UpdateMvProb(&x);
253 }
254 }
255
256 // 6.3 Compressed header syntax
Parse(const uint8_t * stream,off_t frame_size,Vp9FrameHeader * fhdr)257 bool Vp9CompressedHeaderParser::Parse(const uint8_t* stream,
258 off_t frame_size,
259 Vp9FrameHeader* fhdr) {
260 DVLOG(2) << "Vp9CompressedHeaderParser::Parse";
261 if (!reader_.Initialize(stream, frame_size))
262 return false;
263
264 ReadTxMode(fhdr);
265 if (fhdr->compressed_header.tx_mode == Vp9CompressedHeader::TX_MODE_SELECT)
266 ReadTxModeProbs(&fhdr->frame_context);
267
268 ReadCoefProbs(fhdr);
269 ReadSkipProb(&fhdr->frame_context);
270
271 if (!fhdr->IsIntra()) {
272 ReadInterModeProbs(&fhdr->frame_context);
273 if (fhdr->interpolation_filter == SWITCHABLE)
274 ReadInterpFilterProbs(&fhdr->frame_context);
275 ReadIsInterProbs(&fhdr->frame_context);
276 ReadFrameReferenceMode(fhdr);
277 ReadFrameReferenceModeProbs(fhdr);
278 ReadYModeProbs(&fhdr->frame_context);
279 ReadPartitionProbs(&fhdr->frame_context);
280 ReadMvProbs(fhdr->allow_high_precision_mv, &fhdr->frame_context);
281 }
282
283 if (!reader_.IsValid()) {
284 DVLOG(1) << "parser reads beyond the end of buffer";
285 return false;
286 }
287 if (!reader_.ConsumePaddingBits()) {
288 DVLOG(1) << "padding bits are not zero";
289 return false;
290 }
291 return true;
292 }
293
294 } // namespace media
295