diff --git a/src/JT1078.Hls/TS_SDT_Package.cs b/src/JT1078.Hls/TS_SDT_Package.cs
new file mode 100644
index 0000000..80cac8e
--- /dev/null
+++ b/src/JT1078.Hls/TS_SDT_Package.cs
@@ -0,0 +1,123 @@
+using JT1078.Hls.Enums;
+using JT1078.Hls.Interfaces;
+using JT1078.Hls.MessagePack;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace JT1078.Hls
+{
+ ///
+ /// 业务描述表
+ ///
+ public class TS_SDT_Package : ITSMessagePackFormatter
+ {
+ public TS_Header Header { get; set; }
+ ///
+ /// PAT表固定为0x00
+ /// 8bit
+ ///
+ public byte TableId { get; set; } = 0x42;
+ ///
+ /// 固定为二进制1
+ /// 1bit
+ ///
+ internal byte SectionSyntaxIndicator { get; set; }
+ ///
+ ///
+ /// 1bit
+ ///
+ internal byte ReservedFutureUse1 { get; set; }
+ ///
+ ///
+ /// 2bit
+ ///
+ internal byte Reserved1 { get; set; }
+ ///
+ /// 后面数据的长度
+ /// 12bit
+ ///
+ public ushort SectionLength { get; set; }
+ ///
+ /// 传输流ID
+ /// 16bit
+ ///
+ internal ushort TransportStreamId { get; set; } = 0x0001;
+ ///
+ ///
+ /// 2bit
+ ///
+ internal byte Reserved2 { get; set; }
+ ///
+ /// 版本号,
+ /// 5bit
+ ///
+ public byte VersionNumber { get; set; }
+ ///
+ ///
+ /// 1bit
+ ///
+ public byte CurrentNextIndicator { get; set; }
+ ///
+ ///
+ /// bit8
+ ///
+ internal byte SectionNumber { get; set; }
+ ///
+ ///
+ /// bit8
+ ///
+ internal byte LastSectionNumber { get; set; }
+ ///
+ ///
+ /// bit8
+ ///
+ internal ushort OriginalNetworkId { get; set; }
+ ///
+ ///
+ /// 1Byte
+ ///
+ internal byte ReservedFutureUse2 { get; set; }
+ public List Services { get; set; }
+
+ ///
+ /// 前面数据的CRC32校验码
+ ///
+ public uint CRC32 { get; set; }
+
+ public void ToBuffer(ref TSMessagePackWriter writer)
+ {
+ Header.PackageType = PackageType.PAT;
+ Header.ToBuffer(ref writer);
+ writer.WriteByte(TableId);
+ //SectionSyntaxIndicator Zero Reserved1 SectionLength
+ //1 0 11 0000 0000 0000
+ //(ushort)(0b_1011_0000_0000_0000 | SectionLength)
+ writer.Skip(2, out int SectionLengthPosition);
+ writer.WriteUInt16(TransportStreamId);
+ //Reserved2 VersionNumber CurrentNextIndicator
+ //11 00000 1
+ var a = 0xC0 & (Reserved2 << 6);
+ var b = 0x3E & (VersionNumber << 3);
+ var c = (byte)(a | b | CurrentNextIndicator);
+ writer.WriteByte(c);
+ writer.WriteByte(SectionNumber);
+ writer.WriteByte(LastSectionNumber);
+ //if (Programs != null)
+ //{
+ // foreach (var program in Programs)
+ // {
+ // program.ToBuffer(ref writer);
+ // }
+ //}
+ const int crcLength= 4;
+ writer.WriteUInt16Return((ushort)(0b_1011_0000_0000_0000 | (ushort)(writer.GetCurrentPosition() - SectionLengthPosition - 2)+ crcLength), SectionLengthPosition);
+ //打包ts流时PAT和PMT表是没有adaptation field的,不够的长度直接补0xff即可。
+ //ts header(4B) + adaptation field length(1)
+ writer.WriteCRC32(5);
+ var size = TSConstants.FiexdPackageLength - writer.GetCurrentPosition();
+ writer.WriteArray(Enumerable.Range(0, size).Select(s => (byte)0xFF).ToArray());
+ }
+ }
+}
diff --git a/src/JT1078.Hls/TS_SDT_Service_.cs b/src/JT1078.Hls/TS_SDT_Service_.cs
new file mode 100644
index 0000000..e347080
--- /dev/null
+++ b/src/JT1078.Hls/TS_SDT_Service_.cs
@@ -0,0 +1,123 @@
+using JT1078.Hls.Enums;
+using JT1078.Hls.Interfaces;
+using JT1078.Hls.MessagePack;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace JT1078.Hls
+{
+ ///
+ /// 业务描述服务
+ ///
+ public class TS_SDT_Service : ITSMessagePackFormatter
+ {
+ public TS_Header Header { get; set; }
+ ///
+ /// PAT表固定为0x00
+ /// 8bit
+ ///
+ public byte TableId { get; set; } = 0x42;
+ ///
+ /// 固定为二进制1
+ /// 1bit
+ ///
+ internal byte SectionSyntaxIndicator { get; set; }
+ ///
+ ///
+ /// 1bit
+ ///
+ internal byte ReservedFutureUse1 { get; set; }
+ ///
+ ///
+ /// 2bit
+ ///
+ internal byte Reserved1 { get; set; }
+ ///
+ /// 后面数据的长度
+ /// 12bit
+ ///
+ public ushort SectionLength { get; set; }
+ ///
+ /// 传输流ID
+ /// 16bit
+ ///
+ internal ushort TransportStreamId { get; set; } = 0x0001;
+ ///
+ ///
+ /// 2bit
+ ///
+ internal byte Reserved2 { get; set; }
+ ///
+ /// 版本号,
+ /// 5bit
+ ///
+ public byte VersionNumber { get; set; }
+ ///
+ ///
+ /// 1bit
+ ///
+ public byte CurrentNextIndicator { get; set; }
+ ///
+ ///
+ /// bit8
+ ///
+ internal byte SectionNumber { get; set; }
+ ///
+ ///
+ /// bit8
+ ///
+ internal byte LastSectionNumber { get; set; }
+ ///
+ ///
+ /// bit8
+ ///
+ internal ushort OriginalNetworkId { get; set; }
+ ///
+ ///
+ /// 1Byte
+ ///
+ internal byte ReservedFutureUse2 { get; set; }
+ public List Services { get; set; }
+
+ ///
+ /// 前面数据的CRC32校验码
+ ///
+ public uint CRC32 { get; set; }
+
+ public void ToBuffer(ref TSMessagePackWriter writer)
+ {
+ Header.PackageType = PackageType.PAT;
+ Header.ToBuffer(ref writer);
+ writer.WriteByte(TableId);
+ //SectionSyntaxIndicator Zero Reserved1 SectionLength
+ //1 0 11 0000 0000 0000
+ //(ushort)(0b_1011_0000_0000_0000 | SectionLength)
+ writer.Skip(2, out int SectionLengthPosition);
+ writer.WriteUInt16(TransportStreamId);
+ //Reserved2 VersionNumber CurrentNextIndicator
+ //11 00000 1
+ var a = 0xC0 & (Reserved2 << 6);
+ var b = 0x3E & (VersionNumber << 3);
+ var c = (byte)(a | b | CurrentNextIndicator);
+ writer.WriteByte(c);
+ writer.WriteByte(SectionNumber);
+ writer.WriteByte(LastSectionNumber);
+ //if (Programs != null)
+ //{
+ // foreach (var program in Programs)
+ // {
+ // program.ToBuffer(ref writer);
+ // }
+ //}
+ const int crcLength= 4;
+ writer.WriteUInt16Return((ushort)(0b_1011_0000_0000_0000 | (ushort)(writer.GetCurrentPosition() - SectionLengthPosition - 2)+ crcLength), SectionLengthPosition);
+ //打包ts流时PAT和PMT表是没有adaptation field的,不够的长度直接补0xff即可。
+ //ts header(4B) + adaptation field length(1)
+ writer.WriteCRC32(5);
+ var size = TSConstants.FiexdPackageLength - writer.GetCurrentPosition();
+ writer.WriteArray(Enumerable.Range(0, size).Select(s => (byte)0xFF).ToArray());
+ }
+ }
+}
diff --git a/src/JT1078.Hls/TS_SDT_Service_Descriptor.cs b/src/JT1078.Hls/TS_SDT_Service_Descriptor.cs
new file mode 100644
index 0000000..19e0406
--- /dev/null
+++ b/src/JT1078.Hls/TS_SDT_Service_Descriptor.cs
@@ -0,0 +1,123 @@
+using JT1078.Hls.Enums;
+using JT1078.Hls.Interfaces;
+using JT1078.Hls.MessagePack;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace JT1078.Hls
+{
+ ///
+ /// 业务描述服务描述
+ ///
+ public class TS_SDT_Service_Descriptor : ITSMessagePackFormatter
+ {
+ public TS_Header Header { get; set; }
+ ///
+ /// PAT表固定为0x00
+ /// 8bit
+ ///
+ public byte TableId { get; set; } = 0x42;
+ ///
+ /// 固定为二进制1
+ /// 1bit
+ ///
+ internal byte SectionSyntaxIndicator { get; set; }
+ ///
+ ///
+ /// 1bit
+ ///
+ internal byte ReservedFutureUse1 { get; set; }
+ ///
+ ///
+ /// 2bit
+ ///
+ internal byte Reserved1 { get; set; }
+ ///
+ /// 后面数据的长度
+ /// 12bit
+ ///
+ public ushort SectionLength { get; set; }
+ ///
+ /// 传输流ID
+ /// 16bit
+ ///
+ internal ushort TransportStreamId { get; set; } = 0x0001;
+ ///
+ ///
+ /// 2bit
+ ///
+ internal byte Reserved2 { get; set; }
+ ///
+ /// 版本号,
+ /// 5bit
+ ///
+ public byte VersionNumber { get; set; }
+ ///
+ ///
+ /// 1bit
+ ///
+ public byte CurrentNextIndicator { get; set; }
+ ///
+ ///
+ /// bit8
+ ///
+ internal byte SectionNumber { get; set; }
+ ///
+ ///
+ /// bit8
+ ///
+ internal byte LastSectionNumber { get; set; }
+ ///
+ ///
+ /// bit8
+ ///
+ internal ushort OriginalNetworkId { get; set; }
+ ///
+ ///
+ /// 1Byte
+ ///
+ internal byte ReservedFutureUse2 { get; set; }
+ public List Services { get; set; }
+
+ ///
+ /// 前面数据的CRC32校验码
+ ///
+ public uint CRC32 { get; set; }
+
+ public void ToBuffer(ref TSMessagePackWriter writer)
+ {
+ Header.PackageType = PackageType.PAT;
+ Header.ToBuffer(ref writer);
+ writer.WriteByte(TableId);
+ //SectionSyntaxIndicator Zero Reserved1 SectionLength
+ //1 0 11 0000 0000 0000
+ //(ushort)(0b_1011_0000_0000_0000 | SectionLength)
+ writer.Skip(2, out int SectionLengthPosition);
+ writer.WriteUInt16(TransportStreamId);
+ //Reserved2 VersionNumber CurrentNextIndicator
+ //11 00000 1
+ var a = 0xC0 & (Reserved2 << 6);
+ var b = 0x3E & (VersionNumber << 3);
+ var c = (byte)(a | b | CurrentNextIndicator);
+ writer.WriteByte(c);
+ writer.WriteByte(SectionNumber);
+ writer.WriteByte(LastSectionNumber);
+ //if (Programs != null)
+ //{
+ // foreach (var program in Programs)
+ // {
+ // program.ToBuffer(ref writer);
+ // }
+ //}
+ const int crcLength= 4;
+ writer.WriteUInt16Return((ushort)(0b_1011_0000_0000_0000 | (ushort)(writer.GetCurrentPosition() - SectionLengthPosition - 2)+ crcLength), SectionLengthPosition);
+ //打包ts流时PAT和PMT表是没有adaptation field的,不够的长度直接补0xff即可。
+ //ts header(4B) + adaptation field length(1)
+ writer.WriteCRC32(5);
+ var size = TSConstants.FiexdPackageLength - writer.GetCurrentPosition();
+ writer.WriteArray(Enumerable.Range(0, size).Select(s => (byte)0xFF).ToArray());
+ }
+ }
+}