7 #include "packager/media/codecs/vp9_parser.h" 9 #include "packager/base/logging.h" 10 #include "packager/media/base/bit_reader.h" 11 #include "packager/media/base/rcheck.h" 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);
32 const uint32_t MIN_TILE_WIDTH_B64 = 4;
33 const uint32_t MAX_TILE_WIDTH_B64 = 64;
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};
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,
49 uint32_t RoundupShift(uint32_t value, uint32_t n) {
50 return (value + (1 << n) - 1) >> n;
54 uint32_t GetNumMiUnits(uint32_t pixels) {
55 return RoundupShift(pixels, MI_SIZE_LOG2);
59 uint32_t GetNumBlocks(uint32_t mi_units) {
60 return RoundupShift(mi_units, MI_BLOCK_SIZE_LOG2);
63 uint32_t GetMinLog2TileCols(uint32_t sb64_cols) {
64 uint32_t min_log2 = 0;
65 while ((MAX_TILE_WIDTH_B64 << min_log2) < sb64_cols)
70 uint32_t GetMaxLog2TileCols(uint32_t sb64_cols) {
71 uint32_t max_log2 = 1;
72 while ((sb64_cols >> max_log2) >= MIN_TILE_WIDTH_B64)
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);
90 bool ParseIfSuperframeIndex(
const uint8_t* data,
92 std::vector<VPxFrameInfo>* vpx_frames) {
94 uint8_t superframe_marker = data[data_size - 1];
95 VPxFrameInfo vpx_frame;
96 if ((superframe_marker & 0xe0) != 0xc0) {
98 vpx_frame.frame_size = data_size;
99 vpx_frames->push_back(vpx_frame);
103 const size_t num_frames = (superframe_marker & 0x07) + 1;
104 const size_t frame_size_length = ((superframe_marker >> 3) & 0x03) + 1;
106 const size_t index_size = 2 + num_frames * frame_size_length;
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.";
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 " 120 VLOG(3) <<
"Superframe num_frames=" << num_frames
121 <<
" frame_size_length=" << frame_size_length;
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);
131 total_frame_sizes += vpx_frame.frame_size;
132 vpx_frames->push_back(vpx_frame);
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 <<
")";
143 bool ReadProfile(BitReader* reader, VPCodecConfigurationRecord* codec_config) {
145 RCHECK(reader->ReadBits(1, &bit[0]));
146 RCHECK(reader->ReadBits(1, &bit[1]));
147 uint8_t profile = bit[0] | (bit[1] << 1);
150 RCHECK(reader->ReadBits(1, &reserved));
153 codec_config->set_profile(profile);
157 bool ReadSyncCode(BitReader* reader) {
159 RCHECK(reader->ReadBits(24, &sync_code));
160 return sync_code == VP9_SYNC_CODE;
163 void SetColorAttributes(uint8_t bit_depth,
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);
172 case VPX_COLOR_SPACE_BT_601:
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);
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);
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);
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);
193 case VPX_COLOR_SPACE_BT_2020:
194 codec_config->set_color_primaries(AVCOL_PRI_BT2020);
199 codec_config->set_matrix_coefficients(AVCOL_SPC_BT2020_NCL);
202 codec_config->set_transfer_characteristics(AVCOL_TRC_BT2020_10);
205 codec_config->set_transfer_characteristics(AVCOL_TRC_BT2020_12);
208 codec_config->set_transfer_characteristics(AVCOL_TRC_UNSPECIFIED);
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);
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);
226 VPCodecConfigurationRecord::ChromaSubsampling GetChromaSubsampling(
227 uint8_t subsampling) {
228 switch (subsampling) {
230 return VPCodecConfigurationRecord::CHROMA_444;
232 return VPCodecConfigurationRecord::CHROMA_440;
234 return VPCodecConfigurationRecord::CHROMA_422;
238 return VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA;
240 LOG(WARNING) <<
"Unexpected chroma subsampling value: " 241 <<
static_cast<int>(subsampling);
242 return VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA;
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;
254 codec_config->set_bit_depth(bit_depth);
257 RCHECK(reader->ReadBits(3, &color_space));
258 SetColorAttributes(bit_depth, color_space, codec_config);
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));
265 if (codec_config->profile() & 1) {
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());
277 RCHECK(reader->ReadBits(1, &reserved));
281 VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA;
285 chroma_subsampling = VPCodecConfigurationRecord::CHROMA_444;
286 if (codec_config->profile() & 1) {
288 RCHECK(reader->ReadBits(1, &reserved));
291 LOG(ERROR) <<
"4:4:4 color not supported in profile 0 or 2.";
295 codec_config->set_video_full_range_flag(yuv_full_range);
296 codec_config->SetChromaSubsampling(chroma_subsampling);
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())
303 << static_cast<int>(codec_config->video_full_range_flag())
304 <<
"\n chroma subsampling " 305 << static_cast<int>(codec_config->chroma_subsampling());
309 bool ReadFrameSize(BitReader* reader, uint32_t* width, uint32_t* height) {
310 RCHECK(reader->ReadBits(16, width));
312 RCHECK(reader->ReadBits(16, height));
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));
327 bool ReadFrameSizes(BitReader* reader, uint32_t* width, uint32_t* height) {
330 RCHECK(ReadFrameSize(reader, &new_width, &new_height));
331 if (new_width != *width) {
332 VLOG(1) <<
"Width updates from " << *width <<
" to " << new_width;
335 if (new_height != *height) {
336 VLOG(1) <<
"Height updates from " << *height <<
" to " << new_height;
337 *height = new_height;
340 uint32_t display_width = *width;
341 uint32_t display_height = *height;
342 RCHECK(ReadDisplayFrameSize(reader, &display_width, &display_height));
346 bool ReadFrameSizesWithRefs(BitReader* reader,
350 for (uint32_t i = 0; i < REFS_PER_FRAME; ++i) {
351 RCHECK(reader->ReadBits(1, &found));
356 RCHECK(ReadFrameSizes(reader, width, height));
358 uint32_t display_width;
359 uint32_t display_height;
360 RCHECK(ReadDisplayFrameSize(reader, &display_width, &display_height));
365 bool ReadLoopFilter(BitReader* reader) {
366 RCHECK(reader->SkipBits(9));
367 bool mode_ref_delta_enabled;
368 RCHECK(reader->ReadBits(1, &mode_ref_delta_enabled));
369 if (!mode_ref_delta_enabled)
371 bool mode_ref_delta_update;
372 RCHECK(reader->ReadBits(1, &mode_ref_delta_update));
373 if (!mode_ref_delta_update)
376 for (uint32_t i = 0; i < MAX_REF_LF_DELTAS + MAX_MODE_LF_DELTAS; ++i)
377 RCHECK(reader->SkipBitsConditional(
true, 6 + 1));
381 bool ReadQuantization(BitReader* reader) {
382 RCHECK(reader->SkipBits(QINDEX_BITS));
384 for (uint32_t i = 0; i < 3; ++i)
385 RCHECK(reader->SkipBitsConditional(
true, 4 + 1));
389 bool ReadSegmentation(BitReader* reader) {
391 RCHECK(reader->ReadBits(1, &enabled));
396 RCHECK(reader->ReadBits(1, &update_map));
398 for (uint32_t i = 0; i < SEG_TREE_PROBS; ++i)
399 RCHECK(reader->SkipBitsConditional(
true, 8));
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));
410 RCHECK(reader->ReadBits(1, &update_data));
412 RCHECK(reader->SkipBits(1));
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));
428 bool ReadTileInfo(uint32_t width, BitReader* reader) {
429 uint32_t mi_cols = GetNumMiUnits(width);
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;
436 uint32_t log2_tile_cols = min_log2_tile_cols;
439 RCHECK(reader->ReadBits(1, &has_more));
444 RCHECK(log2_tile_cols <= 6);
446 RCHECK(reader->SkipBitsConditional(
true, 1));
452 VP9Parser::VP9Parser() : width_(0), height_(0) {}
453 VP9Parser::~VP9Parser() {}
457 std::vector<VPxFrameInfo>* vpx_frames) {
460 RCHECK(ParseIfSuperframeIndex(data, data_size, vpx_frames));
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);
469 RCHECK(ReadProfile(&reader, writable_codec_config()));
471 bool show_existing_frame;
472 RCHECK(reader.
ReadBits(1, &show_existing_frame));
473 if (show_existing_frame) {
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_;
486 RCHECK(reader.
ReadBits(1, &is_interframe));
487 vpx_frame.is_keyframe = !is_interframe;
490 RCHECK(reader.
ReadBits(1, &show_frame));
491 bool error_resilient_mode;
492 RCHECK(reader.
ReadBits(1, &error_resilient_mode));
494 if (vpx_frame.is_keyframe) {
495 RCHECK(ReadSyncCode(&reader));
496 RCHECK(ReadBitDepthAndColorSpace(&reader, writable_codec_config()));
497 RCHECK(ReadFrameSizes(&reader, &width_, &height_));
499 bool intra_only =
false;
501 RCHECK(reader.
ReadBits(1, &intra_only));
502 if (!error_resilient_mode)
506 RCHECK(ReadSyncCode(&reader));
508 RCHECK(ReadBitDepthAndColorSpace(&reader, writable_codec_config()));
514 writable_codec_config()->SetChromaSubsampling(
515 VPCodecConfigurationRecord::CHROMA_420_COLLOCATED_WITH_LUMA);
516 writable_codec_config()->set_bit_depth(8);
519 RCHECK(reader.
SkipBits(REF_FRAMES));
520 RCHECK(ReadFrameSizes(&reader, &width_, &height_));
522 RCHECK(reader.
SkipBits(REF_FRAMES));
523 RCHECK(reader.
SkipBits(REFS_PER_FRAME * (REF_FRAMES_LOG2 + 1)));
528 RCHECK(ReadFrameSizesWithRefs(&reader, &width_, &height_));
533 RCHECK(reader.
ReadBits(1, &interp_filter));
539 if (!error_resilient_mode) {
543 RCHECK(reader.
SkipBits(FRAME_CONTEXTS_LOG2));
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));
551 uint16_t header_size;
552 RCHECK(reader.
ReadBits(16, &header_size));
553 vpx_frame.uncompressed_header_size =
555 vpx_frame.width = width_;
556 vpx_frame.height = height_;
558 VLOG(3) <<
"\n frame_size: " << vpx_frame.frame_size
559 <<
"\n uncompressed_header_size: " 560 << vpx_frame.uncompressed_header_size
562 <<
"\n header_size: " << header_size;
564 RCHECK(header_size > 0);
567 data += vpx_frame.frame_size;
574 uint8_t frame_marker;
575 RCHECK(reader.
ReadBits(2, &frame_marker));
576 RCHECK(frame_marker == VP9_FRAME_MARKER);
579 RCHECK(ReadProfile(&reader, &codec_config));
581 bool show_existing_frame;
582 RCHECK(reader.
ReadBits(1, &show_existing_frame));
583 if (show_existing_frame)
587 RCHECK(reader.
ReadBits(1, &is_interframe));
593 RCHECK(ReadSyncCode(&reader));
All the methods that are virtual are virtual for mocking.