/// <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 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); }