public virtual void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxOptions) { long currentOffset = -1; long fileSize; byte[] dummy; uint blocksProcessed = 0; uint audioFramesProcessed = 0; uint videoFramesProcessed = 0; uint bytesProcessed = 0; uint expectedBytesProcessed = 0; BlockHeader blockHeader = new BlockHeader(); FrameHeader frameHeader = new FrameHeader(); bool isFirstVideoFrame = true; bool isFirstAudioFrame = true; byte[] fullChunk; uint audioChunkSize; uint audioChunkSamples; long blockStart; long frameStart; Dictionary <string, FileStream> streamWriters = new Dictionary <string, FileStream>(); try { using (FileStream fs = File.OpenRead(this.FilePath)) { fileSize = fs.Length; #region HEADER CHECK // check header dummy = ParseFile.ParseSimpleOffset(fs, 0, 0x10); if (ParseFile.CompareSegment(dummy, 0, HVQM4_13_SIGNATURE)) { this.FileRevision = VersionType.HVQM4_13; currentOffset = 0; } else if (ParseFile.CompareSegment(dummy, 0, HVQM4_15_SIGNATURE)) { this.FileRevision = VersionType.HVQM4_15; currentOffset = 0; } else { throw new Exception("HVQM4 signature not found at offset 0x00"); } #endregion // parse file if (currentOffset >= 0) { // get header this.ParseHeader(fs, 0); currentOffset = this.HeaderSize + 4; // process file while ((currentOffset < fileSize) && (blocksProcessed < this.Blocks)) { // reset flags isFirstVideoFrame = true; isFirstAudioFrame = true; audioFramesProcessed = 0; videoFramesProcessed = 0; //-------------- // parse block //-------------- blockStart = currentOffset; blocksProcessed++; // parse block header this.ParseBlockHeader(fs, currentOffset, ref blockHeader); currentOffset += blockHeader.GetSize(); bytesProcessed = 0; while (bytesProcessed < blockHeader.BlockSize) { frameStart = currentOffset; // verify we haven't processed too much if (audioFramesProcessed > blockHeader.AudioFrameCount) { throw new Exception(String.Format("Processed more audio frames than expected for block starting at 0x{0}", blockStart.ToString("X8"))); } else if (videoFramesProcessed > blockHeader.VideoFrameCount) { throw new Exception(String.Format("Processed more video frames than expected for block starting at 0x{0}", blockStart.ToString("X8"))); } // parse frame header this.ParseFrameHeader(fs, currentOffset, ref frameHeader); currentOffset += frameHeader.GetSize(); bytesProcessed += (uint)frameHeader.GetSize(); //--------------- // process frame //--------------- // audio chunk if (demuxOptions.ExtractAudio && frameHeader.IsAudioFrame(isFirstAudioFrame)) { audioChunkSamples = ParseFile.ReadUintBE(fs, currentOffset); audioChunkSize = (audioChunkSamples * this.AudioChannels) / 2; // get full frame for now fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset, (int)frameHeader.FrameSize); // different frames have different IMA info //if (isFirstAudioFrame) //{ // fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset + 6, (int)audioChunkSize); //} //else //{ // fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset + 4, (int)audioChunkSize); //} this.writeChunkToStream(fullChunk, "audio", streamWriters, this.FileExtensionAudio); isFirstAudioFrame = false; audioFramesProcessed++; } // video chunk else if (demuxOptions.ExtractVideo && frameHeader.IsVideoFrame(isFirstVideoFrame, this.FileRevision)) { fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset, (int)frameHeader.FrameSize); this.writeChunkToStream(fullChunk, "video", streamWriters, this.FileExtensionVideo); isFirstVideoFrame = false; videoFramesProcessed++; } //unknown else { fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset, (int)frameHeader.FrameSize); this.writeChunkToStream(fullChunk, "unknown", streamWriters, ".bin"); } // update number of bytes processed bytesProcessed += frameHeader.FrameSize; // move to next frame currentOffset += frameHeader.FrameSize; } // while (bytesProcessed < blockHeader.BlockSize) // verify proper number of bytes processed if (blocksProcessed < this.Blocks) { bytesProcessed = bytesProcessed + (uint)(blockHeader.GetSize() + 4); expectedBytesProcessed = ParseFile.ReadUintBE(fs, currentOffset); if (expectedBytesProcessed != bytesProcessed) { throw new Exception(String.Format( "Bytes processed 0x{0}does not match expected bytes processed {1} for block starting at 0x{2}.", bytesProcessed.ToString("X8"), expectedBytesProcessed.ToString("X8"), blockStart.ToString("X8"))); } else { currentOffset += 4; } } } } else { throw new Exception(String.Format("Cannot find MVHD header.{0}", Environment.NewLine)); } } } catch (Exception ex) { throw new Exception(ex.Message); } finally { this.DoFinalTasks(streamWriters); } }