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