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); }
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); } } } }
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() { // 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; }
private void ParseStream(StreamInfo si, byte[] payload) { switch (si.StreamType) { case ElementaryStreamTypes.VIDEO_STREAM_VC1: if ((si.ElementaryDescriptors == null) || si.FrameRate == FrameRate.Reserved || si.VideoFormat == VideoFormat.Reserved || si.AspectRatio == AspectRatio.Reserved) { VC1SequenceInfo sq = new VC1SequenceInfo(payload, 0); if (sq.Valid) { if (sq.AspectRatio != AspectRatio.Reserved) si.AspectRatio = sq.AspectRatio; if (sq.FrameRate != FrameRate.Reserved) si.FrameRate = sq.FrameRate; if (sq.VideoFormat != VideoFormat.Reserved) si.VideoFormat = sq.VideoFormat; if (si.ElementaryDescriptors == null) si.ElementaryDescriptors = Constants.vc1_descriptor; } } break; case ElementaryStreamTypes.AUDIO_STREAM_AC3: if ((si.ElementaryDescriptors == null) || si.AudioPresentationType == AudioPresentationType.Reserved || si.SamplingFrequency == SamplingFrequency.Reserved) { AC3Info ac3 = new AC3Info(payload, 0); if (ac3.Valid) { if (ac3.AudioPresentationType != AudioPresentationType.Reserved) si.AudioPresentationType = ac3.AudioPresentationType; if (ac3.SamplingFrequency != SamplingFrequency.Reserved) si.SamplingFrequency = ac3.SamplingFrequency; if (si.ElementaryDescriptors == null) si.ElementaryDescriptors = ac3.ElementaryDescriptors; if (ac3.SyntaxType == Ac3SyntaxType.Enhanced) si.StreamType = ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS; } } break; case ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS: if (si.AudioPresentationType == AudioPresentationType.Reserved || si.SamplingFrequency == SamplingFrequency.Reserved) { AC3Info ac3 = new AC3Info(payload, 0); if (ac3.Valid) { if (ac3.AudioPresentationType != AudioPresentationType.Reserved) si.AudioPresentationType = ac3.AudioPresentationType; if (ac3.SamplingFrequency != SamplingFrequency.Reserved) si.SamplingFrequency = ac3.SamplingFrequency; if (si.ElementaryDescriptors == null) si.ElementaryDescriptors = ac3.ElementaryDescriptors; } } break; case ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD: if (si.AudioPresentationType == AudioPresentationType.Reserved || si.SamplingFrequency == SamplingFrequency.Reserved) { MlpInfo ac3 = new MlpInfo(payload, 0); if (ac3.Valid) { if (ac3.AudioPresentationType != AudioPresentationType.Reserved) si.AudioPresentationType = ac3.AudioPresentationType; if (ac3.SamplingFrequency != SamplingFrequency.Reserved) si.SamplingFrequency = ac3.SamplingFrequency; if (si.ElementaryDescriptors == null) si.ElementaryDescriptors = ac3.ElementaryDescriptors; } } break; case ElementaryStreamTypes.VIDEO_STREAM_H264: if ((si.ElementaryDescriptors == null) || si.FrameRate == FrameRate.Reserved || si.VideoFormat == VideoFormat.Reserved || si.AspectRatio == AspectRatio.Reserved) { H264Info h264 = new H264Info(payload, 0); if(h264.Valid) { if (h264.AspectRatio != AspectRatio.Reserved) si.AspectRatio = h264.AspectRatio; if (h264.FrameRate != FrameRate.Reserved) si.FrameRate = h264.FrameRate; if (h264.VideoFormat != VideoFormat.Reserved) si.VideoFormat = h264.VideoFormat; if (si.ElementaryDescriptors == null) si.ElementaryDescriptors = h264.ElementaryDescriptors; } } break; case ElementaryStreamTypes.AUDIO_STREAM_DTS: case ElementaryStreamTypes.AUDIO_STREAM_DTS_HD: case ElementaryStreamTypes.AUDIO_STREAM_DTS_HD_MASTER_AUDIO: if (si.AudioPresentationType == AudioPresentationType.Reserved || si.SamplingFrequency == SamplingFrequency.Reserved) { DtsInfo dts = new DtsInfo(payload, 0); if (dts.Valid) { if (dts.AudioPresentationType != AudioPresentationType.Reserved) si.AudioPresentationType = dts.AudioPresentationType; if (dts.SamplingFrequency != SamplingFrequency.Reserved) si.SamplingFrequency = dts.SamplingFrequency; } } break; case ElementaryStreamTypes.VIDEO_STREAM_MPEG2: if ((si.ElementaryDescriptors == null) || si.FrameRate == FrameRate.Reserved || si.VideoFormat == VideoFormat.Reserved || si.AspectRatio == AspectRatio.Reserved) { Mpeg2Info mpeg2 = new Mpeg2Info(payload, 0); if (mpeg2.Valid) { if (mpeg2.AspectRatio != AspectRatio.Reserved) si.AspectRatio = mpeg2.AspectRatio; if (mpeg2.FrameRate != FrameRate.Reserved) si.FrameRate = mpeg2.FrameRate; if (mpeg2.VideoFormat != VideoFormat.Reserved) si.VideoFormat = mpeg2.VideoFormat; if (si.ElementaryDescriptors == null) si.ElementaryDescriptors = mpeg2.ElementaryDescriptors; } } break; } }