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 ||