示例#1
0
        public void Scan(
            Dictionary <string, TSStreamFile> streamFiles,
            Dictionary <string, TSStreamClipFile> streamClipFiles)
        {
            FileStream   fileStream     = null;
            Stream       discFileStream = null;
            BinaryReader fileReader     = null;
            ulong        streamLength   = 0;

            try
            {
                Streams.Clear();
                StreamClips.Clear();

                if (FileInfo != null)
                {
                    fileStream   = File.OpenRead(FileInfo.FullName);
                    fileReader   = new BinaryReader(fileStream);
                    streamLength = (ulong)fileStream.Length;
                }
                else
                {
                    CdReader.OpenFile(DFileInfo.FullName, FileMode.Open);
                    discFileStream = CdReader.GetFileInfo(DFileInfo.FullName).OpenRead();
                    fileReader     = new BinaryReader(discFileStream);
                    streamLength   = (ulong)discFileStream.Length;
                }

                byte[] data       = new byte[streamLength];
                int    dataLength = fileReader.Read(data, 0, data.Length);

                int pos = 0;

                FileType = ToolBox.ReadString(data, 8, ref pos);
                if (FileType != "MPLS0100" && FileType != "MPLS0200" && FileType != "MPLS0300")
                {
                    throw new Exception(string.Format(
                                            "Playlist {0} has an unknown file type {1}.",
                                            FileInfo.Name, FileType));
                }

                int playlistOffset   = ReadInt32(data, ref pos);
                int chaptersOffset   = ReadInt32(data, ref pos);
                int extensionsOffset = ReadInt32(data, ref pos);

                // misc flags
                pos = 0x38;
                byte miscFlags = ReadByte(data, ref pos);

                // MVC_Base_view_R_flag is stored in 4th bit
                MVCBaseViewR = (miscFlags & 0x10) != 0;

                pos = playlistOffset;

                int playlistLength   = ReadInt32(data, ref pos);
                int playlistReserved = ReadInt16(data, ref pos);
                int itemCount        = ReadInt16(data, ref pos);
                int subitemCount     = ReadInt16(data, ref pos);

                List <TSStreamClip> chapterClips = new List <TSStreamClip>();
                for (int itemIndex = 0; itemIndex < itemCount; itemIndex++)
                {
                    int    itemStart  = pos;
                    int    itemLength = ReadInt16(data, ref pos);
                    string itemName   = ToolBox.ReadString(data, 5, ref pos);
                    string itemType   = ToolBox.ReadString(data, 4, ref pos);

                    TSStreamFile streamFile     = null;
                    string       streamFileName = string.Format(
                        "{0}.M2TS", itemName);
                    if (streamFiles.ContainsKey(streamFileName))
                    {
                        streamFile = streamFiles[streamFileName];
                    }
                    if (streamFile == null)
                    {
                        Debug.WriteLine(string.Format(
                                            "Playlist {0} referenced missing file {1}.",
                                            FileInfo.Name, streamFileName));
                    }

                    TSStreamClipFile streamClipFile     = null;
                    string           streamClipFileName = string.Format(
                        "{0}.CLPI", itemName);
                    if (streamClipFiles.ContainsKey(streamClipFileName))
                    {
                        streamClipFile = streamClipFiles[streamClipFileName];
                    }
                    if (streamClipFile == null)
                    {
                        throw new Exception(string.Format(
                                                "Playlist {0} referenced missing file {1}.",
                                                FileInfo.Name, streamFileName));
                    }

                    pos += 1;
                    int multiangle = (data[pos] >> 4) & 0x01;
                    int condition  = data[pos] & 0x0F;
                    pos += 2;

                    int inTime = ReadInt32(data, ref pos);
                    if (inTime < 0)
                    {
                        inTime &= 0x7FFFFFFF;
                    }
                    double timeIn = (double)inTime / 45000;

                    int outTime = ReadInt32(data, ref pos);
                    if (outTime < 0)
                    {
                        outTime &= 0x7FFFFFFF;
                    }
                    double timeOut = (double)outTime / 45000;

                    TSStreamClip streamClip = new TSStreamClip(
                        streamFile, streamClipFile);

                    streamClip.Name            = streamFileName; //TODO
                    streamClip.TimeIn          = timeIn;
                    streamClip.TimeOut         = timeOut;
                    streamClip.Length          = streamClip.TimeOut - streamClip.TimeIn;
                    streamClip.RelativeTimeIn  = TotalLength;
                    streamClip.RelativeTimeOut = streamClip.RelativeTimeIn + streamClip.Length;
                    StreamClips.Add(streamClip);
                    chapterClips.Add(streamClip);

                    pos += 12;
                    if (multiangle > 0)
                    {
                        int angles = data[pos];
                        pos += 2;
                        for (int angle = 0; angle < angles - 1; angle++)
                        {
                            string angleName = ToolBox.ReadString(data, 5, ref pos);
                            string angleType = ToolBox.ReadString(data, 4, ref pos);
                            pos += 1;

                            TSStreamFile angleFile     = null;
                            string       angleFileName = string.Format(
                                "{0}.M2TS", angleName);
                            if (streamFiles.ContainsKey(angleFileName))
                            {
                                angleFile = streamFiles[angleFileName];
                            }
                            if (angleFile == null)
                            {
                                throw new Exception(string.Format(
                                                        "Playlist {0} referenced missing angle file {1}.",
                                                        FileInfo.Name, angleFileName));
                            }

                            TSStreamClipFile angleClipFile     = null;
                            string           angleClipFileName = string.Format(
                                "{0}.CLPI", angleName);
                            if (streamClipFiles.ContainsKey(angleClipFileName))
                            {
                                angleClipFile = streamClipFiles[angleClipFileName];
                            }
                            if (angleClipFile == null)
                            {
                                throw new Exception(string.Format(
                                                        "Playlist {0} referenced missing angle file {1}.",
                                                        FileInfo.Name, angleClipFileName));
                            }

                            TSStreamClip angleClip =
                                new TSStreamClip(angleFile, angleClipFile);
                            angleClip.AngleIndex      = angle + 1;
                            angleClip.TimeIn          = streamClip.TimeIn;
                            angleClip.TimeOut         = streamClip.TimeOut;
                            angleClip.RelativeTimeIn  = streamClip.RelativeTimeIn;
                            angleClip.RelativeTimeOut = streamClip.RelativeTimeOut;
                            angleClip.Length          = streamClip.Length;
                            StreamClips.Add(angleClip);
                        }
                        if (angles - 1 > AngleCount)
                        {
                            AngleCount = angles - 1;
                        }
                    }

                    int streamInfoLength = ReadInt16(data, ref pos);
                    pos += 2;
                    int streamCountVideo          = data[pos++];
                    int streamCountAudio          = data[pos++];
                    int streamCountPG             = data[pos++];
                    int streamCountIG             = data[pos++];
                    int streamCountSecondaryAudio = data[pos++];
                    int streamCountSecondaryVideo = data[pos++];
                    int streamCountPIP            = data[pos++];
                    pos += 5;

#if DEBUG
                    Debug.WriteLine(string.Format(
                                        "{0} : {1} -> V:{2} A:{3} PG:{4} IG:{5} 2A:{6} 2V:{7} PIP:{8}",
                                        Name, streamFileName, streamCountVideo, streamCountAudio, streamCountPG, streamCountIG,
                                        streamCountSecondaryAudio, streamCountSecondaryVideo, streamCountPIP));
#endif

                    for (int i = 0; i < streamCountVideo; i++)
                    {
                        TSStream stream = CreatePlaylistStream(data, ref pos);
                        if (stream != null)
                        {
                            PlaylistStreams[stream.PID] = stream;
                        }
                    }
                    for (int i = 0; i < streamCountAudio; i++)
                    {
                        TSStream stream = CreatePlaylistStream(data, ref pos);
                        if (stream != null)
                        {
                            PlaylistStreams[stream.PID] = stream;
                        }
                    }
                    for (int i = 0; i < streamCountPG; i++)
                    {
                        TSStream stream = CreatePlaylistStream(data, ref pos);
                        if (stream != null)
                        {
                            PlaylistStreams[stream.PID] = stream;
                        }
                    }
                    for (int i = 0; i < streamCountIG; i++)
                    {
                        TSStream stream = CreatePlaylistStream(data, ref pos);
                        if (stream != null)
                        {
                            PlaylistStreams[stream.PID] = stream;
                        }
                    }
                    for (int i = 0; i < streamCountSecondaryAudio; i++)
                    {
                        TSStream stream = CreatePlaylistStream(data, ref pos);
                        if (stream != null)
                        {
                            PlaylistStreams[stream.PID] = stream;
                        }
                        pos += 2;
                    }
                    for (int i = 0; i < streamCountSecondaryVideo; i++)
                    {
                        TSStream stream = CreatePlaylistStream(data, ref pos);
                        if (stream != null)
                        {
                            PlaylistStreams[stream.PID] = stream;
                        }
                        pos += 6;
                    }

                    /*
                     * TODO
                     *
                     * for (int i = 0; i < streamCountPIP; i++)
                     * {
                     *  TSStream stream = CreatePlaylistStream(data, ref pos);
                     *  if (stream != null) PlaylistStreams[stream.PID] = stream;
                     * }
                     */

                    pos += itemLength - (pos - itemStart) + 2;
                }

                pos = chaptersOffset + 4;

                int chapterCount = ReadInt16(data, ref pos);

                for (int chapterIndex = 0;
                     chapterIndex < chapterCount;
                     chapterIndex++)
                {
                    int chapterType = data[pos + 1];

                    if (chapterType == 1)
                    {
                        int streamFileIndex =
                            ((int)data[pos + 2] << 8) + data[pos + 3];

                        long chapterTime =
                            ((long)data[pos + 4] << 24) +
                            ((long)data[pos + 5] << 16) +
                            ((long)data[pos + 6] << 8) +
                            ((long)data[pos + 7]);

                        TSStreamClip streamClip = chapterClips[streamFileIndex];

                        double chapterSeconds = (double)chapterTime / 45000;

                        double relativeSeconds =
                            chapterSeconds -
                            streamClip.TimeIn +
                            streamClip.RelativeTimeIn;

                        // TODO: Ignore short last chapter?
                        if (TotalLength - relativeSeconds > 1.0)
                        {
                            streamClip.Chapters.Add(chapterSeconds);
                            this.Chapters.Add(relativeSeconds);
                        }
                    }
                    else
                    {
                        // TODO: Handle other chapter types?
                    }
                    pos += 14;
                }
            }
            finally
            {
                if (fileReader != null)
                {
                    fileReader.Close();
                }
                if (fileStream != null)
                {
                    fileStream.Close();
                }
                if (discFileStream != null)
                {
                    discFileStream.Close();
                }
            }
        }
示例#2
0
        public void Scan()
        {
            FileStream   fileStream     = null;
            Stream       discFileStream = null;
            BinaryReader fileReader     = null;
            ulong        streamLength   = 0;

            try
            {
#if DEBUG
                Debug.WriteLine(string.Format(
                                    "Scanning {0}...", Name));
#endif
                Streams.Clear();

                if (FileInfo != null)
                {
                    fileStream   = File.OpenRead(FileInfo.FullName);
                    fileReader   = new BinaryReader(fileStream);
                    streamLength = (ulong)fileStream.Length;
                }
                else
                {
                    CdReader.OpenFile(DFileInfo.FullName, FileMode.Open);
                    discFileStream = CdReader.GetFileInfo(DFileInfo.FullName).OpenRead();
                    fileReader     = new BinaryReader(discFileStream);
                    streamLength   = (ulong)discFileStream.Length;
                }

                byte[] data = new byte[streamLength];
                fileReader.Read(data, 0, data.Length);

                byte[] fileType = new byte[8];
                Array.Copy(data, 0, fileType, 0, fileType.Length);

                FileType = ASCIIEncoding.ASCII.GetString(fileType);
                if (FileType != "HDMV0100" &&
                    FileType != "HDMV0200" &&
                    FileType != "HDMV0300")
                {
                    throw new Exception(string.Format(
                                            "Clip info file {0} has an unknown file type {1}.",
                                            FileInfo.Name, FileType));
                }
#if DEBUG
                Debug.WriteLine(string.Format(
                                    "\tFileType: {0}", FileType));
#endif
                int clipIndex =
                    ((int)data[12] << 24) +
                    ((int)data[13] << 16) +
                    ((int)data[14] << 8) +
                    ((int)data[15]);

                int clipLength =
                    ((int)data[clipIndex] << 24) +
                    ((int)data[clipIndex + 1] << 16) +
                    ((int)data[clipIndex + 2] << 8) +
                    ((int)data[clipIndex + 3]);

                byte[] clipData = new byte[clipLength];
                Array.Copy(data, clipIndex + 4, clipData, 0, clipData.Length);

                int streamCount = clipData[8];
#if DEBUG
                Debug.WriteLine(string.Format(
                                    "\tStreamCount: {0}", streamCount));
#endif
                int streamOffset = 10;
                for (int streamIndex = 0;
                     streamIndex < streamCount;
                     streamIndex++)
                {
                    TSStream stream = null;

                    ushort PID = (ushort)
                                 ((clipData[streamOffset] << 8) +
                                  clipData[streamOffset + 1]);

                    streamOffset += 2;

                    TSStreamType streamType = (TSStreamType)
                                              clipData[streamOffset + 1];
                    switch (streamType)
                    {
                    case TSStreamType.MVC_VIDEO:
                        // TODO
                        break;

                    case TSStreamType.HEVC_VIDEO:
                    case TSStreamType.AVC_VIDEO:
                    case TSStreamType.MPEG1_VIDEO:
                    case TSStreamType.MPEG2_VIDEO:
                    case TSStreamType.VC1_VIDEO:
                    {
                        TSVideoFormat videoFormat = (TSVideoFormat)
                                                    (clipData[streamOffset + 2] >> 4);
                        TSFrameRate frameRate = (TSFrameRate)
                                                (clipData[streamOffset + 2] & 0xF);
                        TSAspectRatio aspectRatio = (TSAspectRatio)
                                                    (clipData[streamOffset + 3] >> 4);

                        stream = new TSVideoStream();
                        ((TSVideoStream)stream).VideoFormat = videoFormat;
                        ((TSVideoStream)stream).AspectRatio = aspectRatio;
                        ((TSVideoStream)stream).FrameRate   = frameRate;
#if DEBUG
                        Debug.WriteLine(string.Format(
                                            "\t{0} {1} {2} {3} {4}",
                                            PID,
                                            streamType,
                                            videoFormat,
                                            frameRate,
                                            aspectRatio));
#endif
                    }
                    break;

                    case TSStreamType.AC3_AUDIO:
                    case TSStreamType.AC3_PLUS_AUDIO:
                    case TSStreamType.AC3_PLUS_SECONDARY_AUDIO:
                    case TSStreamType.AC3_TRUE_HD_AUDIO:
                    case TSStreamType.DTS_AUDIO:
                    case TSStreamType.DTS_HD_AUDIO:
                    case TSStreamType.DTS_HD_MASTER_AUDIO:
                    case TSStreamType.DTS_HD_SECONDARY_AUDIO:
                    case TSStreamType.LPCM_AUDIO:
                    case TSStreamType.MPEG1_AUDIO:
                    case TSStreamType.MPEG2_AUDIO:
                    {
                        byte[] languageBytes = new byte[3];
                        Array.Copy(clipData, streamOffset + 3,
                                   languageBytes, 0, languageBytes.Length);
                        string languageCode =
                            ASCIIEncoding.ASCII.GetString(languageBytes);

                        TSChannelLayout channelLayout = (TSChannelLayout)
                                                        (clipData[streamOffset + 2] >> 4);
                        TSSampleRate sampleRate = (TSSampleRate)
                                                  (clipData[streamOffset + 2] & 0xF);

                        stream = new TSAudioStream();
                        ((TSAudioStream)stream).LanguageCode  = languageCode;
                        ((TSAudioStream)stream).ChannelLayout = channelLayout;
                        ((TSAudioStream)stream).SampleRate    = TSAudioStream.ConvertSampleRate(sampleRate);
                        ((TSAudioStream)stream).LanguageCode  = languageCode;
#if DEBUG
                        Debug.WriteLine(string.Format(
                                            "\t{0} {1} {2} {3} {4}",
                                            PID,
                                            streamType,
                                            languageCode,
                                            channelLayout,
                                            sampleRate));
#endif
                    }
                    break;

                    case TSStreamType.INTERACTIVE_GRAPHICS:
                    case TSStreamType.PRESENTATION_GRAPHICS:
                    {
                        byte[] languageBytes = new byte[3];
                        Array.Copy(clipData, streamOffset + 2,
                                   languageBytes, 0, languageBytes.Length);
                        string languageCode =
                            ASCIIEncoding.ASCII.GetString(languageBytes);

                        stream = new TSGraphicsStream();
                        stream.LanguageCode = languageCode;
#if DEBUG
                        Debug.WriteLine(string.Format(
                                            "\t{0} {1} {2}",
                                            PID,
                                            streamType,
                                            languageCode));
#endif
                    }
                    break;

                    case TSStreamType.SUBTITLE:
                    {
                        byte[] languageBytes = new byte[3];
                        Array.Copy(clipData, streamOffset + 3,
                                   languageBytes, 0, languageBytes.Length);
                        string languageCode =
                            ASCIIEncoding.ASCII.GetString(languageBytes);
#if DEBUG
                        Debug.WriteLine(string.Format(
                                            "\t{0} {1} {2}",
                                            PID,
                                            streamType,
                                            languageCode));
#endif
                        stream = new TSTextStream();
                        stream.LanguageCode = languageCode;
                    }
                    break;
                    }

                    if (stream != null)
                    {
                        stream.PID        = PID;
                        stream.StreamType = streamType;
                        Streams.Add(PID, stream);
                    }

                    streamOffset += clipData[streamOffset] + 1;
                }
                IsValid = true;
            }
            finally
            {
                if (fileReader != null)
                {
                    fileReader.Close();
                }
                if (fileStream != null)
                {
                    fileStream.Close();
                }
                if (discFileStream != null)
                {
                    discFileStream.Close();
                }
            }
        }