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

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

Powered by Google App Engine
This is Rietveld 408576698