override public IDataBlock DetectData(IDataReader dataReader, IDataBlockBuilder dataBlockBuilder, IScanContext context) { QtAtom root = new QtAtom(context.Detectors); // Try to parse a contiguous block of headers using (QtParser parser = new QtParser(new ByteStreamDataReader(dataReader))) { if (!parser.ParseRoot(root, dataReader.Length)) { dataReader.Position = dataReader.Length; return(null); } // Synchronize the position of the data reader dataReader.Position = parser.Position; } // Trim trailing unknown or large unparsable atoms QtAtom lastHeader = root.LastHeader; long firstHeaderOffset = ((QtAtom)root.Children[0]).Offset; while (lastHeader.IsUnknown && lastHeader.Parent != null) { if (lastHeader.RelativeEndOffset == ((QtAtom)lastHeader.Parent).RelativeEndOffset) { break; // Last child perfectly aligned with parent atom } lastHeader.Parent.RemoveChild(lastHeader); lastHeader = root.LastHeader; } // Discard data blocks of only 1 atom if ((dataReader.State == DataReaderState.Cancelled) || (root.Children.Count == 0) || ((root.Children.Count == 1) && !root.FirstChild.HasChildren())) { // Rewind data reader dataReader.Position = firstHeaderOffset + 1; // lastHeader.Offset + lastHeader.Length; // != lastHeader.RelativeEndOffset; !!! return(null); } context.Results = root; var codecStream = new CodecStream(dataReader, dataBlockBuilder, root); long?rescanPosition = codecStream.CreateCodecStreams(); // TODO: check for (complete) mdat block (for IsFullFile) // Note: For consistency, always report the name of the detector itself, not a specific data format! //dataBlockBuilder.DataFormat = root.DataFormat; dataBlockBuilder.IsFullFile = IsFullFile(root); var firstChild = ((QtAtom)root.Children[0]); dataBlockBuilder.StartOffset = firstChild.Offset; var lastChild = ((QtAtom)root.GetLastDescendant()); var endOffset = (lastChild.Offset + lastChild.Length); dataBlockBuilder.EndOffset = endOffset; dataReader.Position = rescanPosition ?? endOffset; // If the last atom is an 'mdat' atom that was truncated for rescan to its minimum size, truncate the actual result! if ((rescanPosition == (lastChild.Offset + 8)) && (lastChild == root.FindChild(AtomName.MediaData))) { dataBlockBuilder.EndOffset = rescanPosition.Value; } return(dataBlockBuilder.Build()); }
private string GetCodecStreamName() { return(CodecStream.GetCodecStreamName(_track, _sampleDescription, _truncated)); }