Example #1
0
        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);
            }
        }