public void Parse(IMpeg2VideoReader reader, IResultNodeState resultState) { if (reader.State.LastHeaderName == null) { // MPEG data cannot start with an extension! resultState.Invalidate(); return; } var extensionId = (ExtensionId)reader.GetBits(4, Attribute.ExtensionStartCodeIdentifier, _extensionTypeResultFormatter); IExtensionParser extensionParser; if (!_extensionParsers.TryGetValue(extensionId, out extensionParser) || !CheckExtensionOccurance(reader.State, extensionId)) { resultState.Invalidate(); return; } // Note: Do not invoke the reader state here, it is *NOT* recursive!! extensionParser.Parse(reader, resultState); if (resultState.Valid) { if (reader.State.Picture.Initialized) { reader.State.Picture.AddExtension(extensionId); } else { reader.State.Sequence.AddExtension(extensionId); } } }
public void Parse(IMpeg2VideoReader reader, IResultNodeState resultState) { IPictureState pictureState = reader.State.Picture; resultState.Name = Name; // It can occur after the last slice of the previous picture or after a sequence header // or group of pictures header, possible followed by user data and/or extensions. if ((reader.State.LastHeaderName != Slice.Name) && pictureState.Initialized) { resultState.Invalidate(); return; } if (!reader.State.Sequence.Initialized && !reader.State.SeenGop) { reader.InsertReferenceHeaderBeforeStartCode(); } pictureState.Reset(); reader.State.Slice.Reset(); reader.GetBits(10, Attribute.TemporalReference); var pictureCodingType = (PictureCodingType)reader.GetBits(3, Attribute.PictureCodingType, _pictureCodingTypeResultFormatter); pictureState.CodingType = pictureCodingType; reader.GetBits(16, Attribute.VbvDelay); if ((pictureCodingType == PictureCodingType.PType) || (pictureCodingType == PictureCodingType.BType)) { reader.GetFlag(Attribute.FullPelForwardVector); byte forwardFCode = (byte)reader.GetBits(3, Attribute.ForwardFCode); pictureState.ForwardHorizontalFCode = forwardFCode; pictureState.ForwardVerticalFCode = forwardFCode; } if (pictureCodingType == PictureCodingType.BType) { reader.GetFlag(Attribute.FullPelBackwardVector); byte backwardFCode = (byte)reader.GetBits(3, Attribute.BackwardFCode); pictureState.BackwardHorizontalFCode = backwardFCode; pictureState.BackwardVerticalFCode = backwardFCode; } int count = 0; // Sanity check uint maxExtraInformationLength = reader.State.Configuration.PictureHeaderMaxLengthOfExtraInformation; while (reader.ShowBits(1) == 1) { reader.GetBits(1); // ExtraBitPicture reader.GetBits(8); // ExtraInformationPicture if (count++ > maxExtraInformationLength) { resultState.Invalidate(); return; } } }
public void Parse(INalUnitReader reader, IResultNodeState resultState) { reader.GetFixedBits(1, 0, Attribute.ForbiddenZeroBit); reader.State.NalRefIdc = reader.GetBits(2, Attribute.NalRefIdc); reader.State.NalUnitType = (NalUnitType)reader.GetBits(5, Attribute.NalUnitType); INalUnitPayloadParser nalUnitPayloadParser; if (!_nalUnitParsers.TryGetValue(reader.State.NalUnitType, out nalUnitPayloadParser)) { resultState.Invalidate(); return; } //Parse remainder with specific nalunitparser (NOTE: Is not a sub-object) nalUnitPayloadParser.Parse(reader, resultState); if (!resultState.Valid) { return; // Stop processing of invalid NAL unit. } if (!CanParseNalUnitType(reader.State.SliceState, reader.State.NalUnitType)) { // Forward to the estimated end of the NAL unit reader.Position = reader.Length; resultState.Invalidate(); // Invalidates the result resultState.Recover(); // Revalidates the reader state so parsing can continue! return; } if (reader.State.NalUnitType == NalUnitType.SequenceParameterSet) { return; // Note: SPS validate their own data! } if (reader.State.NalUnitType == NalUnitType.PictureParameterSet) { return; // Note: PPS validate their own data! } if (!IsSlice(reader.State.NalUnitType) || !reader.State.SliceState.PictureState.EntropyCodingMode) { if (reader.GetBits(1) != 1) // rbsp_stop_one_bit (equal to 1) { resultState.Invalidate(); return; } } if (IsSlice(reader.State.NalUnitType) && resultState.Valid) { return; // Random (e.g. audio) data is allowed after a valid slice } reader.ReadZeroAlignmentBits(); }
public void Parse(IMpeg2VideoReader reader, IResultNodeState resultState) { resultState.Name = Name; reader.State.Picture.Reset(); reader.State.SeenGop = false; if ((reader.State.LastHeaderName != null) && (reader.State.LastHeaderName != Slice.Name)) { resultState.Invalidate(); return; // Invalid header sequence } ISequenceState sequenceState = reader.State.Sequence; sequenceState.Reset(); sequenceState.Initialized = true; sequenceState.HorizontalSize = (ushort)reader.GetBits(12, Attribute.HorizontalSizeValue); sequenceState.VerticalSize = (ushort)reader.GetBits(12, Attribute.VerticalSizeValue); reader.GetBits(4, Attribute.AspectRatioInformation, AspectRatioResultFormatter); reader.GetBits(4, Attribute.FrameRateCode, FrameRateResultFormatter); reader.GetBits(18, Attribute.BitRateValue); reader.GetMarker(); reader.GetBits(10, Attribute.VbvBufferSizeValue); reader.GetFlag(Attribute.ConstrainedParametersFlag); if (reader.GetFlag(Attribute.LoadIntraQuantiserMatrix)) { reader.GetData(Attribute.IntraQuantiserMatrix, 64); } if (reader.GetFlag(Attribute.LoadNonIntraQuantiserMatrix)) { reader.GetData(Attribute.NonIntraQuantiserMatrix, 64); } }
// ReSharper disable UnusedParameter.Local private static void RefPicListModification(INalUnitReader reader, IResultNodeState resultState) // ReSharper restore UnusedParameter.Local { bool refPicListReorderingFlag = reader.GetBit(); if (refPicListReorderingFlag) // ref_pic_list_reordering_flag_lX { uint reorderingOfPicNumsIdc; // reordering_of_pic_nums_idc do { if (!reader.HasMoreRbspData()) { resultState.Invalidate(); return; } reorderingOfPicNumsIdc = reader.GetExpGolombCoded(); // reordering_of_pic_nums_idc if ((reorderingOfPicNumsIdc == 0) || (reorderingOfPicNumsIdc == 1)) { reader.GetExpGolombCoded(); // abs_diff_pic_num_minus1 } else if (reorderingOfPicNumsIdc == 2) { reader.GetExpGolombCoded(); // long_term_pic_num } } while (reorderingOfPicNumsIdc != 3); } }
public void Parse(IMpeg2VideoReader reader, IResultNodeState resultState) { resultState.Name = Name; if ((reader.State.LastHeaderName != SequenceHeader.Name)) { resultState.Invalidate(); return; // Invalid header sequence } ISequenceState sequenceState = reader.State.Sequence; reader.GetBits(8, Attribute.ProfileAndLevelIndication); sequenceState.Progressive = reader.GetFlag(Attribute.ProgressiveSequence); sequenceState.ChromaFormat = (ChromaFormat)reader.GetBits(2, Attribute.ChromaFormat); uint horizontalSizeExtension = reader.GetBits(2, Attribute.HorizontalSizeExtension); sequenceState.HorizontalSize = (ushort)((sequenceState.HorizontalSize & 0x0fff) | (horizontalSizeExtension << 12)); uint verticalSizeExtension = reader.GetBits(2, Attribute.VerticalSizeExtension); sequenceState.VerticalSize = (ushort)((sequenceState.VerticalSize & 0x0fff) | (verticalSizeExtension << 12)); reader.GetBits(12, Attribute.BitRateExtension); reader.GetMarker(); reader.GetBits(8, Attribute.VbvBufferSizeExtension); reader.GetBits(1, Attribute.LowDelay); reader.GetBits(2, Attribute.FrameRateExtensionN); reader.GetBits(5, Attribute.FrameRateExtensionD); }
public void Parse(IH264Reader reader, IResultNodeState resultState) { long bytesRemaining = (reader.Length - reader.Position); if (bytesRemaining < 4) { resultState.Invalidate(); return; } long startPosition = reader.Position; // Check whether a sequence parameter set and a picture parameter set are // separated by exactly one byte in a NAL unit stream. // This is the case for H.264 streams embedded in 3GPP files. ulong nextFiveBytes = reader.PeekFiveBytes(); if ((_state.NalUnitType == NalUnitType.SequenceParameterSet) && !IsShortLengthPrefixedNalUnit((uint)(nextFiveBytes >> 16), bytesRemaining) && IsShortLengthPrefixedNalUnit((uint)(nextFiveBytes >> 8) & 0xffffff, (bytesRemaining - 1))) { // Skip the byte that is part of the 3GPP container reader.Position++; bytesRemaining--; nextFiveBytes = reader.PeekFiveBytes(); } if (IsShortLengthPrefixedNalUnit((uint)(nextFiveBytes >> 16), bytesRemaining)) { if (ParseShortLengthPrefixedNalUnit(reader, resultState) && resultState.Valid) { return; // Successfully parse SPS or PPS NAL unit } resultState.Reset(); reader.Position = startPosition; } if (IsLongLengthPrefixedNalUnit(nextFiveBytes, bytesRemaining)) { if (ParseLongLengthPrefixedNalUnit(reader, resultState)) { return; // Successfully parse slice NAL unit } } resultState.Invalidate(); }
/// <summary> /// Parse the ExampleHeader. /// </summary> /// <param name="reader">The <see cref="IExampleReader"/> for parsing the data</param> public void Parse(IExampleReader reader, IResultNodeState resultState) { // Now parse the header. Implement your own parsing code below. reader.GetEqualByteSequence(Attribute.Count); if (!reader.GetFinalExampleHeaderByte(Attribute.ValueOfLastByte)) { resultState.Invalidate(); } }
public void Parse(IMpeg2SystemReader reader, IResultNodeState resultState) { resultState.Name = Name; // This header should not be the first header in a block or directly succeeding a program end code string lastHeaderName = reader.State.LastHeaderName; if ((lastHeaderName == null) || (lastHeaderName == Name)) { resultState.Invalidate(); } }
public void Parse(IMpeg2SystemReader reader, IResultNodeState resultState) { resultState.Name = Name; resultState.ParentName = PackHeader.Name; // This header should be preceeded by a pack header, but which may have been overwritten if ((reader.State.LastHeaderName != PackHeader.Name) && reader.State.SeenPackHeader /*|| SeenPesPacket)*/) { resultState.Invalidate(); return; } reader.GetBits(16, Attribute.HeaderLength); reader.GetMarker(); uint rateBound = reader.GetBits(22, Attribute.RateBound); if (reader.State.SeenPackHeader && (rateBound < reader.State.ProgramMuxRate)) { resultState.Invalidate(); return; } reader.GetMarker(); reader.GetBits(6, Attribute.AudioBound, ab => ab <= 32); reader.GetFlag(Attribute.FixedFlag); reader.GetFlag(Attribute.CspsFlag); reader.GetFlag(Attribute.SystemAudioLockFlag); reader.GetFlag(Attribute.SystemVideoLockFlag); reader.GetMarker(); reader.GetBits(5, Attribute.VideoBound, vb => vb <= 16); reader.GetFlag(Attribute.PacketRateRestrictionFlag); reader.GetReservedBits(7); // 0x7F // Stream information (MPEG-2 only) while (resultState.Valid && (reader.ShowBits(1) == 1)) { resultState.Parse(_streamInfoAttributeParser, reader); } }
public void Parse(IMpeg2VideoReader reader, IResultNodeState resultState) { resultState.Name = Name; reader.State.Sequence.Reset(); reader.State.Picture.Reset(); reader.State.SeenGop = false; if (reader.State.LastHeaderName != Slice.Name) { resultState.Invalidate(); return; // Invalid header sequence } }
public void Parse(IMpeg2SystemReader reader, IResultNodeState resultState) { resultState.Name = Name; resultState.ParentName = PackHeader.Name; // if no pack headers have been encountered, it ends up in the root. int bytesRemaining = (int)reader.GetBits(16, Attribute.ProgramStreamMapLength, n => (n >= 10) && (n <= Math.Min(1018, reader.BytesRemaining))); if (!resultState.Valid) { return; } reader.GetBits(1, Attribute.CurrentNextIndicator); reader.GetReservedBits(2); reader.GetBits(5, Attribute.ProgramStreamMapVersion); reader.GetReservedBits(7); reader.GetMarker(); bytesRemaining -= 2; // TODO: issue 2282: MPEG-2 system detector does not implement full specification int maxProgramStreamInfoLength = (bytesRemaining - 2); uint programStreamInfoLength = reader.GetBits(16, Attribute.ProgramStreamInfoLength, n => n <= maxProgramStreamInfoLength); if (!resultState.Valid) { return; } bytesRemaining -= 2 + reader.SkipBytes((int)programStreamInfoLength); int maxElementaryStreamInfoLength = (bytesRemaining - 2); uint elementaryStreamInfoLength = reader.GetBits(16, Attribute.ElementaryStreamMapLength, n => n <= maxElementaryStreamInfoLength); if (!resultState.Valid) { return; } bytesRemaining -= 2 + reader.SkipBytes((int)elementaryStreamInfoLength); if (bytesRemaining < 4) { resultState.Invalidate(); return; } reader.GetBits(32, Attribute.Crc32); reader.SkipBytes(bytesRemaining - 4); }
public void Parse(IMpeg2VideoReader reader, IResultNodeState resultState) { resultState.Name = Name; // Note: Last header must be a sequence, group of pictures or picture header, or an extension. // Note: Sequence end code always ends parsing of a block, so it cannot occur at this point! string lastHeader = reader.State.LastHeaderName; if ((lastHeader == Slice.Name) || (lastHeader == UserData.Name)) { // User data cannot occur immediately after a slice or (another) user data resultState.Invalidate(); return; } reader.GetAttribute(_userDataAttribute); }
public void Parse(IMpeg2SystemReader reader, IResultNodeState resultState) { IMpeg2SystemState state = reader.State; // Check start code and determine header-specific parsing strategy state.StartCode = reader.GetBits(32, Attribute.StartCode, "{0:X8}"); ISystemHeaderParser headerParser; if (!resultState.Valid || !_headerParsers.TryGetValue(state.StartCode, out headerParser)) { resultState.Invalidate(); return; } // Invoke the header-specific parsing strategy headerParser.Parse(reader, resultState); if (!reader.Valid) { return; } // Handle stuffing (leading 00's before the next start code) uint zeroByteStuffing = reader.GetZeroByteStuffing(Attribute.ZeroByteStuffing); if (IsFragmentBreakPoint(state)) { reader.BreakFragment(); return; } string headerName = resultState.Name as string; // Record the header and (possible) the extension if (state.LastHeaderName == null) { state.FirstHeaderName = headerName; } state.LastHeaderName = headerName; state.LastHeaderZeroByteStuffing = zeroByteStuffing; state.ParsedHeaderCount++; }
public void AddNode(IResultNode rootNode, IResultNode newChildNode, IResultNodeState resultState) { if (IsSlice(newChildNode)) { _state.SliceCount++; } // Check occurance of new child node (at this point) if (!IsSuitableSibling(_lastHeader, newChildNode)) { resultState.Invalidate(); return; } // Add new child node to the tree var parent = GetParentFor(rootNode, newChildNode); parent.AddChild(newChildNode); _lastHeader = newChildNode; _state.ParsedHeaderCount++; }
// 7.3.3.3 Decoded reference picture marking syntax private static void DecRefPicMarking(INalUnitReader reader, IResultNodeState resultState) { if (reader.State.NalUnitType == NalUnitType.CodedSliceOfAnIdrPicture) { reader.GetBit(); // no_output_of_prior_pics_flag reader.GetBit(); // long_term_reference_flag } else if (reader.GetBit()) // adaptive_ref_pic_marking_mode_flag { uint memoryManagementControlOperation; do { if (!reader.HasMoreRbspData()) { resultState.Invalidate(); return; } memoryManagementControlOperation = reader.GetExpGolombCoded(); // memory_management_control_operation if ((memoryManagementControlOperation == 1) || (memoryManagementControlOperation == 3)) { reader.GetExpGolombCoded(); // difference_of_pic_nums_minus1 } if (memoryManagementControlOperation == 2) { reader.GetExpGolombCoded(); // long_term_pic_num } if ((memoryManagementControlOperation == 3) || (memoryManagementControlOperation == 6)) { reader.GetExpGolombCoded(); // long_term_frame_idx } if (memoryManagementControlOperation == 4) { reader.GetExpGolombCoded(); // max_long_term_frame_idx_plus1 } } while (memoryManagementControlOperation != 0); } }
public void Parse(IH264Reader reader, IResultNodeState resultState) { if (reader.Position == reader.Length) { resultState.Invalidate(); return; } long nalUnitEndPosition; // Remove 'zero byte' and 'start code prefix' for the 'byte stream' format if (reader.PeekUInt() == 0x00000001) { // TODO: hoort eigenlijk bij de StartCodePrefix - zie pg. 305 van ITU-T H.264 (03/2010) reader.GetFixedByte(0x00, NalUnitParser.Attribute.ZeroByte); } reader.GetFixedThreeBytes(0x000001, NalUnitParser.Attribute.StartCodePrefix); var windowStart = reader.Position; if (reader.NextNalUnit()) //Forward till after next nalunit startcode { nalUnitEndPosition = reader.Position; //Position of next nalunit start } else { nalUnitEndPosition = reader.Length; } reader.Position = windowStart; //rewind if (!resultState.Valid) { return; } //Parse remainder with specific nalunitparser (NOTE: Is not a sub-object) reader.ParseOneNalUnit(_nalUnitParser, resultState, nalUnitEndPosition); }
public void Parse(IMpeg2SystemReader reader, IResultNodeState resultState) { resultState.Name = Name; if (reader.ShowBits(2) == 1) { reader.GetBits(2, Attribute.Mpeg2Flag); reader.SetMpegFormat(CodecID.Mpeg2System); } else if (reader.ShowBits(4) == 2) { reader.GetBits(4, Attribute.Mpeg2Flag); reader.SetMpegFormat(CodecID.Mpeg1System); } else { // Unknown whether it is MPEG-1 or 2, cannot parse header! reader.GetBits(2, Attribute.Mpeg2Flag, mpeg2Flag => false); resultState.Invalidate(); return; } reader.GetAttribute(_systemClockReferenceAttribute); reader.GetMarker(); reader.State.ProgramMuxRate = reader.GetBits(22, Attribute.ProgramMuxRate, muxRate => muxRate != 0); reader.GetMarker(); if (reader.State.IsMpeg2()) { reader.GetMarker(); reader.GetReservedBits(5); int packStuffingLength = (int)reader.GetBits(3, Attribute.PackStuffingLength); if (packStuffingLength > 0) { reader.GetStuffingBytes(packStuffingLength); } } }
public void Parse(IMpeg2VideoReader reader, IResultNodeState resultState) { resultState.Name = Name; if (reader.State.LastHeaderName != PictureHeader.Name) { resultState.Invalidate(); return; // Invalid header sequence } IPictureState pictureState = reader.State.Picture; pictureState.ForwardHorizontalFCode = (byte)reader.GetBits(4, Attribute.ForwardHorizontalFCode); pictureState.ForwardVerticalFCode = (byte)reader.GetBits(4, Attribute.ForwardVerticalFCode); pictureState.BackwardHorizontalFCode = (byte)reader.GetBits(4, Attribute.BackwardHorizontalFCode); pictureState.BackwardVerticalFCode = (byte)reader.GetBits(4, Attribute.BackwardVerticalFCode); reader.GetBits(2, Attribute.IntraDCPrecision); pictureState.Structure = (PictureStructure)reader.GetBits(2, Attribute.PictureStructure, _pictureStructureResultFormatter); pictureState.TopFieldFirst = reader.GetFlag(Attribute.TopFieldFirst); pictureState.FramePredFrameDct = reader.GetFlag(Attribute.FramePredFrameDct); pictureState.ConcealmentMotionVectors = reader.GetFlag(Attribute.ConcealmentMotionVectors); reader.GetBits(1, Attribute.QuantiserScaleType); pictureState.IntraVlcFormat = (reader.GetBits(1, Attribute.IntraVlcFormat) == 0) ? false : true; reader.GetFlag(Attribute.AlternateScan); pictureState.RepeatFirstField = reader.GetFlag(Attribute.RepeatFirstField); reader.GetFlag(Attribute.Chroma420Type); reader.GetFlag(Attribute.ProgressiveFrame); if (reader.GetFlag(Attribute.CompositeDisplayFlag)) { reader.GetBits(1, Attribute.VAxis); reader.GetBits(3, Attribute.FieldSequence); reader.GetBits(1, Attribute.SubCarrier); reader.GetBits(7, Attribute.BurstAmplitude); reader.GetBits(8, Attribute.SubCarrierPhase); } }
public void Parse(IMpeg2VideoReader reader, IResultNodeState resultState) { resultState.Name = Name; IMpeg2VideoState state = reader.State; // It can occur after the last slice of a picture or after a sequence header, possible followed by user data and/or extensions if ((state.LastHeaderName != Slice.Name) && (state.LastHeaderName != null) && (!state.Sequence.Initialized || state.SeenGop || state.Picture.Initialized)) { resultState.Invalidate(); return; } if (!reader.State.Sequence.Initialized) { reader.InsertReferenceHeaderBeforeStartCode(); } state.SeenGop = true; state.Picture.Reset(); reader.GetAttribute(_timeCodeAttribute); reader.GetFlag(Attribute.ClosedGop); reader.GetFlag(Attribute.BrokenLink); }
// 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(); } } }
public void Parse(IMpeg2SystemReader reader, IResultNodeState resultState) { resultState.Name = Name; resultState.ParentName = PackHeader.Name; uint pesPacketLength = reader.GetBits(16, Attribute.PesPacketLength, n => n <= reader.BytesRemaining); long pesPacketEnd = reader.Position + pesPacketLength; resultState.Recover(); // Invalid PES packets should not end the current block! ushort streamId = (ushort)(reader.State.StartCode & 0xFF); if (streamId == 0xBE || streamId == 0xBF || streamId == 0xF0 || streamId == 0xF1 || streamId == 0xF2 || streamId == 0xF8) { // These streams do not contain further header details } else if (reader.ShowBits(2) == 2) { #region MPEG-2 reader.SetMpegFormat(CodecID.Mpeg2System); reader.GetBits(2, Attribute.Mpeg2Flag, f => f == 0x2); reader.GetBits(2, Attribute.PesScramblingControl); reader.GetBits(1, Attribute.PesPriority); reader.GetFlag(Attribute.DataAlignmentIndicator); reader.GetFlag(Attribute.Copyright); reader.GetFlag(Attribute.OriginalOrCopy); uint ptsDtsFlags = reader.GetBits(2, Attribute.PtsDtsFlags, f => f != 0x1); bool escrFlag = reader.GetFlag(Attribute.EscrFlag); bool esRateFlag = reader.GetFlag(Attribute.ESRateFlag); bool dsmTrickModeFlag = reader.GetFlag(Attribute.DsmTrickModeFlag); bool additionalCopyInfoFlag = reader.GetFlag(Attribute.AdditionalCopyInfoFlag); bool pesCrcFlag = reader.GetFlag(Attribute.PesCrcFlag); bool pesExtensionFlag = reader.GetFlag(Attribute.PesExtensionFlag); uint bytesRemaining = pesPacketLength - 3; uint pesHeaderDataLength = reader.GetBits(8, Attribute.PesHeaderDataLength, n => n <= bytesRemaining); long pesHeaderDataEnd = reader.Position + pesHeaderDataLength; if (!resultState.Valid) { return; } // Decode optional header fields switch (ptsDtsFlags) { case 2: reader.GetBits(4, 0x2); reader.GetAttribute(_presentationTimeStampAttribute); break; case 3: reader.GetBits(4, 0x3); reader.GetAttribute(_presentationTimeStampAttribute); reader.GetBits(4, 0x1); reader.GetAttribute(_decodingTimeStampAttribute); break; } if (escrFlag) { reader.GetAttribute(_escrAttribute); reader.GetMarker(); } if (esRateFlag) { reader.GetMarker(); reader.GetBits(22, Attribute.ESRate); reader.GetMarker(); } if (dsmTrickModeFlag) { switch (reader.GetBits(3, Attribute.TrickModeControl)) { case 0: case 3: reader.GetBits(2, Attribute.FieldId); reader.GetFlag(Attribute.IntraSliceRefresh); reader.GetBits(1, Attribute.FrequencyTruncation); // TODO: is this a flag?? break; case 1: case 4: reader.GetBits(5, Attribute.RepCntrl); break; case 2: reader.GetBits(2, Attribute.FieldId); reader.GetBits(3, Attribute.TrickModeReserved); break; default: reader.GetBits(5, Attribute.TrickModeReserved); break; } } if (additionalCopyInfoFlag) { reader.GetMarker(); reader.GetBits(7, Attribute.AdditionalCopyInfo); } if (pesCrcFlag) { reader.GetBits(16, Attribute.PreviousPesPacketCrc); } if (pesExtensionFlag) { bool pesPrivateDataFlag = reader.GetFlag(Attribute.PesPrivateDataFlag); bool packHeaderFieldFlag = reader.GetFlag(Attribute.PackHeaderFieldFlag); bool programPacketSequenceCounterFlag = reader.GetFlag(Attribute.ProgramPacketSequenceCounterFlag); bool pStdBufferFlag = reader.GetFlag(Attribute.PStdBufferFlag); reader.GetReservedBits(3); bool pesExtensionFlag2 = reader.GetFlag(Attribute.PesExtensionFlag2); if (pesPrivateDataFlag) { reader.GetData(Attribute.PesPrivateData, 16); } if (packHeaderFieldFlag) { reader.GetBits(8, Attribute.PackFieldLength); // TODO: pack_header(); } if (programPacketSequenceCounterFlag) { reader.GetMarker(); reader.GetBits(7, Attribute.ProgramPacketSequenceCounter); reader.GetMarker(); reader.GetBits(1, Attribute.Mpeg1Mpeg2Identifier); reader.GetBits(6, Attribute.OriginalStuffLength); } if (pStdBufferFlag) { reader.GetBits(2, 0x1); reader.GetBits(1, Attribute.PStdBufferBoundScale); reader.GetBits(13, Attribute.PStdBufferSizeBound); } if (pesExtensionFlag2) { reader.GetMarker(); uint pesExtensionFieldLength = reader.GetBits(7, Attribute.PesExtensionFieldLength); reader.GetData(Attribute.PesExtensionField, (int)pesExtensionFieldLength); } } if (reader.Position > pesHeaderDataEnd || reader.Position < (pesHeaderDataEnd - 32)) { // FIXME: reader.CheckAttribute(Attribute.PesHeaderDataLength, false); resultState.Invalidate(); return; } int stuffingBytes = (int)(pesHeaderDataEnd - reader.Position); if (stuffingBytes > 0) { // TODO issue 2323 MPEG-2 systems detector does not check header stuffing of private stream 1 if (streamId == 0xBD) { // Note: The format of these bytes is different! reader.SkipBytes(stuffingBytes); } else { reader.GetStuffingBytes(stuffingBytes); } } #endregion MPEG-2 } else { #region MPEG-1 reader.SetMpegFormat(CodecID.Mpeg1System); //FIXME: Attributes.Add(new FormattedAttribute<Attribute, bool>(Attribute.Mpeg2Flag, false)); uint maxUnknownByteCount = (uint)Mpeg2SystemDetector.Configurable[Mpeg2SystemDetector.ConfigurationKey.PesPacketMaxUnknownByteCount]; int count = 0; // Sanity check while (reader.ShowBits(1) == 1 && count++ < maxUnknownByteCount) { reader.GetBits(8); // TODO: attribute? } if (reader.ShowBits(2) == 0x1) { reader.GetBits(2, 0x1); reader.GetBits(1, Attribute.PStdBufferBoundScale); reader.GetBits(13, Attribute.PStdBufferSizeBound); } switch (reader.GetBits(4, Attribute.PtsDtsFlags)) { case 0: reader.GetBits(4, 0xF); break; case 2: reader.GetAttribute(_presentationTimeStampAttribute); break; case 3: reader.GetAttribute(_presentationTimeStampAttribute); reader.GetBits(4, 0x1); reader.GetAttribute(_decodingTimeStampAttribute); break; default: //reader.CheckAttribute(Attribute.PtsDtsFlags, false); break; } #endregion MPEG-1 } if (reader.Position >= pesPacketEnd) { // FIXME: reader.CheckAttribute(Attribute.PesPacketLength, reader.Position <= pesPacketEnd); resultState.Invalidate(); return; } int dataLength = (int)Math.Min((pesPacketEnd - reader.Position), reader.BytesRemaining); if (streamId == 0xBE) // Padding stream { // Read padding bytes if (reader.ShowBits(8) == 0x0F) { reader.GetByte(); // MPEG-1 padding stream dataLength--; } for (int i = 0; i < dataLength; i++) { if (reader.GetByte() != 0xFF) { // Truncate packet // TODO: reader.CheckAttribute(Attribute.PesPacketLength, reader.GetByte() == 0xFF, false)) pesPacketEnd = reader.Position - 1; reader.SkipBytes(dataLength - i - 1); break; } } } else { IDataPacket pesPacketData = reader.GetDataPacket(reader.Position, dataLength); reader.SkipBytes(dataLength); reader.State.Streams[streamId].AddPayload(pesPacketData); } // TODO: Check for truncated packet }
// 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(); } }
// 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(); } }
public void Parse(IMpeg2VideoReader reader, IResultNodeState resultState) { IMpeg2VideoState state = reader.State; // Check start code and determine header-specific parsing strategy uint startCode = reader.GetBits(32, Attribute.StartCode, "{0:X8}"); state.StartCode = startCode; IVideoHeaderParser headerParser; if (!resultState.Valid || !_headerParsers.TryGetValue(startCode, out headerParser)) { resultState.Invalidate(); return; } // Check consistent use of MPEG-2 extensions and detect version (MPEG-1 or MPEG-2) if ((state.LastHeaderName == PictureHeader.Name) || (state.LastHeaderName == SequenceHeader.Name)) { var detectedFormat = (startCode == ExtensionParser.ExtensionStartCode) ? CodecID.Mpeg2Video : CodecID.Mpeg1Video; if (state.MpegFormat == CodecID.Unknown) { state.MpegFormat = detectedFormat; } else if (detectedFormat != state.MpegFormat) { // Inconsistent use of MPEG-2 extensions: // Extensions are not allowed in MPEG-1 streams and are mandatory in MPEG-2 streams! resultState.Invalidate(); return; } } // Determine parent node for this result *BEFORE* parsing this result (and changing the internal state)!! resultState.ParentName = GetSuitableParent(reader.State); // Invoke the header-specific parsing strategy headerParser.Parse(reader, resultState); if (!reader.Valid) { return; } // Handle stuffing (leading 00's before the next start code) uint zeroByteStuffing = reader.GetZeroByteStuffing(Attribute.ZeroByteStuffing); // Break if the maximum number of headers has been reached var headerName = resultState.Name as string; if (IsFragmentBreakPoint(state, headerName)) { reader.BreakFragment(); return; } // Record the header and (possible) the extension if (state.LastHeaderName == null) { state.FirstHeaderName = headerName; } state.LastHeaderName = headerName; state.LastHeaderZeroByteStuffing = zeroByteStuffing; state.ParsedHeaderCount++; if (headerName == Slice.Name) { if (resultState.Valid) { state.ValidSliceCount++; } else { state.InvalidSliceCount++; } } }