private long parseDataPacket(Stream inStream, long currentOffset, MpegStream.DemuxOptionsStruct demuxOptions)
        {
            long packetSize = 0;
            AsfDataPacketPayloadParsingObject dataPacketPayloadParsingObject;
            AsfDataPacketPayloadObject        dataPacketPayloadObject;

            // get payload parsing info
            dataPacketPayloadParsingObject = this.parseAsfDataPacketPayloadParsingObject(inStream, currentOffset);
            currentOffset += dataPacketPayloadParsingObject.PacketOverheadLength;
            packetSize    += dataPacketPayloadParsingObject.PacketOverheadLength;

            // parse payload(s)
            for (int i = 0; i < dataPacketPayloadParsingObject.NumberOfPayloads; i++)
            {
                dataPacketPayloadObject = this.parseAsfDataPacketPayloadObject(inStream, currentOffset, dataPacketPayloadParsingObject, demuxOptions);
                currentOffset          += dataPacketPayloadObject.PayloadSize;
                packetSize += dataPacketPayloadObject.PayloadSize;
            }

            // skip padding
            currentOffset += dataPacketPayloadParsingObject.PaddingLength;
            packetSize    += dataPacketPayloadParsingObject.PaddingLength;

            return(packetSize);
        }
 protected virtual void DoFinalTasks(MpegStream.DemuxOptionsStruct demuxOptions)
 {
     foreach (uint key in this.streamWriterDictionary.Keys)
     {
         try
         {
         }
         catch (Exception ex)
         {
             if (this.streamWriterDictionary[key] != null)
             {
                 throw new Exception(String.Format("Exception building header for file: {0}{1}{2}", this.streamWriterDictionary[key].Name, ex.Message, Environment.NewLine));
             }
             else
             {
                 throw new Exception(String.Format("Exception building header for file: {0}{1}{2}", "UNKNOWN", ex.Message, Environment.NewLine));
             }
         }
         finally
         {
             // close streams if open
             if (this.streamWriterDictionary[key] != null &&
                 this.streamWriterDictionary[key].CanRead)
             {
                 this.streamWriterDictionary[key].Close();
                 this.streamWriterDictionary[key].Dispose();
             }
         }
     }
 }
Beispiel #3
0
 protected virtual void DoFinalTasks(Dictionary <uint, FileStream> streamWriters,
                                     MpegStream.DemuxOptionsStruct demuxOptions)
 {
     foreach (uint key in streamWriters.Keys)
     {
         if (streamWriters[key] != null &&
             streamWriters[key].CanRead)
         {
             streamWriters[key].Close();
             streamWriters[key].Dispose();
         }
     }
 }
Beispiel #4
0
        protected virtual void DoFinalTasks(Dictionary <uint, FileStream> streamWriters,
                                            MpegStream.DemuxOptionsStruct demuxOptions)
        {
            GenhCreationStruct gcStruct;
            string             sourceFile;
            string             genhFile;

            foreach (uint key in streamWriters.Keys)
            {
                // create GENH since MIB support is spotty
                if (demuxOptions.AddHeader)
                {
                    if (streamWriters[key].Name.EndsWith(this.FileExtensionAudio))
                    {
                        sourceFile = streamWriters[key].Name;

                        streamWriters[key].Close();
                        streamWriters[key].Dispose();

                        gcStruct            = new GenhCreationStruct();
                        gcStruct.Format     = "0x00";
                        gcStruct.HeaderSkip = "0";
                        gcStruct.Interleave = "0x100";
                        gcStruct.Channels   = "2";
                        gcStruct.Frequency  = "48000";
                        gcStruct.NoLoops    = true;

                        genhFile = GenhUtil.CreateGenhFile(sourceFile, gcStruct);

                        // delete original file
                        if (!String.IsNullOrEmpty(genhFile))
                        {
                            File.Delete(sourceFile);
                        }
                    }
                }

                // close streams if open
                if (streamWriters[key] != null &&
                    streamWriters[key].CanRead)
                {
                    streamWriters[key].Close();
                    streamWriters[key].Dispose();
                }
            }
        }
Beispiel #5
0
        public virtual void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxOptions)
        {
            long currentOffset = 0;
            long fileSize;

            long blockSize;
            long videoChunkSize;

            Dictionary <uint, FileStream> streamOutputWriters = new Dictionary <uint, FileStream>();

            ChunkStruct currentChunk = new ChunkStruct();

            ChunkStruct[] audioChunks;

            try
            {
                using (FileStream fs = File.OpenRead(this.FilePath))
                {
                    this.ReadHeader(fs, currentOffset);

                    fileSize      = fs.Length;
                    currentOffset = ParseFile.GetNextOffset(fs, currentOffset, DataStartBytes) + 4;

                    while (currentOffset < fileSize)
                    {
                        if (currentOffset == 0x4C7DC)
                        {
                        }

                        blockSize = this.GetBlockSize(fs, currentOffset);

                        if (blockSize > 0)
                        {
                            // write video block to stream
                            currentChunk = this.GetVideoChunk(fs, currentOffset);

                            if (demuxOptions.ExtractVideo && (currentChunk.Chunk != null))
                            {
                                this.writeChunkToStream(currentChunk.Chunk, currentChunk.ChunkId, streamOutputWriters, this.FileExtensionVideo);
                            }
                            // NDS -- currentBlockId = (uint)(BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(fs, currentOffset, 2), 0) & 0x00FF);


                            // write audio block to stream
                            if (demuxOptions.ExtractAudio && (this.AudioStreamCount > 0))
                            {
                                videoChunkSize = currentChunk.Chunk == null ? 0 : currentChunk.Chunk.Length;
                                audioChunks    = this.GetAudioChunk(fs, currentOffset, blockSize, videoChunkSize);

                                for (uint i = 0; i < this.AudioStreamCount; i++)
                                {
                                    if (audioChunks[i].Chunk != null)
                                    {
                                        this.writeChunkToStream(audioChunks[i].Chunk, audioChunks[i].ChunkId, streamOutputWriters, this.FileExtensionAudio);
                                    }
                                }
                            }

                            // move offset
                            currentOffset += blockSize;
                        }
                        else
                        {
                            break;
                        }
                    }
                } // using (FileStream fs = File.OpenRead(this.FilePath))
            }
            catch (Exception ex)
            {
                throw new Exception(String.Format("Exception processing block at offset 0x{0}: {1}{2}", currentOffset.ToString("X"), ex.Message, Environment.NewLine));
            }
            finally
            {
                // clean up
                this.DoFinalTasks(streamOutputWriters, demuxOptions);
            }
        }
Beispiel #6
0
        public void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxStruct)
        {
            long fileSize;
            long currentOffset = 0;
            long blockStart    = 0;
            long packetSize;
            long nextPacketSize = -1;

            long videoPacketSize;

            long[] audioStreamPacketSizes;

            Dictionary <string, FileStream> streamOutputWriters = new Dictionary <string, FileStream>();
            long audioStreamOffset;
            long videoStreamOffset;

            GenhCreationStruct gcStruct;
            string             genhFile;

            using (FileStream fs = File.Open(this.FilePath, FileMode.Open, FileAccess.Read))
            {
                fileSize = fs.Length;

                while ((nextPacketSize != 0) && (currentOffset < fileSize))
                {
                    blockStart = currentOffset;

                    if (currentOffset == 0)
                    {
                        // get main header
                        this.FileHeader            = new XmvVideoDataHeader();
                        this.FileHeader.MagicBytes = ParseFile.ParseSimpleOffset(fs, 0xC, 4);

                        if (!ParseFile.CompareSegment(this.FileHeader.MagicBytes, 0, XmvMagicBytes))
                        {
                            throw new FormatException(String.Format("XMV Magic Bytes: 'xobX' not found at offset 0xC{0}", Environment.NewLine));
                        }

                        this.FileHeader.InitialPacketSize = ParseFile.ParseSimpleOffset(fs, 4, 4);
                        this.FileHeader.VideoWidth        = ParseFile.ParseSimpleOffset(fs, 0x14, 4);
                        this.FileHeader.VideoHeight       = ParseFile.ParseSimpleOffset(fs, 0x18, 4);

                        // get audio subheaders
                        this.FileHeader.AudioStreamCount = (UInt32)BitConverter.ToUInt16(ParseFile.ParseSimpleOffset(fs, 0x20, 2), 0);
                        this.FileHeader.AudioHeaders     = new XmvAudioDataHeader[this.FileHeader.AudioStreamCount];

                        for (uint i = 0; i < this.FileHeader.AudioStreamCount; i++)
                        {
                            this.FileHeader.AudioHeaders[i]                  = new XmvAudioDataHeader();
                            this.FileHeader.AudioHeaders[i].WaveFormat       = ParseFile.ParseSimpleOffset(fs, 0x24 + (i * 0xC), 2);
                            this.FileHeader.AudioHeaders[i].ChannelCount     = ParseFile.ParseSimpleOffset(fs, 0x24 + (i * 0xC) + 2, 2);
                            this.FileHeader.AudioHeaders[i].SamplesPerSecond = ParseFile.ParseSimpleOffset(fs, 0x24 + (i * 0xC) + 4, 4);
                            this.FileHeader.AudioHeaders[i].BitsPerSample    = ParseFile.ParseSimpleOffset(fs, 0x24 + (i * 0xC) + 8, 4);
                        }

                        // set next packet size
                        nextPacketSize = (long)BitConverter.ToUInt32(this.FileHeader.InitialPacketSize, 0);
                        currentOffset  = 0x24 + (this.FileHeader.AudioStreamCount * 0xC);
                    }

                    // set packet size of current packet
                    packetSize = nextPacketSize;

                    // get size of next packet
                    nextPacketSize = (long)BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, currentOffset, 4), 0);

                    // get size of video data
                    videoPacketSize  = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, currentOffset + 4, 4), 0);
                    videoPacketSize &= 0x000FFFFF;
                    videoPacketSize -= (this.FileHeader.AudioStreamCount * 4);

                    //------------------
                    // write video data
                    //------------------
                    if (demuxStruct.ExtractVideo)
                    {
                        this.FileHeader.OutputPath = Path.Combine(Path.GetDirectoryName(this.FilePath), String.Format("{0}.xmv.raw", Path.GetFileNameWithoutExtension(this.FilePath)));

                        // add output stream to Dictionary
                        if (!streamOutputWriters.ContainsKey(this.FileHeader.OutputPath))
                        {
                            streamOutputWriters.Add(this.FileHeader.OutputPath, new FileStream(this.FileHeader.OutputPath, FileMode.Create, FileAccess.ReadWrite));
                        }

                        // write the video packet
                        videoStreamOffset = currentOffset + 0xC + (this.FileHeader.AudioStreamCount * 4);
                        streamOutputWriters[this.FileHeader.OutputPath].Write(ParseFile.ParseSimpleOffset(fs, videoStreamOffset, (int)videoPacketSize), 0, (int)videoPacketSize);
                    }

                    //------------------
                    // write audio data
                    //------------------
                    if (demuxStruct.ExtractAudio)
                    {
                        // setup audio for writing
                        audioStreamPacketSizes = new long[this.FileHeader.AudioStreamCount];
                        audioStreamOffset      = currentOffset + 0xC + (this.FileHeader.AudioStreamCount * 4) + videoPacketSize;

                        for (uint i = 0; i < this.FileHeader.AudioStreamCount; i++)
                        {
                            audioStreamPacketSizes[i] = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, currentOffset + 0xC + (i * 4), 4), 0);

                            // write audio streams
                            this.FileHeader.AudioHeaders[i].OutputPath = Path.Combine(Path.GetDirectoryName(this.FilePath), String.Format("{0}_{1}.raw", Path.GetFileNameWithoutExtension(this.FilePath), i.ToString("X2")));

                            // add output stream to Dictionary
                            if (!streamOutputWriters.ContainsKey(this.FileHeader.AudioHeaders[i].OutputPath))
                            {
                                streamOutputWriters.Add(this.FileHeader.AudioHeaders[i].OutputPath, new FileStream(this.FileHeader.AudioHeaders[i].OutputPath, FileMode.Create, FileAccess.ReadWrite));
                            }

                            // write this audio packet
                            streamOutputWriters[this.FileHeader.AudioHeaders[i].OutputPath].Write(ParseFile.ParseSimpleOffset(fs, audioStreamOffset, (int)audioStreamPacketSizes[i]), 0, (int)audioStreamPacketSizes[i]);

                            // increase source offset to next packet
                            audioStreamOffset += audioStreamPacketSizes[i];
                        }
                    }

                    currentOffset = blockStart + packetSize;
                } // (currentOffset < fileSize)

                //-------------------
                // close all writers
                //-------------------
                foreach (string k in streamOutputWriters.Keys)
                {
                    if (streamOutputWriters[k].CanRead)
                    {
                        streamOutputWriters[k].Close();
                        streamOutputWriters[k].Dispose();
                    }
                }

                // interleave audio
                // is this needed at all, ONLY FOR MULTI-STREAM, SINGLE CHANNEL PER STREAM?

                //------------------
                // add audio header
                //------------------
                if (demuxStruct.ExtractAudio && demuxStruct.AddHeader)
                {
                    for (int i = 0; i < this.FileHeader.AudioStreamCount; i++)
                    {
                        if (BitConverter.ToUInt16(this.FileHeader.AudioHeaders[i].WaveFormat, 0) == 0x69)
                        {
                            gcStruct            = new GenhCreationStruct();
                            gcStruct.Format     = "0x01";
                            gcStruct.HeaderSkip = "0";
                            gcStruct.Interleave = "0x1";
                            gcStruct.Channels   = BitConverter.ToUInt16(this.FileHeader.AudioHeaders[i].ChannelCount, 0).ToString();
                            gcStruct.Frequency  = BitConverter.ToUInt16(this.FileHeader.AudioHeaders[i].SamplesPerSecond, 0).ToString();
                            gcStruct.NoLoops    = true;

                            genhFile = GenhUtil.CreateGenhFile(this.FileHeader.AudioHeaders[i].OutputPath, gcStruct);

                            // delete original file
                            if (!String.IsNullOrEmpty(genhFile))
                            {
                                File.Delete(this.FileHeader.AudioHeaders[i].OutputPath);
                            }
                        }
                    }
                }

                //------------------
                // add video header
                //------------------
            }
        }
Beispiel #7
0
        public virtual void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxOptions)
        {
            long currentOffset = 0;
            long fileSize;
            long packetEndOffset;

            uint audioPacketSize;

            byte[] audioPacket;
            byte[] emptyAudioPacket = new byte[] { 0x00, 0x00, 0x00, 0x00 };

            uint videoPacketSize;

            byte[] videoPacket;

            long currentPacketOffset;

            Dictionary <uint, FileStream> streamOutputWriters = new Dictionary <uint, FileStream>();

            // set audio extension based on flags
            if (demuxOptions.SplitAudioStreams)
            {
                this.FileExtensionAudio = BinkStream.DefaultFileExtensionAudioSplit;
            }
            else
            {
                this.FileExtensionAudio = BinkStream.DefaultFileExtensionAudioMulti;
            }

            try
            {
                using (FileStream fs = File.OpenRead(this.FilePath))
                {
                    fileSize      = fs.Length;
                    currentOffset = 0;

                    // parse the header
                    this.ParseHeader(fs, currentOffset);

                    // setup new offsets and first frame
                    this.NewFrameOffsetsVideo    = new uint[this.FrameCount];
                    this.NewFrameOffsetsVideo[0] = this.FrameOffsetList[0].FrameOffset - (this.AudioTrackCount * 0xC); // subtract audio frame header info

                    // setup audio frames
                    this.NewFrameOffsetsAudio = new uint[this.AudioTrackCount][];

                    if (demuxOptions.SplitAudioStreams)
                    {
                        this.FileExtensionAudio = BinkStream.DefaultFileExtensionAudioSplit;

                        for (uint i = 0; i < this.AudioTrackCount; i++)
                        {
                            this.NewFrameOffsetsAudio[i]    = new uint[this.FrameCount];
                            this.NewFrameOffsetsAudio[i][0] = this.FrameOffsetList[0].FrameOffset - ((this.AudioTrackCount - 1) * 0xC); // only need one audio header area
                        }
                    }
                    else if (this.AudioTrackCount > 0)
                    {
                        this.FileExtensionAudio         = BinkStream.DefaultFileExtensionAudioMulti;
                        this.NewFrameOffsetsAudio[0]    = new uint[this.FrameCount];
                        this.NewFrameOffsetsAudio[0][0] = this.FrameOffsetList[0].FrameOffset; // all header info stays
                    }

                    //////////////////////
                    // process each frame
                    //////////////////////
                    for (uint frameId = 0; frameId < this.FrameCount; frameId++)
                    {
                        try
                        {
                            currentPacketOffset = 0;

                            //// check to see if final frame offset is file size frame
                            //if (this.FrameOffsetList[frameId].FrameOffset + currentPacketOffset >= fileSize)
                            //{
                            //    break;
                            //}

                            if (demuxOptions.SplitAudioStreams)
                            {
                                //////////////////
                                // extract audio  - separate tracks
                                //////////////////
                                for (uint audioTrackId = 0; audioTrackId < this.AudioTrackCount; audioTrackId++)
                                {
                                    audioPacketSize  = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, this.FrameOffsetList[frameId].FrameOffset + currentPacketOffset, 4), 0);
                                    audioPacketSize += 4;

                                    if (demuxOptions.ExtractAudio)
                                    {
                                        audioPacket = ParseFile.ParseSimpleOffset(fs, this.FrameOffsetList[frameId].FrameOffset + currentPacketOffset, (int)audioPacketSize);
                                        this.writeChunkToStream(audioPacket, this.AudioTrackIds[audioTrackId], streamOutputWriters, this.FileExtensionAudio);
                                    }

                                    currentPacketOffset += audioPacketSize; // goto next packet

                                    // update audio frame id
                                    if ((frameId + 1) < this.FrameCount)
                                    {
                                        this.NewFrameOffsetsAudio[audioTrackId][frameId + 1] = this.NewFrameOffsetsAudio[audioTrackId][frameId] + audioPacketSize;
                                    }
                                }
                            }
                            else
                            {
                                ////////////////////////////////////
                                // extract audio  - combine tracks
                                ////////////////////////////////////
                                for (uint audioTrackId = 0; audioTrackId < this.AudioTrackCount; audioTrackId++)
                                {
                                    audioPacketSize  = BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, this.FrameOffsetList[frameId].FrameOffset + currentPacketOffset, 4), 0);
                                    audioPacketSize += 4;

                                    if ((demuxOptions.ExtractAudio))
                                    {
                                        audioPacket = ParseFile.ParseSimpleOffset(fs, this.FrameOffsetList[frameId].FrameOffset + currentPacketOffset, (int)audioPacketSize);
                                        this.writeChunkToStream(audioPacket, 0, streamOutputWriters, this.FileExtensionAudio);
                                    }

                                    currentPacketOffset += audioPacketSize; // goto next packet
                                }

                                // update audio frame id
                                if ((this.AudioTrackCount > 0) && ((frameId + 1) < this.FrameCount))
                                {
                                    this.NewFrameOffsetsAudio[0][frameId + 1] = this.NewFrameOffsetsAudio[0][frameId] + (uint)currentPacketOffset;
                                }
                            }

                            /////////////////
                            // extract video
                            /////////////////
                            if (frameId == (this.FrameCount - 1)) // last frame
                            {
                                packetEndOffset = fileSize;
                            }
                            else
                            {
                                packetEndOffset = this.FrameOffsetList[frameId + 1].FrameOffset;
                            }

                            videoPacketSize = (uint)(packetEndOffset - (this.FrameOffsetList[frameId].FrameOffset + currentPacketOffset));

                            if (demuxOptions.ExtractVideo)
                            {
                                // parse video packet
                                videoPacket = ParseFile.ParseSimpleOffset(fs, this.FrameOffsetList[frameId].FrameOffset + currentPacketOffset, (int)videoPacketSize);
                                this.writeChunkToStream(videoPacket, 0xFFFF, streamOutputWriters, this.FileExtensionVideo);
                            }

                            // update video frame offset
                            if ((frameId + 1) < this.NewFrameOffsetsVideo.Length)
                            {
                                this.NewFrameOffsetsVideo[frameId + 1] = this.NewFrameOffsetsVideo[frameId] + (uint)videoPacketSize;
                            }
                        }
                        catch (Exception fex)
                        {
                            throw new Exception(String.Format("Exception processing frame 0x{0} at offset 0x{1}: {2}{3}", frameId.ToString("X"), this.FrameOffsetList[frameId].FrameOffset.ToString("X"), fex.Message, Environment.NewLine));
                        }
                    } // for (uint frameId = 0; frameId < this.FrameCount; frameId++)
                }     // using (FileStream fs = File.OpenRead(this.FilePath))
            }
            catch (Exception ex)
            {
                throw new Exception(String.Format("Exception processing block at offset 0x{0}: {1}{2}", currentOffset.ToString("X"), ex.Message, Environment.NewLine));
            }
            finally
            {
                // clean up
                this.DoFinalTasks(streamOutputWriters, demuxOptions);
            }
        }
Beispiel #8
0
        protected virtual void DoFinalTasks(Dictionary <uint, FileStream> streamWriters,
                                            MpegStream.DemuxOptionsStruct demuxOptions)
        {
            string sourceFile;
            string headeredFile;

            int headerSize;

            byte[] headerBytes;
            byte[] frameOffsetBytes;

            uint previousFrameOffset;
            uint frameOffset;

            uint maxFrameSize;
            uint fileLength;

            int audioTrackIndex;

            uint frameStartLocation;

            byte[] dummyValues = new byte[4];

            foreach (uint key in streamWriters.Keys)
            {
                try
                {
                    if (demuxOptions.AddHeader)
                    {
                        //////////////////////
                        // Multi-Track Audio
                        //////////////////////
                        if (streamWriters[key].Name.EndsWith(BinkStream.DefaultFileExtensionAudioMulti))
                        {
                            //////////////////////////
                            // update original header
                            //////////////////////////
                            headerBytes = new byte[this.FullHeader.Length];
                            Array.Copy(this.FullHeader, headerBytes, this.FullHeader.Length);

                            // set frame start location
                            frameStartLocation = 0x2C + (this.AudioTrackCount * 0xC);

                            if (this.BinkVersion == BinkType.Version02)
                            {
                                frameStartLocation += 4;
                            }

                            // set file size
                            fileLength = (uint)(streamWriters[key].Length + headerBytes.Length - 8);

                            // set video size to minimum
                            Array.Copy(BitConverter.GetBytes((uint)1), 0, headerBytes, 0x14, 4);
                            Array.Copy(BitConverter.GetBytes((uint)1), 0, headerBytes, 0x18, 4);

                            // insert file length
                            Array.Copy(BitConverter.GetBytes(fileLength), 0, headerBytes, 4, 4);

                            // insert frame offsets
                            previousFrameOffset = 0;
                            frameOffset         = 0;
                            maxFrameSize        = 0;

                            for (uint i = 0; i < this.FrameCount; i++)
                            {
                                // set previous offset
                                previousFrameOffset = frameOffset;
                                frameOffset         = this.NewFrameOffsetsAudio[0][i];

                                if (this.FrameOffsetList[i].IsKeyFrame)
                                {
                                    // add key frame bit
                                    frameOffsetBytes = BitConverter.GetBytes(frameOffset | 1);
                                }
                                else
                                {
                                    frameOffsetBytes = BitConverter.GetBytes(frameOffset);
                                }

                                // insert offset
                                Array.Copy(frameOffsetBytes, 0, headerBytes, (frameStartLocation + (i * 4)), 4);

                                // calculate max frame size
                                if ((frameOffset - previousFrameOffset) > maxFrameSize)
                                {
                                    maxFrameSize = frameOffset - previousFrameOffset;
                                }
                            }

                            // Add last frame offset (EOF)
                            fileLength = (uint)(streamWriters[key].Length + headerBytes.Length);
                            Array.Copy(BitConverter.GetBytes(fileLength), 0, headerBytes, (frameStartLocation + (this.FrameCount * 4)), 4);

                            // insert max frame size
                            if ((fileLength - frameOffset) > maxFrameSize)
                            {
                                maxFrameSize = fileLength - frameOffset;
                            }

                            Array.Copy(BitConverter.GetBytes(maxFrameSize), 0, headerBytes, 0xC, 4);

                            // append to file
                            sourceFile   = streamWriters[key].Name;
                            headeredFile = sourceFile + ".headered";

                            streamWriters[key].Close();
                            streamWriters[key].Dispose();

                            FileUtil.AddHeaderToFile(headerBytes, streamWriters[key].Name, headeredFile);
                            File.Delete(streamWriters[key].Name);
                            File.Move(headeredFile, streamWriters[key].Name);
                        }

                        //////////////////////
                        // Split Track Audio
                        //////////////////////
                        else if (streamWriters[key].Name.EndsWith(BinkStream.DefaultFileExtensionAudioSplit))
                        {
                            //////////////////////////
                            // update original header
                            //////////////////////////
                            headerBytes = new byte[this.FullHeader.Length];
                            Array.Copy(this.FullHeader, headerBytes, this.FullHeader.Length);

                            // set video size to minimum
                            Array.Copy(BitConverter.GetBytes((uint)1), 0, headerBytes, 0x14, 4);
                            Array.Copy(BitConverter.GetBytes((uint)1), 0, headerBytes, 0x18, 4);

                            // get track info
                            audioTrackIndex = this.getIndexForSplitAudioTrackFileName(streamWriters[key].Name);

                            // resize header since all audio info except this track will be removied
                            headerSize = (int)(0x2C + 0xC + ((this.FrameCount + 1) * 4));

                            if (this.BinkVersion == BinkType.Version02)
                            {
                                headerSize += 4;
                            }

                            Array.Resize(ref headerBytes, headerSize);

                            // insert audio info for this track
                            headerBytes[0x28] = 1;
                            Array.Copy(this.FullHeader, 0x2C + (audioTrackIndex * 4), headerBytes, 0x2C, 4);

                            // only one audio track, audio track id must equal zero
                            if (this.BinkVersion == BinkType.Version01)
                            {
                                Array.Copy(this.FullHeader, 0x2C + (this.AudioTrackCount * 4) + (audioTrackIndex * 4), headerBytes, 0x30, 4);
                                Array.Copy(BitConverter.GetBytes((uint)0), 0, headerBytes, 0x34, 4);
                            }
                            else if (this.BinkVersion == BinkType.Version02)
                            {
                                Array.Copy(this.FullHeader, 0x30 + (audioTrackIndex * 4), headerBytes, 0x30, 4);
                                Array.Copy(this.FullHeader, 0x30 + (this.AudioTrackCount * 4) + (audioTrackIndex * 4), headerBytes, 0x34, 4);
                                Array.Copy(BitConverter.GetBytes((uint)0), 0, headerBytes, 0x38, 4);
                            }
                            else
                            {
                                throw new FormatException("Unsupported Bink type for split audio streams.");
                            }

                            // set file size
                            fileLength = (uint)(streamWriters[key].Length + headerBytes.Length - 8);
                            Array.Copy(BitConverter.GetBytes(fileLength), 0, headerBytes, 4, 4);

                            // insert frame offsets
                            previousFrameOffset = 0;
                            frameOffset         = 0;
                            maxFrameSize        = 0;

                            frameStartLocation = 0x2C + 0xC;

                            if (this.BinkVersion == BinkType.Version02)
                            {
                                frameStartLocation += 4;
                            }

                            for (uint i = 0; i < this.FrameCount; i++)
                            {
                                // set previous offset
                                previousFrameOffset = frameOffset;
                                frameOffset         = this.NewFrameOffsetsAudio[audioTrackIndex][i];

                                if (this.FrameOffsetList[i].IsKeyFrame)
                                {
                                    // add key frame bit
                                    frameOffsetBytes = BitConverter.GetBytes(this.NewFrameOffsetsAudio[audioTrackIndex][i] | 1);
                                }
                                else
                                {
                                    frameOffsetBytes = BitConverter.GetBytes(this.NewFrameOffsetsAudio[audioTrackIndex][i]);
                                }

                                // insert offset
                                Array.Copy(frameOffsetBytes, 0, headerBytes, (frameStartLocation + (i * 4)), 4);

                                // calculate max frame size
                                if ((frameOffset - previousFrameOffset) > maxFrameSize)
                                {
                                    maxFrameSize = frameOffset - previousFrameOffset;
                                }
                            }

                            // Add last frame offset (EOF)
                            fileLength = (uint)(streamWriters[key].Length + headerBytes.Length);
                            Array.Copy(BitConverter.GetBytes(fileLength), 0, headerBytes, (frameStartLocation + (this.FrameCount * 4)), 4);

                            // insert max frame size
                            if ((fileLength - frameOffset) > maxFrameSize)
                            {
                                maxFrameSize = fileLength - frameOffset;
                            }

                            Array.Copy(BitConverter.GetBytes(maxFrameSize), 0, headerBytes, 0xC, 4);

                            // append to file
                            sourceFile   = streamWriters[key].Name;
                            headeredFile = sourceFile + ".headered";

                            streamWriters[key].Close();
                            streamWriters[key].Dispose();

                            FileUtil.AddHeaderToFile(headerBytes, streamWriters[key].Name, headeredFile);
                            File.Delete(streamWriters[key].Name);
                            File.Move(headeredFile, streamWriters[key].Name);
                        }

                        //////////////////////
                        // Video
                        //////////////////////
                        else if (streamWriters[key].Name.EndsWith(BinkStream.DefaultFileExtensionVideo))
                        {
                            //////////////////////////
                            // update original header
                            //////////////////////////
                            headerBytes = new byte[this.FullHeader.Length];
                            Array.Copy(this.FullHeader, headerBytes, this.FullHeader.Length);

                            // resize header since audio info will be removied
                            headerSize = (int)(0x2C + ((this.FrameCount + 1) * 4));

                            if (this.BinkVersion == BinkType.Version02)
                            {
                                headerSize += 4;
                            }

                            Array.Resize(ref headerBytes, headerSize);

                            // set file size
                            fileLength = (uint)(streamWriters[key].Length + headerBytes.Length - 8);
                            Array.Copy(BitConverter.GetBytes(fileLength), 0, headerBytes, 4, 4);

                            // set audio track count to zero
                            headerBytes[0x28] = 0;

                            // insert frame offsets
                            previousFrameOffset = 0;
                            frameOffset         = 0;
                            maxFrameSize        = 0;

                            frameStartLocation = 0x2C;

                            if (this.BinkVersion == BinkType.Version02)
                            {
                                frameStartLocation += 4;
                            }

                            for (uint i = 0; i < this.FrameCount; i++)
                            {
                                // set previous offset
                                previousFrameOffset = frameOffset;
                                frameOffset         = this.NewFrameOffsetsVideo[i];

                                if (this.FrameOffsetList[i].IsKeyFrame)
                                {
                                    // add key frame bit
                                    frameOffsetBytes = BitConverter.GetBytes(this.NewFrameOffsetsVideo[i] | 1);
                                }
                                else
                                {
                                    frameOffsetBytes = BitConverter.GetBytes(this.NewFrameOffsetsVideo[i]);
                                }

                                // insert frame offset
                                Array.Copy(frameOffsetBytes, 0, headerBytes, (frameStartLocation + (i * 4)), 4);

                                // calculate max frame size
                                if ((frameOffset - previousFrameOffset) > maxFrameSize)
                                {
                                    maxFrameSize = frameOffset - previousFrameOffset;
                                }
                            }

                            // Add last frame offset (EOF)
                            fileLength = (uint)(streamWriters[key].Length + headerBytes.Length);
                            Array.Copy(BitConverter.GetBytes(fileLength), 0, headerBytes, (frameStartLocation + (this.FrameCount * 4)), 4);

                            // insert max frame size
                            if ((fileLength - frameOffset) > maxFrameSize)
                            {
                                maxFrameSize = fileLength - frameOffset;
                            }

                            Array.Copy(BitConverter.GetBytes(maxFrameSize), 0, headerBytes, 0xC, 4);

                            // append to file
                            sourceFile   = streamWriters[key].Name;
                            headeredFile = sourceFile + ".headered";

                            streamWriters[key].Close();
                            streamWriters[key].Dispose();

                            FileUtil.AddHeaderToFile(headerBytes, streamWriters[key].Name, headeredFile);
                            File.Delete(streamWriters[key].Name);
                            File.Move(headeredFile, streamWriters[key].Name);
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (streamWriters[key] != null)
                    {
                        throw new Exception(String.Format("Exception building header for file: {0}{1}{2}", streamWriters[key].Name, ex.Message, Environment.NewLine));
                    }
                    else
                    {
                        throw new Exception(String.Format("Exception building header for file: {0}{1}{2}", "UNKNOWN", ex.Message, Environment.NewLine));
                    }
                }
                finally
                {
                    // close streams if open
                    if (streamWriters[key] != null &&
                        streamWriters[key].CanRead)
                    {
                        streamWriters[key].Close();
                        streamWriters[key].Dispose();
                    }
                }
            }
        }
        public virtual void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxOptions)
        {
            long currentOffset = -1;
            long fileSize;

            byte[] chunkId;
            byte[] fullChunk;
            uint   chunkSize = 0;

            long mvhdOffset = -1;
            long schlOffset = -1;
            long shenOffset = -1;

            Dictionary <string, FileStream> streamWriters = new Dictionary <string, FileStream>();

            try
            {
                using (FileStream fs = File.OpenRead(this.FilePath))
                {
                    fileSize = fs.Length;

                    // find header first header (audio or video)
                    mvhdOffset = ParseFile.GetNextOffset(fs, 0, ElectronicArtsVp6Stream.MVHD_BYTES);

                    if (mvhdOffset == 0) // video header comes first
                    {
                        currentOffset = mvhdOffset;
                    }
                    else // audio header comes first
                    {
                        schlOffset = ParseFile.GetNextOffset(fs, 0, ElectronicArtsVp6Stream.SCHl_BYTES);

                        if ((schlOffset > -1) && (schlOffset < mvhdOffset))
                        {
                            currentOffset = schlOffset;
                        }
                        else
                        {
                            shenOffset = ParseFile.GetNextOffset(fs, 0, ElectronicArtsVp6Stream.SHEN_BYTES);

                            if ((shenOffset > -1) && (shenOffset < mvhdOffset))
                            {
                                currentOffset = shenOffset;
                            }
                        }
                    }

                    // verify headers found
                    if (mvhdOffset >= 0)
                    {
                        if (currentOffset >= 0)
                        {
                            // process file
                            while (currentOffset < fileSize)
                            {
                                // get chunk
                                chunkId = ParseFile.ParseSimpleOffset(fs, currentOffset, 4);

                                // get chunk size
                                chunkSize = (uint)BitConverter.ToUInt32(ParseFile.ParseSimpleOffset(fs, currentOffset + 4, 4), 0);

                                // audio chunk
                                if (demuxOptions.ExtractAudio && this.IsThisAnAudioBlock(chunkId))
                                {
                                    fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset, (int)chunkSize);
                                    this.writeChunkToStream(fullChunk, "audio", streamWriters, this.FileExtensionAudio);
                                }

                                // video chunk
                                if (demuxOptions.ExtractVideo && this.IsThisAVideoBlock(chunkId))
                                {
                                    fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset, (int)chunkSize);
                                    this.writeChunkToStream(fullChunk, "video", streamWriters, this.FileExtensionVideo);
                                }

                                // unknown chunk
                                if (!this.IsThisAnAudioBlock(chunkId) && !this.IsThisAVideoBlock(chunkId))
                                {
                                    fullChunk = ParseFile.ParseSimpleOffset(fs, currentOffset, (int)chunkSize);
                                    this.writeChunkToStream(fullChunk, "unknown", streamWriters, ".bin");
                                }

                                // move to next chunk
                                currentOffset += (long)chunkSize;
                            }
                        }
                        else
                        {
                            throw new Exception(String.Format("Cannot find MVHD, SCHl, or SHEN headers.{0}", Environment.NewLine));
                        }
                    }
                    else
                    {
                        throw new Exception(String.Format("Cannot find MVHD header.{0}", Environment.NewLine));
                    } // if (mvhdOffset >= 0)
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            finally
            {
                this.DoFinalTasks(streamWriters);
            }
        }
Beispiel #10
0
        public void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxOptions)
        {
            long currentOffset = 0;
            uint frameCount    = 1;
            uint nextFrameSize;

            byte[] currentFrame;

            byte[] videoChunkSizeBytes = null;
            uint   videoChunkSize;

            byte[] audioChunkSizeBytes = null;
            uint   audioChunkSize;
            long   dataStart;

            byte[] videoChunk;
            byte[] audioChunk;

            // bool isAudioHeaderWritten = false;
            Dictionary <string, bool> isAudioHeaderWritten = new Dictionary <string, bool>();
            bool isVideoHeaderWritten = false;

            byte[] thpHeader;
            byte[] firstFrameSize;
            long   headerLocation;

            uint previousFrameSizeVideo = 0;
            uint previousFrameSizeAudio = 0;
            uint nextFrameSizeVideo;
            uint nextFrameSizeAudio;

            byte[] previousFrameSizeBytes;
            byte[] nextFrameSizeBytes;

            uint totalDataSize = 0;

            byte[] totalDataSizeBytes;

            byte[] fourEmptyBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 };

            long videoFrameOffset = 0;
            long audioFrameOffset = 0;

            byte[] lastOffsetBytes;

            string audioStreamHashKey;

            byte[] bigEndianOne = new byte[] { 0x00, 0x00, 0x00, 0x01 };

            Dictionary <string, FileStream> streamWriters = new Dictionary <string, FileStream>();

            try
            {
                using (FileStream fs = File.OpenRead(this.FilePath))
                {
                    headerLocation = ParseFile.GetNextOffset(fs, currentOffset, MAGIC_BYTES);
                    currentOffset  = headerLocation;

                    if (currentOffset > -1)
                    {
                        // read header
                        this.ReadHeader(fs, currentOffset);
                        nextFrameSize = this.FirstFrameSize;

                        // get component info
                        this.ParseComponents(fs);

                        // process frames
                        currentOffset = this.FirstFrameOffset;

                        while (currentOffset <= this.LastFrameOffset)
                        {
                            // read frame
                            currentFrame = ParseFile.ParseSimpleOffset(fs, (long)currentOffset, (int)nextFrameSize);

                            // get size of next frame
                            nextFrameSize = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(currentFrame, 0, 4));

                            // get size of next audio/video frame (for writing output frame headers)
                            if (frameCount < this.NumberOfFrames)
                            {
                                nextFrameSizeVideo = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(fs, currentOffset + currentFrame.Length + 8, 4));
                                nextFrameSizeAudio = ByteConversion.GetUInt32BigEndian(ParseFile.ParseSimpleOffset(fs, currentOffset + currentFrame.Length + 0xC, 4));
                            }
                            else
                            {
                                nextFrameSizeVideo = 0;
                                nextFrameSizeAudio = 0;
                            }

                            videoChunkSizeBytes = ParseFile.ParseSimpleOffset(currentFrame, 8, 4);
                            videoChunkSize      = ByteConversion.GetUInt32BigEndian(videoChunkSizeBytes);

                            if (this.ContainsAudio)
                            {
                                audioChunkSizeBytes = ParseFile.ParseSimpleOffset(currentFrame, 0xC, 4);
                                audioChunkSize      = ByteConversion.GetUInt32BigEndian(audioChunkSizeBytes);
                                dataStart           = 0x10;
                            }
                            else
                            {
                                audioChunkSize = 0;
                                dataStart      = 0xC;
                            }

                            #region WRITE VIDEO
                            ///////////////
                            // write video
                            ///////////////
                            if (demuxOptions.ExtractVideo)
                            {
                                if (streamWriters.ContainsKey("video"))
                                {
                                    videoFrameOffset = streamWriters["video"].Length;
                                }

                                // attach THP header
                                if (!isVideoHeaderWritten)
                                {
                                    // get original header
                                    thpHeader = ParseFile.ParseSimpleOffset(fs, headerLocation, (int)(fs.Length - this.DataSize));

                                    // clean out audio info
                                    thpHeader = this.RemoveAudioInfoFromThpHeader(thpHeader);

                                    // update first frame size in header
                                    firstFrameSize = ByteConversion.GetBytesBigEndian((uint)(videoChunkSize + 0xC));
                                    Array.Copy(firstFrameSize, 0, thpHeader, 0x18, 4);

                                    // write updated header
                                    this.writeChunkToStream(thpHeader, "video", streamWriters, this.FileExtensionVideo);
                                    isVideoHeaderWritten = true;
                                }

                                // add frame header

                                // write next frame size
                                nextFrameSizeBytes = ByteConversion.GetBytesBigEndian((uint)(nextFrameSizeVideo + 0xC));
                                this.writeChunkToStream(nextFrameSizeBytes, "video", streamWriters, this.FileExtensionVideo);

                                // write previous frame size
                                previousFrameSizeBytes = ByteConversion.GetBytesBigEndian((uint)(previousFrameSizeVideo + 0xC));
                                this.writeChunkToStream(nextFrameSizeBytes, "video", streamWriters, this.FileExtensionVideo);

                                // write video size
                                this.writeChunkToStream(videoChunkSizeBytes, "video", streamWriters, this.FileExtensionVideo);

                                // write data
                                videoChunk = ParseFile.ParseSimpleOffset(currentFrame, (int)dataStart, (int)videoChunkSize);
                                this.writeChunkToStream(videoChunk, "video", streamWriters, this.FileExtensionVideo);

                                // save previous bytes for next frame
                                previousFrameSizeVideo = videoChunkSize;
                            }
                            #endregion

                            #region WRITE AUDIO
                            ///////////////
                            // write audio
                            ///////////////
                            if (demuxOptions.ExtractAudio && this.ContainsAudio)
                            {
                                //if (this.NumberOfAudioBlocksPerFrame > 1)
                                //{
                                //    int x = 1;
                                //}

                                // add blocks
                                for (int i = 0; i < this.NumberOfAudioBlocksPerFrame; i++)
                                {
                                    audioStreamHashKey = String.Format("track_{0}", i.ToString("D2"));

                                    // write file header
                                    if (streamWriters.ContainsKey(audioStreamHashKey))
                                    {
                                        audioFrameOffset = streamWriters[audioStreamHashKey].Position;
                                    }

                                    // attach THP header
                                    if (!isAudioHeaderWritten.ContainsKey(audioStreamHashKey) ||
                                        isAudioHeaderWritten[audioStreamHashKey] == false)
                                    {
                                        // get original header
                                        thpHeader = ParseFile.ParseSimpleOffset(fs, headerLocation, (int)(fs.Length - this.DataSize));

                                        // clean out video info
                                        thpHeader = this.RemoveVideoInfoFromThpHeader(thpHeader);

                                        // update first frame size in header
                                        firstFrameSize = ByteConversion.GetBytesBigEndian((uint)(audioChunkSize + 0x10));
                                        Array.Copy(firstFrameSize, 0, thpHeader, 0x18, 4);

                                        // set NumberOfAudioBlocksPerFrame to 1
                                        Array.Copy(bigEndianOne, 0, thpHeader, 0x50, 4);

                                        // write updated header
                                        this.writeChunkToStream(thpHeader, audioStreamHashKey, streamWriters, this.FileExtensionAudio);
                                        isAudioHeaderWritten.Add(audioStreamHashKey, true);
                                    }

                                    //////////////////////
                                    // write frame header
                                    //////////////////////

                                    // write next frame size
                                    nextFrameSizeBytes = ByteConversion.GetBytesBigEndian((uint)(nextFrameSizeAudio + 0x10));
                                    this.writeChunkToStream(nextFrameSizeBytes, audioStreamHashKey, streamWriters, this.FileExtensionAudio);

                                    // write previous frame size
                                    previousFrameSizeBytes = ByteConversion.GetBytesBigEndian((uint)(previousFrameSizeAudio + 0x10));
                                    this.writeChunkToStream(nextFrameSizeBytes, audioStreamHashKey, streamWriters, this.FileExtensionAudio);

                                    // write video size (zero)
                                    this.writeChunkToStream(fourEmptyBytes, audioStreamHashKey, streamWriters, this.FileExtensionAudio);

                                    // write audio size for this frame
                                    this.writeChunkToStream(audioChunkSizeBytes, audioStreamHashKey, streamWriters, this.FileExtensionAudio);

                                    // write chunk
                                    audioChunk = ParseFile.ParseSimpleOffset(currentFrame, (int)(dataStart + videoChunkSize + (i * audioChunkSize)), (int)audioChunkSize);
                                    this.writeChunkToStream(audioChunk, audioStreamHashKey, streamWriters, this.FileExtensionAudio);

                                    // set previous frame size for next frame
                                    previousFrameSizeAudio = audioChunkSize;
                                }
                            }
                            #endregion

                            // increment offset and frame counter
                            currentOffset += currentFrame.Length;
                            frameCount++;
                        }

                        // fix headers as needed

                        // data size
                        foreach (string key in streamWriters.Keys)
                        {
                            totalDataSize      = (uint)(streamWriters[key].Length - this.FirstFrameOffset);
                            totalDataSizeBytes = ByteConversion.GetBytesBigEndian(totalDataSize);

                            streamWriters[key].Position = 0x1C;
                            streamWriters[key].Write(totalDataSizeBytes, 0, 4);
                        }

                        // frame offsets
                        for (int i = 0; i < this.NumberOfAudioBlocksPerFrame; i++)
                        {
                            audioStreamHashKey = String.Format("audio_{0}", i.ToString("DD"));

                            if (streamWriters.ContainsKey(audioStreamHashKey))
                            {
                                lastOffsetBytes = ByteConversion.GetBytesBigEndian((uint)audioFrameOffset);

                                streamWriters[audioStreamHashKey].Position = 0x2C;
                                streamWriters[audioStreamHashKey].Write(lastOffsetBytes, 0, 4);
                            }
                        }

                        if (streamWriters.ContainsKey("video"))
                        {
                            lastOffsetBytes = ByteConversion.GetBytesBigEndian((uint)videoFrameOffset);

                            streamWriters["video"].Position = 0x2C;
                            streamWriters["video"].Write(lastOffsetBytes, 0, 4);
                        }
                    }
                    else
                    {
                        throw new FormatException("Cannot find THP header.");
                    }
                } // using (FileStream fs = File.OpenRead(this.FilePath))
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
            finally
            {
                foreach (string key in streamWriters.Keys)
                {
                    // close writers
                    if (streamWriters[key] != null &&
                        streamWriters[key].CanWrite)
                    {
                        streamWriters[key].Close();
                        streamWriters[key].Dispose();
                    }
                }
            }
        }
        public virtual void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxOptions)
        {
            long currentOffset = 0;
            long packetOffset  = 0;
            long packetSize;
            long fileSize;

            Dictionary <uint, FileStream> streamOutputWriters = new Dictionary <uint, FileStream>();

            Guid  checkGuid;
            ulong blockSize;

            try
            {
                using (FileStream fs = File.OpenRead(this.FilePath))
                {
                    fileSize      = fs.Length;
                    currentOffset = 0;

                    currentOffset = ParseFile.GetNextOffset(fs, 0, MicrosoftAsfContainer.ASF_HEADER_BYTES);

                    if (currentOffset > -1)
                    {
                        while (currentOffset < fileSize)
                        {
                            // get guid
                            checkGuid = new Guid(ParseFile.ParseSimpleOffset(fs, currentOffset, 0x10));
                            blockSize = BitConverter.ToUInt64(ParseFile.ParseSimpleOffset(fs, (currentOffset + 0x10), 8), 0);

                            // process block
                            if (checkGuid.Equals(MicrosoftAsfContainer.ASF_Header_Object))
                            {
                                // parse header
                                this.parseHeader(fs, currentOffset);
                            }
                            else if (checkGuid.Equals(MicrosoftAsfContainer.ASF_Data_Object))
                            {
                                // parse data object
                                this.DataObject = this.parseDataObject(fs, currentOffset);

                                // process data packets
                                packetOffset = currentOffset + 0x32; // header has been parsed

                                for (ulong i = 0; i < this.DataObject.TotalDataPackets; i++)
                                {
                                    // parse packet
                                    try
                                    {
                                        packetSize = this.parseDataPacket(fs, packetOffset, demuxOptions);

                                        // move to next packet
                                        if (packetSize < 0)
                                        {
                                            throw new Exception(String.Format("Error parsing data packet at offset 0x{0}.", packetOffset.ToString("X8")));
                                        }
                                        else
                                        {
                                            packetOffset += packetSize;
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        throw new Exception(String.Format("Error parsing data packet at offset 0x{0}: {1}.{2}", packetOffset.ToString("X8"), ex.Message, Environment.NewLine));
                                    }
                                }
                            }

                            // increment counter
                            currentOffset += (long)blockSize;
                        } // while
                    }
                    else
                    {
                        throw new Exception(String.Format("ASF/WMV Header not found.{0}", Environment.NewLine));
                    }
                } // using (FileStream fs = File.OpenRead(this.FilePath))
            }
            catch (Exception ex)
            {
                throw new Exception(String.Format("Exception processing block at offset 0x{0}: {1}{2}", currentOffset.ToString("X"), ex.Message, Environment.NewLine));
            }
            finally
            {
                // clean up
                this.DoFinalTasks(demuxOptions);
            }
        }
        private AsfDataPacketPayloadObject parseAsfDataPacketPayloadObject(Stream inStream, long currentOffset, AsfDataPacketPayloadParsingObject payloadParsingObject, MpegStream.DemuxOptionsStruct demuxOptions)
        {
            AsfDataPacketPayloadObject packetPayloadObject = new AsfDataPacketPayloadObject();
            uint bytesRead   = 0;
            uint valueOffset = 0;
            uint packetLength;

            packetPayloadObject.StreamNumber = ParseFile.ParseSimpleOffset(inStream, currentOffset, 1)[0];
            packetPayloadObject.KeyFrame     = (byte)((packetPayloadObject.StreamNumber & 0x80) >> 7);
            packetPayloadObject.StreamNumber = (byte)(packetPayloadObject.StreamNumber & 0x7F);
            valueOffset += 1;

            packetPayloadObject.MediaObjectNumber = this.GetLengthTypeValue(inStream, currentOffset + valueOffset, payloadParsingObject.MediaObjectNumberLengthType, ref bytesRead);
            valueOffset += bytesRead;

            packetPayloadObject.OffsetIntoMediaObject = this.GetLengthTypeValue(inStream, currentOffset + valueOffset, payloadParsingObject.OffsetIntoMediaObjectLengthType, ref bytesRead);
            valueOffset += bytesRead;

            packetPayloadObject.ReplicatedDataLength = this.GetLengthTypeValue(inStream, currentOffset + valueOffset, payloadParsingObject.ReplicatedDataLengthType, ref bytesRead);
            valueOffset += bytesRead;

            if (packetPayloadObject.ReplicatedDataLength == 1)
            {
                throw new FormatException(String.Format("Error processing data packet payload at offset 0x{0}, compressed payloads are not supported.", currentOffset.ToString("X8")));
            }

            // get replicated data
            packetPayloadObject.ReplicatedData = ParseFile.ParseSimpleOffset(inStream, currentOffset + valueOffset, (int)packetPayloadObject.ReplicatedDataLength);
            valueOffset += packetPayloadObject.ReplicatedDataLength;

            if (payloadParsingObject.MultiplePayloadsPresent)
            {
                packetPayloadObject.PayloadDataLength = this.GetLengthTypeValue(inStream, currentOffset + valueOffset, payloadParsingObject.PayloadLengthType, ref bytesRead);
                valueOffset += bytesRead;
            }
            else
            {
                packetLength = payloadParsingObject.PacketLengthType == LengthType.NotExist ? this.Header.FileProperties.MinimumPacketSize : payloadParsingObject.PacketLength;
                packetPayloadObject.PayloadDataLength = packetLength - payloadParsingObject.PacketOverheadLength - valueOffset - payloadParsingObject.PaddingLength;
            }

            packetPayloadObject.PayloadData = ParseFile.ParseSimpleOffset(inStream, currentOffset + valueOffset, (int)packetPayloadObject.PayloadDataLength);
            valueOffset += packetPayloadObject.PayloadDataLength;

            // set payload size and get raw block
            packetPayloadObject.PayloadSize = valueOffset;
            // packetPayloadObject.RawBlock = ParseFile.ParseSimpleOffset(inStream, currentOffset, (int)packetPayloadObject.PayloadSize);

            // write raw data to stream
            if ((demuxOptions.ExtractAudio) && this.IsAudioStream(packetPayloadObject.StreamNumber))
            {
                this.writeChunkToStream(packetPayloadObject.PayloadData, (uint)packetPayloadObject.StreamNumber, this.FileExtensionAudio);
            }



            if ((demuxOptions.ExtractVideo) && this.IsVideoStream(packetPayloadObject.StreamNumber))
            {
                this.writeChunkToStream(packetPayloadObject.PayloadData, (uint)packetPayloadObject.StreamNumber, this.FileExtensionVideo);
            }

            return(packetPayloadObject);
        }
Beispiel #13
0
        protected override void DoFinalTasks(Dictionary <uint, FileStream> streamWriters,
                                             MpegStream.DemuxOptionsStruct demuxOptions)
        {
            GenhCreationStruct gcStruct;
            ushort             frequency;
            string             sourceFile;
            string             genhFile = null;

            string rawFile;

            foreach (uint key in streamWriters.Keys)
            {
                if (demuxOptions.AddHeader &&
                    (key != MobiclipWiiStream.VideoChunkId) &&
                    (this.AudioStreamFeatures[key].StreamType != null) &&
                    (this.AudioStreamFeatures[key].StreamType == AudioChunkSignaturePcm))
                {
                    if (streamWriters[key].Name.EndsWith(this.FileExtensionAudio))
                    {
                        sourceFile = streamWriters[key].Name;

                        streamWriters[key].Close();
                        streamWriters[key].Dispose();

                        gcStruct = new GenhCreationStruct();

                        switch (this.AudioStreamFeatures[key].StreamType)
                        {
                        case AudioChunkSignaturePcm:
                            gcStruct.Format = "0x04";

                            gcStruct.HeaderSkip = "0";
                            gcStruct.Interleave = "0x2";
                            gcStruct.Channels   = this.AudioStreamFeatures[key].Channels.ToString();
                            gcStruct.Frequency  = this.AudioStreamFeatures[key].Frequency.ToString();
                            gcStruct.NoLoops    = true;

                            genhFile = GenhUtil.CreateGenhFile(sourceFile, gcStruct);

                            break;

                        default:
                            break;
                        }

                        // delete original file
                        if (!String.IsNullOrEmpty(genhFile))
                        {
                            File.Delete(sourceFile);
                        }
                    }
                }
                else if (key != MobiclipWiiStream.VideoChunkId)
                {
                    // update raw file extension
                    if (this.AudioStreamFeatures[key].StreamType == AudioChunkSignatureA3)
                    {
                        rawFile = streamWriters[key].Name;
                        streamWriters[key].Close();
                        streamWriters[key].Dispose();

                        File.Copy(rawFile, Path.ChangeExtension(rawFile, FileExtensionAudioA3));
                        File.Delete(rawFile);
                    }
                }
            }

            base.DoFinalTasks(streamWriters, demuxOptions);
        }
Beispiel #14
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);
            }
        }
Beispiel #15
0
        public virtual void DemultiplexStreams(MpegStream.DemuxOptionsStruct demuxOptions)
        {
            long currentOffset = 0;
            long fileSize;
            long blockEndOffset;

            StreamChunkStruct[] streamChunks;

            Dictionary <uint, FileStream> streamOutputWriters = new Dictionary <uint, FileStream>();

            try
            {
                using (FileStream fs = File.OpenRead(this.FilePath))
                {
                    fileSize      = fs.Length;
                    currentOffset = 0;

                    while (currentOffset < fileSize)
                    {
                        blockEndOffset = 0;
                        streamChunks   = parseStreamChunk(fs, currentOffset);

                        if (streamChunks.Length > 0)
                        {
                            foreach (StreamChunkStruct sc in streamChunks)
                            {
                                blockEndOffset = sc.AbsoluteOffset + sc.ChunkSize;

                                if (this.isVideoBlock(sc.StreamChunkType))
                                {
                                    if (demuxOptions.ExtractVideo)
                                    {
                                        this.writeChunkToStream(sc.ChunkData, sc.StreamChunkId, streamOutputWriters, RacjinDsiStream.DefaultFileExtensionVideo);
                                    }
                                }
                                else if (this.isAudioBlock(sc.StreamChunkType))
                                {
                                    if (demuxOptions.ExtractAudio)
                                    {
                                        this.writeChunkToStream(sc.ChunkData, sc.StreamChunkId, streamOutputWriters, RacjinDsiStream.DefaultFileExtensionAudio);
                                    }
                                }
                                else
                                {
                                    throw new Exception(String.Format("Exception processing block at offset 0x{0}: {1}{2}", currentOffset.ToString("X"), "Unknown Stream Type Identifier", Environment.NewLine));
                                }
                            }

                            // move offset
                            currentOffset = blockEndOffset;
                            currentOffset = (currentOffset + RacjinDsiStream.BlockAlignment - 1) / RacjinDsiStream.BlockAlignment * RacjinDsiStream.BlockAlignment;
                        }
                        else
                        {
                            break;
                        }
                    }
                } // using (FileStream fs = File.OpenRead(this.FilePath))
            }
            catch (Exception ex)
            {
                throw new Exception(String.Format("Exception processing block at offset 0x{0}: {1}{2}", currentOffset.ToString("X"), ex.Message, Environment.NewLine));
            }
            finally
            {
                // clean up
                this.DoFinalTasks(streamOutputWriters, demuxOptions);
            }
        }