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(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 }