private static void ParseFrameNum(INalUnitReader reader, ISequenceState sequenceState) // TODO:checks uitbreiden volgens 7.4.3(Current Header Semantics).frame_num specs { uint frameNum = reader.GetBits((int)sequenceState.Log2MaxFrameNum, Attribute.FrameNumber); #if DEBUG H264Debug.WriteLine("+ frame_num={0} ({1} bits)", frameNum, sequenceState.Log2MaxFrameNum); #endif if (reader.State.IdrPicFlag && (frameNum != 0)) { //FIXME: Some H.264 files seem to use frame number != 0 for IDR pictures!? //readerState.Invalidate(); } }
public void Parse(INalUnitReader reader, IResultNodeState resultState) { var sliceState = reader.State.SliceState; if (sliceState == null) { return; //Apparently no header data is available, so skip the deepslice parsing. } #if DEBUG H264Debug.WriteLine(sliceState.SliceType + " at " + reader.Position + " (" + sliceState.FirstMacroBlockInSlice + ")"); #endif var sliceData = CreateSliceData(reader, resultState, sliceState); sliceData.Parse(); H264Debug.DebugEnabled = false; }
// 7.3.3 Slice header syntax public void Parse(INalUnitReader reader, IResultNodeState resultState) { reader.State.SliceState = null; // Invalid, unless the slice header is valid! uint firstMacroblockInSlice = reader.GetExpGolombCoded(Attribute.FirstMacroblockInSlice, uint.MaxValue); // first_mb_in_slice #if DEBUG H264Debug.WriteLine("+ first_mb_in_slice={0}", firstMacroblockInSlice); #endif SliceType pictureSliceType = (SliceType)reader.GetExpGolombCoded(Attribute.SliceType, _sliceTypeResultFormatter); SliceType sliceType = (SliceType)((int)pictureSliceType % 5); #if DEBUG H264Debug.WriteLine("+ slice_type={0}", (int)sliceType); #endif byte pictureParamaterSetId = (byte)reader.GetExpGolombCoded(Attribute.PictureParameterSetId, 255); #if DEBUG H264Debug.WriteLine("+ pic_parameter_set_id={0}", pictureParamaterSetId); #endif var pictureState = reader.State.PictureStates[pictureParamaterSetId]; if (pictureState == null) { if (resultState.Valid) { if (IsFalseHit(firstMacroblockInSlice, sliceType, pictureParamaterSetId) || (pictureParamaterSetId > 10)) { resultState.Invalidate(); } } return; // cannot validate slice header!! } ISliceStateBuilder builder = new SliceStateBuilder(pictureState); builder.FirstMacroBlockInSlice = firstMacroblockInSlice; builder.SliceType = sliceType; if (pictureState.PictureSliceType.HasValue && (sliceType != pictureState.PictureSliceType)) { // FIXME: This rule only applies to slices within a single picture. // Since we currently don't detect whether this slice starts a // new picture, we have to disable this rule for now! // oldIReaderState.Invalidate(); // return; } if (/*!pictureState.PictureSliceType.HasValue && */ sliceType != pictureSliceType) { pictureState.PictureSliceType = pictureSliceType; } if (IsNonIntraSliceInIntraCodedPicture(reader, sliceType, pictureState)) { resultState.Invalidate(); return; } var sequenceState = pictureState.SequenceState; if (sequenceState.ChromaFormat == ChromaFormat.SeparateColorPlane) { reader.GetBits(2, Attribute.ColorPlane, _colorPlaneResultFormatter); // colour_plane_id } ParseFrameNum(reader, sequenceState); bool fieldPicFlag = false; if (!sequenceState.FrameMbsOnlyFlag) { fieldPicFlag = reader.GetBit(); // field_pic_flag builder.FieldPicFlag = fieldPicFlag; if (fieldPicFlag) { reader.GetBit(); // bottom_field_flag } } if (reader.State.IdrPicFlag) { reader.GetExpGolombCoded(Attribute.IdrPictureId, 65535); // idr_pic_id } if (sequenceState.PictureOrderCountType == 0) { reader.GetBits((int)sequenceState.Log2MaxPicOrderCntLsb); // pic_order_cnt_lsb if (pictureState.PictureOrderPresent && !fieldPicFlag) { reader.GetSignedExpGolombCoded(); // delta_pic_order_cnt_bottom } } else if ((sequenceState.PictureOrderCountType == 1) && !sequenceState.DeltaPicOrderAlwaysZeroFlag) { reader.GetSignedExpGolombCoded(); // delta_pic_order_cnt_0 if (pictureState.PictureOrderPresent && !fieldPicFlag) { reader.GetSignedExpGolombCoded(); // delta_pic_order_cnt_1 } } if (pictureState.RedundantPictureControlPresent) { reader.GetExpGolombCoded(Attribute.RedundantPictureCounter, 127); // redundant_pic_cnt } if (sliceType == SliceType.B) { reader.GetBit(); // direct_spatial_mv_pred_flag } uint activeReferencePictureCount0 = pictureState.DefaultReferencePictureCount0; uint activeReferencePictureCount1 = pictureState.DefaultReferencePictureCount1; if (!IsIntraCoded(sliceType) && reader.GetBit()) // num_ref_idx_active_override_flag { uint maxRefIdxActiveMinus1 = fieldPicFlag ? 31U : 15U; activeReferencePictureCount0 = reader.GetExpGolombCoded(maxRefIdxActiveMinus1) + 1; // num_ref_idx_l0_active_minus1 if (sliceType == SliceType.B) { activeReferencePictureCount1 = reader.GetExpGolombCoded(maxRefIdxActiveMinus1) + 1; // num_ref_idx_l1_active_minus1 } } builder.ActiveReferencePictureCount0 = activeReferencePictureCount0; builder.ActiveReferencePictureCount1 = activeReferencePictureCount1; RefPicListModification(reader, resultState, sliceType); if ((pictureState.WeightedPrediction && (sliceType == SliceType.P || sliceType == SliceType.Sp)) || (pictureState.WeightedBidirectionalPrediction == WeightedBidirectionalPredictionType.ExplicitWeightedPrediction && sliceType == SliceType.B)) { PredWeightTable(reader, sequenceState, sliceType, activeReferencePictureCount0, activeReferencePictureCount1); } if (reader.State.NalRefIdc != 0) { DecRefPicMarking(reader, resultState); } if (pictureState.EntropyCodingMode && !IsIntraCoded(sliceType)) { builder.CabacInitIdc = reader.GetExpGolombCoded(2U); } builder.SliceQpDelta = reader.GetSignedExpGolombCoded(); if ((sliceType == SliceType.Sp) || (sliceType == SliceType.Si)) { if (sliceType == SliceType.Sp) { reader.GetBit(); // sp_for_switch_flag } reader.GetSignedExpGolombCoded(); // slice_qs_delta } if (pictureState.DeblockingFilterControlPresent) { uint disableDeblockingFilterIdc = reader.GetExpGolombCoded(); // disable_deblocking_filter_idc if (disableDeblockingFilterIdc != 1) { reader.GetSignedExpGolombCoded(); // slice_alpha_c0_offset_div2 reader.GetSignedExpGolombCoded(); // slice_beta_offset_div2 } } if (pictureState.SliceGroupCount > 1 && pictureState.SliceGroupMapType >= SliceGroupMapType.ChangingSliceGroups3 && pictureState.SliceGroupMapType <= SliceGroupMapType.ChangingSliceGroups5) { uint value = (sequenceState.PicSizeInMapUnits / pictureState.SliceGroupChangeRate); int requiredBitsToRepresentValue = DetectorUtils.Log2(value) + 1; builder.SliceGroupChangeCycle = reader.GetBits(requiredBitsToRepresentValue); // slice_group_change_cycle; } // Check 'firstMacroblockInSlice' field uint picHeightInMbs = sequenceState.FrameHeightInMbs / (fieldPicFlag ? 2U : 1U); uint picSizeInMbs = sequenceState.PicWidthInMbs * picHeightInMbs; bool mbAffFrameFlag = sequenceState.MbAdaptiveFrameFieldFlag && !fieldPicFlag; if ((firstMacroblockInSlice * (mbAffFrameFlag ? 2U : 1U)) >= picSizeInMbs) { resultState.Invalidate(); } if (resultState.Valid) { // Since the 'pictureParameterSetId' is probably correct at this point, // we prevent the check for 'pictureParameterSetId > 10'. if (IsFalseHit(firstMacroblockInSlice, sliceType, Math.Min((byte)1, pictureParamaterSetId))) { resultState.Invalidate(); } else { reader.State.SliceState = builder.Build(); } } }