Shaka Packager SDK
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 
16 namespace shaka {
17 namespace media {
18 namespace {
19 
20 const uint32_t VP9_FRAME_MARKER = 2;
21 const uint32_t VP9_SYNC_CODE = 0x498342;
22 const uint32_t REFS_PER_FRAME = 3;
23 const uint32_t REF_FRAMES_LOG2 = 3;
24 const uint32_t REF_FRAMES = (1 << REF_FRAMES_LOG2);
25 const uint32_t FRAME_CONTEXTS_LOG2 = 2;
26 const uint32_t MAX_REF_LF_DELTAS = 4;
27 const uint32_t MAX_MODE_LF_DELTAS = 2;
28 const uint32_t QINDEX_BITS = 8;
29 const uint32_t MAX_SEGMENTS = 8;
30 const uint32_t SEG_TREE_PROBS = (MAX_SEGMENTS - 1);
31 const uint32_t PREDICTION_PROBS = 3;
32 const uint32_t SEG_LVL_MAX = 4;
33 const uint32_t MI_SIZE_LOG2 = 3;
34 const uint32_t MI_BLOCK_SIZE_LOG2 = (6 - MI_SIZE_LOG2); // 64 = 2^6
35 const uint32_t MIN_TILE_WIDTH_B64 = 4;
36 const uint32_t MAX_TILE_WIDTH_B64 = 64;
37 
38 const bool SEG_FEATURE_DATA_SIGNED[SEG_LVL_MAX] = {true, true, false, false};
39 const uint32_t SEG_FEATURE_DATA_MAX_BITS[SEG_LVL_MAX] = {8, 6, 2, 0};
40 
41 enum 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 
52 uint32_t RoundupShift(uint32_t value, uint32_t n) {
53  return (value + (1 << n) - 1) >> n;
54 }
55 
56 // Number of MI-units (8*8).
57 uint32_t GetNumMiUnits(uint32_t pixels) {
58  return RoundupShift(pixels, MI_SIZE_LOG2);
59 }
60 
61 // Number of sb64 (64x64) blocks per mi_units.
62 uint32_t GetNumBlocks(uint32_t mi_units) {
63  return RoundupShift(mi_units, MI_BLOCK_SIZE_LOG2);
64 }
65 
66 uint32_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 
73 uint32_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 
80 void 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.
93 bool 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 
146 bool 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 
160 bool ReadSyncCode(BitReader* reader) {
161  uint32_t sync_code;
162  RCHECK(reader->ReadBits(24, &sync_code));
163  return sync_code == VP9_SYNC_CODE;
164 }
165 
166 void 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 
229 VPCodecConfigurationRecord::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 
249 bool 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 
313 bool 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 
321 bool 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 
331 bool 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 
350 bool 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 
369 bool 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 
385 bool 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 
393 bool 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 
432 bool 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 
456 VP9Parser::VP9Parser() : width_(0), height_(0) {}
457 VP9Parser::~VP9Parser() {}
458 
459 bool 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 
576 bool 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.
Definition: crypto_flags.cc:66