diff --git a/src/JT1078.Hls.Test/TS_Package_Test.cs b/src/JT1078.Hls.Test/TS_Package_Test.cs index c559ca0..4ae2a2a 100644 --- a/src/JT1078.Hls.Test/TS_Package_Test.cs +++ b/src/JT1078.Hls.Test/TS_Package_Test.cs @@ -5,6 +5,7 @@ using JT1078.Protocol; using JT1078.Protocol.Extensions; using System; using System.Buffers.Binary; +using System.Collections; using System.Collections.Generic; using System.IO; using System.Security.Cryptography; @@ -162,12 +163,29 @@ namespace JT1078.Hls.Test fileStream?.Dispose(); } } + /// + /// + /// PTS[32..30] 3 bslbf + /// marker_bit 1 bslbf + /// PTS[29..15] 15 bslbf + /// marker_bit 1 bslbf + /// PTS[14..0] 15 bslbf + /// marker_bit 1 bslbf + /// '0001' 4 bslbf + /// DTS[32..30] 3 bslbf + /// marker_bit 1 bslbf + /// DTS[29..15] 15 bslbf + /// marker_bit 1 bslbf + /// DTS[14..0] 15 bslbf + /// marker_bit 1 bslbf + /// + /// [Fact] public void PTSTest() { //pts //31 00 09 08 97 - + //'0011' long ptsvalue = 132171; var str = Convert.ToString(ptsvalue, 2).PadLeft(40, '0'); str = str.Insert(str.Length, "1"); @@ -176,7 +194,9 @@ namespace JT1078.Hls.Test str = str.Insert(str.Length - 36, "0011"); str = str.Substring(str.Length - 40, 40); var pts = Convert.ToInt64(str, 2); + //210453989527 } + [Fact] public void DTSTest1() { diff --git a/src/JT1078.Hls/PES_Package.cs b/src/JT1078.Hls/PES_Package.cs index e3facf3..de0a5f4 100644 --- a/src/JT1078.Hls/PES_Package.cs +++ b/src/JT1078.Hls/PES_Package.cs @@ -59,23 +59,45 @@ namespace JT1078.Hls writer.WriteUInt16(PESPacketLength); writer.WriteByte(Flag1); writer.WriteByte((byte)PTS_DTS_Flag); - if(PTS_DTS_Flag== PTS_DTS_Flags.all) + if (PTS_DTS_Flag== PTS_DTS_Flags.all) { writer.WriteByte(10); - writer.WriteInt5(PTS); - writer.WriteInt5(DTS); + writer.WriteInt5(ToPTS()); + writer.WriteInt5(ToDTS()); } else if(PTS_DTS_Flag == PTS_DTS_Flags.pts) { writer.WriteByte(5); - writer.WriteInt5(PTS); + writer.WriteInt5(ToPTS()); } else if (PTS_DTS_Flag == PTS_DTS_Flags.dts) { writer.WriteByte(5); - writer.WriteInt5(DTS); + writer.WriteInt5(ToDTS()); } Payload.ToBuffer(ref writer); } + + public long ToPTS() + { + var str = Convert.ToString(PTS, 2).PadLeft(40, '0'); + str = str.Insert(str.Length, "1"); + str = str.Insert(str.Length - 16, "1"); + str = str.Insert(str.Length - 32, "1"); + str = str.Insert(str.Length - 36, "0011"); + str = str.Substring(str.Length - 40, 40); + return Convert.ToInt64(str, 2); + } + + public long ToDTS() + { + var str = Convert.ToString(DTS, 2).PadLeft(40, '0'); + str = str.Insert(str.Length, "1"); + str = str.Insert(str.Length - 16, "1"); + str = str.Insert(str.Length - 32, "1"); + str = str.Insert(str.Length - 36, "0001"); + str = str.Substring(str.Length - 40, 40); + return Convert.ToInt64(str, 2); + } } } diff --git a/src/JT1078.Hls/TSEncoder.cs b/src/JT1078.Hls/TSEncoder.cs index 170a2dd..9b41a16 100644 --- a/src/JT1078.Hls/TSEncoder.cs +++ b/src/JT1078.Hls/TSEncoder.cs @@ -11,6 +11,7 @@ using JT1078.Hls.Enums; using System.Collections.Concurrent; using System.Security.Cryptography; using JT1078.Hls.Descriptors; +using JT1078.Protocol.Extensions; [assembly: InternalsVisibleTo("JT1078.Hls.Test")] @@ -29,9 +30,9 @@ namespace JT1078.Hls private const string ServiceName = "Koike&TK"; public TSEncoder() { - VideoCounter = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + VideoCounter = new Dictionary(StringComparer.OrdinalIgnoreCase); } - private ConcurrentDictionary VideoCounter; + private Dictionary VideoCounter; //private ConcurrentDictionary AudioCounter = new ConcurrentDictionary(); public byte[] CreateSDT(JT1078Package jt1078Package, int minBufferSize = 188) { @@ -131,6 +132,12 @@ namespace JT1078.Hls TSArrayPool.Return(buffer); } } + + public static long LastIFrameInterval = 0; + public static long LastFrameInterval = 0; + public static ulong? PrevTimestamp; + public static ulong TimestampTotal = 0; + public byte[] CreatePES(JT1078Package jt1078Package, int minBufferSize = 188) { //将1078一帧的数据拆分成一小段一小段的PES包 @@ -149,22 +156,23 @@ namespace JT1078.Hls package.Header.PID = 256; package.Header.PackageType = PackageType.Data_Start; string key = jt1078Package.GetKey(); - //if (jt1078Package.Label3.DataType == JT1078DataType.视频P帧) - //{ + if (jt1078Package.Label3.DataType == JT1078DataType.视频P帧) + { - //} - byte counter = VideoCounter.AddOrUpdate(key, 0, (a, b) => + } + if(VideoCounter.TryGetValue(key,out byte counter)) { - if (b > 0xf) + if (counter > 0xf) { - return 0; + counter = 0; } - else - { - return b; - } - }); + } + else + { + VideoCounter.Add(key, counter); + } package.Header.ContinuityCounter = counter; + counter++; package.Header.PayloadUnitStartIndicator = 1; package.Header.Adaptation = new TS_AdaptationInfo(); package.Payload = new PES_Package(); @@ -181,9 +189,21 @@ namespace JT1078.Hls //1 + 6 totalLength += (1 + 6); package.Header.Adaptation.PCRIncluded = PCRInclude.包含; - package.Header.Adaptation.Timestamp = (long)jt1078Package.Timestamp; - package.Payload.DTS = jt1078Package.LastIFrameInterval; - package.Payload.PTS = jt1078Package.LastIFrameInterval; + if (!PrevTimestamp.HasValue) + { + PrevTimestamp = jt1078Package.Timestamp; + TimestampTotal = 0; + } + else + { + TimestampTotal += (jt1078Package.Timestamp - PrevTimestamp.Value); + PrevTimestamp = jt1078Package.Timestamp; + } + package.Header.Adaptation.Timestamp = (long)(jt1078Package.Timestamp / 1000); + //package.Header.Adaptation.Timestamp = (long)TimestampTotal; + LastIFrameInterval += jt1078Package.LastIFrameInterval; + package.Payload.DTS = LastIFrameInterval; + package.Payload.PTS = LastIFrameInterval; } else { @@ -192,8 +212,9 @@ namespace JT1078.Hls //1 totalLength += 1; package.Header.Adaptation.PCRIncluded = PCRInclude.不包含; - package.Payload.DTS = jt1078Package.LastFrameInterval; - package.Payload.PTS = jt1078Package.LastFrameInterval; + LastFrameInterval += jt1078Package.LastFrameInterval; + package.Payload.DTS = LastFrameInterval; + package.Payload.PTS = LastFrameInterval; } //Flag1 + PTS_DTS_Flag + DTS + PTS //1 + 1 + 5 + 5 = 12 @@ -210,7 +231,6 @@ namespace JT1078.Hls package.Payload.Payload = new ES_Package(); if (fullSize < 0) { - counter++; //这个很重要,需要控制 package.Header.AdaptationFieldControl = AdaptationFieldControl.同时带有自适应域和有效负载; //还差一点 @@ -221,7 +241,6 @@ namespace JT1078.Hls } else if(fullSize==0) { - counter++; //这个很重要,需要控制 package.Header.AdaptationFieldControl = AdaptationFieldControl.无自适应域_仅含有效负载; //刚刚好 @@ -247,29 +266,27 @@ namespace JT1078.Hls counter = 0; } int segmentFullSize = jt1078Package.Bodies.Length - index; - if(segmentFullSize >= FiexdSegmentPESLength) + if (segmentFullSize >= FiexdSegmentPESLength) { - CreateSegmentPES(ref messagePackReader, dataReader.Slice(index, FiexdSegmentPESLength).ToArray(), counter++); + CreateSegmentPES(ref messagePackReader, dataReader.Slice(index, FiexdSegmentPESLength).ToArray(), counter); index += FiexdSegmentPESLength; } else { - CreateSegmentPES(ref messagePackReader, dataReader.Slice(index, segmentFullSize).ToArray(), counter++); + var nalu = dataReader.Slice(index, segmentFullSize).ToArray(); + //当等于183字节的时候 + //12698D08E8DBDBCDF6C6FA19DD88490E908D687D1755BE87DF82754BE2D245270569310B3030A4904DF1883ED09A68CA1C79BC4B97642B5BC095A55E56868D05370D3BC8B7B60B4642A486B6852656C01FFADACEF4BD4320E8BE9C54D44177A433CC37493FA1D8ACD0164E92454D03B6EC0617B133AEF43B599BF85632AB9B5FF671F0DDAA07E8F279F5639BA88E3FFFFCE1D3351FAF43DF23BCEB7E3B2CAB3EABAED23B25097B7F51FF38E8D0EBAB589CEC42B0440EB8 + //if (jt1078Package.Label3.DataType == JT1078DataType.视频P帧) + //{ + // string hex = dataReader.Slice(index, segmentFullSize).ToArray().ToHexString(); + //} + CreateSegmentPES(ref messagePackReader, dataReader.Slice(index, segmentFullSize).ToArray(), counter); index += segmentFullSize; } + counter++; } } - VideoCounter.AddOrUpdate(key, counter, (a, b) => - { - if (b > 0xf) - { - return 0; - } - else - { - return b; - } - }); + VideoCounter[key]= counter; return messagePackReader.FlushAndGetArray(); } finally @@ -289,15 +306,25 @@ namespace JT1078.Hls //package.Header.AdaptationFieldControl= AdaptationFieldControl.同时带有自适应域和有效负载 //这个很重要,填充大小 //package.Header.Adaptation.FillSize - if (nalu.Length < FiexdSegmentPESLength) + //AdaptationLengthPosition + PCRIncluded + //1 + 1 + if (nalu.Length < (FiexdSegmentPESLength)) { + int size = FiexdSegmentPESLength - 1 - 1 - nalu.Length; package.Header.PackageType = PackageType.Data_End; - package.Header.Adaptation = new TS_AdaptationInfo(); - package.Header.Adaptation.PCRIncluded = PCRInclude.不包含; - //AdaptationLengthPosition + PCRIncluded - //1 + 1 - package.Header.Adaptation.FillSize = (byte)(FiexdSegmentPESLength - 1 - 1 - nalu.Length); - package.Header.AdaptationFieldControl = AdaptationFieldControl.同时带有自适应域和有效负载; + if (size < 0) + { + // nalu剩余183字节的时候 + // 头部4个字节 + 自适应域长度1字节(0)+183 =188 + package.Header.AdaptationFieldControl = AdaptationFieldControl.仅含自适应域_无有效负载; + } + else + { + package.Header.Adaptation = new TS_AdaptationInfo(); + package.Header.Adaptation.PCRIncluded = PCRInclude.不包含; + package.Header.Adaptation.FillSize = (byte)(size); + package.Header.AdaptationFieldControl = AdaptationFieldControl.同时带有自适应域和有效负载; + } } else {