private void MuxPesPacketToTs(PesPacket pp, bool priority) { byte[] data = new byte[Constants.TS_SIZE]; int j = 0; int i = 0; byte[] pes = pp.GetData(); // take care of the first packet data[0] = Constants.SYNC_BYTE; data[1] = 0x40; // payload start data[2] = 0; if (pes.Length < Constants.TS_PAYLOAD_SIZE) { data[3] = 0x30; // adaptation and payload int stufLength = Constants.TS_PAYLOAD_SIZE - pes.Length - 1; data[4] = (byte)stufLength; i = 5; if (stufLength > 0) { data[i] = 0; i++; stufLength--; } for (; i < (6 + stufLength); i++) data[i] = 0xff; for (; i < Constants.TS_SIZE; i++) { data[i] = pes[j]; j++; } } else { data[3] = 0x10; // no adaptation, payload only for (i = 4; i < data.Length; i++) { data[i] = pes[j]; j++; } } TsPacket ts = new TsPacket(); ts.SetData(data, 0); ushort pid = pidMappings[pp.PID]; ts.PID = pid; ts.Priority = priority; ts.ContinuityCounter = Continuities[pid]; ts.IncrementContinuityCounter(); Continuities[pid] = ts.ContinuityCounter; buffer.Add(ts); while (j < ((pes.Length / Constants.TS_PAYLOAD_SIZE) * Constants.TS_PAYLOAD_SIZE)) { // take care of the other packets data[0] = Constants.SYNC_BYTE; data[1] = 0x00; // no payload start data[2] = 0; data[3] = 0x10; // no adaptation, payload only for (i = 4; i < data.Length; i++) { data[i] = pes[j]; j++; } ts = new TsPacket(); ts.SetData(data, 0); ts.PID = pid; ts.Priority = priority; ts.ContinuityCounter = Continuities[pid]; ts.IncrementContinuityCounter(); Continuities[pid] = ts.ContinuityCounter; buffer.Add(ts); } // take care of the last packet if (j < pes.Length) { data[0] = Constants.SYNC_BYTE; data[1] = 0x00; // no payload start data[2] = 0; data[3] = 0x30; // adaptation and payload int stufLength = Constants.TS_PAYLOAD_SIZE - (pes.Length - j) - 1; data[4] = (byte)stufLength; i = 5; if (stufLength > 0) { data[i] = 0; i++; stufLength--; for (; i < (6 + stufLength); i++) data[i] = 0xff; } for (; i < Constants.TS_SIZE; i++) { data[i] = pes[j]; j++; } ts = new TsPacket(); ts.SetData(data, 0); ts.PID = pid; ts.Priority = priority; ts.ContinuityCounter = Continuities[pid]; ts.IncrementContinuityCounter(); Continuities[pid] = ts.ContinuityCounter; buffer.Add(ts); } }
private void MuxDtsToTs(PesPacket pp, ElementaryStreamTypes type) { Int64 pts = 0; PesHeader ph = pp.GetHeader(); if (ph.HasPts == false) { if (lastPtsList.ContainsKey(pp.PID)) pts = lastPtsList[pp.PID]; } else { pts = ph.Pts; lastPtsList[pp.PID] = pts; } byte[] payload = pp.GetPayload(); DtsInfo dts = new DtsInfo(payload, 0); if (this.processAudio || (dts.Valid && dts.FrameSize == payload.Length)) MuxSingleDtsToTs(payload, 0, payload.Length, pts, type, pp.PID); else { if (soundFrames.ContainsKey(pp.PID) == false) { // skip to the good part. UInt32 mk2 = 0xffffffff; int index = 0; for (index = 0; index < payload.Length; index++) { mk2 <<= 8; mk2 |= payload[index]; if (mk2 == Constants.DTS_SYNC) break; } if (index == payload.Length) MuxSingleDtsToTs(payload, 0, payload.Length, pts, type, pp.PID); else { index--; List<byte> framelist = new List<byte>(); for (; index < payload.Length; index++) framelist.Add(payload[index]); soundFrames.Add(pp.PID, framelist); } } else soundFrames[pp.PID].AddRange(payload); if (soundFrames.ContainsKey(pp.PID)) { payload = soundFrames[pp.PID].ToArray(); dts = new DtsInfo(payload, 0); int len = 0; while (dts.Valid && dts.FrameSize > 0 && dts.FrameSize + len <= payload.Length) { len += dts.FrameSize; dts = new DtsInfo(payload, len); } if (len > 0) { MuxSingleDtsToTs(payload, 0, len, pts, type, pp.PID); soundFrames[pp.PID].RemoveRange(0, len); } } } }
private void MuxMlpToTs(PesPacket pp, ElementaryStreamTypes type) { Int64 pts = 0; PesHeader ph = pp.GetHeader(); if (ph.HasPts == false) { if (lastPtsList.ContainsKey(pp.PID)) pts = lastPtsList[pp.PID]; } else { pts = ph.Pts; lastPtsList[pp.PID] = pts; } byte[] payload = pp.GetPayload(); /* int index = 0; int len = 0; len = payload.Length - index; */ MuxSingleAc3ToTs(payload, 0, payload.Length, pts, type, pp.PID); }
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 void MuxAc3ToTs(PesPacket pp, ElementaryStreamTypes type) { Int64 pts = 0; PesHeader ph = pp.GetHeader(); if (ph.HasPts == false) { if (lastPtsList.ContainsKey(pp.PID)) pts = lastPtsList[pp.PID]; } else { pts = ph.Pts; lastPtsList[pp.PID] = pts; } byte[] payload = pp.GetPayload(); AC3Info ac3 = new AC3Info(payload, 0); if (this.processAudio || (ac3.Valid && ac3.FrameLength == payload.Length)) MuxSingleAc3ToTs(payload, 0, payload.Length, pts, type, pp.PID); else { if (soundFrames.ContainsKey(pp.PID) == false) { // skip to the good part. ushort mk2 = 0xffff; int index = 0; for (index = 0; index < payload.Length; index++) { mk2 <<= 8; mk2 |= payload[index]; if (mk2 == Constants.AC3_SYNC) break; } if (index == payload.Length) MuxSingleAc3ToTs(payload, 0, payload.Length, pts, type, pp.PID); else { index--; List<byte> framelist = new List<byte>(); for (; index < payload.Length; index++) framelist.Add(payload[index]); soundFrames.Add(pp.PID, framelist); } } else soundFrames[pp.PID].AddRange(payload); if (soundFrames.ContainsKey(pp.PID)) { payload = soundFrames[pp.PID].ToArray(); ac3 = new AC3Info(payload, 0); int len = 0; if (payload.Length > ac3.MaxFrameLength) { // resync ac3 ushort mk2 = 0xffff; int index = 0; for (index = 2; index < payload.Length; index++) { mk2 <<= 8; mk2 |= payload[index]; if (mk2 == Constants.AC3_SYNC) { ac3 = new AC3Info(payload, index - 1); if (ac3.Valid && ac3.FrameLength > 0) break; } } if (index == payload.Length) len = payload.Length; else { index -= 1; len = index; ac3 = new AC3Info(payload, len); while (ac3.Valid && ac3.FrameLength > 0 && ac3.FrameLength + len <= payload.Length) { len += ac3.FrameLength; ac3 = new AC3Info(payload, len); } } } else while (ac3.Valid && ac3.FrameLength > 0 && ac3.FrameLength + len <= payload.Length) { len += ac3.FrameLength; ac3 = new AC3Info(payload, len); } if (len > 0) { MuxSingleAc3ToTs(payload, 0, len, pts, type, pp.PID); soundFrames[pp.PID].RemoveRange(0, len); } } } }
public override PesPacket[] GetNextPesPackets() { byte b0 = 0; byte b1 = 0; byte[] inData = new byte[1]; byte[] pgHeader = new byte[3]; while (tsior.Read(inData, 0, inData.Length) == inData.Length) { b0 = b1; b1 = inData[0]; if ((b0 == (byte)'P' || b0 == (byte)'p') && (b1 == (byte)'G' || b1 == (byte)'g')) { Int64 Pts = 0; Int64 Dts = 0; ushort len = 0; for (int k = 0; k < 4; k++) { if (0 == tsior.Read(inData, 0, inData.Length)) return null; Pts <<= 8; Pts |= inData[0]; } Pts <<= 1; if (ptsDelegate != null) ptsDelegate(Pts, sis[0].ElementaryPID); for (int k = 0; k < 4; k++) { if (0 == tsior.Read(inData, 0, inData.Length)) return null; Dts <<= 8; Dts |= inData[0]; } Dts <<= 1; for (int k = 0; k < 3; k++) { if (0 == tsior.Read(inData, 0, inData.Length)) return null; pgHeader[k] = inData[0]; if (k > 0) { len <<= 8; len |= inData[0]; } } byte hlen = (byte)(Dts == 0 ? 0x05 : 0x0a); ushort plen = (ushort)(6 + hlen + len); PesPacket pp = new PesPacket(PesTemplate, 0, PesTemplate.Length, sis[0].ElementaryPID); inData[0] = (byte)((plen >> 8) & 0xff); pp.AddData(inData, 0, 1); inData[0] = (byte)(plen & 0xff); pp.AddData(inData, 0, 1); inData[0] = 0x81; pp.AddData(inData, 0, 1); inData[0] = (byte)(Dts == 0 ? 0x80 : 0xc0); pp.AddData(inData, 0, 1); inData[0] = hlen; pp.AddData(inData, 0, 1); byte old = (byte)(Dts == 0 ? 0x21 : 0x31); inData[0] = (byte)(((Pts & 0x1C0000000) >> 29) | old); pp.AddData(inData, 0, 1); inData[0] = (byte)((Pts & 0x3fC00000) >> 22); pp.AddData(inData, 0, 1); inData[0] = (byte)(((Pts & 0x3f8000) >> 14) | 0x01); pp.AddData(inData, 0, 1); inData[0] = (byte)((Pts & 0x7f80) >> 7); pp.AddData(inData, 0, 1); inData[0] = (byte)(((Pts & 0x7f) << 1) | 0x01); pp.AddData(inData, 0, 1); if (Dts != 0) { inData[0] = (byte)(((Dts & 0x1C0000000) >> 29) | 0x11); pp.AddData(inData, 0, 1); inData[0] = (byte)((Dts & 0x3fC00000) >> 22); pp.AddData(inData, 0, 1); inData[0] = (byte)(((Dts & 0x3f8000) >> 14) | 0x01); pp.AddData(inData, 0, 1); inData[0] = (byte)((Dts & 0x7f80) >> 7); pp.AddData(inData, 0, 1); inData[0] = (byte)(((Dts & 0x7f) << 1) | 0x01); pp.AddData(inData, 0, 1); } pp.AddData(pgHeader, 0, pgHeader.Length); for (int k = 0; k < len; k++) { if (0 == tsior.Read(inData, 0, inData.Length)) return null; pp.AddData(inData, 0, 1); } PesPacket[] ppa = new PesPacket[1]; ppa[0] = pp; return ppa; } } return null; }
/* public UInt32 CurrentPacketNumber { get { return packetCount + (UInt32)buffer.Count; } } public EpElement[] EpData { get { return epData.ToArray(); } } public StreamInfo[] Psi { get { return pmtStreams.ToArray(); } } */ public override void MuxPacket(PesPacket pp) { if (fileType == TsFileType.TS || fileType == TsFileType.M2TS || fileType == TsFileType.BLU_RAY) MuxTsPacket(pp); else if (fileType == TsFileType.SUP_ELEMENTARY && pidMappings.ContainsKey(pp.PID)) { byte[] data = pp.GetData(); PesHeader ph = pp.GetHeader(); if (ph.HasPts) { Int64 Pts = ph.Pts; Int64 Dts = 0; if (ph.HasDts) Dts = ph.Dts; supHeader[2] = (byte)((Pts >> 24) & 0xff); supHeader[3] = (byte)((Pts >> 16) & 0xff); supHeader[4] = (byte)((Pts >> 8) & 0xff); supHeader[5] = (byte)(Pts & 0xff); supHeader[6] = (byte)((Dts >> 24) & 0xff); supHeader[7] = (byte)((Dts >> 16) & 0xff); supHeader[8] = (byte)((Dts >> 8) & 0xff); supHeader[9] = (byte)(Dts & 0xff); tsiow.Write(supHeader, 0, supHeader.Length); } tsiow.Write(data, ph.HeaderLength + 9, data.Length - (ph.HeaderLength + 9)); } else if (fileType == TsFileType.PES_ELEMENTARY && pidMappings.ContainsKey(pp.PID)) { byte[] data = pp.GetData(); tsiow.Write(data, 0, data.Length); } else if (fileType == TsFileType.ELEMENTARY && pidMappings.ContainsKey(pp.PID)) { byte[] data = pp.GetData(); PesHeader ph = pp.GetHeader(); tsiow.Write(data, ph.HeaderLength + 9, data.Length - (ph.HeaderLength + 9)); } }
// If PesPacket contains valid stream data, store it // in the respective output stream. public override void MuxPacket(PesPacket pp) { foreach (DeMuxStream S in _Streams) { if (pp.PID == S.PID) { byte[] data = pp.GetData(); S.FileStream.Write(data, 0, data.Length); } } }
public override void MuxPacket(PesPacket pp) { // TODO: Fix, just QnD ... bool bKeep = false; foreach (StreamInfo si in _StreamsToKeep) { if (si.ElementaryPID == pp.PID) bKeep = true; } if (bKeep) { byte[] data = pp.GetData(); _FileStream.Write(data, 0, data.Length); } }
private void MuxTsPacket(PesPacket pp) { if (pidMappings.ContainsKey(pp.PID)) { pp = CheckAndFixDiscontinuities(pp); ElementaryStreamTypes type = GetStreamType(pidMappings[pp.PID]); switch (type) { case ElementaryStreamTypes.AUDIO_STREAM_AC3: case ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS: if (MlpToAc3 == false || pp.Priority) MuxAc3ToTs(pp, type); break; case ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD: MuxMlpToTs(pp, type); break; case ElementaryStreamTypes.AUDIO_STREAM_DTS: case ElementaryStreamTypes.AUDIO_STREAM_DTS_HD: case ElementaryStreamTypes.AUDIO_STREAM_DTS_HD_MASTER_AUDIO: if (MlpToAc3 = false || pp.Priority) MuxDtsToTs(pp, type); break; case ElementaryStreamTypes.AUDIO_STREAM_LPCM: case ElementaryStreamTypes.AUDIO_STREAM_MPEG1: case ElementaryStreamTypes.AUDIO_STREAM_MPEG2: MuxPesPacketToTs(pp, true); break; default: MuxPesPacketToTs(pp, pp.Priority); break; } } }
public BlueMux(string fileName, TsFileType fileType, List<StreamInfo> StreamsToKeep, bool fAsync, bool fProcessAudio, bool fMlpToAc3) { fsw = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None, Constants.DISK_BUFFER, fAsync); this.tsiow = new TsIo(null, fsw, Constants.DISK_BUFFER); this.fileType = fileType; this.StreamsToKeep = StreamsToKeep; this.buffer = new List<TsPacket>(); this.currentPcr = -1; this.lastPcr = -1; this.lastDelta = -1; this.pcrOffset = -1; this.lastPts = -1; this.currentPts = -1; this.ptsDelta = -1; this.ptsOffset = 0; this.ptsCount = -1; this.pcrPacket = null; this.header = new byte[4]; this.supHeader = new byte[10]; this.supHeader[0] = (byte)'P'; this.supHeader[1] = (byte)'G'; this.VideoType = 0; this.lastPacket = null; this.sitCount = 0; this.packetCount = 0; this.epData = new List<EpElement>(); this.pmtStreams = null; this.lastPtsList = new Dictionary<ushort, long>(); this.soundFrames = new Dictionary<ushort, List<byte>>(); this.processAudio = fProcessAudio; this.MlpToAc3 = fMlpToAc3; CreatePsi(); }
public override PesPacket[] GetNextPesPackets() { // there was a big optimization opportunity here: // this method added to partial packets one byte at a time // the calls to PesPacket.AddData used about 40% of total CPU byte[] inData = new byte[1]; byte[] inData2 = new byte[128]; int bytesRead = 0; int bytesToRead = 0; int bytesToGo = 0; UInt32 marker = 0xffffffff; PesPacket pp = null; PesPacket partial = null; int i = 0; while (tsior.Read(inData, 0, inData.Length) == inData.Length) { marker = marker << 8; marker &= 0xffffff00; marker += inData[0]; if ((marker & 0xffffff00) == 0x00000100) { if ((marker & 0xff) == Constants.PACK_ID) { // pack start code UInt64 header = 0; for (i = 4; i < 10; i++) { if (tsior.Read(inData, 0, inData.Length) != inData.Length) goto done; header <<= 8; header |= inData[0]; } for (i = 10; i < 14; i++) // skip mux rate etc. { if (tsior.Read(inData, 0, inData.Length) != inData.Length) goto done; } Int64 pcr = (Int64)((header & 0x380000000000) >> 13); pcr |= (Int64)((header & 0x3fff8000000) >> 12); pcr |= (Int64)((header & 0x3fff800) >> 11); pcr *= 300; pcr |= (Int64)((header & 0x3fe) >> 1); Int64 delta = pcr - lastPcr; if (delta > Constants.MPEG2TS_CLOCK_RATE / 9) { if (pcrDelegate != null) pcrDelegate(pcr); lastPcr = pcr; } } else if (((marker & 0xff) == Constants.SYS_ID) || ((marker & 0xff) == Constants.MAP_ID) || ((marker & 0xff) == Constants.PAD_ID) || ((marker & 0xff) == Constants.DIR_ID)) { ushort Length = 0; for (i = 4; i < 6; i++) { if (tsior.Read(inData, 0, inData.Length) != inData.Length) goto done; Length <<= 8; Length |= inData[0]; } Length += 6; for (i = 6; i < Length; i++) { if (tsior.Read(inData, 0, inData.Length) != inData.Length) goto done; } } else { byte end = inData[0]; inData[0] = 0; partial = new PesPacket(inData, 0, 1, 0); partial.AddData(inData, 0, 1); inData[0] = 1; partial.AddData(inData, 0, 1); inData[0] = end; partial.AddData(inData, 0, 1); ushort Length = 0; for (i = 4; i < 6; i++) { if (tsior.Read(inData, 0, inData.Length) != inData.Length) goto done; partial.AddData(inData, 0, 1); Length <<= 8; Length |= inData[0]; } Length += 6; // we don't need this byte-by-byte loop here, as we have just gotten the length: /* for (i = 6; i < Length; i++) { if (tsior.Read(inData, 0, inData.Length) != inData.Length) goto done; partial.AddData(inData, 0, 1); } */ bytesToGo = Length - 6; while (bytesToGo > 0) { bytesToRead = (bytesToGo > inData2.Length) ? inData2.Length : bytesToGo; if ((bytesRead = tsior.Read(inData2, 0, bytesToRead)) != bytesToRead) goto done; partial.AddData(inData2, 0, bytesRead); bytesToGo -= bytesRead; } pp = partial; PesHeader ph = partial.GetHeader(); if (partial.BaseId == Constants.PES_PRIVATE1) { if ((partial.ExtendedId & 0xf0) == Constants.PES_PRIVATE_AC3_PLUS || (partial.ExtendedId & 0xf8) == Constants.PES_PRIVATE_AC3) { if (soundFrames.ContainsKey(partial.ExtendedId) == false) soundFrames.Add(partial.ExtendedId, new List<byte>()); byte[] tempd = partial.GetPayload(); for (int j = 4; j < tempd.Length; j++) soundFrames[partial.ExtendedId].Add(tempd[j]); tempd = soundFrames[partial.ExtendedId].ToArray(); int len = 0; ushort mk2 = 0xffff; if (tempd.Length > 2 && tempd[0] == (byte)(Constants.AC3_SYNC >> 8) && tempd[1] == (byte)(Constants.AC3_SYNC & 0xff)) { pp = null; while (tempd.Length > 2 && tempd[0] == (byte)(Constants.AC3_SYNC >> 8) && tempd[1] == (byte)(Constants.AC3_SYNC & 0xff)) { AC3Info ac3 = new AC3Info(tempd, 0); if (ac3.Valid == false || ac3.FrameLength == 0 || tempd.Length < ac3.FrameLength) break; if (pp == null) pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId); pp.AddData(tempd, 0, ac3.FrameLength); soundFrames[partial.ExtendedId].RemoveRange(0, ac3.FrameLength); tempd = soundFrames[partial.ExtendedId].ToArray(); } if (pp != null) { pp.Complete = true; goto done; } } for (int j = 2; j < tempd.Length; j++) { mk2 <<= 8; mk2 |= tempd[j]; if (mk2 == Constants.AC3_SYNC) { len = j - 1; mk2 = 0xffff; break; } } if (len == 0) len = tempd.Length; soundFrames[partial.ExtendedId].RemoveRange(0, len); pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId); pp.AddData(tempd, 0, len); pp.Complete = true; } else if ((partial.ExtendedId & 0xf8) == Constants.PES_PRIVATE_AC3_TRUE_HD) { if (soundFrames.ContainsKey(partial.ExtendedId) == false) soundFrames.Add(partial.ExtendedId, new List<byte>()); byte[] tempd = partial.GetPayload(); for (int j = 5; j < tempd.Length; j++) soundFrames[partial.ExtendedId].Add(tempd[j]); tempd = soundFrames[partial.ExtendedId].ToArray(); int len = tempd.Length; /* UInt32 mk2 = 0xffffffff; for (int j = 5; j < tempd.Length; j++) { mk2 <<= 8; mk2 |= tempd[j]; if (mk2 == Constants.MLP_SYNC) { len = j - 3; mk2 = 0xffffffff; } } if (len == 0) { len = tempd.Length; } */ soundFrames[partial.ExtendedId].RemoveRange(0, len); pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId); pp.AddData(tempd, 0, len); pp.Complete = true; } else if ((partial.ExtendedId & 0xf8) == Constants.PES_PRIVATE_LPCM) { if (soundFrames.ContainsKey(partial.ExtendedId) == false) soundFrames.Add(partial.ExtendedId, new List<byte>()); byte[] tempd = partial.GetPayload(); for (int j = 7; j < tempd.Length; j++) soundFrames[partial.ExtendedId].Add(tempd[j]); tempd = soundFrames[partial.ExtendedId].ToArray(); int len = tempd.Length; /* UInt32 mk2 = 0xffffffff; for (int j = 5; j < tempd.Length; j++) { mk2 <<= 8; mk2 |= tempd[j]; if (mk2 == Constants.MLP_SYNC) { len = j - 3; mk2 = 0xffffffff; } } if (len == 0) { len = tempd.Length; } */ soundFrames[partial.ExtendedId].RemoveRange(0, len); pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId); pp.AddData(tempd, 0, len); pp.Complete = true; } else if ((partial.ExtendedId & 0xf8) == Constants.PES_PRIVATE_DTS_HD) { if (soundFrames.ContainsKey(partial.ExtendedId) == false) soundFrames.Add(partial.ExtendedId, new List<byte>()); byte[] tempd = partial.GetPayload(); for (int j = 4; j < tempd.Length; j++) soundFrames[partial.ExtendedId].Add(tempd[j]); tempd = soundFrames[partial.ExtendedId].ToArray(); int len = 0; UInt32 mk2 = 0xffffffff; for (int j = 4; j < tempd.Length; j++) { mk2 <<= 8; mk2 |= tempd[j]; if (mk2 == Constants.DTS_SYNC) { len = j - 3; mk2 = 0xffffffff; } } if (len == 0) { DtsInfo dts = new DtsInfo(tempd, 0); if (dts.Valid && (int)dts.FrameSize < tempd.Length && (tempd.Length - (int)dts.FrameSize < 4)) len = (int)dts.FrameSize; else len = tempd.Length; } soundFrames[partial.ExtendedId].RemoveRange(0, len); pp = new PesPacket(partial.GetData(), 0, ph.TotalHeaderLength, partial.ExtendedId); pp.AddData(tempd, 0, len); pp.Complete = true; } else pp.PID = pp.ExtendedId; } else if (pp.BaseId == Constants.PES_PADDING || pp.BaseId == Constants.PES_PRIVATE2) { marker = 0xffffffff; continue; } else if (((pp.BaseId & 0xe0) == Constants.PES_AUDIO_MPEG) || ((pp.BaseId & 0xf0) == Constants.PES_VIDEO)) pp.PID = pp.BaseId; else if (pp.BaseId == Constants.PES_VIDEO_VC1 && ph != null) pp.PID = ph.Extention2; if (ph != null && ph.HasPts) { if (ptsDelegate != null) ptsDelegate(ph.Pts, pp.PID); } goto done; } marker = 0xffffffff; } } done: if (null != pp) { PesPacket[] ppa = new PesPacket[1]; ppa[0] = pp; return ppa; } else return null; }
protected override void GetInitialValues() { GetTimestamps(); Seek(-1); PatPacket pp = null; PmtPacket pm = null; bool bluray = false; bool validPmt = false; ushort pmtPid = 0; int i = 0; Dictionary<ushort, StreamInfo> streams = new Dictionary<ushort, StreamInfo>(); while (true) { for (i = tsior.Read(tsPack, 0, 1 + stride); (i > 0) && (tsPack[stride] != Constants.SYNC_BYTE); i = tsior.Read(tsPack, stride, 1)) ; // ensure a good sync byte if (i == 0) break; // end of stream i = tsior.Read(tsPack, stride + 1, tsPack.Length - (stride + 1)); if (i < tsPack.Length - (stride + 1)) break; // end of stream ts.SetData(tsPack, stride); if (ts.PID == Constants.PAT_PID) { pp = new PatPacket(ts.GetData()); ProgramInfo[] pi = pp.Programs; if (null != pi && pi.Length == 2) { if ((pi[0].ProgramNumber == 0 && pi[0].ProgramPID == 0x001f && pi[1].ProgramNumber == 1 && pi[1].ProgramPID == 0x0100) || (pi[1].ProgramNumber == 0 && pi[1].ProgramPID == 0x001f && pi[0].ProgramNumber == 1 && pi[0].ProgramPID == 0x0100)) { bluray = true; } } else if (null != pi && pi[0] != null && pi[0].ProgramNumber == 1) pmtPid = pi[0].ProgramPID; } else if (bluray && ts.PID == 0x0100) { if (pm == null) pm = new PmtPacket(ts.GetData()); else if (pm.Complete == false) pm.AddData(ts.Payload, 0, ts.Payload.Length); if (pm.Complete) { sis = pm.ElementaryStreams; dt = pm.DtcpInfo; return; } } else if (ts.PID == pmtPid) { pm = new PmtPacket(ts.GetData()); sis = pm.ElementaryStreams; dt = pm.DtcpInfo; } else if (streams.ContainsKey(ts.PID) == false && ts.HasPesHeader) { byte[] payload = ts.Payload; PesHeader ph = new PesHeader(ts.Payload); PesPacket pes = new PesPacket(payload, 0, payload.Length, ts.PID); if (ph.StreamId == Constants.PES_PRIVATE1) { byte[] audio = pes.GetPayload(); AC3Info ac3 = new AC3Info(audio, 0); DtsInfo dts = new DtsInfo(audio, 0); MlpInfo mlp = new MlpInfo(audio, 0); if (ac3.Valid) { if (ac3.SyntaxType == Ac3SyntaxType.Standard || ac3.SyntaxType == Ac3SyntaxType.Alternative) { StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3, ts.PID); streams.Add(ts.PID, si); } else if (ac3.SyntaxType == Ac3SyntaxType.Enhanced) { StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS, ts.PID); streams.Add(ts.PID, si); } } else if (dts.Valid) { StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_DTS_HD, ts.PID); streams.Add(ts.PID, si); } else if (mlp.Valid) { StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD, ts.PID); streams.Add(ts.PID, si); } else if ((pes.ExtendedId & 0xf8) == Constants.PES_PRIVATE_LPCM) { StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_LPCM, ts.PID); streams.Add(ts.PID, si); } } else if ((ph.StreamId & 0xe0) == Constants.PES_AUDIO_MPEG) { StreamInfo si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_MPEG2, ts.PID); streams.Add(ts.PID, si); } else if ((ph.StreamId & 0xf0) == Constants.PES_VIDEO) { UInt32 format = pes.ExtendedType; if ((format & 0xffff) == 0x1) { } else if ((format & 0xffffff00) == 0x100) { } H264Info h264 = new H264Info(payload, 0); Mpeg2Info mpg2 = new Mpeg2Info(payload, 0); if (h264.Valid) { StreamInfo si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_H264, ts.PID); streams.Add(ts.PID, si); } else if (mpg2.Valid) { StreamInfo si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_MPEG2, ts.PID); streams.Add(ts.PID, si); } } else if (ph.StreamId == Constants.PES_VIDEO_VC1) { StreamInfo si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_VC1, ts.PID); streams.Add(ts.PID, si); } } if (sis != null) { validPmt = true; foreach (StreamInfo si in sis) { if (streams.ContainsKey(si.ElementaryPID) == false) { validPmt = false; break; } } if (validPmt) return; } if (fs.Position > (Constants.DISK_BUFFER << 1)) break; } sis = new StreamInfo[streams.Values.Count]; streams.Values.CopyTo(sis, 0); }
public override PesPacket[] GetNextPesPackets() { int i; while (true) { for (i = tsior.Read(tsPack, 0, 1 + stride); (i > 0) && (tsPack[stride] != Constants.SYNC_BYTE); i = tsior.Read(tsPack, stride, 1)) ; // ensure a good sync byte if (i == 0) { List<PesPacket> ppa = new List<PesPacket>(); foreach (ushort pd in PesPackets.Keys) { PesPacket pp = PesPackets[pd]; pp.Complete = true; ppa.Add(pp); } PesPackets.Clear(); if (ppa.Count == 0) return null; // end of stream else { return ppa.ToArray(); } } i = tsior.Read(tsPack, stride + 1, tsPack.Length - (stride + 1)); if (i < tsPack.Length - (stride + 1)) { List<PesPacket> ppa = new List<PesPacket>(); foreach (ushort pd in PesPackets.Keys) { PesPacket pp = PesPackets[pd]; pp.Complete = true; ppa.Add(pp); } PesPackets.Clear(); if (ppa.Count == 0) return null; // end of stream else return ppa.ToArray(); } ts.SetData(tsPack, stride); ushort pid = ts.PID; byte[] payload = ts.Payload; if (ts.HasPcr) { if (null != pcrDelegate && pcrPID == pid) pcrDelegate(ts.Pcr); } if (ts.HasPesHeader) { if (payload != null && payload.Length > 3 && payload[0] == 0x00 && payload[1] == 0x00 && payload[2] == 0x01) { PesPacket newpp = new PesPacket(payload, 0, payload.Length, pid); newpp.Priority = ts.Priority; PesHeader ph = newpp.GetHeader(); if (ph != null && ph.HasPts) { if (ptsDelegate != null) ptsDelegate(ph.Pts, pid); } if (PesPackets.ContainsKey(pid)) { PesPacket pp = PesPackets[ts.PID]; pp.Complete = true; PesPackets[ts.PID] = newpp; PesPacket[] ppa = new PesPacket[1]; ppa[0] = pp; return ppa; } else { if (newpp.Complete == true) { PesPacket[] ppa = new PesPacket[1]; ppa[0] = newpp; return ppa; } PesPackets[ts.PID] = newpp; } } else { throw new InvalidDataException("invalid stream"); } } else if (PesPackets.ContainsKey(pid)) { PesPacket pp = PesPackets[ts.PID]; if (payload != null) { pp.AddData(payload, 0, payload.Length); if (pp.Complete) { PesPackets.Remove(pid); PesPacket[] ppa = new PesPacket[1]; ppa[0] = pp; return ppa; } } } } }
private void MuxSingleAc3ToTs(byte[] payload, int offset, int len, Int64 pts, ElementaryStreamTypes type, ushort pid) { List<byte> pes = new List<byte>(); bool priority = false; pes.Add(0x00); pes.Add(0x00); pes.Add(0x01); if (this.fileType == TsFileType.BLU_RAY) pes.Add(0xfd); else pes.Add(0xbd); pes.Add(0x00); pes.Add(0x00); pes.Add(0x84); pes.Add(0x81); pes.Add(0x08); pes.Add(0x21); pes.Add(0x00); pes.Add(0x01); pes.Add(0x00); pes.Add(0x01); pes.Add(0x01); pes.Add(0x81); if ((type == ElementaryStreamTypes.AUDIO_STREAM_AC3) || (type == ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS)) { AC3Info info = new AC3Info(payload, offset); if (this.MlpToAc3 || (info.Valid && info.IndependentStream)) { pes.Add(0x71); priority = true; } else { pes.Add(0x72); priority = false; } } else if (type == ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD) { if (payload.Length - offset > 1 && payload[offset] == (byte)(Constants.AC3_SYNC >> 8) && payload[offset + 1] == (byte)(Constants.AC3_SYNC & 0xff)) { pes.Add(0x76); priority = true; } else { pes.Add(0x72); priority = false; } } PesHeader ph = new PesHeader(pes.ToArray()); ph.Pts = pts; PesPacket pp = new PesPacket(ph.Data, 0, ph.Data.Length, pid); pp.AddData(payload, offset, len); pp.Complete = true; MuxPesPacketToTs(pp, priority); }
// Called with every used / valid PesPacket from source stream. public abstract void MuxPacket(PesPacket pp);
private void MuxSingleDtsToTs(byte[] payload, int offset, int len, Int64 pts, ElementaryStreamTypes type, ushort pid) { List<byte> pes = new List<byte>(); bool priority = false; pes.Add(0x00); pes.Add(0x00); pes.Add(0x01); if (this.fileType == TsFileType.BLU_RAY) pes.Add(0xfd); else pes.Add(0xbd); pes.Add(0x00); pes.Add(0x00); pes.Add(0x84); pes.Add(0x81); pes.Add(0x08); pes.Add(0x21); pes.Add(0x00); pes.Add(0x01); pes.Add(0x00); pes.Add(0x01); pes.Add(0x01); pes.Add(0x81); DtsInfo info = new DtsInfo(payload, offset); if (this.MlpToAc3 || (info.Valid && info.FrameSize == len)) { pes.Add(0x71); priority = true; } else { pes.Add(0x72); priority = false; } PesHeader ph = new PesHeader(pes.ToArray()); ph.Pts = pts; PesPacket pp = new PesPacket(ph.Data, 0, ph.Data.Length, pid); pp.AddData(payload, offset, len); pp.Complete = true; MuxPesPacketToTs(pp, priority); }
private PesPacket BuildVc1Pes(Int64 timestamp, byte[] data, ushort pid) { List<byte> pes = new List<byte>(); pes.Add(0x00); pes.Add(0x00); pes.Add(0x01); pes.Add(Constants.PES_VIDEO_VC1); pes.Add(0x00); pes.Add(0x00); pes.Add(0x84); pes.Add(0x81); pes.Add(0x08); pes.Add(0x21); pes.Add(0x00); pes.Add(0x01); pes.Add(0x00); pes.Add(0x01); pes.Add(0x01); pes.Add(0x81); pes.Add(0x55); PesHeader ph = new PesHeader(pes.ToArray()); ph.Pts = timestamp; PesPacket pp = new PesPacket(ph.Data, 0, ph.Data.Length, pid); pp.AddData(data, 0, data.Length); pp.Complete = true; return pp; }