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

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

Issue 1258083004: Add a Vp9Parser implementation (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nits Created 5 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 2015 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 // This file contains an implementation of a VP9 bitstream parser.
6
7 #include "media/filters/vp9_parser.h"
8
9 #include "base/logging.h"
10
11 namespace {
12
13 // Helper function for Vp9Parser::ReadTiles. Defined as get_min_log2_tile_cols
14 // in spec.
15 int GetMinLog2TileCols(int sb64_cols) {
16 const int kMaxTileWidthB64 = 64;
17 int min_log2 = 0;
18 while ((kMaxTileWidthB64 << min_log2) < sb64_cols)
19 min_log2++;
20 return min_log2;
21 }
22
23 // Helper function for Vp9Parser::ReadTiles. Defined as get_max_log2_tile_cols
24 // in spec.
25 int GetMaxLog2TileCols(int sb64_cols) {
26 const int kMinTileWidthB64 = 4;
27 int max_log2 = 1;
28 while ((sb64_cols >> max_log2) >= kMinTileWidthB64)
29 max_log2++;
30 return max_log2 - 1;
31 }
32
33 } // namespace
34
35 namespace media {
36
37 void Vp9ReferenceSlots::Update(const Vp9FrameHeader& fhdr) {
38 for (size_t i = 0; i < kVp9NumRefFrames; i++) {
39 if (fhdr.refresh_flag[i]) {
40 slot[i].SetSize(fhdr.width, fhdr.height);
41 }
42 }
43 }
44
45 Vp9Parser::Vp9Parser() : stream_(nullptr), size_(0) {}
46
47 uint8_t Vp9Parser::ReadProfile() {
48 uint8_t profile = 0;
49
50 // LSB first.
51 profile |= reader_.ReadBit();
52 profile |= reader_.ReadBit() << 1;
53 if (profile > 2)
54 profile += reader_.ReadBit();
55 return profile;
56 }
57
58 bool Vp9Parser::VerifySyncCode() {
59 const int kSyncCode = 0x498342;
60 if (reader_.ReadLiteral(8 * 3) != kSyncCode) {
61 DVLOG(1) << "Invalid frame sync code";
62 return false;
63 }
64 return true;
65 }
66
67 bool Vp9Parser::ReadBitDepthColorSpaceSampling(Vp9FrameHeader* fhdr) {
68 if (fhdr->profile >= 2) {
Ville-Mikko Rautio 2015/08/02 23:43:49 if (profile == 2 || profile == 3) { ... to make t
kcwu 2015/08/03 10:05:52 Done.
69 if (reader_.ReadBit())
70 fhdr->bit_depth = 12;
71 else
72 fhdr->bit_depth = 10;
73 } else {
74 fhdr->bit_depth = 8;
75 }
76
77 fhdr->color_space = static_cast<Vp9ColorSpace>(reader_.ReadLiteral(3));
78 if (fhdr->color_space != Vp9ColorSpace::SRGB) {
79 fhdr->yuv_range = reader_.ReadBit();
80 if (fhdr->profile == 1 || fhdr->profile == 3) {
81 fhdr->subsampling_x = reader_.ReadBit();
82 fhdr->subsampling_y = reader_.ReadBit();
83 if (fhdr->subsampling_x == 1 && fhdr->subsampling_y == 1) {
84 DVLOG(1) << "4:2:0 color not supported in profile 1 or 3";
85 return false;
86 }
87 bool reserved = reader_.ReadBit();
88 if (reserved) {
89 DVLOG(1) << "reserved bit set";
90 return false;
91 }
92 } else {
93 fhdr->subsampling_x = fhdr->subsampling_y = 1;
94 }
95 } else {
96 if (fhdr->profile == 1 || fhdr->profile == 3) {
97 fhdr->subsampling_x = fhdr->subsampling_y = 0;
98
99 // this bit is not specified in spec??
Ville-Mikko Rautio 2015/08/02 23:43:49 s/this bit is not specified in spec??//
kcwu 2015/08/03 10:05:52 Done.
100 bool reserved = reader_.ReadBit();
101 if (reserved) {
102 DVLOG(1) << "reserved bit set";
103 return false;
104 }
105 } else {
106 DVLOG(1) << "4:4:4 color not supported in profile 0 or 2";
107 return false;
108 }
109 }
110
111 return true;
112 }
113
114 void Vp9Parser::ReadFrameSize(Vp9FrameHeader* fhdr) {
115 fhdr->width = reader_.ReadLiteral(16) + 1;
116 fhdr->height = reader_.ReadLiteral(16) + 1;
117 }
118
119 bool Vp9Parser::ReadFrameSizeFromRefs(const Vp9ReferenceSlots& ref_slots,
120 Vp9FrameHeader* fhdr) {
121 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
122 if (reader_.ReadBit()) {
123 fhdr->width = ref_slots.slot[i].width();
124 fhdr->height = ref_slots.slot[i].height();
125
126 const int kMaxDimension = 1 << 16;
127 if (!(1 <= fhdr->width && fhdr->width <= kMaxDimension &&
128 1 <= fhdr->height && fhdr->height <= kMaxDimension)) {
Pawel Osciak 2015/08/01 15:22:48 if (width < 1 || width > kMaxDimension || height <
kcwu 2015/08/03 10:05:52 Done.
129 DVLOG(1) << "The size of referenced frame is out of range: "
130 << ref_slots.slot[i].ToString();
131 return false;
132 }
133 return true;
134 }
135 }
136
137 fhdr->width = reader_.ReadLiteral(16) + 1;
138 fhdr->height = reader_.ReadLiteral(16) + 1;
139 return true;
140 }
141
142 void Vp9Parser::ReadDisplayFrameSize(Vp9FrameHeader* fhdr) {
143 if (reader_.ReadBit()) {
144 fhdr->display_width = reader_.ReadLiteral(16) + 1;
145 fhdr->display_height = reader_.ReadLiteral(16) + 1;
146 } else {
147 fhdr->display_width = fhdr->width;
148 fhdr->display_height = fhdr->height;
149 }
150 }
151
152 Vp9InterpFilter Vp9Parser::ReadInterpFilter() {
153 if (reader_.ReadBit())
154 return Vp9InterpFilter::INTERP_FILTER_SELECT;
155
156 // The mapping table for next two bits.
157 const Vp9InterpFilter table[] = {
158 Vp9InterpFilter::EIGHTTAP_SMOOTH, Vp9InterpFilter::EIGHTTAP,
159 Vp9InterpFilter::EIGHTTAP_SHARP, Vp9InterpFilter::BILINEAR,
160 };
161 return table[reader_.ReadLiteral(2)];
162 }
163
164 void Vp9Parser::ReadLoopFilter(Vp9LoopFilter* loop_filter) {
165 loop_filter->filter_level = reader_.ReadLiteral(6);
166 loop_filter->sharpness_level = reader_.ReadLiteral(3);
167
168 loop_filter->mode_ref_delta_enabled = reader_.ReadBit();
169 if (loop_filter->mode_ref_delta_enabled) {
170 loop_filter->mode_ref_delta_update = reader_.ReadBit();
171 if (loop_filter->mode_ref_delta_update) {
172 for (size_t i = 0; i < Vp9LoopFilter::kNumRefDeltas; i++) {
173 loop_filter->update_ref_deltas[i] = reader_.ReadBit();
174 if (loop_filter->update_ref_deltas[i])
175 loop_filter->ref_deltas[i] = reader_.ReadSignedLiteral(6);
176 }
177
178 for (size_t i = 0; i < Vp9LoopFilter::kNumModeDeltas; i++) {
179 loop_filter->update_mode_deltas[i] = reader_.ReadBit();
180 if (loop_filter->update_mode_deltas[i])
181 loop_filter->mode_deltas[i] = reader_.ReadLiteral(6);
182 }
183 }
184 }
185 }
186
187 void Vp9Parser::ReadQuantization(Vp9QuantizationParams* quants) {
188 quants->base_qindex = reader_.ReadLiteral(8);
189
190 if (reader_.ReadBit())
191 quants->y_dc_delta = reader_.ReadSignedLiteral(4);
192
193 if (reader_.ReadBit())
194 quants->uv_ac_delta = reader_.ReadSignedLiteral(4);
195
196 if (reader_.ReadBit())
197 quants->uv_dc_delta = reader_.ReadSignedLiteral(4);
198 }
199
200 void Vp9Parser::ReadSegmentationMap(Vp9Segmentation* segment) {
201 for (size_t i = 0; i < Vp9Segmentation::kNumTreeProbs; i++) {
202 if (reader_.ReadBit())
203 segment->tree_probs[i] = reader_.ReadLiteral(8);
204 else
205 segment->tree_probs[i] = kVp9MaxProb;
206 }
207
208 for (size_t i = 0; i < Vp9Segmentation::kNumPredictionProbs; i++)
209 segment->pred_probs[i] = kVp9MaxProb;
210 segment->temporal_update = reader_.ReadBit();
Pawel Osciak 2015/08/01 15:22:48 Empty line above please.
kcwu 2015/08/03 10:05:52 Done.
211 if (segment->temporal_update) {
212 for (size_t i = 0; i < Vp9Segmentation::kNumPredictionProbs; i++) {
213 if (reader_.ReadBit())
214 segment->pred_probs[i] = reader_.ReadLiteral(8);
215 }
216 }
217 }
218
219 void Vp9Parser::ReadSegmentationData(Vp9Segmentation* segment) {
220 segment->abs_delta = reader_.ReadBit();
221
222 const int kFeatureDataBits[] = {7, 6, 2, 0};
223 const bool kFeatureDataSigned[] = {true, true, false, false};
224
225 for (size_t i = 0; i < Vp9Segmentation::kNumSegments; i++) {
226 for (size_t j = 0; j < Vp9Segmentation::kNumFeature; j++) {
227 int8_t data = 0;
228 segment->feature_enabled[i][j] = reader_.ReadBit();
229 if (segment->feature_enabled[i][j]) {
230 data = reader_.ReadLiteral(kFeatureDataBits[j]);
231 if (kFeatureDataSigned[j])
232 if (reader_.ReadBit())
233 data = -data;
234 }
235 segment->feature_data[i][j] = data;
236 }
237 }
238 }
239
240 void Vp9Parser::ReadSegmentation(Vp9Segmentation* segment) {
241 segment->enabled = reader_.ReadBit();
242
243 if (!segment->enabled) {
244 return;
245 }
246
247 segment->update_map = reader_.ReadBit();
248 if (segment->update_map)
249 ReadSegmentationMap(segment);
250
251 segment->update_data = reader_.ReadBit();
252 if (segment->update_data)
253 ReadSegmentationData(segment);
254 }
255
256 void Vp9Parser::ReadTiles(Vp9FrameHeader* fhdr) {
257 int sb64_cols = (fhdr->width + 63) / 64;
258
259 int min_log2_tile_cols = GetMinLog2TileCols(sb64_cols);
260 int max_log2_tile_cols = GetMaxLog2TileCols(sb64_cols);
261
262 int max_ones = max_log2_tile_cols - min_log2_tile_cols;
263 fhdr->log2_tile_cols = min_log2_tile_cols;
264 while (max_ones-- && reader_.ReadBit())
265 fhdr->log2_tile_cols++;
266
267 if (reader_.ReadBit())
268 fhdr->log2_tile_rows = reader_.ReadLiteral(2) - 1;
269 }
270
271 bool Vp9Parser::ParseUncompressedHeader(const Vp9ReferenceSlots& ref_slots,
272 Vp9FrameHeader* fhdr) {
273 reader_.Initialize(stream_, size_);
274
275 // frame marker
276 if (reader_.ReadLiteral(2) != 0x2)
277 return false;
278
279 fhdr->profile = ReadProfile();
280 if (fhdr->profile >= kVp9MaxProfile) {
281 DVLOG(1) << "Unsupported bitstream profile";
282 return false;
283 }
284
285 fhdr->show_existing_frame = reader_.ReadBit();
286 if (fhdr->show_existing_frame) {
287 fhdr->frame_to_show = reader_.ReadLiteral(3);
288 fhdr->show_frame = true;
289
290 if (reader_.IsOutOfBuffer()) {
291 DVLOG(1) << "parser reads beyond the end of buffer";
292 return false;
293 }
294 fhdr->uncompressed_header_size = reader_.GetBytesRead();
295 return true;
296 }
297
298 fhdr->frame_type = static_cast<Vp9FrameHeader::FrameType>(reader_.ReadBit());
299 fhdr->show_frame = reader_.ReadBit();
300 fhdr->error_resilient_mode = reader_.ReadBit();
301
302 if (fhdr->IsKeyframe()) {
303 if (!VerifySyncCode())
304 return false;
305
306 if (!ReadBitDepthColorSpaceSampling(fhdr))
307 return false;
308
309 for (size_t i = 0; i < kVp9NumRefFrames; i++)
310 fhdr->refresh_flag[i] = true;
311
312 ReadFrameSize(fhdr);
313 ReadDisplayFrameSize(fhdr);
314 } else {
315 if (!fhdr->show_frame)
316 fhdr->intra_only = reader_.ReadBit();
317
318 if (!fhdr->error_resilient_mode)
319 fhdr->reset_context = reader_.ReadLiteral(2);
320
321 if (fhdr->intra_only) {
322 if (!VerifySyncCode())
323 return false;
324
325 if (fhdr->profile > 0) {
326 if (!ReadBitDepthColorSpaceSampling(fhdr))
327 return false;
328 } else {
329 fhdr->bit_depth = 8;
330 fhdr->color_space = Vp9ColorSpace::BT_601;
331 fhdr->subsampling_x = fhdr->subsampling_y = 1;
332 }
333
334 for (size_t i = 0; i < kVp9NumRefFrames; i++)
335 fhdr->refresh_flag[i] = reader_.ReadBit();
336 ReadFrameSize(fhdr);
337 ReadDisplayFrameSize(fhdr);
338 } else {
339 for (size_t i = 0; i < kVp9NumRefFrames; i++)
340 fhdr->refresh_flag[i] = reader_.ReadBit();
341
342 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
343 fhdr->frame_refs[i] = reader_.ReadLiteral(kVp9NumRefFramesLog2);
344 fhdr->ref_sign_biases[i] = reader_.ReadBit();
345 }
346
347 if (!ReadFrameSizeFromRefs(ref_slots, fhdr))
348 return false;
349 ReadDisplayFrameSize(fhdr);
350
351 fhdr->allow_high_precision_mv = reader_.ReadBit();
352 fhdr->interp_filter = ReadInterpFilter();
353 }
354 }
355
356 if (fhdr->error_resilient_mode) {
357 fhdr->frame_parallel_decoding_mode = true;
358 } else {
359 fhdr->refresh_frame_context = reader_.ReadBit();
360 fhdr->frame_parallel_decoding_mode = reader_.ReadBit();
361 }
362
363 fhdr->frame_context_idx = reader_.ReadLiteral(2);
364
365 ReadLoopFilter(&fhdr->loop_filter);
366 ReadQuantization(&fhdr->quant_params);
367 ReadSegmentation(&fhdr->segment);
368
369 ReadTiles(fhdr);
370
371 fhdr->first_partition_size = reader_.ReadLiteral(16);
372 if (fhdr->first_partition_size == 0) {
373 DVLOG(1) << "invalid header size";
374 return false;
375 }
376
377 if (reader_.IsOutOfBuffer()) {
378 DVLOG(1) << "parser reads beyond the end of buffer";
379 return false;
380 }
381 fhdr->uncompressed_header_size = reader_.GetBytesRead();
382
383 return true;
384 }
385
386 bool Vp9Parser::ParseFrame(const uint8_t* stream,
387 size_t frame_size,
388 const Vp9ReferenceSlots& ref_slots,
389 Vp9FrameHeader* fhdr) {
390 stream_ = stream;
391 size_ = frame_size;
392 memset(fhdr, 0, sizeof(*fhdr));
393
394 return ParseUncompressedHeader(ref_slots, fhdr);
Pawel Osciak 2015/08/01 15:22:48 Sorry, I think I introduced some confusion, but I
kcwu 2015/08/03 10:05:52 Done.
395 }
396
397 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698