public IDataBlock DetectData(IDataReader dataReader, IDataBlockBuilder dataBlockBuilder, IScanContext context) { if (dataReader.State != DataReaderState.Ready) { return(null); } try { long startPosition = dataReader.Position; IDataBlock dataBlock = _detector.DetectData(dataReader, dataBlockBuilder, context); if (dataReader.State == DataReaderState.Cancelled) { dataReader.Position = dataReader.Length; } else if (dataReader.Position <= startPosition) { // Force advance stream reader one byte Log.Error(string.Format("Detector {0} did not advance the stream reader position.", _detector.Name)); dataReader.Position = startPosition + 1; } return(dataBlock); } catch (OutOfMemoryException) { // TODO improve out of memory exception handling and remove reference to System.Windows.Forms System.Windows.Forms.MessageBox.Show("There is not enough memory available to continue scanning current data block (2); Position: " + dataReader.Position + "; Detector: " + _detector.Name + "; Header count: ?", "Out Of Memory"); // Skip rest of the stream dataReader.Position = dataReader.Length; return(null); } }
/// <summary> /// Gets the data for the given <paramref name="codecStream"/> and /// reports progress to the given <paramref name="progressReporter"/>. /// This rescans the parent (container) of the codecStream to determine /// the data of codecStream. /// </summary> /// <param name="codecStream">the codec stream to retrieve the data for</param> /// <param name="progressReporter">the progress reporter</param> /// <param name="dataReaderPool">The shared pool of file data readers</param> /// <returns>the root node of the results</returns> public IDataPacket GetData(ICodecStream codecStream, IProgressReporter progressReporter, IDataReaderPool dataReaderPool) { IDataPacket data; if (_dataCache.TryGetValue(codecStream, out data)) { return(new RescannedCodecStream(codecStream, data)); } IDataBlock containerStreamDataBlock = codecStream.DataBlock; using (IDataReader dataReader = new ProgressDataReader(new FragmentedDataReader(containerStreamDataBlock, dataReaderPool), progressReporter)) { IDetector containerDetector = containerStreamDataBlock.Detectors.FirstOrDefault(); IScanContext scanContext = _createScanContext(containerStreamDataBlock.InputFile.Project); scanContext.Detectors = new[] { containerDetector }; IDataBlockBuilder containerStreamDataBlockBuilder = _createDataBlockBuilder(); containerStreamDataBlockBuilder.Detectors = scanContext.Detectors; containerStreamDataBlockBuilder.InputFile = containerStreamDataBlock.InputFile; IDataBlock newContainerStream = containerDetector.DetectData(dataReader, containerStreamDataBlockBuilder, scanContext); // Check cancellation request if (progressReporter.CancellationPending) { return(null); } // Check results / container stream if (newContainerStream == null) { RetrievedDetectableIsDifferentThanTheOneRetrievedDuringTheInitialScan(); return(null); } data = newContainerStream.CodecStreams.Where(c => c.StreamNumber == codecStream.StreamNumber).FirstOrDefault(); if ((data == null) || (data.Length < codecStream.EndOffset)) { RetrievedDetectableIsDifferentThanTheOneRetrievedDuringTheInitialScan(); return(null); } data = data.GetSubPacket(codecStream.StartOffset, codecStream.Length); } CacheData(codecStream, data); return(new RescannedCodecStream(codecStream, data)); }
private bool GetNextDataBlock(IInputFile file, IDataReader dataReader, IScanContext scanContext, out IDataBlock volBlock, out IDataBlockBuilder volBuilder) { IDataBlock volBlockAttempt = null; IDataBlockBuilder volBlockAttemptBuilder = null; while (volBlockAttempt == null && dataReader.State == DataReaderState.Ready) { volBlockAttemptBuilder = CreateBuilder(file); scanContext.Detectors = new[] { _detector }; volBlockAttempt = _detector.DetectData(dataReader, volBlockAttemptBuilder, scanContext); } volBlock = volBlockAttempt; volBuilder = volBlockAttemptBuilder; return(volBlock != null); }
private IDataBlock ScanDataBlock(byte[] byteStream, IScanContext scanContext) { scanContext.Detectors = new[] { _videoDetector }; IDataBlockBuilder builder = TestFramework.CreateDataBlockBuilder(); builder.Detectors = scanContext.Detectors; var inputFile = _mockRepository.StrictMock <IInputFile>(); With.Mocks(_mockRepository).Expecting(delegate { SetupResult.For(inputFile.Name).Return("<ByteArrayDataReader>"); SetupResult.For(inputFile.Length).Return(byteStream.Length); }); builder.InputFile = inputFile; var mockDataReader = new MockDataReader(byteStream, inputFile); IDataBlock dataBlock = _videoDetector.DetectData(mockDataReader, builder, scanContext); Assert.IsNotNull(dataBlock); return(dataBlock); }
public void TestDetectData() { using (IDataReader dataReader = new MockDataReader(new byte[DataFileLength], _inputFile)) { IScanContext scanContext = TestFramework.CreateScanContext(_project); scanContext.Detectors = new[] { _detector }; IDataBlockBuilder builder = TestFramework.CreateDataBlockBuilder(); builder.Detectors = scanContext.Detectors; builder.InputFile = _inputFile; IDataBlock dataBlock = _detector.DetectData(dataReader, builder, scanContext); Assert.IsNotNull(dataBlock, "Unknown format detector (DetectData not null)"); IResultNode results = scanContext.Results; Assert.IsNotNull(results, "Unknown format detector (Results not null)"); Assert.AreEqual(_detector, dataBlock.Detectors.First(), "Detector of data block"); Assert.AreEqual(1, results.Children.Count, "One child 'Data'"); IResultNode data = results.Children[0]; Assert.IsEmpty((ICollection)data.Children, "Data has no children"); Assert.AreEqual(0, data.StartOffset, ""); Assert.AreEqual(DataFileLength, data.Length, ""); Assert.IsFalse(data.IsFragmented(), "Single fragment"); Assert.AreEqual(_inputFile, data.InputFile, "Input file"); Assert.IsFalse(dataBlock.IsFullFile, "Does not produce full files"); } }
private IResultNode RescanDetectable(IFragment detectable, IProgressReporter progressReporter, IDataReaderPool dataReaderPool) { IDataPacket data = detectable; if (detectable is ICodecStream) { // Data is specified relative to the codec stream (see IDetectable.Data) data = GetData(detectable as ICodecStream, progressReporter, dataReaderPool); if (progressReporter.CancellationPending) { return(null); // The rescan is cancelled } var codecStream = detectable as ICodecStream; if (codecStream.ReferenceHeader != null) { long off = codecStream.ReferenceHeaderOffset; if (off == 0L) { data = codecStream.ReferenceHeader.Append(data); } else { data = data.GetSubPacket(0, off).Append(codecStream.ReferenceHeader).Append(data.GetSubPacket(off, data.Length - off)); } } } if (detectable is IDataBlock) { IDataBlock dataBlock = detectable as IDataBlock; if (dataBlock.ReferenceHeader != null) { long off = dataBlock.ReferenceHeaderOffset; if (off == 0L) { data = dataBlock.ReferenceHeader.Append(detectable); } else { data = detectable.GetSubPacket(0, off).Append(dataBlock.ReferenceHeader).Append(detectable.GetSubPacket(off, detectable.Length - off)); } } } IResultNode results; using (IDataReader dataReader = new ProgressDataReader(new FragmentedDataReader(data, dataReaderPool), progressReporter)) { IScanContext scanContext = _createScanContext(detectable.InputFile.Project); scanContext.Detectors = detectable.Detectors; IDataBlockBuilder dataBlockBuilder = _createDataBlockBuilder(); dataBlockBuilder.Detectors = scanContext.Detectors; dataBlockBuilder.InputFile = detectable.InputFile; IDetector detector = GetDetector(detectable); IDataBlock newDataBlock; var codecDetector = (detector as ICodecDetector); if (codecDetector == null) { newDataBlock = detector.DetectData(dataReader, dataBlockBuilder, scanContext); } else { var referenceHeaders = codecDetector.ReferenceHeaders; try { // Disable reference headers during rescan codecDetector.ReferenceHeaders = null; newDataBlock = detector.DetectData(dataReader, dataBlockBuilder, scanContext); } finally { // Restore reference headers codecDetector.ReferenceHeaders = referenceHeaders; } } if (!progressReporter.CancellationPending && newDataBlock == null) { RetrievedDetectableIsDifferentThanTheOneRetrievedDuringTheInitialScan(); return(null); } results = scanContext.Results; // Check cancellation request and results / data block if (!progressReporter.CancellationPending && (detectable is IDataBlock) && !IsDataBlockCorrect(detectable as IDataBlock, newDataBlock)) { //RetrievedDetectableIsDifferentThanTheOneRetrievedDuringTheInitialScan(); //return null; } } return(results); }