public void Parse() { _currMbAddr = _sliceState.FirstMacroBlockInSlice * (MbAffFrameFlag ? 2U : 1U); MbFieldDecodingFlag = _sliceState.FieldPicFlag; // The default for non-MBAFF frames bool moreDataFlag = true; bool prevMbSkipped = false; while (_readerState.Valid && moreDataFlag) { if (!_sliceState.IntraCoded) { uint mbSkipRun = _reader.GetExpGolombCoded(); prevMbSkipped = (mbSkipRun > 0); if (mbSkipRun > 0) { for (uint i = 0; i < (mbSkipRun - 1); i++) { UpdateSkippedMacroblockPrediction(); NextMbAddress(); if (!_readerState.Valid) { return; //Could not find expected macroblock } } moreDataFlag = HasMoreRbspData(); if (moreDataFlag) { // Skip the last block UpdateSkippedMacroblockPrediction(); NextMbAddress(); if (!_readerState.Valid) { return; //Could not find expected macroblock } } } } if (moreDataFlag) { if (MbAffFrameFlag && (IsFirstMacroblockInPair() || prevMbSkipped)) { MbFieldDecodingFlag = _reader.GetBit(); // is field macro block } MacroBlockLayer(); moreDataFlag = HasMoreRbspData(); } if (moreDataFlag) { NextMbAddress(); } } }
private static void GetHrdParameters(INalUnitReader reader, IState resultState) { uint cpbCntMinus1 = reader.GetExpGolombCoded(); // cpb_cnt_minus1 reader.GetBits(4); // bit_rate_scale reader.GetBits(4); // cpb_size_scale // for (SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; SchedSelIdx++) for (int schedSelIdx = 0; schedSelIdx <= cpbCntMinus1; schedSelIdx++) { if (!reader.HasMoreRbspData()) { resultState.Invalidate(); return; } reader.GetExpGolombCoded(); // bit_rate_value_minus1[SchedSelIdx] reader.GetExpGolombCoded(); // cpb_size_value_minus1[SchedSelIdx] reader.GetBit(); // cbr_flag[SchedSelIdx] } reader.GetBits(5); // initial_cpb_removal_delay_length_minus1 reader.GetBits(5); // cpb_removal_delay_length_minus1 reader.GetBits(5); // dpb_output_delay_length_minus1 reader.GetBits(5); // time_offset_length }
private static void DecodePictureOrderCount(INalUnitReader reader, ISequenceStateBuilder builder) { uint pictureOrderCountType = reader.GetExpGolombCoded(Attribute.PictureOrderCountType, 2); // pic_order_cnt_type builder.PictureOrderCountType = pictureOrderCountType; switch (pictureOrderCountType) { case 0: builder.Log2MaxPicOrderCntLsbMinus4 = reader.GetExpGolombCoded(Attribute.Log2MaxPictureOrderCountLsbMinus4, 12); // log2_max_pic_order_cnt_lsb_minus4us4 break; case 1: builder.DeltaPicOrderAlwaysZeroFlag = reader.GetBit(); // delta_pic_order_always_zero_flag reader.GetSignedExpGolombCoded(); // offset_for_non_ref_pic reader.GetSignedExpGolombCoded(); // offset_for_top_to_bottom_field // num_ref_frames_in_pic_order_cnt_cycle uint numRefFramesInPicOrderCntCycle = reader.GetExpGolombCoded(Attribute.NumRefFramesInPicOrderCountCycle, 255); for (uint i = 0; i < numRefFramesInPicOrderCntCycle; i++) { reader.GetSignedExpGolombCoded(); // offset_for_ref_frame[i] } break; case 2: break; } }
private void ParseSliceGroupMap(INalUnitReader reader, IState resultState, IPictureStateBuilder builder, uint sliceGroupCount) { var sliceGroupMapType = (SliceGroupMapType)reader.GetExpGolombCoded(Attribute.SliceGroupMapType, _sliceGroupMapTypeFormatter); // slice_group_map_type builder.SliceGroupMapType = sliceGroupMapType; switch (sliceGroupMapType) { case SliceGroupMapType.InterleavedSliceGroups: uint[] runLengthMinus1 = new uint[sliceGroupCount]; for (int iGroup = 0; iGroup < sliceGroupCount; iGroup++) { runLengthMinus1[iGroup] = reader.GetExpGolombCoded(); // run_length_minus1[iGroup] } builder.RunLengthMinus1 = runLengthMinus1; break; case SliceGroupMapType.DispersedSliceGroups: break; case SliceGroupMapType.ForegroundAndLeftoverSliceGroups: uint[] topLeft = new uint[sliceGroupCount - 1]; uint[] bottomRight = new uint[sliceGroupCount - 1]; for (int iGroup = 0; iGroup < (sliceGroupCount - 1); iGroup++) { topLeft[iGroup] = reader.GetExpGolombCoded(); bottomRight[iGroup] = reader.GetExpGolombCoded(); } builder.TopLeft = topLeft; builder.BottomRight = bottomRight; break; case SliceGroupMapType.ChangingSliceGroups3: case SliceGroupMapType.ChangingSliceGroups4: case SliceGroupMapType.ChangingSliceGroups5: builder.SliceGroupChangeDirectionFlag = reader.GetBit(); builder.SliceGroupChangeRateMinus1 = reader.GetExpGolombCoded(); break; case SliceGroupMapType.ExplicitSliceGroups: uint pictureSizeInMapUnits = 1 + reader.GetExpGolombCoded(); // pic_size_in_map_units_minus1 int syntaxElementSize = DetectorUtils.Log2(sliceGroupCount - 1) + 1; uint[] sliceGroupId = new uint[pictureSizeInMapUnits]; for (int i = 0; i < pictureSizeInMapUnits; i++) { sliceGroupId[i] = reader.GetBits(syntaxElementSize); } builder.SliceGroupId = sliceGroupId; break; default: resultState.Invalidate(); break; } }
// 7.3.2.2 PictureState parameter set RBSP syntax public void Parse(INalUnitReader reader, IResultNodeState resultState) { resultState.Name = Name; uint pictureParameterSetId = reader.GetExpGolombCoded(Attribute.PictureParameterSetId, 255 /*7.4.2.2*/); uint sequenceParameterSetId = reader.GetExpGolombCoded(Attribute.SequenceParameterSetId, 31 /*7.4.2.2*/); var sequenceState = reader.State.SequenceStates[sequenceParameterSetId]; if (sequenceState == null) { resultState.Invalidate(); return; } IPictureStateBuilder builder = new PictureStateBuilder(pictureParameterSetId, sequenceState); builder.EntropyCodingMode = reader.GetBit(Attribute.EntropyCodingMode); builder.BottomFieldPicOrderInFramePresentFlag = reader.GetBit(Attribute.PictureOrderPresent); uint numSliceGroupsMinus1 = reader.GetExpGolombCoded(Attribute.NumSliceGroupsMinus1, 7 /*A.2*/); builder.NumSliceGroupsMinus1 = numSliceGroupsMinus1; if (numSliceGroupsMinus1 > 0) { if (sequenceState.Profile == Profile.Main) { resultState.Invalidate(); return; } ParseSliceGroupMap(reader, resultState, builder, (numSliceGroupsMinus1 + 1)); // FIXME: this code contains too many bugs, so it is disabled for now! resultState.Invalidate(); // (end of FIXME) if (!resultState.Valid) { return; } } builder.NumRefIdxL0DefaultActiveMinus1 = reader.GetExpGolombCoded(Attribute.NumRefIdxl0DefaultActiveMinus1, 31 /*7.4.2.2*/); builder.NumRefIdxL1DefaultActiveMinus1 = reader.GetExpGolombCoded(Attribute.NumRefIdxl1DefaultActiveMinus1, 31 /*7.4.2.2*/); builder.WeightedPredFlag = reader.GetBit(Attribute.WeightedPrediction); builder.WeightedBipredIdc = reader.GetBits(2, Attribute.WeightedBidirectionalPrediction, _weightBidirectionalPredictionFormatter); // SliceQPY = 26 + PicInitQpMinus26 + slice_qp_delta int qpBdOffset = (6 * ((int)sequenceState.BitDepthLuma - 8)); builder.PicInitQpMinus26 = reader.GetSignedExpGolombCoded(Attribute.PictureInitialQPyMinus26, -(26 + qpBdOffset), 25); reader.GetSignedExpGolombCoded(Attribute.PictureInitialQSyMinus26, -26, 25); // pic_init_qs_minus26; relative to 26 reader.GetSignedExpGolombCoded(Attribute.ChromaQpIndexOffset, -12, 12); // chroma_qp_index_offset builder.DeblockingFilterControlPresentFlag = reader.GetBit(Attribute.DeblockingFilterControlPresent); reader.GetBit(Attribute.ConstrainedIntraPrediction); // constrained_intra_pred_flag builder.RedundantPicCntPresentFlag = reader.GetBit(Attribute.RedundantPictureControlPresent); // Note: Total size upto this point is between 11 and 59 bits (+ 'slice group map') if (reader.HasMoreRbspData()) // more_rbsp_data() { builder.Transform8X8ModeFlag = reader.GetBit(); // transform_8x8_mode_flag bool picScalingMatrixPresentFlag = reader.GetBit(); //if (picScalingMatrixPresentFlag) // pic_scaling_matrix_present_flag //{ // for (int i = 0; i < 6 + 2 * pictureState.transform_8x8_mode_flag; i++) // { // bool picScalingListPresentFlag = reader.GetBit(); // if (picScalingListPresentFlag) // pic_scaling_list_present_flag[i] // { // if (i < 6) // { // throw new NotImplementedException("scaling_list(ScalingList4x4[i], 16, UseDefaultScalingMatrix4x4Flag[i]);"); // TODO // } // else // { // throw new NotImplementedException("scaling_list(ScalingList8x8[i – 6], 64, UseDefaultScalingMatrix8x8Flag[i – 6]);"); // TODO // } // } // } //} reader.GetSignedExpGolombCoded(); // second_chroma_qp_index_offset } // rbsp_trailing_bits() if (reader.ShowBits(1) == 1) { reader.GetBit(); // rbsp_stop_one_bit (equal to 1) // trailing zero bits } if (resultState.Valid) { reader.State.PictureStates[pictureParameterSetId] = builder.Build(); } }
// 7.3.2.1.1 SequenceState parameter set data syntax public void Parse(INalUnitReader reader, IResultNodeState resultState) { // Constraints from 7.4.2.11 resultState.Name = Name; Profile profileIdc = reader.GetBits(8, Attribute.ProfileIdc, _profileValidator); reader.GetBits(6); // constraint_set{0-5}_flag if (reader.GetBits(2) != 0) // reserved_zero_2bits { resultState.Invalidate(); return; } reader.GetByte(false, Attribute.LevelIdc, 59); // level_idc, Table A-1 - Level limits uint sequenceParameterSetId = reader.GetExpGolombCoded(Attribute.SequenceParameterSetId, 31); ISequenceStateBuilder builder = new SequenceStateBuilder(sequenceParameterSetId); builder.ByteStreamFormat = reader.State.ByteStreamFormat; builder.ProfileIdc = profileIdc; if (IsHighProfile(profileIdc)) { uint chromaFormatIdc = reader.GetExpGolombCoded(Attribute.ChromaFormatIdc, 3); // Table 6-1 builder.ChromaFormatIdc = chromaFormatIdc; if (chromaFormatIdc == 3) { builder.SeparateColourPlaneFlag = reader.GetBit(Attribute.SeparateColorPlaneFlag); } builder.BitDepthLumaMinus8 = reader.GetExpGolombCoded(Attribute.BitDepthLumaArraySampleMinus8, 6); builder.BitDepthChromaMinus8 = reader.GetExpGolombCoded(Attribute.BitDepthChromaArraySampleMinus8, 6); reader.GetBit(); // qpprime_y_zero_transform_bypass_flag if (reader.GetBit()) // seq_scaling_matrix_present_flag { for (int i = 0; i < ((chromaFormatIdc != 3) ? 8 : 12); i++) { if (reader.GetBit()) // seq_scaling_list_present_flag[i] { // FIXME: scaling_list() is not implemented!! resultState.Invalidate(); return; } } } } builder.Log2MaxFrameNumMinus4 = reader.GetExpGolombCoded(Attribute.Log2MaxFrameNumMinus4, 28); DecodePictureOrderCount(reader, builder); uint maxDpbFramesUpperLimit = (profileIdc == Profile.MultiviewHigh) ? 160U : 16U; //could use the exact maxDpbFrames, but this is easier builder.MaxNumRefFrames = reader.GetExpGolombCoded(Attribute.MaxNumberReferenceFrames, maxDpbFramesUpperLimit); reader.GetBit(); // gaps_in_frame_num_value_allowed_flag builder.PicWidthInMbsMinus1 = reader.GetExpGolombCoded(Attribute.PictureWidthInMacroBlocksMinus1, 543); builder.PicHeightInMapUnitsMinus1 = reader.GetExpGolombCoded(Attribute.PictureHeightInMapUnitsMinus1, 543); var frameMbsOnlyFlag = reader.GetBit(Attribute.FrameMbsOnlyFlag); builder.FrameMbsOnlyFlag = frameMbsOnlyFlag; if (!frameMbsOnlyFlag) { builder.MbAdaptiveFrameFieldFlag = reader.GetBit(); } bool direct8X8InferenceFlag = reader.GetBit(); builder.Direct8X8InferenceFlag = direct8X8InferenceFlag; if (!frameMbsOnlyFlag && !direct8X8InferenceFlag) { resultState.Invalidate(); return; } if (reader.GetBit()) // frame_cropping_flag { // TODO: Cropping should not exceed the size of a frame! reader.GetExpGolombCoded(Attribute.FrameCropLeftOffset, 8703); reader.GetExpGolombCoded(Attribute.FrameCropRightOffset, 8703); reader.GetExpGolombCoded(Attribute.FrameCropTopOffset, 8703); reader.GetExpGolombCoded(Attribute.FrameCropBottomOffset, 8703); } if (reader.GetBit()) // vui_parameters_present_flag { GetVuiParameters(reader, resultState); } if (reader.ShowBits(1) == 1) { reader.GetBit(); // rbsp_stop_one_bit (equal to 1) // trailing zero bits } if (resultState.Valid) { reader.State.SequenceStates[sequenceParameterSetId] = builder.Build(); } }
private static void GetVuiParameters(INalUnitReader reader, IResultNodeState resultState) { const byte extendedSar = 255; // Extended_SAR bool aspectRatioInfoPresentFlag = reader.GetBit(); if (aspectRatioInfoPresentFlag) // aspect_ratio_info_present_flag { byte aspectRatioIdc = reader.GetByte(false); if (aspectRatioIdc == extendedSar) // aspect_ratio_idc { reader.GetBits(16); // sar_width reader.GetBits(16); // sar_height } } bool overscanInfoPresentFlag = reader.GetBit(); if (overscanInfoPresentFlag) // overscan_info_present_flag { reader.GetBit(); // overscan_appropriate_flag } bool videoSignalTypePresentFlag = reader.GetBit(); if (videoSignalTypePresentFlag) // video_signal_type_present_flag { reader.GetBits(3); // video_format reader.GetBit(); // video_full_range_flag bool colourDescriptionPresentFlag = reader.GetBit(); if (colourDescriptionPresentFlag) // colour_description_present_flag { reader.GetByte(false); // colour_primaries reader.GetByte(false); // transfer_characteristics reader.GetByte(false); // matrix_coefficients } } bool chromaLocInfoPresentFlag = reader.GetBit(); if (chromaLocInfoPresentFlag) // chroma_loc_info_present_flag { reader.GetExpGolombCoded(); // chroma_sample_loc_type_top_field reader.GetExpGolombCoded(); // chroma_sample_loc_type_bottom_field } bool timingInfoPresentFlag = reader.GetBit(); if (timingInfoPresentFlag) // timing_info_present_flag { reader.GetBits(32); // num_units_in_tick reader.GetBits(32); // time_scale reader.GetBit(); // fixed_frame_rate_flag } bool nalHrdParametersPresentFlag = reader.GetBit(); if (nalHrdParametersPresentFlag) //nal_hrd_parameters_present_flag { GetHrdParameters(reader, resultState); // hrd_parameters() } bool vclHrdParametersPresentFlag = reader.GetBit(); if (vclHrdParametersPresentFlag) // vcl_hrd_parameters_present_flag { GetHrdParameters(reader, resultState); // hrd_parameters() } if (nalHrdParametersPresentFlag || vclHrdParametersPresentFlag) { reader.GetBit(); // low_delay_hrd_flag } reader.GetBit(); // pic_struct_present_flag bool bitstreamRestrictionFlag = reader.GetBit(); if (bitstreamRestrictionFlag) // bitstream_restriction_flag { reader.GetBit(); // motion_vectors_over_pic_boundaries_flag reader.GetExpGolombCoded(); // max_bytes_per_pic_denom reader.GetExpGolombCoded(); // max_bits_per_mb_denom reader.GetExpGolombCoded(); // log2_max_mv_length_horizontal reader.GetExpGolombCoded(); // log2_max_mv_length_vertical reader.GetExpGolombCoded(); // num_reorder_frames reader.GetExpGolombCoded(); // max_dec_frame_buffering } }