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