1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/vp9_uncompressed_header_parser.h"
9 #include "base/logging.h"
15 // 10.5 Default probability tables
16 Vp9FrameContext kVp9DefaultFrameContext = {
20 {{20, 152}, {15, 101}},
22 {{3, 136, 37}, {5, 52, 13}},
25 {{{{{195, 29, 183}, {84, 49, 136}, {8, 42, 71}},
56 {{{191, 107, 226}, {124, 117, 204}, {25, 99, 155}},
87 {{{{214, 49, 220}, {132, 63, 188}, {42, 65, 137}},
118 {{{229, 99, 249}, {143, 111, 235}, {46, 109, 192}},
150 {{{{{125, 34, 187}, {52, 41, 133}, {6, 31, 56}},
181 {{{202, 105, 245}, {108, 106, 216}, {18, 90, 144}},
212 {{{{212, 35, 215}, {113, 47, 169}, {29, 48, 105}},
243 {{{225, 86, 251}, {144, 104, 235}, {42, 99, 181}},
275 {{{{{7, 27, 153}, {5, 30, 95}, {1, 16, 30}},
306 {{{19, 55, 240}, {19, 59, 196}, {3, 52, 105}},
337 {{{{211, 29, 217}, {96, 47, 156}, {22, 43, 87}},
368 {{{233, 29, 248}, {146, 47, 220}, {43, 52, 140}},
400 {{{{{17, 38, 140}, {7, 34, 80}, {1, 17, 29}},
431 {{{36, 41, 235}, {29, 36, 193}, {10, 27, 111}},
462 {{{{181, 21, 201}, {61, 37, 123}, {10, 38, 71}},
493 {{{197, 13, 247}, {82, 17, 222}, {25, 17, 162}},
534 // interp_filter_probs
535 {{235, 162}, {36, 255}, {34, 3}, {149, 144}},
539 {239, 183, 119, 96, 41},
541 {{33, 16}, {77, 74}, {142, 142}, {172, 170}, {238, 247}},
543 {50, 126, 123, 221, 226},
545 {{65, 32, 18, 144, 162, 194, 41, 51, 98},
546 {132, 68, 18, 165, 217, 196, 45, 40, 78},
547 {173, 80, 19, 176, 240, 193, 64, 35, 46},
548 {221, 135, 38, 194, 248, 121, 96, 85, 29}},
550 {{120, 7, 76, 176, 208, 126, 28, 54, 103},
551 {48, 12, 154, 155, 139, 90, 34, 117, 119},
552 {67, 6, 25, 204, 243, 158, 13, 21, 96},
553 {97, 5, 44, 131, 176, 139, 48, 68, 97},
554 {83, 5, 42, 156, 111, 152, 26, 49, 152},
555 {80, 5, 58, 178, 74, 83, 33, 62, 145},
556 {86, 5, 32, 154, 192, 168, 14, 22, 163},
557 {85, 5, 32, 156, 216, 148, 19, 29, 73},
558 {77, 7, 64, 116, 132, 122, 37, 126, 120},
559 {101, 21, 107, 181, 192, 103, 19, 67, 125}},
582 {{224, 144, 192, 168, 192, 176, 192, 198, 198, 245},
583 {216, 128, 176, 160, 176, 176, 192, 198, 198, 208}},
584 // mv_class0_bit_prob
587 {{136, 140, 148, 160, 176, 192, 224, 234, 234, 240},
588 {136, 140, 148, 160, 176, 192, 224, 234, 234, 240}},
589 // mv_class0_fr_probs
590 {{{128, 128, 64}, {96, 112, 64}}, {{128, 128, 64}, {96, 112, 64}}},
592 {{64, 96, 64}, {64, 96, 64}},
599 // Helper function for Vp9Parser::ReadTileInfo. Defined as
600 // calc_min_log2_tile_cols in spec 6.2.14 Tile size calculation.
601 int GetMinLog2TileCols(int sb64_cols) {
602 const int kMaxTileWidthB64 = 64;
604 while ((kMaxTileWidthB64 << min_log2) < sb64_cols)
609 // Helper function for Vp9Parser::ReadTileInfo. Defined as
610 // calc_max_log2_tile_cols in spec 6.2.14 Tile size calculation.
611 int GetMaxLog2TileCols(int sb64_cols) {
612 const int kMinTileWidthB64 = 4;
614 while ((sb64_cols >> max_log2) >= kMinTileWidthB64)
621 Vp9UncompressedHeaderParser::Vp9UncompressedHeaderParser(
622 Vp9Parser::Context* context)
623 : context_(context) {}
625 const Vp9FrameContext&
626 Vp9UncompressedHeaderParser::GetVp9DefaultFrameContextForTesting() const {
627 return kVp9DefaultFrameContext;
630 uint8_t Vp9UncompressedHeaderParser::ReadProfile() {
634 if (reader_.ReadBool())
636 if (reader_.ReadBool())
638 if (profile > 2 && reader_.ReadBool())
643 // 6.2.1 Frame sync syntax
644 bool Vp9UncompressedHeaderParser::VerifySyncCode() {
645 const int kSyncCode = 0x498342;
646 if (reader_.ReadLiteral(8 * 3) != kSyncCode) {
647 DVLOG(1) << "Invalid frame sync code";
653 // 6.2.2 Color config syntax
654 bool Vp9UncompressedHeaderParser::ReadColorConfig(Vp9FrameHeader* fhdr) {
655 if (fhdr->profile == 2 || fhdr->profile == 3) {
656 fhdr->bit_depth = reader_.ReadBool() ? 12 : 10;
661 fhdr->color_space = static_cast<Vp9ColorSpace>(reader_.ReadLiteral(3));
662 if (fhdr->color_space != Vp9ColorSpace::SRGB) {
663 fhdr->color_range = reader_.ReadBool();
664 if (fhdr->profile == 1 || fhdr->profile == 3) {
665 fhdr->subsampling_x = reader_.ReadBool() ? 1 : 0;
666 fhdr->subsampling_y = reader_.ReadBool() ? 1 : 0;
667 if (fhdr->subsampling_x == 1 && fhdr->subsampling_y == 1) {
668 DVLOG(1) << "4:2:0 color not supported in profile 1 or 3";
671 bool reserved = reader_.ReadBool();
673 DVLOG(1) << "reserved bit set";
677 fhdr->subsampling_x = fhdr->subsampling_y = 1;
680 fhdr->color_range = true;
681 if (fhdr->profile == 1 || fhdr->profile == 3) {
682 fhdr->subsampling_x = fhdr->subsampling_y = 0;
684 bool reserved = reader_.ReadBool();
686 DVLOG(1) << "reserved bit set";
690 DVLOG(1) << "4:4:4 color not supported in profile 0 or 2";
698 // 6.2.3 Frame size syntax
699 void Vp9UncompressedHeaderParser::ReadFrameSize(Vp9FrameHeader* fhdr) {
700 fhdr->frame_width = reader_.ReadLiteral(16) + 1;
701 fhdr->frame_height = reader_.ReadLiteral(16) + 1;
704 // 6.2.4 Render size syntax
705 void Vp9UncompressedHeaderParser::ReadRenderSize(Vp9FrameHeader* fhdr) {
706 if (reader_.ReadBool()) {
707 fhdr->render_width = reader_.ReadLiteral(16) + 1;
708 fhdr->render_height = reader_.ReadLiteral(16) + 1;
710 fhdr->render_width = fhdr->frame_width;
711 fhdr->render_height = fhdr->frame_height;
715 // 6.2.5 Frame size with refs syntax
716 bool Vp9UncompressedHeaderParser::ReadFrameSizeFromRefs(Vp9FrameHeader* fhdr) {
717 bool found_ref = false;
718 for (const auto& idx : fhdr->ref_frame_idx) {
719 found_ref = reader_.ReadBool();
721 const Vp9Parser::ReferenceSlot& ref = context_->GetRefSlot(idx);
722 DCHECK(ref.initialized);
723 fhdr->frame_width = ref.frame_width;
724 fhdr->frame_height = ref.frame_height;
726 const unsigned kMaxDimension = 1u << 16;
727 DCHECK_LE(fhdr->frame_width, kMaxDimension);
728 DCHECK_LE(fhdr->frame_height, kMaxDimension);
736 // 7.2.5 Frame size with refs semantics
737 bool has_valid_ref_frame = false;
738 for (const auto& idx : fhdr->ref_frame_idx) {
739 const Vp9Parser::ReferenceSlot& ref = context_->GetRefSlot(idx);
740 if (2 * fhdr->frame_width >= ref.frame_width &&
741 2 * fhdr->frame_height >= ref.frame_height &&
742 fhdr->frame_width <= 16 * ref.frame_width &&
743 fhdr->frame_height <= 16 * ref.frame_height) {
744 has_valid_ref_frame = true;
748 if (!has_valid_ref_frame) {
749 DVLOG(1) << "There should be at least one reference frame meeting "
750 << "size conditions.";
754 ReadRenderSize(fhdr);
758 // 6.2.7 Interpolation filter syntax
759 Vp9InterpolationFilter Vp9UncompressedHeaderParser::ReadInterpolationFilter() {
760 if (reader_.ReadBool())
761 return Vp9InterpolationFilter::SWITCHABLE;
763 // The mapping table for next two bits.
764 const Vp9InterpolationFilter table[] = {
765 Vp9InterpolationFilter::EIGHTTAP_SMOOTH, Vp9InterpolationFilter::EIGHTTAP,
766 Vp9InterpolationFilter::EIGHTTAP_SHARP, Vp9InterpolationFilter::BILINEAR,
768 return table[reader_.ReadLiteral(2)];
771 void Vp9UncompressedHeaderParser::SetupPastIndependence(Vp9FrameHeader* fhdr) {
772 memset(&context_->segmentation_, 0, sizeof(context_->segmentation_));
773 memset(fhdr->ref_frame_sign_bias, 0, sizeof(fhdr->ref_frame_sign_bias));
776 fhdr->frame_context = kVp9DefaultFrameContext;
777 DCHECK(fhdr->frame_context.IsValid());
780 // 6.2.8 Loop filter params syntax
781 void Vp9UncompressedHeaderParser::ReadLoopFilterParams() {
782 Vp9LoopFilterParams& loop_filter = context_->loop_filter_;
784 loop_filter.level = reader_.ReadLiteral(6);
785 loop_filter.sharpness = reader_.ReadLiteral(3);
786 loop_filter.delta_update = false;
788 loop_filter.delta_enabled = reader_.ReadBool();
789 if (loop_filter.delta_enabled) {
790 loop_filter.delta_update = reader_.ReadBool();
791 if (loop_filter.delta_update) {
792 for (size_t i = 0; i < Vp9RefType::VP9_FRAME_MAX; i++) {
793 loop_filter.update_ref_deltas[i] = reader_.ReadBool();
794 if (loop_filter.update_ref_deltas[i])
795 loop_filter.ref_deltas[i] = reader_.ReadSignedLiteral(6);
798 for (size_t i = 0; i < Vp9LoopFilterParams::kNumModeDeltas; i++) {
799 loop_filter.update_mode_deltas[i] = reader_.ReadBool();
800 if (loop_filter.update_mode_deltas[i])
801 loop_filter.mode_deltas[i] = reader_.ReadSignedLiteral(6);
807 // 6.2.9 Quantization params syntax
808 void Vp9UncompressedHeaderParser::ReadQuantizationParams(
809 Vp9QuantizationParams* quants) {
810 quants->base_q_idx = reader_.ReadLiteral(8);
812 quants->delta_q_y_dc = ReadDeltaQ();
813 quants->delta_q_uv_dc = ReadDeltaQ();
814 quants->delta_q_uv_ac = ReadDeltaQ();
817 // 6.2.10 Delta quantizer syntax
818 int8_t Vp9UncompressedHeaderParser::ReadDeltaQ() {
819 if (reader_.ReadBool())
820 return reader_.ReadSignedLiteral(4);
824 // 6.2.11 Segmentation params syntax
825 bool Vp9UncompressedHeaderParser::ReadSegmentationParams() {
826 Vp9SegmentationParams& segmentation = context_->segmentation_;
827 segmentation.update_map = false;
828 segmentation.update_data = false;
830 segmentation.enabled = reader_.ReadBool();
831 if (!segmentation.enabled)
834 segmentation.update_map = reader_.ReadBool();
835 if (segmentation.update_map) {
836 for (auto& tree_prob : segmentation.tree_probs) {
837 tree_prob = ReadProb();
840 segmentation.temporal_update = reader_.ReadBool();
841 for (auto& pred_prob : segmentation.pred_probs) {
842 pred_prob = segmentation.temporal_update ? ReadProb() : kVp9MaxProb;
846 segmentation.update_data = reader_.ReadBool();
847 if (segmentation.update_data) {
848 segmentation.abs_or_delta_update = reader_.ReadBool();
850 const int kFeatureDataBits[] = {8, 6, 2, 0};
851 const bool kFeatureDataSigned[] = {true, true, false, false};
853 for (size_t i = 0; i < Vp9SegmentationParams::kNumSegments; i++) {
854 for (size_t j = 0; j < Vp9SegmentationParams::SEG_LVL_MAX; j++) {
856 segmentation.feature_enabled[i][j] = reader_.ReadBool();
857 if (segmentation.feature_enabled[i][j]) {
858 data = reader_.ReadLiteral(kFeatureDataBits[j]);
859 if (kFeatureDataSigned[j])
860 if (reader_.ReadBool()) {
862 if (segmentation.abs_or_delta_update) {
863 DVLOG(1) << "feature_sign should be 0"
864 << " if abs_or_delta_update is 1";
870 segmentation.feature_data[i][j] = data;
877 // 6.2.12 Probability syntax
878 uint8_t Vp9UncompressedHeaderParser::ReadProb() {
879 return reader_.ReadBool() ? reader_.ReadLiteral(8) : kVp9MaxProb;
882 // 6.2.13 Tile info syntax
883 bool Vp9UncompressedHeaderParser::ReadTileInfo(Vp9FrameHeader* fhdr) {
884 int sb64_cols = (fhdr->frame_width + 63) / 64;
886 int min_log2_tile_cols = GetMinLog2TileCols(sb64_cols);
887 int max_log2_tile_cols = GetMaxLog2TileCols(sb64_cols);
889 int max_ones = max_log2_tile_cols - min_log2_tile_cols;
890 fhdr->tile_cols_log2 = min_log2_tile_cols;
891 while (max_ones-- && reader_.ReadBool())
892 fhdr->tile_cols_log2++;
894 fhdr->tile_rows_log2 = reader_.ReadBool() ? 1 : 0;
895 if (fhdr->tile_rows_log2 > 0 && reader_.ReadBool())
896 fhdr->tile_rows_log2++;
898 // 7.2.11 Tile info semantics
899 if (fhdr->tile_cols_log2 > 6) {
900 DVLOG(1) << "tile_cols_log2 should be <= 6";
907 void Vp9UncompressedHeaderParser::ResetLoopfilter() {
908 Vp9LoopFilterParams& loop_filter = context_->loop_filter_;
910 loop_filter.delta_enabled = true;
911 loop_filter.delta_update = true;
913 loop_filter.ref_deltas[VP9_FRAME_INTRA] = 1;
914 loop_filter.ref_deltas[VP9_FRAME_LAST] = 0;
915 loop_filter.ref_deltas[VP9_FRAME_GOLDEN] = -1;
916 loop_filter.ref_deltas[VP9_FRAME_ALTREF] = -1;
918 memset(loop_filter.mode_deltas, 0, sizeof(loop_filter.mode_deltas));
921 // 6.2 Uncompressed header syntax
922 bool Vp9UncompressedHeaderParser::Parse(const uint8_t* stream,
924 Vp9FrameHeader* fhdr) {
925 DVLOG(2) << "Vp9UncompressedHeaderParser::Parse";
926 reader_.Initialize(stream, frame_size);
929 fhdr->frame_size = frame_size;
932 if (reader_.ReadLiteral(2) != 0x2) {
933 DVLOG(1) << "frame marker shall be equal to 2";
937 fhdr->profile = ReadProfile();
938 if (fhdr->profile >= kVp9MaxProfile) {
939 DVLOG(1) << "Unsupported bitstream profile";
943 fhdr->show_existing_frame = reader_.ReadBool();
944 if (fhdr->show_existing_frame) {
945 fhdr->frame_to_show_map_idx = reader_.ReadLiteral(3);
946 fhdr->show_frame = true;
948 if (!reader_.ConsumeTrailingBits()) {
949 DVLOG(1) << "trailing bits are not zero";
952 if (!reader_.IsValid()) {
953 DVLOG(1) << "parser reads beyond the end of buffer";
956 fhdr->uncompressed_header_size = reader_.GetBytesRead();
957 fhdr->header_size_in_bytes = 0;
961 fhdr->frame_type = static_cast<Vp9FrameHeader::FrameType>(reader_.ReadBool());
962 fhdr->show_frame = reader_.ReadBool();
963 fhdr->error_resilient_mode = reader_.ReadBool();
965 if (fhdr->IsKeyframe()) {
966 if (!VerifySyncCode())
969 if (!ReadColorConfig(fhdr))
973 ReadRenderSize(fhdr);
974 fhdr->refresh_frame_flags = 0xff;
976 if (!fhdr->show_frame)
977 fhdr->intra_only = reader_.ReadBool();
979 if (!fhdr->error_resilient_mode)
980 fhdr->reset_frame_context = reader_.ReadLiteral(2);
982 if (fhdr->intra_only) {
983 if (!VerifySyncCode())
986 if (fhdr->profile > 0) {
987 if (!ReadColorConfig(fhdr))
991 fhdr->color_space = Vp9ColorSpace::BT_601;
992 fhdr->subsampling_x = fhdr->subsampling_y = 1;
995 fhdr->refresh_frame_flags = reader_.ReadLiteral(8);
998 ReadRenderSize(fhdr);
1000 fhdr->refresh_frame_flags = reader_.ReadLiteral(8);
1002 static_assert(std::extent<decltype(fhdr->ref_frame_sign_bias)>() >=
1003 Vp9RefType::VP9_FRAME_LAST + kVp9NumRefsPerFrame,
1004 "ref_frame_sign_bias is not big enough");
1005 for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) {
1006 fhdr->ref_frame_idx[i] = reader_.ReadLiteral(kVp9NumRefFramesLog2);
1007 fhdr->ref_frame_sign_bias[Vp9RefType::VP9_FRAME_LAST + i] =
1010 // 8.2 Frame order constraints
1011 // ref_frame_idx[i] refers to an earlier decoded frame.
1012 const Vp9Parser::ReferenceSlot& ref =
1013 context_->GetRefSlot(fhdr->ref_frame_idx[i]);
1014 if (!ref.initialized) {
1015 DVLOG(1) << "ref_frame_idx[" << i
1016 << "]=" << static_cast<int>(fhdr->ref_frame_idx[i])
1017 << " refers to unused frame";
1021 // 7.2 Uncompressed header semantics
1022 // the selected reference frames match the current frame in bit depth,
1023 // profile, chroma subsampling, and color space.
1024 if (ref.profile != fhdr->profile) {
1025 DVLOG(1) << "profile of referenced frame mismatch";
1029 // Below fields are not specified for inter-frame in header, so copy
1030 // them from referenced frame.
1031 fhdr->bit_depth = ref.bit_depth;
1032 fhdr->color_space = ref.color_space;
1033 fhdr->subsampling_x = ref.subsampling_x;
1034 fhdr->subsampling_y = ref.subsampling_y;
1036 if (fhdr->bit_depth != ref.bit_depth) {
1037 DVLOG(1) << "bit_depth of referenced frame mismatch";
1040 // There are encoded streams with no color_space information
1041 // with in the frame header of an Intra only frame, so we assigned the
1042 // default color_space :BT_601 as per the spec. But reference list
1043 // might have frames with UNKNOWN color space information too. So we
1044 // relax the requirement a bit to cover more video samples and added
1045 // an exception for UNKNOWN colorspace
1046 if (fhdr->color_space != ref.color_space &&
1047 fhdr->color_space != Vp9ColorSpace::UNKNOWN &&
1048 ref.color_space != Vp9ColorSpace::UNKNOWN) {
1049 DVLOG(1) << "color_space of referenced frame mismatch";
1052 if (fhdr->subsampling_x != ref.subsampling_x ||
1053 fhdr->subsampling_y != ref.subsampling_y) {
1054 DVLOG(1) << "chroma subsampling of referenced frame mismatch";
1060 if (!ReadFrameSizeFromRefs(fhdr))
1063 fhdr->allow_high_precision_mv = reader_.ReadBool();
1064 fhdr->interpolation_filter = ReadInterpolationFilter();
1068 if (fhdr->error_resilient_mode) {
1069 fhdr->refresh_frame_context = false;
1070 fhdr->frame_parallel_decoding_mode = true;
1072 fhdr->refresh_frame_context = reader_.ReadBool();
1073 fhdr->frame_parallel_decoding_mode = reader_.ReadBool();
1076 fhdr->frame_context_idx_to_save_probs = fhdr->frame_context_idx =
1077 reader_.ReadLiteral(kVp9NumFrameContextsLog2);
1079 if (fhdr->IsIntra() || fhdr->error_resilient_mode) {
1080 SetupPastIndependence(fhdr);
1081 if (fhdr->IsKeyframe() || fhdr->error_resilient_mode ||
1082 fhdr->reset_frame_context == 3) {
1083 for (size_t i = 0; i < kVp9NumFrameContexts; ++i) {
1084 if (!context_->UpdateFrameContext(i, fhdr->frame_context)) {
1088 } else if (fhdr->reset_frame_context == 2) {
1089 if (!context_->UpdateFrameContext(fhdr->frame_context_idx,
1090 fhdr->frame_context)) {
1094 fhdr->frame_context_idx = 0;
1097 ReadLoopFilterParams();
1098 // Update loop_filter in current_frame_hdr
1099 fhdr->loop_filter = context_->loop_filter_;
1100 ReadQuantizationParams(&fhdr->quant_params);
1101 if (!ReadSegmentationParams())
1103 // Update segmentation in current_frame_hdr
1104 fhdr->segmentation = context_->segmentation_;
1105 if (!ReadTileInfo(fhdr))
1108 fhdr->header_size_in_bytes = reader_.ReadLiteral(16);
1109 if (fhdr->header_size_in_bytes == 0) {
1110 DVLOG(1) << "invalid header size";
1114 if (!reader_.ConsumeTrailingBits()) {
1115 DVLOG(1) << "trailing bits are not zero";
1118 if (!reader_.IsValid()) {
1119 DVLOG(1) << "parser reads beyond the end of buffer";
1122 fhdr->uncompressed_header_size = reader_.GetBytesRead();
1127 } // namespace media