예제 #1
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();
                }
            }
        }
예제 #2
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
                //------------------
            }
        }
예제 #3
0
        protected override void DoFinalTasks(FileStream sourceFileStream, Dictionary <uint, FileStream> outputFiles, bool addHeader)
        {
            byte[] headerBytes;
            byte[] aa3HeaderBytes;
            uint   headerBlock;
            string sourceFile;

            long streamInfoOffset;
            byte streamIdByte;
            byte streamIdCheckByte;
            byte channelCount;
            GenhCreationStruct gcStruct;
            string             genhFile;

            foreach (uint streamId in outputFiles.Keys)
            {
                if (this.IsThisAnAudioBlock(BitConverter.GetBytes(streamId)))
                {
                    if (outputFiles[streamId].Name.EndsWith(Atrac3AudioExtension))
                    {
                        headerBytes = ParseFile.ParseSimpleOffset(outputFiles[streamId], 0, 0x8);

                        // remove all header chunks
                        string cleanedFile = FileUtil.RemoveAllChunksFromFile(outputFiles[streamId], headerBytes);

                        // close stream and rename file
                        sourceFile = outputFiles[streamId].Name;

                        outputFiles[streamId].Close();
                        outputFiles[streamId].Dispose();

                        File.Delete(sourceFile);
                        File.Move(cleanedFile, sourceFile);

                        // add header
                        if (addHeader)
                        {
                            Array.Reverse(headerBytes);
                            headerBlock = BitConverter.ToUInt32(headerBytes, 4);

                            string headeredFile = Path.ChangeExtension(sourceFile, Atrac3Plus.FileExtension);
                            aa3HeaderBytes = Atrac3Plus.GetAa3Header(headerBlock);
                            FileUtil.AddHeaderToFile(aa3HeaderBytes, sourceFile, headeredFile);

                            File.Delete(sourceFile);
                        }
                    }
                    else if (addHeader &&
                             outputFiles[streamId].Name.EndsWith(LpcmAudioExtension))
                    {
                        // get this block's stream id
                        streamIdByte = BitConverter.GetBytes(streamId)[0];

                        // get location of first audio stream info block
                        streamInfoOffset = ParseFile.GetNextOffset(sourceFileStream, 0, PamAudioStreamInfoStartBytes);

                        // find matching info block
                        while ((streamInfoOffset > -1))
                        {
                            streamIdCheckByte = ParseFile.ParseSimpleOffset(sourceFileStream, streamInfoOffset + 0x4, 1)[0];

                            if (streamIdCheckByte == streamIdByte)
                            {
                                // get channel count
                                channelCount = ParseFile.ParseSimpleOffset(sourceFileStream, streamInfoOffset + 0x11, 1)[0];

                                // close stream and build GENH file
                                sourceFile = outputFiles[streamId].Name;

                                outputFiles[streamId].Close();
                                outputFiles[streamId].Dispose();

                                gcStruct            = new GenhCreationStruct();
                                gcStruct.Format     = "0x03";
                                gcStruct.HeaderSkip = "0";
                                gcStruct.Interleave = "0x2";
                                gcStruct.Channels   = channelCount.ToString();
                                gcStruct.Frequency  = "48000";
                                gcStruct.NoLoops    = true;

                                genhFile = GenhUtil.CreateGenhFile(sourceFile, gcStruct);

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

                                break;
                            }

                            streamInfoOffset = ParseFile.GetNextOffset(sourceFileStream, streamInfoOffset + 1, PamAudioStreamInfoStartBytes);
                        }
                    }
                }
            }
        }
예제 #4
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);
        }
예제 #5
0
        private void createGenhs(GenhCreatorStruct pGenhCreatorStruct, DoWorkEventArgs e)
        {
            int progress;
            GenhCreationStruct genhCreationStruct;

            this.maxFiles = pGenhCreatorStruct.SourcePaths.Length;

            string        outputFilePath = String.Empty;
            string        extractedFilePath;
            string        outputMessageAction = String.Empty;
            StringBuilder outputMessage       = new StringBuilder();

            int progressReportingPercentage = 10;
            int progressReportingPercentageIncrementValue = 10;

            foreach (string file in pGenhCreatorStruct.SourcePaths)
            {
                progress = (++this.fileCount * 100) / this.maxFiles;

                // throttle output to prevent locking up the GUI
                if ((progress > progressReportingPercentage) ||
                    (this.fileCount == this.maxFiles))
                {
                    this.progressStruct.Clear();
                    this.progressStruct.FileName = file;
                    ReportProgress(progress, this.progressStruct);
                }

                if (File.Exists(file))
                {
                    if (pGenhCreatorStruct.DoExtract)
                    {
                        outputFilePath      = GenhUtil.ExtractGenhFile(file, true, true, true);
                        outputMessageAction = "Extracted";
                    }
                    else
                    {
                        genhCreationStruct = pGenhCreatorStruct.ToGenhCreationStruct();

                        if (pGenhCreatorStruct.DoCreation)
                        {
                            outputFilePath      = GenhUtil.CreateGenhFile(file, genhCreationStruct);
                            outputMessageAction = "Created";
                        }
                        else if (pGenhCreatorStruct.DoEdit)
                        {
                            extractedFilePath = GenhUtil.ExtractGenhFile(file, false, false, false);

                            if (!String.IsNullOrEmpty(extractedFilePath))
                            {
                                genhCreationStruct.SourcePaths    = new string[1];
                                genhCreationStruct.SourcePaths[0] = extractedFilePath;

                                outputFilePath = GenhUtil.CreateGenhFile(extractedFilePath, genhCreationStruct);

                                File.Delete(extractedFilePath);
                            }

                            outputMessageAction = "Edited";
                        }
                    }

                    if (!String.IsNullOrEmpty(outputFilePath))
                    {
                        outputMessage.AppendFormat("{0} {1}.{2}", outputFilePath, outputMessageAction, Environment.NewLine);
                    }

                    // throttle output to prevent locking up the GUI
                    if ((progress > progressReportingPercentage) ||
                        (this.fileCount == this.maxFiles))
                    {
                        progressReportingPercentage += progressReportingPercentageIncrementValue;

                        this.progressStruct.Clear();
                        this.progressStruct.GenericMessage = outputMessage.ToString();
                        ReportProgress(Constants.ProgressMessageOnly, this.progressStruct);

                        outputMessage.Length = 0;
                    }
                }
            }
        }