private static bool IsFragmentBreakPoint(IMpeg2VideoState state, string headerName) { if (state.ParsedHeaderCount <= state.Configuration.MaxVideoHeaderCount) { return(false); } if (headerName == SequenceHeader.Name) { return(true); } if (headerName == GroupOfPicturesHeader.Name) { return(!state.Sequence.Initialized); } if (headerName == PictureHeader.Name) { return(!state.Sequence.Initialized && !state.SeenGop); } if (headerName == Slice.Name) { return(!state.Picture.Initialized); } return(false); }
private static object GetSuitableParent(IMpeg2VideoState state) { uint startCode = state.StartCode; if (startCode == SequenceHeader.SequenceStartCode || startCode == SequenceEndCode.SequenceEndStartCode) { return(null); // root } if (startCode == GroupOfPicturesHeader.GopStartCode) { return(SequenceHeader.Name); // or root, if no sequence is open } if (startCode == PictureHeader.PictureStartCode) { return(state.SeenGop ? GroupOfPicturesHeader.Name : SequenceHeader.Name); // or root, if no sequence is open } if (state.Picture.Initialized) { return(PictureHeader.Name); } if (state.SeenGop) { return(GroupOfPicturesHeader.Name); } if (state.Sequence.Initialized) { return(SequenceHeader.Name); } return(null); // Place the result in the root }
public Mpeg2VideoCarver(IMpeg2VideoReader reader, IResultParser <IMpeg2VideoReader> videoHeaderParser, IScanContext scanContext) { _reader = reader; _videoHeaderParser = videoHeaderParser; _scanContext = scanContext; _state = reader.State; _minHeaderCount = (uint)Mpeg2VideoDetector.Configurable[Mpeg2VideoDetector.ConfigurationKey.MinVideoHeaderCount]; }
public Mpeg2VideoReader(BitStreamDataReader dataReader, IMpeg2VideoState state, IReaderState readerState) { _dataReader = dataReader; _state = state; _readerState = readerState; _maxZeroByteStuffingLength = (uint)Mpeg2VideoDetector.Configurable[Mpeg2VideoDetector.ConfigurationKey.ParserMaxZeroByteStuffingLength]; ReferenceHeaders = NoDefaultHeaders; }
private static bool CheckExtensionOccurance(IMpeg2VideoState state, ExtensionId extensionId) { if (extensionId == ExtensionId.SequenceExtensionId) { return(true); } if (extensionId == ExtensionId.PictureCodingExtensionId) { return(true); } // Extensions other than 'SequenceExtension' and 'PictureCodingExtension', // which are the first extension to follow a sequence or picture header // respectively in a valid MPEG-2 stream, can only occur after extension of // the same type (sequence or picture). Duplicates are not allowed! if (state.Picture.Initialized) { // No duplicates allowed! if (state.Picture.HasExtension(extensionId)) { return(false); } // FIXME: 'extensionId' must be a picture extension!! // Last header must be a picture extension return(IsPictureExtension(state.LastHeaderName)); } else { // No duplicates allowed! if (state.Sequence.HasExtension(extensionId)) { return(false); } // FIXME: 'extensionId' must be a sequence extension!! // Last header must be a sequence extension return(IsSequenceExtension(state.LastHeaderName)); } }
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); }
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++; } } }