public TSStreamClip( TSStreamFile streamFile, TSStreamClipFile streamClipFile) { if (streamFile != null) { Name = streamFile.Name; StreamFile = streamFile; FileSize = (ulong)StreamFile.FileInfo.Length; if (StreamFile.InterleavedFile != null) { InterleavedFileSize = (ulong)StreamFile.InterleavedFile.FileInfo.Length; } } StreamClipFile = streamClipFile; }
public void Scan( Dictionary <string, TSStreamFile> streamFiles, Dictionary <string, TSStreamClipFile> streamClipFiles) { FileStream fileStream = null; BinaryReader fileReader = null; try { Streams.Clear(); StreamClips.Clear(); fileStream = File.OpenRead(FileInfo.FullName); fileReader = new BinaryReader(fileStream); byte[] data = new byte[fileStream.Length]; int dataLength = fileReader.Read(data, 0, data.Length); int pos = 0; FileType = ReadString(data, 8, ref pos); if (FileType != "MPLS0100" && FileType != "MPLS0200") { 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 = ReadString(data, 5, ref pos); string itemType = 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 = ReadString(data, 5, ref pos); string angleType = 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(); } } }