Shaka Packager SDK
Loading...
Searching...
No Matches
vp9_parser.cc
1// Copyright 2015 Google LLC. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file or at
5// https://developers.google.com/open-source/licenses/bsd
6
7#include <packager/media/codecs/vp9_parser.h>
8
9#include <absl/log/check.h>
10#include <absl/log/log.h>
11
12#include <packager/macros/logging.h>
13#include <packager/media/base/bit_reader.h>
14#include <packager/media/base/rcheck.h>
15
16namespace shaka {
17namespace media {
18namespace {
19
20const uint32_t VP9_FRAME_MARKER = 2;
21const uint32_t VP9_SYNC_CODE = 0x498342;
22const uint32_t REFS_PER_FRAME = 3;
23const uint32_t REF_FRAMES_LOG2 = 3;
24const uint32_t REF_FRAMES = (1 << REF_FRAMES_LOG2);
25const uint32_t FRAME_CONTEXTS_LOG2 = 2;
26const uint32_t MAX_REF_LF_DELTAS = 4;
27const uint32_t MAX_MODE_LF_DELTAS = 2;
28const uint32_t QINDEX_BITS = 8;
29const uint32_t MAX_SEGMENTS = 8;
30const uint32_t SEG_TREE_PROBS = (MAX_SEGMENTS - 1);
31const uint32_t PREDICTION_PROBS = 3;
32const uint32_t SEG_LVL_MAX = 4;
33const uint32_t MI_SIZE_LOG2 = 3;
34const uint32_t MI_BLOCK_SIZE_LOG2 = (6 - MI_SIZE_LOG2); // 64 = 2^6
35const uint32_t MIN_TILE_WIDTH_B64 = 4;
36const uint32_t MAX_TILE_WIDTH_B64 = 64;
37
38const bool SEG_FEATURE_DATA_SIGNED[SEG_LVL_MAX] = {true, true, false, false};
39const uint32_t SEG_FEATURE_DATA_MAX_BITS[SEG_LVL_MAX] = {8, 6, 2, 0};
40
41enum VpxColorSpace {
42 VPX_COLOR_SPACE_UNKNOWN = 0,
43 VPX_COLOR_SPACE_BT_601 = 1,
44 VPX_COLOR_SPACE_BT_709 = 2,
45 VPX_COLOR_SPACE_SMPTE_170 = 3,
46 VPX_COLOR_SPACE_SMPTE_240 = 4,
47 VPX_COLOR_SPACE_BT_2020 = 5,
48 VPX_COLOR_SPACE_RESERVED = 6,
49 VPX_COLOR_SPACE_SRGB = 7,
50};
51
52uint32_t RoundupShift(uint32_t value, uint32_t n) {
53 return (value + (1 << n) - 1) >> n;
54}
55
56// Number of MI-units (8*8).
57uint32_t GetNumMiUnits(uint32_t pixels) {
58 return RoundupShift(pixels, MI_SIZE_LOG2);
59}
60
61// Number of sb64 (64x64) blocks per mi_units.
62uint32_t GetNumBlocks(uint32_t mi_units) {
63 return RoundupShift(mi_units, MI_BLOCK_SIZE_LOG2);
64}
65
66uint32_t GetMinLog2TileCols(uint32_t sb64_cols) {
67 uint32_t min_log2 = 0;
68 while ((MAX_TILE_WIDTH_B64 << min_log2) < sb64_cols)
69 ++min_log2;
70 return min_log2;
71}
72
73uint32_t GetMaxLog2TileCols(uint32_t sb64_cols) {
74 uint32_t max_log2 = 1;
75 while ((sb64_cols >> max_log2) >= MIN_TILE_WIDTH_B64)
76 ++max_log2;
77 return max_log2 - 1;
78}
79
80void GetTileNBits(uint32_t mi_cols,
81 uint32_t* min_log2_tile_cols,
82 uint32_t* max_log2_tile_cols) {
83 const uint32_t sb64_cols = GetNumBlocks(mi_cols);
84 *min_log2_tile_cols = GetMinLog2TileCols(sb64_cols);
85 *max_log2_tile_cols = GetMaxLog2TileCols(sb64_cols);
86 CHECK_LE(*min_log2_tile_cols, *max_log2_tile_cols);
87}
88
89// Parse superframe index if it is a superframe. Fill |vpx_frames| with the
90// frames information, which contains the sizes of the frames indicated in
91// superframe index if it is a superframe; otherwise it should contain one
92// single frame with |data_size| as frame size.
93bool ParseIfSuperframeIndex(const uint8_t* data,
94 size_t data_size,
95 std::vector<VPxFrameInfo>* vpx_frames) {
96 vpx_frames->clear();
97 uint8_t superframe_marker = data[data_size - 1];
98 VPxFrameInfo vpx_frame;
99 if ((superframe_marker & 0xe0) != 0xc0) {
100 // This is not a super frame. There should be only one frame.
101 vpx_frame.frame_size = data_size;
102 vpx_frames->push_back(vpx_frame);
103 return true;
104 }
105
106 const size_t num_frames = (superframe_marker & 0x07) + 1;
107 const size_t frame_size_length = ((superframe_marker >> 3) & 0x03) + 1;
108 // Two maker bytes + frame sizes.
109 const size_t index_size = 2 + num_frames * frame_size_length;
110
111 if (data_size < index_size) {
112 LOG(ERROR) << "This chunk is marked as having a superframe index but "
113 "doesn't have enough data for it.";
114 return false;
115 }
116 const uint8_t superframe_marker2 = data[data_size - index_size];
117 if (superframe_marker2 != superframe_marker) {
118 LOG(ERROR) << "This chunk is marked as having a superframe index but "
119 "doesn't have the matching marker byte at the front of the "
120 "index.";
121 return false;
122 }
123 VLOG(3) << "Superframe num_frames=" << num_frames
124 << " frame_size_length=" << frame_size_length;
125
126 data += data_size - index_size + 1;
127 size_t total_frame_sizes = 0;
128 for (size_t frame = 0; frame < num_frames; ++frame) {
129 vpx_frame.frame_size = 0;
130 for (size_t i = 0; i < frame_size_length; ++i) {
131 vpx_frame.frame_size |= *data << (i * 8);
132 ++data;
133 }
134 total_frame_sizes += vpx_frame.frame_size;
135 vpx_frames->push_back(vpx_frame);
136 }
137 if (total_frame_sizes + index_size != data_size) {
138 LOG(ERROR) << "Data size (" << data_size
139 << ") does not match with sum of frame sizes ("
140 << total_frame_sizes << ") + index_size (" << index_size << ")";
141 return false;
142 }
143 return true;
144}
145
146bool ReadProfile(BitReader* reader, VPCodecConfigurationRecord* codec_config) {
147 uint8_t bit[2];
148 RCHECK(reader->ReadBits(1, &bit[0]));
149 RCHECK(reader->ReadBits(1, &bit[1]));
150 uint8_t profile = bit[0] | (bit[1] << 1);
151 if (profile == 3) {
152 bool reserved;
153 RCHECK(reader->ReadBits(1, &reserved));
154 RCHECK(!reserved);
155 }
156 codec_config->set_profile(profile);
157 return true;
158}
159
160bool ReadSyncCode(BitReader* reader) {
161 uint32_t sync_code;
162 RCHECK(reader->ReadBits(24, &sync_code));
163 return sync_code == VP9_SYNC_CODE;
164}
165
166void SetColorAttributes(uint8_t bit_depth,
167 uint8_t color_space,
168 VPCodecConfigurationRecord* codec_config) {
169 switch (color_space) {
170 case VPX_COLOR_SPACE_UNKNOWN:
171 codec_config->set_color_primaries(AVCOL_PRI_UNSPECIFIED);
172 codec_config->set_matrix_coefficients(AVCOL_SPC_UNSPECIFIED);
173 codec_config->set_transfer_characteristics(AVCOL_TRC_UNSPECIFIED);
174 break;
175 case VPX_COLOR_SPACE_BT_601:
176 // Don't know if it is 525 line or 625 line.
177 codec_config->set_color_primaries(AVCOL_PRI_UNSPECIFIED);
178 codec_config->set_matrix_coefficients(AVCOL_SPC_UNSPECIFIED);
179 codec_config->set_transfer_characteristics(AVCOL_TRC_SMPTE170M);
180 break;
181 case VPX_COLOR_SPACE_BT_709:
182 codec_config->set_color_primaries(AVCOL_PRI_BT709);
183 codec_config->set_matrix_coefficients(AVCOL_SPC_BT709);
184 codec_config->set_transfer_characteristics(AVCOL_TRC_BT709);
185 break;
186 case VPX_COLOR_SPACE_SMPTE_170:
187 codec_config->set_color_primaries(AVCOL_PRI_SMPTE170M);
188 codec_config->set_matrix_coefficients(AVCOL_SPC_SMPTE170M);
189 codec_config->set_transfer_characteristics(AVCOL_TRC_SMPTE170M);
190 break;
191 case VPX_COLOR_SPACE_SMPTE_240:
192 codec_config->set_color_primaries(AVCOL_PRI_SMPTE240M);
193 codec_config->set_matrix_coefficients(AVCOL_SPC_SMPTE240M);
194 codec_config->set_transfer_characteristics(AVCOL_TRC_SMPTE240M);
195 break;
196 case VPX_COLOR_SPACE_BT_2020:
197 codec_config->set_color_primaries(AVCOL_PRI_BT2020);
198 // VP9 does not specify if it is in the form of “constant luminance” or
199 // “non-constant luminance”. As such, application should rely on the
200 // signaling outside of VP9 bitstream. If there is no such signaling,
201 // application may assume non-constant luminance for BT.2020.
202 codec_config->set_matrix_coefficients(AVCOL_SPC_BT2020_NCL);
203 switch (bit_depth) {
204 case 10:
205 codec_config->set_transfer_characteristics(AVCOL_TRC_BT2020_10);
206 break;
207 case 12:
208 codec_config->set_transfer_characteristics(AVCOL_TRC_BT2020_12);
209 break;
210 default:
211 codec_config->set_transfer_characteristics(AVCOL_TRC_UNSPECIFIED);
212 break;
213 }
214 break;
215 case VPX_COLOR_SPACE_SRGB:
216 codec_config->set_color_primaries(AVCOL_PRI_UNSPECIFIED);
217 codec_config->set_matrix_coefficients(AVCOL_SPC_RGB);
218 codec_config->set_transfer_characteristics(AVCOL_TRC_UNSPECIFIED);
219 break;
220 default:
221 LOG(WARNING) << "Unknown color space: " << static_cast<int>(color_space);
222 codec_config->set_color_primaries(AVCOL_PRI_UNSPECIFIED);
223 codec_config->set_matrix_coefficients(AVCOL_SPC_UNSPECIFIED);
224 codec_config->set_transfer_characteristics(AVCOL_TRC_UNSPECIFIED);
225 break;
226 }
227}
228
229VPCodecConfigurationRecord::ChromaSubsampling GetChromaSubsampling(
230 uint8_t subsampling) {
231 switch (subsampling) {
232 case 0:
233 return VPCodecConfigurationRecord::CHROMA_444;
234 case 1:
235 return VPCodecConfigurationRecord::CHROMA_440;
236 case 2:
237 return VPCodecConfigurationRecord::CHROMA_422;
238 case 3:
239 // VP9 assumes that chrome samples are collocated with luma samples if
240 // there is no explicit signaling outside of VP9 bitstream.
241 return VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA;
242 default:
243 LOG(WARNING) << "Unexpected chroma subsampling value: "
244 << static_cast<int>(subsampling);
245 return VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA;
246 }
247}
248
249bool ReadBitDepthAndColorSpace(BitReader* reader,
250 VPCodecConfigurationRecord* codec_config) {
251 uint8_t bit_depth = 8;
252 if (codec_config->profile() >= 2) {
253 bool use_vpx_bits_12;
254 RCHECK(reader->ReadBits(1, &use_vpx_bits_12));
255 bit_depth = use_vpx_bits_12 ? 12 : 10;
256 }
257 codec_config->set_bit_depth(bit_depth);
258
259 uint8_t color_space;
260 RCHECK(reader->ReadBits(3, &color_space));
261 SetColorAttributes(bit_depth, color_space, codec_config);
262
263 bool yuv_full_range = false;
264 auto chroma_subsampling = VPCodecConfigurationRecord::CHROMA_444;
265 if (color_space != VPX_COLOR_SPACE_SRGB) {
266 RCHECK(reader->ReadBits(1, &yuv_full_range));
267
268 if (codec_config->profile() & 1) {
269 uint8_t subsampling;
270 RCHECK(reader->ReadBits(2, &subsampling));
271 chroma_subsampling = GetChromaSubsampling(subsampling);
272 if (chroma_subsampling ==
273 VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA) {
274 LOG(ERROR) << "4:2:0 color not supported in profile "
275 << static_cast<int>(codec_config->profile());
276 return false;
277 }
278
279 bool reserved;
280 RCHECK(reader->ReadBits(1, &reserved));
281 RCHECK(!reserved);
282 } else {
283 chroma_subsampling =
284 VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA;
285 }
286 } else {
287 // Assume 4:4:4 for colorspace SRGB.
288 yuv_full_range = true;
289 chroma_subsampling = VPCodecConfigurationRecord::CHROMA_444;
290 if (codec_config->profile() & 1) {
291 bool reserved;
292 RCHECK(reader->ReadBits(1, &reserved));
293 RCHECK(!reserved);
294 } else {
295 LOG(ERROR) << "4:4:4 color not supported in profile 0 or 2.";
296 return false;
297 }
298 }
299 codec_config->set_video_full_range_flag(yuv_full_range);
300 codec_config->SetChromaSubsampling(chroma_subsampling);
301
302 VLOG(3) << "\n profile " << static_cast<int>(codec_config->profile())
303 << "\n bit depth " << static_cast<int>(codec_config->bit_depth())
304 << "\n matrix coefficients "
305 << static_cast<int>(codec_config->matrix_coefficients())
306 << "\n full_range "
307 << static_cast<int>(codec_config->video_full_range_flag())
308 << "\n chroma subsampling "
309 << static_cast<int>(codec_config->chroma_subsampling());
310 return true;
311}
312
313bool ReadFrameSize(BitReader* reader, uint32_t* width, uint32_t* height) {
314 RCHECK(reader->ReadBits(16, width));
315 *width += 1; // Off by 1.
316 RCHECK(reader->ReadBits(16, height));
317 *height += 1; // Off by 1.
318 return true;
319}
320
321bool ReadDisplayFrameSize(BitReader* reader,
322 uint32_t* display_width,
323 uint32_t* display_height) {
324 bool has_display_size;
325 RCHECK(reader->ReadBits(1, &has_display_size));
326 if (has_display_size)
327 RCHECK(ReadFrameSize(reader, display_width, display_height));
328 return true;
329}
330
331bool ReadFrameSizes(BitReader* reader, uint32_t* width, uint32_t* height) {
332 uint32_t new_width;
333 uint32_t new_height;
334 RCHECK(ReadFrameSize(reader, &new_width, &new_height));
335 if (new_width != *width) {
336 VLOG(1) << "Width updates from " << *width << " to " << new_width;
337 *width = new_width;
338 }
339 if (new_height != *height) {
340 VLOG(1) << "Height updates from " << *height << " to " << new_height;
341 *height = new_height;
342 }
343
344 uint32_t display_width = *width;
345 uint32_t display_height = *height;
346 RCHECK(ReadDisplayFrameSize(reader, &display_width, &display_height));
347 return true;
348}
349
350bool ReadFrameSizesWithRefs(BitReader* reader,
351 uint32_t* width,
352 uint32_t* height) {
353 bool found = false;
354 for (uint32_t i = 0; i < REFS_PER_FRAME; ++i) {
355 RCHECK(reader->ReadBits(1, &found));
356 if (found)
357 break;
358 }
359 if (!found) {
360 RCHECK(ReadFrameSizes(reader, width, height));
361 } else {
362 uint32_t display_width;
363 uint32_t display_height;
364 RCHECK(ReadDisplayFrameSize(reader, &display_width, &display_height));
365 }
366 return true;
367}
368
369bool ReadLoopFilter(BitReader* reader) {
370 RCHECK(reader->SkipBits(9)); // filter_evel, sharness_level
371 bool mode_ref_delta_enabled;
372 RCHECK(reader->ReadBits(1, &mode_ref_delta_enabled));
373 if (!mode_ref_delta_enabled)
374 return true;
375 bool mode_ref_delta_update;
376 RCHECK(reader->ReadBits(1, &mode_ref_delta_update));
377 if (!mode_ref_delta_update)
378 return true;
379
380 for (uint32_t i = 0; i < MAX_REF_LF_DELTAS + MAX_MODE_LF_DELTAS; ++i)
381 RCHECK(reader->SkipBitsConditional(true, 6 + 1));
382 return true;
383}
384
385bool ReadQuantization(BitReader* reader) {
386 RCHECK(reader->SkipBits(QINDEX_BITS));
387 // Skip delta_q bits.
388 for (uint32_t i = 0; i < 3; ++i)
389 RCHECK(reader->SkipBitsConditional(true, 4 + 1));
390 return true;
391}
392
393bool ReadSegmentation(BitReader* reader) {
394 bool enabled;
395 RCHECK(reader->ReadBits(1, &enabled));
396 if (!enabled)
397 return true;
398
399 bool update_map;
400 RCHECK(reader->ReadBits(1, &update_map));
401 if (update_map) {
402 for (uint32_t i = 0; i < SEG_TREE_PROBS; ++i)
403 RCHECK(reader->SkipBitsConditional(true, 8));
404
405 bool temporal_update;
406 RCHECK(reader->ReadBits(1, &temporal_update));
407 if (temporal_update) {
408 for (uint32_t j = 0; j < PREDICTION_PROBS; ++j)
409 RCHECK(reader->SkipBitsConditional(true, 8));
410 }
411 }
412
413 bool update_data;
414 RCHECK(reader->ReadBits(1, &update_data));
415 if (update_data) {
416 RCHECK(reader->SkipBits(1)); // abs_delta
417 for (uint32_t i = 0; i < MAX_SEGMENTS; ++i) {
418 for (uint32_t j = 0; j < SEG_LVL_MAX; ++j) {
419 bool feature_enabled;
420 RCHECK(reader->ReadBits(1, &feature_enabled));
421 if (feature_enabled) {
422 RCHECK(reader->SkipBits(SEG_FEATURE_DATA_MAX_BITS[j]));
423 if (SEG_FEATURE_DATA_SIGNED[j])
424 RCHECK(reader->SkipBits(1)); // signness
425 }
426 }
427 }
428 }
429 return true;
430}
431
432bool ReadTileInfo(uint32_t width, BitReader* reader) {
433 uint32_t mi_cols = GetNumMiUnits(width);
434
435 uint32_t min_log2_tile_cols;
436 uint32_t max_log2_tile_cols;
437 GetTileNBits(mi_cols, &min_log2_tile_cols, &max_log2_tile_cols);
438 uint32_t max_ones = max_log2_tile_cols - min_log2_tile_cols;
439
440 uint32_t log2_tile_cols = min_log2_tile_cols;
441 while (max_ones--) {
442 bool has_more;
443 RCHECK(reader->ReadBits(1, &has_more));
444 if (!has_more)
445 break;
446 ++log2_tile_cols;
447 }
448 RCHECK(log2_tile_cols <= 6);
449
450 RCHECK(reader->SkipBitsConditional(true, 1)); // log2_tile_rows
451 return true;
452}
453
454} // namespace
455
456VP9Parser::VP9Parser() : width_(0), height_(0) {}
457VP9Parser::~VP9Parser() {}
458
459bool VP9Parser::Parse(const uint8_t* data,
460 size_t data_size,
461 std::vector<VPxFrameInfo>* vpx_frames) {
462 DCHECK(data);
463 DCHECK(vpx_frames);
464 RCHECK(ParseIfSuperframeIndex(data, data_size, vpx_frames));
465
466 for (auto& vpx_frame : *vpx_frames) {
467 VLOG(4) << "process frame with size " << vpx_frame.frame_size;
468 BitReader reader(data, vpx_frame.frame_size);
469 uint8_t frame_marker;
470 RCHECK(reader.ReadBits(2, &frame_marker));
471 RCHECK(frame_marker == VP9_FRAME_MARKER);
472
473 RCHECK(ReadProfile(&reader, writable_codec_config()));
474
475 bool show_existing_frame;
476 RCHECK(reader.ReadBits(1, &show_existing_frame));
477 if (show_existing_frame) {
478 RCHECK(reader.SkipBits(3)); // ref_frame_index
479 // End of current frame data. There should be no more bytes available.
480 RCHECK(reader.bits_available() < 8);
481
482 vpx_frame.is_keyframe = false;
483 vpx_frame.uncompressed_header_size = vpx_frame.frame_size;
484 vpx_frame.width = width_;
485 vpx_frame.height = height_;
486 continue;
487 }
488
489 bool is_interframe;
490 RCHECK(reader.ReadBits(1, &is_interframe));
491 vpx_frame.is_keyframe = !is_interframe;
492
493 bool show_frame;
494 RCHECK(reader.ReadBits(1, &show_frame));
495 bool error_resilient_mode;
496 RCHECK(reader.ReadBits(1, &error_resilient_mode));
497
498 if (vpx_frame.is_keyframe) {
499 RCHECK(ReadSyncCode(&reader));
500 RCHECK(ReadBitDepthAndColorSpace(&reader, writable_codec_config()));
501 RCHECK(ReadFrameSizes(&reader, &width_, &height_));
502 } else {
503 bool intra_only = false;
504 if (!show_frame)
505 RCHECK(reader.ReadBits(1, &intra_only));
506 if (!error_resilient_mode)
507 RCHECK(reader.SkipBits(2)); // reset_frame_context
508
509 if (intra_only) {
510 RCHECK(ReadSyncCode(&reader));
511 if (codec_config().profile() > 0) {
512 RCHECK(ReadBitDepthAndColorSpace(&reader, writable_codec_config()));
513 } else {
514 // NOTE: The intra-only frame header does not include the
515 // specification of either the color format or color sub-sampling in
516 // profile 0. VP9 specifies that the default color format should be
517 // YUV 4:2:0 in this case (normative).
518 writable_codec_config()->SetChromaSubsampling(
519 VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA);
520 writable_codec_config()->set_bit_depth(8);
521 }
522
523 RCHECK(reader.SkipBits(REF_FRAMES)); // refresh_frame_flags
524 RCHECK(ReadFrameSizes(&reader, &width_, &height_));
525 } else {
526 RCHECK(reader.SkipBits(REF_FRAMES)); // refresh_frame_flags
527 RCHECK(reader.SkipBits(REFS_PER_FRAME * (REF_FRAMES_LOG2 + 1)));
528
529 // TODO(kqyang): We may need to actually build the refs to extract the
530 // correct width and height for the current frame. The width will be
531 // used later in ReadTileInfo.
532 RCHECK(ReadFrameSizesWithRefs(&reader, &width_, &height_));
533
534 RCHECK(reader.SkipBits(1)); // allow_high_precision_mv
535
536 bool interp_filter;
537 RCHECK(reader.ReadBits(1, &interp_filter));
538 if (!interp_filter)
539 RCHECK(reader.SkipBits(2)); // more interp_filter
540 }
541 }
542
543 if (!error_resilient_mode) {
544 RCHECK(reader.SkipBits(1)); // refresh_frame_context
545 RCHECK(reader.SkipBits(1)); // frame_parallel_decoding_mode
546 }
547 RCHECK(reader.SkipBits(FRAME_CONTEXTS_LOG2)); // frame_context_idx
548
549 VLOG(4) << "bits read before ReadLoopFilter: " << reader.bit_position();
550 RCHECK(ReadLoopFilter(&reader));
551 RCHECK(ReadQuantization(&reader));
552 RCHECK(ReadSegmentation(&reader));
553 RCHECK(ReadTileInfo(width_, &reader));
554
555 uint16_t header_size;
556 RCHECK(reader.ReadBits(16, &header_size));
557 vpx_frame.uncompressed_header_size =
558 vpx_frame.frame_size - reader.bits_available() / 8;
559 vpx_frame.width = width_;
560 vpx_frame.height = height_;
561
562 VLOG(3) << "\n frame_size: " << vpx_frame.frame_size
563 << "\n uncompressed_header_size: "
564 << vpx_frame.uncompressed_header_size
565 << "\n bits read: " << reader.bit_position()
566 << "\n header_size: " << header_size;
567
568 RCHECK(header_size > 0);
569 RCHECK(header_size * 8u <= reader.bits_available());
570
571 data += vpx_frame.frame_size;
572 }
573 return true;
574}
575
576bool VP9Parser::IsKeyframe(const uint8_t* data, size_t data_size) {
577 BitReader reader(data, data_size);
578 uint8_t frame_marker;
579 RCHECK(reader.ReadBits(2, &frame_marker));
580 RCHECK(frame_marker == VP9_FRAME_MARKER);
581
582 VPCodecConfigurationRecord codec_config;
583 RCHECK(ReadProfile(&reader, &codec_config));
584
585 bool show_existing_frame;
586 RCHECK(reader.ReadBits(1, &show_existing_frame));
587 if (show_existing_frame)
588 return false;
589
590 bool is_interframe;
591 RCHECK(reader.ReadBits(1, &is_interframe));
592 if (is_interframe)
593 return false;
594
595 RCHECK(reader.SkipBits(2)); // show_frame, error_resilient_mode.
596
597 RCHECK(ReadSyncCode(&reader));
598 return true;
599}
600
601} // namespace media
602} // namespace shaka
A class to read bit streams.
Definition bit_reader.h:20
size_t bit_position() const
Definition bit_reader.h:97
bool SkipBits(size_t num_bits)
Definition bit_reader.cc:26
size_t bits_available() const
Definition bit_reader.h:92
bool ReadBits(size_t num_bits, T *out)
Definition bit_reader.h:38
Class for parsing or writing VP codec configuration record.
All the methods that are virtual are virtual for mocking.