@@ -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 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 | //47 | ||||
//41 00 | //41 00 | ||||
@@ -54,7 +54,7 @@ namespace JT1078.Hls.Test | |||||
package.Header.PackageType = PackageType.Data_Start; | package.Header.PackageType = PackageType.Data_Start; | ||||
package.Header.PayloadUnitStartIndicator = 1; | package.Header.PayloadUnitStartIndicator = 1; | ||||
package.Header.Adaptation = new TS_AdaptationInfo(); | package.Header.Adaptation = new TS_AdaptationInfo(); | ||||
package.Header.Adaptation.PCR = 18900000; | |||||
package.Header.Adaptation.Timestamp = 18900000; | |||||
package.Header.Adaptation.PCRIncluded = PCRInclude.包含; | package.Header.Adaptation.PCRIncluded = PCRInclude.包含; | ||||
package.Payload = new PES_Package(); | package.Payload = new PES_Package(); | ||||
package.Payload.PTS = 132171; | package.Payload.PTS = 132171; | ||||
@@ -133,14 +133,21 @@ namespace JT1078.Hls.Test | |||||
{ | { | ||||
if (isNeedFirstHeadler) | 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; | isNeedFirstHeadler = false; | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
fileStream.Write(tSEncoder.CreatePES(fullpackage, 1888)); | |||||
fileStream.Write(tSEncoder.CreatePES(fullpackage, 18888)); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -65,15 +65,6 @@ namespace JT1078.Hls.MessagePack | |||||
writer.Free[4] = (byte)(value); | writer.Free[4] = (byte)(value); | ||||
writer.Advance(5); | 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) | public void WriteInt6(long value) | ||||
{ | { | ||||
writer.Free[0] = (byte)(value >> 40); | writer.Free[0] = (byte)(value >> 40); | ||||
@@ -16,6 +16,10 @@ namespace JT1078.Hls | |||||
/// 固定包长度 | /// 固定包长度 | ||||
/// </summary> | /// </summary> | ||||
public const int FiexdPackageLength = 188; | public const int FiexdPackageLength = 188; | ||||
/// <summary> | |||||
/// 固定ES包头的长度 | |||||
/// </summary> | |||||
public const int FiexdESPackageHeaderLength = 6; | |||||
} | } | ||||
} | } |
@@ -26,8 +26,12 @@ namespace JT1078.Hls | |||||
private const int FiexdSegmentPESLength = 184; | private const int FiexdSegmentPESLength = 184; | ||||
private const int FiexdTSLength = 188; | private const int FiexdTSLength = 188; | ||||
private const string ServiceProvider = "JTT1078"; | private const string ServiceProvider = "JTT1078"; | ||||
private const string ServiceName = "Koike&TK"; | |||||
private ConcurrentDictionary<string, byte> VideoCounter = new ConcurrentDictionary<string, byte>(); | |||||
private const string ServiceName = "Koike&TK"; | |||||
public TSEncoder() | |||||
{ | |||||
VideoCounter = new ConcurrentDictionary<string, byte>(StringComparer.OrdinalIgnoreCase); | |||||
} | |||||
private ConcurrentDictionary<string, byte> VideoCounter; | |||||
//private ConcurrentDictionary<string, byte> AudioCounter = new ConcurrentDictionary<string, byte>(); | //private ConcurrentDictionary<string, byte> AudioCounter = new ConcurrentDictionary<string, byte>(); | ||||
public byte[] CreateSDT(JT1078Package jt1078Package, int minBufferSize = 188) | public byte[] CreateSDT(JT1078Package jt1078Package, int minBufferSize = 188) | ||||
{ | { | ||||
@@ -143,38 +147,41 @@ namespace JT1078.Hls | |||||
//ts header 4 | //ts header 4 | ||||
totalLength += 4; | totalLength += 4; | ||||
package.Header.PID = 256; | package.Header.PID = 256; | ||||
package.Header.PackageType = PackageType.Data_Start; | |||||
string key = jt1078Package.GetKey(); | 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.PayloadUnitStartIndicator = 1; | ||||
package.Header.Adaptation = new TS_AdaptationInfo(); | package.Header.Adaptation = new TS_AdaptationInfo(); | ||||
package.Payload = new PES_Package(); | package.Payload = new PES_Package(); | ||||
package.Payload.StreamId = 0xe0; | package.Payload.StreamId = 0xe0; | ||||
package.Payload.PESPacketLength = 0; | 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; | package.Payload.PTS_DTS_Flag = PTS_DTS_Flags.all; | ||||
if (jt1078Package.Label3.DataType== JT1078DataType.视频I帧) | if (jt1078Package.Label3.DataType== JT1078DataType.视频I帧) | ||||
{ | { | ||||
//ts header adaptation | //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.PCRIncluded = PCRInclude.包含; | ||||
package.Header.Adaptation.PCR = (long)jt1078Package.Timestamp; | |||||
package.Header.Adaptation.Timestamp = (long)jt1078Package.Timestamp; | |||||
package.Payload.DTS = jt1078Package.LastIFrameInterval; | package.Payload.DTS = jt1078Package.LastIFrameInterval; | ||||
package.Payload.PTS = jt1078Package.LastIFrameInterval; | package.Payload.PTS = jt1078Package.LastIFrameInterval; | ||||
} | } | ||||
@@ -189,8 +196,9 @@ namespace JT1078.Hls | |||||
package.Payload.PTS = jt1078Package.LastFrameInterval; | package.Payload.PTS = jt1078Package.LastFrameInterval; | ||||
} | } | ||||
//Flag1 + PTS_DTS_Flag + DTS + PTS | //Flag1 + PTS_DTS_Flag + DTS + PTS | ||||
//1 + 1 + 5 + 5 | |||||
//1 + 1 + 5 + 5 = 12 | |||||
totalLength += 12; | totalLength += 12; | ||||
totalLength += TSConstants.FiexdESPackageHeaderLength; | |||||
//根据计算剩余的长度进行是否需要填充第一包 | //根据计算剩余的长度进行是否需要填充第一包 | ||||
var remainingLength = FiexdTSLength - totalLength; | var remainingLength = FiexdTSLength - totalLength; | ||||
int index = 0; | int index = 0; | ||||
@@ -202,6 +210,7 @@ namespace JT1078.Hls | |||||
package.Payload.Payload = new ES_Package(); | package.Payload.Payload = new ES_Package(); | ||||
if (fullSize < 0) | if (fullSize < 0) | ||||
{ | { | ||||
counter++; | |||||
//这个很重要,需要控制 | //这个很重要,需要控制 | ||||
package.Header.AdaptationFieldControl = AdaptationFieldControl.同时带有自适应域和有效负载; | package.Header.AdaptationFieldControl = AdaptationFieldControl.同时带有自适应域和有效负载; | ||||
//还差一点 | //还差一点 | ||||
@@ -212,6 +221,7 @@ namespace JT1078.Hls | |||||
} | } | ||||
else if(fullSize==0) | else if(fullSize==0) | ||||
{ | { | ||||
counter++; | |||||
//这个很重要,需要控制 | //这个很重要,需要控制 | ||||
package.Header.AdaptationFieldControl = AdaptationFieldControl.无自适应域_仅含有效负载; | package.Header.AdaptationFieldControl = AdaptationFieldControl.无自适应域_仅含有效负载; | ||||
//刚刚好 | //刚刚好 | ||||
@@ -230,7 +240,7 @@ namespace JT1078.Hls | |||||
package.Payload.Payload.NALUs.Add(dataReader.Slice(index, remainingLength).ToArray()); | package.Payload.Payload.NALUs.Add(dataReader.Slice(index, remainingLength).ToArray()); | ||||
index += remainingLength; | index += remainingLength; | ||||
package.ToBuffer(ref messagePackReader); | package.ToBuffer(ref messagePackReader); | ||||
while(index!= jt1078Package.Bodies.Length) | |||||
while (index!= jt1078Package.Bodies.Length) | |||||
{ | { | ||||
if (counter > 0xf) | if (counter > 0xf) | ||||
{ | { | ||||
@@ -248,8 +258,18 @@ namespace JT1078.Hls | |||||
index += segmentFullSize; | index += segmentFullSize; | ||||
} | } | ||||
} | } | ||||
VideoCounter.TryUpdate(key, counter, counter); | |||||
} | } | ||||
VideoCounter.AddOrUpdate(key, counter, (a, b) => | |||||
{ | |||||
if (b > 0xf) | |||||
{ | |||||
return 0; | |||||
} | |||||
else | |||||
{ | |||||
return b; | |||||
} | |||||
}); | |||||
return messagePackReader.FlushAndGetArray(); | return messagePackReader.FlushAndGetArray(); | ||||
} | } | ||||
finally | finally | ||||
@@ -274,7 +294,9 @@ namespace JT1078.Hls | |||||
package.Header.PackageType = PackageType.Data_End; | package.Header.PackageType = PackageType.Data_End; | ||||
package.Header.Adaptation = new TS_AdaptationInfo(); | package.Header.Adaptation = new TS_AdaptationInfo(); | ||||
package.Header.Adaptation.PCRIncluded = PCRInclude.不包含; | 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.同时带有自适应域和有效负载; | package.Header.AdaptationFieldControl = AdaptationFieldControl.同时带有自适应域和有效负载; | ||||
} | } | ||||
else | else | ||||
@@ -16,11 +16,12 @@ namespace JT1078.Hls | |||||
/// </summary> | /// </summary> | ||||
public PCRInclude PCRIncluded { get; set; } | public PCRInclude PCRIncluded { get; set; } | ||||
/// <summary> | /// <summary> | ||||
/// JT1078时间戳 | |||||
/// 第一包的数据、关键帧 | /// 第一包的数据、关键帧 | ||||
/// Program Clock Reference,节目时钟参考,用于恢复出与编码端一致的系统时序时钟STC(System Time Clock) | /// Program Clock Reference,节目时钟参考,用于恢复出与编码端一致的系统时序时钟STC(System Time Clock) | ||||
/// 5B | /// 5B | ||||
/// </summary> | /// </summary> | ||||
public long PCR { get; set; } | |||||
public long Timestamp { get; set; } | |||||
/// <summary> | /// <summary> | ||||
/// 填充字节大小 | /// 填充字节大小 | ||||
/// </summary> | /// </summary> | ||||
@@ -28,16 +29,27 @@ namespace JT1078.Hls | |||||
public void ToBuffer(ref TSMessagePackWriter writer) | public void ToBuffer(ref TSMessagePackWriter writer) | ||||
{ | { | ||||
writer.WriteByte((byte)PCRIncluded); | 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) | if (FillSize > 0) | ||||
{ | { | ||||
writer.WriteArray(Enumerable.Range(0, FillSize).Select(s => (byte)0xFF).ToArray()); | writer.WriteArray(Enumerable.Range(0, FillSize).Select(s => (byte)0xFF).ToArray()); | ||||
} | } | ||||
} | } | ||||
/// <summary> | |||||
/// if(PCR_flag == '1'){ | |||||
/// program_clock_reference_base 33 uimsbf | |||||
/// Reserved 6 bslbf | |||||
/// program_clock_reference_extension 9 uimsbf | |||||
/// } | |||||
/// </summary> | |||||
/// <returns></returns> | |||||
private long ToPCR() | |||||
{ | |||||
return (Timestamp / 300 << 15 | 0x7E00); | |||||
} | |||||
} | } | ||||
} | } |
@@ -64,7 +64,8 @@ namespace JT1078.Hls | |||||
writer.WriteByte(SyncByte); | writer.WriteByte(SyncByte); | ||||
//TransportErrorIndicator PayloadUnitStartIndicator TransportPriority PID | //TransportErrorIndicator PayloadUnitStartIndicator TransportPriority PID | ||||
//0 1 0 0000 0000 0000 0 | //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)); | writer.WriteByte((byte)((byte)AdaptationFieldControl | ContinuityCounter)); | ||||
if(PackageType== PackageType.PAT || | if(PackageType== PackageType.PAT || | ||||
PackageType == PackageType.PMT || | PackageType == PackageType.PMT || | ||||