private PesPacket CheckAndFixDiscontinuities(PesPacket pp) { // checks for PTS/DTS discontinuities PesHeader ph = pp.GetHeader(); byte[] data = pp.GetData(); int len = ph.TotalHeaderLength; int i = len; UInt32 marker = 0xffffffff; if (Constants.DEFAULT_VIDEO_PID == pidMappings[pp.PID]) { // checks for end of stream headers switch (VideoType) { case (byte)ElementaryStreamTypes.VIDEO_STREAM_VC1: for (; i < data.Length; i++) { marker <<= 8; marker |= data[i]; if (marker == Constants.VC1_END_OF_STREAM) break; } if (i < data.Length) { // we have an end of stream marker i -= 3; PesPacket pnew = new PesPacket(data, 0, i, pp.PID); i += 4; pnew.AddData(data, i, data.Length - i); pp = pnew; ph = pp.GetHeader(); data = pp.GetData(); } break; case (byte)ElementaryStreamTypes.VIDEO_STREAM_MPEG2: for (; i < data.Length; i++) { marker <<= 8; marker |= data[i]; if (marker == Constants.MPEG2_SEQ_END) break; } if (i < data.Length) { // we have an end of stream marker i -= 3; PesPacket pnew = new PesPacket(data, 0, i, pp.PID); i += 4; pnew.AddData(data, i, data.Length - i); pp = pnew; ph = pp.GetHeader(); data = pp.GetData(); } break; case (byte)ElementaryStreamTypes.VIDEO_STREAM_H264: for (; i < data.Length; i++) { marker <<= 8; marker |= data[i]; if ((marker & 0xffffff9f) == Constants.H264_END_OF_STREAM) break; } if (i < data.Length) { // we have an end of stream marker i -= 3; PesPacket pnew = new PesPacket(data, 0, i, pp.PID); i += 4; pnew.AddData(data, i, data.Length - i); pp = pnew; ph = pp.GetHeader(); data = pp.GetData(); } break; } if (ph.HasPts) { lastPts = currentPts; currentPts = ph.Pts; ptsCount = ptsDelta; ptsDelta = currentPts - lastPts; if (lastPts != -1) { if (ptsDelta < (0 - (Constants.PTS_CLOCK_RATE << 2)) || ptsDelta > (Constants.PTS_CLOCK_RATE << 2)) { ptsOffset += (lastPts + ptsCount - currentPts); } } } // build EP Map info marker = 0xffffffff; switch (VideoType) { case (byte)ElementaryStreamTypes.VIDEO_STREAM_VC1: for (i = ph.TotalHeaderLength; i < data.Length; i++) { marker <<= 8; marker |= data[i]; if (marker == Constants.VC1_SEQ_SC && ph.HasPts) { EpElement ep = new EpElement(ph.Pts, this.CurrentPacketNumber); epData.Add(ep); break; } } break; case (byte)ElementaryStreamTypes.VIDEO_STREAM_MPEG2: for (i = ph.TotalHeaderLength; i < data.Length; i++) { marker <<= 8; marker |= data[i]; if (marker == Constants.MPEG2_SEQ_CODE && ph.HasPts) { EpElement ep = new EpElement(ph.Pts, this.CurrentPacketNumber); epData.Add(ep); break; } } break; case (byte)ElementaryStreamTypes.VIDEO_STREAM_H264: for (i = ph.TotalHeaderLength; i < data.Length; i++) { marker <<= 8; marker |= data[i]; if ((marker & 0xffffff9f) == Constants.H264_PREFIX && ph.HasPts) { EpElement ep = new EpElement(ph.Pts, this.CurrentPacketNumber); epData.Add(ep); break; } } break; } } if (ph.HasPts && ptsOffset != 0) { Int64 time = ph.Pts + ptsOffset; if (time < 0) time += Constants.MAX_PTS_CLOCK; else if (time > Constants.MAX_PTS_CLOCK) time -= Constants.MAX_PTS_CLOCK; ph.Pts = time; for (i = 9; i < 14; i++) pp[i] = ph[i]; // copy PTS if (ph.HasDts) { time = ph.Dts + ptsOffset; if (time < 0) time += Constants.MAX_PTS_CLOCK; else if (time > Constants.MAX_PTS_CLOCK) time -= Constants.MAX_PTS_CLOCK; ph.Dts = time; for (i = 14; i < 19; i++) pp[i] = ph[i]; // copy DTS } } lastPacket = pp; return pp; }
private PesPacket CheckAndFixDiscontinuities(PesPacket pp) { // checks for PTS/DTS discontinuities PesHeader ph = pp.GetHeader(); byte[] data = pp.GetData(); int len = ph.TotalHeaderLength; int i = len; UInt32 marker = 0xffffffff; if (Constants.DEFAULT_VIDEO_PID == pidMappings[pp.PID]) { // checks for end of stream headers switch (VideoType) { case (byte)ElementaryStreamTypes.VIDEO_STREAM_VC1: for (; i < data.Length; i++) { marker <<= 8; marker |= data[i]; if (marker == Constants.VC1_END_OF_STREAM) { break; } } if (i < data.Length) { // we have an end of stream marker i -= 3; PesPacket pnew = new PesPacket(data, 0, i, pp.PID); i += 4; pnew.AddData(data, i, data.Length - i); pp = pnew; ph = pp.GetHeader(); data = pp.GetData(); } break; case (byte)ElementaryStreamTypes.VIDEO_STREAM_MPEG2: for (; i < data.Length; i++) { marker <<= 8; marker |= data[i]; if (marker == Constants.MPEG2_SEQ_END) { break; } } if (i < data.Length) { // we have an end of stream marker i -= 3; PesPacket pnew = new PesPacket(data, 0, i, pp.PID); i += 4; pnew.AddData(data, i, data.Length - i); pp = pnew; ph = pp.GetHeader(); data = pp.GetData(); } break; case (byte)ElementaryStreamTypes.VIDEO_STREAM_H264: for (; i < data.Length; i++) { marker <<= 8; marker |= data[i]; if ((marker & 0xffffff9f) == Constants.H264_END_OF_STREAM) { break; } } if (i < data.Length) { // we have an end of stream marker i -= 3; PesPacket pnew = new PesPacket(data, 0, i, pp.PID); i += 4; pnew.AddData(data, i, data.Length - i); pp = pnew; ph = pp.GetHeader(); data = pp.GetData(); } break; } if (ph.HasPts) { lastPts = currentPts; currentPts = ph.Pts; ptsCount = ptsDelta; ptsDelta = currentPts - lastPts; if (lastPts != -1) { if (ptsDelta < (0 - (Constants.PTS_CLOCK_RATE << 2)) || ptsDelta > (Constants.PTS_CLOCK_RATE << 2)) { ptsOffset += (lastPts + ptsCount - currentPts); } } } // build EP Map info marker = 0xffffffff; switch (VideoType) { case (byte)ElementaryStreamTypes.VIDEO_STREAM_VC1: for (i = ph.TotalHeaderLength; i < data.Length; i++) { marker <<= 8; marker |= data[i]; if (marker == Constants.VC1_SEQ_SC && ph.HasPts) { EpElement ep = new EpElement(ph.Pts, this.CurrentPacketNumber); epData.Add(ep); break; } } break; case (byte)ElementaryStreamTypes.VIDEO_STREAM_MPEG2: for (i = ph.TotalHeaderLength; i < data.Length; i++) { marker <<= 8; marker |= data[i]; if (marker == Constants.MPEG2_SEQ_CODE && ph.HasPts) { EpElement ep = new EpElement(ph.Pts, this.CurrentPacketNumber); epData.Add(ep); break; } } break; case (byte)ElementaryStreamTypes.VIDEO_STREAM_H264: for (i = ph.TotalHeaderLength; i < data.Length; i++) { marker <<= 8; marker |= data[i]; if ((marker & 0xffffff9f) == Constants.H264_PREFIX && ph.HasPts) { EpElement ep = new EpElement(ph.Pts, this.CurrentPacketNumber); epData.Add(ep); break; } } break; } } if (ph.HasPts && ptsOffset != 0) { Int64 time = ph.Pts + ptsOffset; if (time < 0) { time += Constants.MAX_PTS_CLOCK; } else if (time > Constants.MAX_PTS_CLOCK) { time -= Constants.MAX_PTS_CLOCK; } ph.Pts = time; for (i = 9; i < 14; i++) { pp[i] = ph[i]; // copy PTS } if (ph.HasDts) { time = ph.Dts + ptsOffset; if (time < 0) { time += Constants.MAX_PTS_CLOCK; } else if (time > Constants.MAX_PTS_CLOCK) { time -= Constants.MAX_PTS_CLOCK; } ph.Dts = time; for (i = 14; i < 19; i++) { pp[i] = ph[i]; // copy DTS } } } lastPacket = pp; return(pp); }
byte[] BuildClipInfo(UInt32 numOfSourcePackets, EpElement[] EpInfo) { List<byte> clip = new List<byte>(); List<byte> temp = new List<byte>(); clip.Add(0x00); clip.Add(0x00); clip.Add(0x01); clip.Add(0x01); clip.Add(0x00); clip.Add(0x00); clip.Add(0x00); clip.Add(0x00); Int64 rate = EpInfo[EpInfo.Length - 1].SPN - EpInfo[0].SPN; rate *= 192; rate /= ((EpInfo[EpInfo.Length - 1].PTS - EpInfo[0].PTS) / 90000); clip.AddRange(UintToByteArraryNetwork((UInt32)rate)); clip.AddRange(UintToByteArraryNetwork(numOfSourcePackets)); for (int i = 0; i < 128; i++) clip.Add(0x00); clip.AddRange(TsTypeInfoBlock); UInt32 len = (UInt32)clip.Count; temp.AddRange(UintToByteArraryNetwork(len)); temp.AddRange(clip); return temp.ToArray(); }
byte[] BuildEpMap(EpElement[] EpInfo) { UInt32 lastepfine = 0x7ff; UInt32 lastspnfine = 0x1ffff; UInt32 numofcoarse = 0; List<byte> coarseloop = new List<byte>(); List<byte> fineloop = new List<byte>(EpInfo.Length); List<byte> EpMap = new List<byte>(); for (int i = 0; i < EpInfo.Length; i++) { UInt32 epfine = (UInt32)((EpInfo[i].PTS >> 9) % 0x800); UInt32 epcoarse = (UInt32)((EpInfo[i].PTS >> 19) % 0x4000); UInt32 spnfine = EpInfo[i].SPN % 0x20000; if (lastepfine > epfine || lastspnfine > spnfine) { UInt32 reftofine = (UInt32)i; reftofine <<= 14; reftofine |= epcoarse; coarseloop.AddRange(UintToByteArraryNetwork(reftofine)); coarseloop.AddRange(UintToByteArraryNetwork(EpInfo[i].SPN)); numofcoarse++; } UInt32 value = 0x1000; value |= (epfine << 17); value |= spnfine; fineloop.AddRange(UintToByteArraryNetwork(value)); lastepfine = epfine; lastspnfine = spnfine; } EpMap.Add(0x00); EpMap.Add(0x01); EpMap.Add((byte)((Constants.DEFAULT_VIDEO_PID >> 8) & 0xff)); EpMap.Add((byte)(Constants.DEFAULT_VIDEO_PID & 0xff)); EpMap.Add(0x00); byte btemp = 4; btemp |= (byte)((numofcoarse >> 14) & 0xff); EpMap.Add(btemp); btemp = (byte)((numofcoarse >> 6) & 0xff); EpMap.Add(btemp); btemp = (byte)((numofcoarse & 0x3f) << 2); btemp |= (byte)((EpInfo.Length >> 16) & 0x03); EpMap.Add(btemp); btemp = (byte)((EpInfo.Length >> 8) & 0xff); EpMap.Add(btemp); btemp = (byte)(EpInfo.Length& 0xff); EpMap.Add(btemp); UInt32 count = 4 + (UInt32)EpMap.Count; EpMap.AddRange(UintToByteArraryNetwork(count)); UInt32 start = 4 + (UInt32)coarseloop.Count; EpMap.AddRange(UintToByteArraryNetwork(start)); EpMap.AddRange(coarseloop); EpMap.AddRange(fineloop); return EpMap.ToArray(); }
public void Author(EpElement[] EpInfo, StreamInfo[] sis, UInt32 numOfSourcePackets) { List<ushort> Pids = new List<ushort>(); List<byte[]> StreamCodingInfos = new List<byte[]>(); List<byte[]> AudioEntries = new List<byte[]>(); List<byte[]> AudioAttributes = new List<byte[]>(); List<byte[]> PgEntries = new List<byte[]>(); List<byte[]> PgAttributes = new List<byte[]>(); byte[] VideoEntry = null; byte[] VideoAttribute = null; ElementaryStreamTypes VideoType = ElementaryStreamTypes.INVALID; foreach(StreamInfo si in sis) { switch (si.StreamType) { case ElementaryStreamTypes.AUDIO_STREAM_AC3: case ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS: case ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD: case ElementaryStreamTypes.AUDIO_STREAM_DTS: case ElementaryStreamTypes.AUDIO_STREAM_DTS_HD: case ElementaryStreamTypes.AUDIO_STREAM_DTS_HD_MASTER_AUDIO: case ElementaryStreamTypes.AUDIO_STREAM_LPCM: case ElementaryStreamTypes.AUDIO_STREAM_MPEG1: case ElementaryStreamTypes.AUDIO_STREAM_MPEG2: byte[] AudioEntry = BuildStreamEntry(si.ElementaryPID); byte[] AudioAttribute = BuildAudioStreamAttributes((byte)si.StreamType,si.AudioPresentationType,si.SamplingFrequency); AudioEntries.Add(AudioEntry); AudioAttributes.Add(AudioAttribute); byte[] AudioCodingInfo = BuildAudioStreamCodingInfo(si.StreamType, si.AudioPresentationType, si.SamplingFrequency); Pids.Add(si.ElementaryPID); StreamCodingInfos.Add(AudioCodingInfo); break; case ElementaryStreamTypes.VIDEO_STREAM_H264: case ElementaryStreamTypes.VIDEO_STREAM_MPEG1: case ElementaryStreamTypes.VIDEO_STREAM_MPEG2: case ElementaryStreamTypes.VIDEO_STREAM_VC1: VideoType = si.StreamType; VideoEntry = BuildStreamEntry(si.ElementaryPID); VideoAttribute = BuildVideoStreamAttributes((byte)si.StreamType,si.VideoFormat,si.FrameRate); byte[] VideoCodingInfo = BuildVideoStreamCodingInfo(si.StreamType, si.VideoFormat, si.FrameRate, si.AspectRatio); Pids.Add(si.ElementaryPID); StreamCodingInfos.Add(VideoCodingInfo); break; case ElementaryStreamTypes.PRESENTATION_GRAPHICS_STREAM: byte[] PgEntry = BuildStreamEntry(si.ElementaryPID); PgEntries.Add(PgEntry); PgAttributes.Add(PgStreamAttributes); byte[] PgCodingInfo = BuildPgStreamCodingInfo(); Pids.Add(si.ElementaryPID); StreamCodingInfos.Add(PgCodingInfo); break; } } byte[][] PlayItems = new byte[1][]; UInt32 Start = (UInt32)((EpInfo[0].PTS >> 1) & 0xffffffff); UInt32 End = (UInt32)((EpInfo[EpInfo.Length - 1].PTS >> 1) & 0xffffffff); UInt32 Interval = ((UInt32)(chapterLen.TotalMinutes)) * 2700000; byte[] StnTable = BuildStnTable(VideoEntry, VideoAttribute, AudioEntries.ToArray(), AudioAttributes.ToArray(), PgEntries.ToArray(), PgAttributes.ToArray()); PlayItems[0] = BuildFirstPlayItem(0, Start, End, StnTable); byte[] PlayList = BuildPlayList(PlayItems); byte[] PlayListMark = BuildFirstPlayMarks(Start, End, Interval); byte[] mlps = Build_mlps(PlayList, PlayListMark); File.WriteAllBytes(Path.Combine(path, @"BDMV\PLAYLIST\00000.mpls"), mlps); File.Copy(Path.Combine(path, @"BDMV\PLAYLIST\00000.mpls"), Path.Combine(path, @"BDMV\BACKUP\PLAYLIST\00000.mpls"),true); byte[] ClipInfo = BuildClipInfo(numOfSourcePackets,EpInfo); byte[] SequenceInfo = BuildSequenceInfo(Start, End); byte[] ProgramInf = BuildProgramInfo(Pids.ToArray(), StreamCodingInfos.ToArray()); byte[] EpMap = BuildEpMap(EpInfo); byte[] CPI = BuildCpi(EpMap); byte[] clpi = Build_clpi(ClipInfo, SequenceInfo, ProgramInf, CPI); File.WriteAllBytes(Path.Combine(path, @"BDMV\CLIPINF\00001.clpi"), clpi); File.Copy(Path.Combine(path, @"BDMV\CLIPINF\00001.clpi"), Path.Combine(path, @"BDMV\BACKUP\CLIPINF\00001.clpi"),true); }