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