diff --git a/src/JT1078.Hls.Test/TS_Package_Test.cs b/src/JT1078.Hls.Test/TS_Package_Test.cs index f0e66e6..55716de 100644 --- a/src/JT1078.Hls.Test/TS_Package_Test.cs +++ b/src/JT1078.Hls.Test/TS_Package_Test.cs @@ -24,7 +24,7 @@ namespace JT1078.Hls.Test //47 41 00 30 07 50 00 00 7B 0C 7E 00 00 00 01 E0 00 00 80 C0 0A 31 00 09 08 97 11 00 07 D8 61 00 00 00 01 09 F0 00 00 00 01 67 64 00 1F AC D9 40 88 1E 68 40 00 00 03 01 80 00 00 57 83 C6 0C 65 80 00 00 00 01 68 EB E3 CB 22 C0 00 00 01 06 05 FF FF AB DC 45 E9 BD E6 D9 48 B7 96 2C D8 20 D9 23 EE EF 78 32 36 34 20 2D 20 63 6F 72 65 20 31 35 38 20 72 32 39 38 34 20 33 37 35 39 66 63 62 20 2D 20 48 2E 32 36 34 2F 4D 50 45 47 2D 34 20 41 56 43 20 63 6F 64 65 63 20 2D 20 43 6F 70 79 6C 65 66 74 20 32 30 30 33 2D 32 30 31 39 20 2D 20 68 74 74 70 3A 2F 2F 77 77 77 2E //47 41 00 30 07 50 00 00 7B 0C 7E 00 00 00 01 E0 00 00 80 C0 0A 31 00 09 08 97 11 00 07 D8 61 00 00 00 01 09 F0 00 00 00 01 67 64 00 1F AC D9 40 88 1E 68 40 00 00 03 01 80 00 00 57 83 C6 0C 65 80 00 00 00 01 68 EB E3 CB 22 C0 00 00 01 06 05 FF FF AB DC 45 E9 BD E6 D9 48 B7 96 2C D8 20 D9 23 EE EF 78 32 36 34 20 2D 20 63 6F 72 65 20 31 35 38 20 72 32 39 38 34 20 33 37 35 39 66 63 62 20 2D 20 48 2E 32 36 34 2F 4D 50 45 47 2D 34 20 41 56 43 20 63 6F 64 65 63 20 2D 20 43 6F 70 79 6C 65 66 74 20 32 30 30 33 2D 32 30 31 39 20 2D 20 68 74 74 70 3A 2F 2F 77 77 77 2E - //47 41 00 30 07 50 00 90 32 10 7E 00 00 00 01 E0 00 00 80 C0 0A 00 00 02 04 4B 00 00 01EC300000000109FF000000016764001FACD940881E6840000003018000005783C60C65800000000168EBE3CB22C00000010605FFFFABDC45E9BDE6D948B7962CD820D923EEEF78323634202D20636F7265203135382072323938342033373539666362202D20482E3236342F4D5045472D342041564320636F646563202D20436F70796C65667420323030332D32303139202D20687474703A2F2F7777772E + //47 41 00 30 07 50 00 00 7B 0C 7E 00 00 00 01 E0 00 00 80 C0 0A 00 00 02 04 4B 00 00 01 EC 30 00 00 00 01 09 FF 000000016764001FACD940881E6840000003018000005783C60C65800000000168EBE3CB22C00000010605FFFFABDC45E9BDE6D948B7962CD820D923EEEF78323634202D20636F7265203135382072323938342033373539666362202D20482E3236342F4D5045472D342041564320636F646563202D20436F70796C65667420323030332D32303139202D20687474703A2F2F7777772E //47 //41 00 @@ -54,7 +54,7 @@ namespace JT1078.Hls.Test package.Header.PackageType = PackageType.Data_Start; package.Header.PayloadUnitStartIndicator = 1; package.Header.Adaptation = new TS_AdaptationInfo(); - package.Header.Adaptation.PCR = 18900000; + package.Header.Adaptation.Timestamp = 18900000; package.Header.Adaptation.PCRIncluded = PCRInclude.包含; package.Payload = new PES_Package(); package.Payload.PTS = 132171; @@ -133,14 +133,21 @@ namespace JT1078.Hls.Test { if (isNeedFirstHeadler) { - fileStream.Write(tSEncoder.CreatePAT(fullpackage)); - fileStream.Write(tSEncoder.CreatePMT(fullpackage)); - fileStream.Write(tSEncoder.CreatePES(fullpackage,1888)); + var sdt = tSEncoder.CreateSDT(fullpackage); + string sdtHEX = sdt.ToHexString(); + fileStream.Write(sdt); + var pat = tSEncoder.CreatePAT(fullpackage); + string patHEX = pat.ToHexString(); + fileStream.Write(pat); + var pmt = tSEncoder.CreatePMT(fullpackage); + fileStream.Write(pmt); + var pes = tSEncoder.CreatePES(fullpackage, 18888); + fileStream.Write(pes); isNeedFirstHeadler = false; } else { - fileStream.Write(tSEncoder.CreatePES(fullpackage, 1888)); + fileStream.Write(tSEncoder.CreatePES(fullpackage, 18888)); } } } diff --git a/src/JT1078.Hls/MessagePack/TSMessagePackWriter.cs b/src/JT1078.Hls/MessagePack/TSMessagePackWriter.cs index 4b24d6f..08791c9 100644 --- a/src/JT1078.Hls/MessagePack/TSMessagePackWriter.cs +++ b/src/JT1078.Hls/MessagePack/TSMessagePackWriter.cs @@ -65,15 +65,6 @@ namespace JT1078.Hls.MessagePack writer.Free[4] = (byte)(value); writer.Advance(5); } - public void WritePCR(long value) - { - writer.Free[0] = (byte)(value >> 25); - writer.Free[1] = (byte)((value >> 17) & 0xff); - writer.Free[2] = (byte)((value >> 9) & 0xff); - writer.Free[3] = (byte)((value >> 1) & 0xff); - writer.Free[4] = (byte)(((value & 0x1) << 7) | 0x7e); - writer.Advance(5); - } public void WriteInt6(long value) { writer.Free[0] = (byte)(value >> 40); diff --git a/src/JT1078.Hls/TSConstants.cs b/src/JT1078.Hls/TSConstants.cs index 78cd0a3..abf2f6d 100644 --- a/src/JT1078.Hls/TSConstants.cs +++ b/src/JT1078.Hls/TSConstants.cs @@ -16,6 +16,10 @@ namespace JT1078.Hls /// 固定包长度 /// public const int FiexdPackageLength = 188; + /// + /// 固定ES包头的长度 + /// + public const int FiexdESPackageHeaderLength = 6; } } diff --git a/src/JT1078.Hls/TSEncoder.cs b/src/JT1078.Hls/TSEncoder.cs index 7a9ecc4..170a2dd 100644 --- a/src/JT1078.Hls/TSEncoder.cs +++ b/src/JT1078.Hls/TSEncoder.cs @@ -26,8 +26,12 @@ namespace JT1078.Hls private const int FiexdSegmentPESLength = 184; private const int FiexdTSLength = 188; private const string ServiceProvider = "JTT1078"; - private const string ServiceName = "Koike&TK"; - private ConcurrentDictionary VideoCounter = new ConcurrentDictionary(); + private const string ServiceName = "Koike&TK"; + public TSEncoder() + { + VideoCounter = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + } + private ConcurrentDictionary VideoCounter; //private ConcurrentDictionary AudioCounter = new ConcurrentDictionary(); public byte[] CreateSDT(JT1078Package jt1078Package, int minBufferSize = 188) { @@ -143,38 +147,41 @@ namespace JT1078.Hls //ts header 4 totalLength += 4; package.Header.PID = 256; + package.Header.PackageType = PackageType.Data_Start; string key = jt1078Package.GetKey(); - if (VideoCounter.TryGetValue(key, out byte counter)) + //if (jt1078Package.Label3.DataType == JT1078DataType.视频P帧) + //{ + + //} + byte counter = VideoCounter.AddOrUpdate(key, 0, (a, b) => { - if (counter > 0xf) + if (b > 0xf) { - counter = 0; + return 0; } - package.Header.ContinuityCounter = counter++; - VideoCounter.TryUpdate(key, counter, counter); - } - else - { - package.Header.ContinuityCounter = counter++; - VideoCounter.TryAdd(key, counter); - } + else + { + return b; + } + }); + package.Header.ContinuityCounter = counter; package.Header.PayloadUnitStartIndicator = 1; package.Header.Adaptation = new TS_AdaptationInfo(); package.Payload = new PES_Package(); package.Payload.StreamId = 0xe0; package.Payload.PESPacketLength = 0; - //PESStartCode + StreamId + PESPacketLength - //3 + 1 + 2 - totalLength += (3+1+2); + //PESStartCode + StreamId+ Flag1 + PTS_DTS_Flag + PESPacketLength + //3 + 1 + 1 + 1 + 2 + totalLength += (3+1+1+1+2); package.Payload.PTS_DTS_Flag = PTS_DTS_Flags.all; if (jt1078Package.Label3.DataType== JT1078DataType.视频I帧) { //ts header adaptation - //PCRIncluded + PCR - //1 + 5 - totalLength += (1 + 5); + //PCRIncluded + Timestamp + //1 + 6 + totalLength += (1 + 6); package.Header.Adaptation.PCRIncluded = PCRInclude.包含; - package.Header.Adaptation.PCR = (long)jt1078Package.Timestamp; + package.Header.Adaptation.Timestamp = (long)jt1078Package.Timestamp; package.Payload.DTS = jt1078Package.LastIFrameInterval; package.Payload.PTS = jt1078Package.LastIFrameInterval; } @@ -189,8 +196,9 @@ namespace JT1078.Hls package.Payload.PTS = jt1078Package.LastFrameInterval; } //Flag1 + PTS_DTS_Flag + DTS + PTS - //1 + 1 + 5 + 5 + //1 + 1 + 5 + 5 = 12 totalLength += 12; + totalLength += TSConstants.FiexdESPackageHeaderLength; //根据计算剩余的长度进行是否需要填充第一包 var remainingLength = FiexdTSLength - totalLength; int index = 0; @@ -202,6 +210,7 @@ namespace JT1078.Hls package.Payload.Payload = new ES_Package(); if (fullSize < 0) { + counter++; //这个很重要,需要控制 package.Header.AdaptationFieldControl = AdaptationFieldControl.同时带有自适应域和有效负载; //还差一点 @@ -212,6 +221,7 @@ namespace JT1078.Hls } else if(fullSize==0) { + counter++; //这个很重要,需要控制 package.Header.AdaptationFieldControl = AdaptationFieldControl.无自适应域_仅含有效负载; //刚刚好 @@ -230,7 +240,7 @@ namespace JT1078.Hls package.Payload.Payload.NALUs.Add(dataReader.Slice(index, remainingLength).ToArray()); index += remainingLength; package.ToBuffer(ref messagePackReader); - while(index!= jt1078Package.Bodies.Length) + while (index!= jt1078Package.Bodies.Length) { if (counter > 0xf) { @@ -248,8 +258,18 @@ namespace JT1078.Hls index += segmentFullSize; } } - VideoCounter.TryUpdate(key, counter, counter); } + VideoCounter.AddOrUpdate(key, counter, (a, b) => + { + if (b > 0xf) + { + return 0; + } + else + { + return b; + } + }); return messagePackReader.FlushAndGetArray(); } finally @@ -274,7 +294,9 @@ namespace JT1078.Hls package.Header.PackageType = PackageType.Data_End; package.Header.Adaptation = new TS_AdaptationInfo(); package.Header.Adaptation.PCRIncluded = PCRInclude.不包含; - package.Header.Adaptation.FillSize = (byte)(FiexdSegmentPESLength - nalu.Length); + //AdaptationLengthPosition + PCRIncluded + //1 + 1 + package.Header.Adaptation.FillSize = (byte)(FiexdSegmentPESLength - 1 - 1 - nalu.Length); package.Header.AdaptationFieldControl = AdaptationFieldControl.同时带有自适应域和有效负载; } else diff --git a/src/JT1078.Hls/TS_AdaptationInfo.cs b/src/JT1078.Hls/TS_AdaptationInfo.cs index 3f17f49..25416b5 100644 --- a/src/JT1078.Hls/TS_AdaptationInfo.cs +++ b/src/JT1078.Hls/TS_AdaptationInfo.cs @@ -16,11 +16,12 @@ namespace JT1078.Hls /// public PCRInclude PCRIncluded { get; set; } /// + /// JT1078时间戳 /// 第一包的数据、关键帧 /// Program Clock Reference,节目时钟参考,用于恢复出与编码端一致的系统时序时钟STC(System Time Clock) /// 5B /// - public long PCR { get; set; } + public long Timestamp { get; set; } /// /// 填充字节大小 /// @@ -28,16 +29,27 @@ namespace JT1078.Hls public void ToBuffer(ref TSMessagePackWriter writer) { writer.WriteByte((byte)PCRIncluded); - if (PCRIncluded== PCRInclude.包含) + if (PCRIncluded == PCRInclude.包含) { - writer.WritePCR(PCR); -#warning PCR 0???? - writer.WriteByte(0); + writer.WriteInt6(ToPCR()); } if (FillSize > 0) { writer.WriteArray(Enumerable.Range(0, FillSize).Select(s => (byte)0xFF).ToArray()); } } + + /// + /// if(PCR_flag == '1'){ + /// program_clock_reference_base 33 uimsbf + /// Reserved 6 bslbf + /// program_clock_reference_extension 9 uimsbf + /// } + /// + /// + private long ToPCR() + { + return (Timestamp / 300 << 15 | 0x7E00); + } } } diff --git a/src/JT1078.Hls/TS_Header.cs b/src/JT1078.Hls/TS_Header.cs index 4ea04c8..ca955b8 100644 --- a/src/JT1078.Hls/TS_Header.cs +++ b/src/JT1078.Hls/TS_Header.cs @@ -64,7 +64,8 @@ namespace JT1078.Hls writer.WriteByte(SyncByte); //TransportErrorIndicator PayloadUnitStartIndicator TransportPriority PID //0 1 0 0000 0000 0000 0 - writer.WriteUInt16((ushort)(0b_0100_0000_0000_0000 | PID)); + //writer.WriteUInt16((ushort)((0b_0100_0000_0000_0000 & (PayloadUnitStartIndicator<<14)) | PID)); + writer.WriteUInt16((ushort)((PayloadUnitStartIndicator<<14) | PID)); writer.WriteByte((byte)((byte)AdaptationFieldControl | ContinuityCounter)); if(PackageType== PackageType.PAT || PackageType == PackageType.PMT ||