Exemplo n.º 1
0
        private byte[] RemoveAudioInfoFromThpHeader(byte[] dirtyThpHeader)
        {
            byte[] dataBytes;
            byte[] fourEmptyBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 };

            // clear max audio samples
            Array.Copy(fourEmptyBytes, 0, dirtyThpHeader, 0xC, 4);

            // reset components
            Array.Copy(fourEmptyBytes, 0, dirtyThpHeader, this.ComponentDataOffset, 4);
            dirtyThpHeader[this.ComponentDataOffset + 3] = 0x01;
            dirtyThpHeader[this.ComponentDataOffset + 4] = 0x00; // set to video
            dirtyThpHeader[this.ComponentDataOffset + 5] = 0xFF;

            // add video details in case it was the second component
            dataBytes = ByteConversion.GetBytesBigEndian(this.Width);
            Array.Copy(dataBytes, 0, dirtyThpHeader, 0x44, 4);

            dataBytes = ByteConversion.GetBytesBigEndian(this.Height);
            Array.Copy(dataBytes, 0, dirtyThpHeader, 0x48, 4);

            if (this.Version == ThpVersion.Version11)
            {
                dataBytes = ByteConversion.GetBytesBigEndian(this.Unknown);
                Array.Copy(dataBytes, 0, dirtyThpHeader, 0x4C, 4);
            }

            // remove audio component details
            if (this.ContainsAudio)
            {
                if (this.Version == ThpVersion.Version10)
                {
                    for (int i = 0x4C; i < this.FirstFrameOffset; i++)
                    {
                        dirtyThpHeader[i] = 0;
                    }
                }
                else // version 1.1
                {
                    for (int i = 0x50; i < this.FirstFrameOffset; i++)
                    {
                        dirtyThpHeader[i] = 0;
                    }
                }
            }

            return(dirtyThpHeader);
        }
Exemplo n.º 2
0
        private byte[] RemoveVideoInfoFromThpHeader(byte[] dirtyThpHeader)
        {
            byte[] dataBytes;
            byte[] fourEmptyBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 };

            // reset components
            Array.Copy(fourEmptyBytes, 0, dirtyThpHeader, this.ComponentDataOffset, 4);
            dirtyThpHeader[this.ComponentDataOffset + 3] = 0x01;
            dirtyThpHeader[this.ComponentDataOffset + 4] = 0x01; // set to audio
            dirtyThpHeader[this.ComponentDataOffset + 5] = 0xFF;

            // add audio details in case it was the second component
            dataBytes = ByteConversion.GetBytesBigEndian(this.NumberOfChannels);
            Array.Copy(dataBytes, 0, dirtyThpHeader, 0x44, 4);

            dataBytes = ByteConversion.GetBytesBigEndian(this.Frequency);
            Array.Copy(dataBytes, 0, dirtyThpHeader, 0x48, 4);

            dataBytes = ByteConversion.GetBytesBigEndian(this.NumberOfSamples);
            Array.Copy(dataBytes, 0, dirtyThpHeader, 0x4C, 4);

            if (this.Version == ThpVersion.Version11)
            {
                dataBytes = ByteConversion.GetBytesBigEndian(this.NumberOfAudioBlocksPerFrame);
                Array.Copy(dataBytes, 0, dirtyThpHeader, 0x50, 4);

                for (int i = 0x54; i < this.FirstFrameOffset; i++)
                {
                    dirtyThpHeader[i] = 0;
                }
            }
            else
            {
                for (int i = 0x50; i < this.FirstFrameOffset; i++)
                {
                    dirtyThpHeader[i] = 0;
                }
            }

            return(dirtyThpHeader);
        }
Exemplo n.º 3
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();
                    }
                }
            }
        }