diff --git a/doc/video/demo.264 b/doc/video/demo.264
new file mode 100644
index 0000000..e289d5e
Binary files /dev/null and b/doc/video/demo.264 differ
diff --git a/src/JT1078.Hls.Test/JT1078.Hls.Test.csproj b/src/JT1078.Hls.Test/JT1078.Hls.Test.csproj
index ed587fa..09ae7e2 100644
--- a/src/JT1078.Hls.Test/JT1078.Hls.Test.csproj
+++ b/src/JT1078.Hls.Test/JT1078.Hls.Test.csproj
@@ -17,4 +17,10 @@
+
+
+ Always
+
+
+
diff --git a/src/JT1078.Hls.Test/TS_PAT_Package_Test.cs b/src/JT1078.Hls.Test/TS_PAT_Package_Test.cs
new file mode 100644
index 0000000..6745d86
--- /dev/null
+++ b/src/JT1078.Hls.Test/TS_PAT_Package_Test.cs
@@ -0,0 +1,53 @@
+using JT1078.Hls.Enums;
+using JT1078.Hls.MessagePack;
+using JT1078.Protocol.Extensions;
+using System;
+using System.Collections.Generic;
+using Xunit;
+
+namespace JT1078.Hls.Test
+{
+ ///
+ /// ʹdemo0.ts
+ ///
+ public class TS_PAT_Package_Test
+ {
+ [Fact]
+ public void ToBufferTest()
+ {
+ //47 40 00 10 00 00 B0 0D 00 01 C1 00 00 00 01 F0 00 2A B1 04 B2 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
+ //----------PAT
+ //47
+ //40 00
+ //10
+ //00
+ //00
+ //B0 0D
+ //00 01
+ //C1
+ //00
+ //00
+ //00 01
+ //F0 00
+ //2A B1 04 B2
+ TS_PAT_Package package = new TS_PAT_Package();
+ package.Header = new TS_Header();
+ package.Header.PID = 0;
+ package.Header.AdaptationFieldControl = AdaptationFieldControl.Ӧ_Ч;
+ package.Header.ContinuityCounter = 0;
+ package.TableId = 0;
+ package.TransportStreamId = 0x0001;
+ package.VersionNumber = 0;
+ package.Programs = new List();
+ package.Programs.Add(new TS_PAT_Program()
+ {
+ ProgramNumber = 0x0001,
+ PID = 0x1000,
+ });
+ TSMessagePackWriter writer = new TSMessagePackWriter(new byte[188]);
+ package.ToBuffer(ref writer);
+ var patData=writer.FlushAndGetArray().ToHexString();
+ Assert.Equal("47 40 00 10 00 00 B0 0D 00 01 C1 00 00 00 01 F0 00 2A B1 04 B2 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF".Replace(" ",""), patData);
+ }
+ }
+}
diff --git a/src/JT1078.Hls.Test/TS_PMT_Package_Test.cs b/src/JT1078.Hls.Test/TS_PMT_Package_Test.cs
new file mode 100644
index 0000000..ee00d04
--- /dev/null
+++ b/src/JT1078.Hls.Test/TS_PMT_Package_Test.cs
@@ -0,0 +1,80 @@
+using JT1078.Hls.Descriptors;
+using JT1078.Hls.Enums;
+using JT1078.Hls.MessagePack;
+using JT1078.Protocol.Extensions;
+using System;
+using System.Collections.Generic;
+using Xunit;
+using System.Buffers.Binary;
+
+namespace JT1078.Hls.Test
+{
+ ///
+ /// 使用demo0.ts
+ ///
+ public class TS_PMT_Package_Test
+ {
+ [Fact]
+ public void ToBufferTest()
+ {
+ //47 50 00 10 00 02 B0 1D 00 01 C1 00 00 E1 00 F0 00 1B E1 00 F0 00 0F E1 01 F0 06 0A 04 75 6E 64 00 08 7D E8 77
+ //47
+ //50 00
+ //10
+ //00
+ //02
+ //B0 1D
+ //00 01
+ //C1
+ //00
+ //00
+ //E1 00
+ //F0 00
+ //1B
+ //E1 00
+ // F0 00
+ //0F
+ //E1 01
+ // F0 06
+ // 0A
+ // 04
+ // 75 6E 64 00
+ //08 7D E8 77
+ TS_PMT_Package package = new TS_PMT_Package();
+ package.Header = new TS_Header();
+ package.Header.PID = 4096;
+ package.Header.AdaptationFieldControl = AdaptationFieldControl.无自适应域_仅含有效负载;
+ package.Header.PayloadUnitStartIndicator = 1;
+ package.Header.ContinuityCounter = 0;
+ package.TableId = 0x02;
+ package.ProgramNumber = 0x0001;
+ package.PCR_PID = 256;
+ package.Components = new List();
+ package.Components.Add(new TS_PMT_Component()
+ {
+ StreamType= StreamType.h264,
+ ElementaryPID= 256,
+ });
+ package.Components.Add(new TS_PMT_Component()
+ {
+ StreamType = StreamType.aac,
+ ElementaryPID = 257,
+ Descriptor=new ISO_639_Language_Descriptor
+ {
+ ISO_639_Language_Infos=new List()
+ {
+ new ISO_639_Language_Descriptor.ISO_639_Language_Info
+ {
+ Audio_Type=0,
+ ISO_639_Language_Code=BinaryPrimitives.ReadUInt32BigEndian(new byte[]{ 0x75, 0x6E, 0x64, 0x00})
+ }
+ }
+ }
+ });
+ TSMessagePackWriter writer = new TSMessagePackWriter(new byte[188]);
+ package.ToBuffer(ref writer);
+ var pmtData = writer.FlushAndGetArray().ToHexString();
+ Assert.Equal("47 50 00 10 00 02 B0 1D 00 01 C1 00 00 E1 00 F0 00 1B E1 00 F0 00 0F E1 01 F0 06 0A 04 75 6E 64 00 08 7D E8 77 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ".Replace(" ",""), pmtData);
+ }
+ }
+}
diff --git a/src/JT1078.Hls.Test/TS_Package_Test.cs b/src/JT1078.Hls.Test/TS_Package_Test.cs
new file mode 100644
index 0000000..af46635
--- /dev/null
+++ b/src/JT1078.Hls.Test/TS_Package_Test.cs
@@ -0,0 +1,31 @@
+using JT1078.Hls.Descriptors;
+using JT1078.Hls.Enums;
+using JT1078.Hls.MessagePack;
+using JT1078.Protocol.Extensions;
+using System;
+using System.Buffers.Binary;
+using System.Collections.Generic;
+using Xunit;
+
+namespace JT1078.Hls.Test
+{
+ ///
+ /// 使用demo0.ts
+ ///
+ public class TS_Package_Test
+ {
+ [Fact]
+ public void ToBufferTest()
+ {
+ TS_Package package = new TS_Package();
+ package.Header = new TS_Header();
+ package.Header.PID = 4096;
+ package.Header.AdaptationFieldControl = AdaptationFieldControl.无自适应域_仅含有效负载;
+ package.Header.PayloadUnitStartIndicator = 1;
+ package.Header.ContinuityCounter = 0;
+ TSMessagePackWriter writer = new TSMessagePackWriter(new byte[188]);
+ package.ToBuffer(ref writer);
+ var psData = writer.FlushAndGetArray().ToHexString();
+ }
+ }
+}
diff --git a/src/JT1078.Hls.Test/UnitTest1.cs b/src/JT1078.Hls.Test/UnitTest1.cs
deleted file mode 100644
index 7f9854e..0000000
--- a/src/JT1078.Hls.Test/UnitTest1.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-using System;
-using Xunit;
-
-namespace JT1078.Hls.Test
-{
- public class UnitTest1
- {
- [Fact]
- public void Test1()
- {
-
- }
- //---------PMT
- //47 50 00 10 00 02 B0 1D 00 01 C1 00 00 E1 00 F0 00 1B E1 00 F0 00 0F E1 01 F0 06 0A 04 75 6E 64 00 08 7D E8 77
- //47
- //50 00
- //10
- //00
- //02
- //B0 1D
- //00 01
- //C1
- //00
- //00
- //E1 00
- //F0 00
- //1B
- //E1 00
- // F0 00
- //0F
- //E1 01
- // F0 06
- // 0A
- // 04 75
- // 6E 64
- // 00
- //08 7D E8 77
-
- //----------PAT
- //47 40 00 10 00 00 B0 0D 00 01 C1 00 00 00 01 F0 00 2A B1 04 B2
- //47
- //40 00
- //10
- //00
- //00
- //B0 0D
- //00 01
- //C1
- //00
- //00
- //00 01
- //F0 00
- //2A B1 04 B2
- }
-}
diff --git a/src/JT1078.Hls.Test/file/demo.264 b/src/JT1078.Hls.Test/file/demo.264
new file mode 100644
index 0000000..e289d5e
Binary files /dev/null and b/src/JT1078.Hls.Test/file/demo.264 differ
diff --git a/src/JT1078.Hls/Descriptors/DescriptorBase.cs b/src/JT1078.Hls/Descriptors/DescriptorBase.cs
new file mode 100644
index 0000000..8d16331
--- /dev/null
+++ b/src/JT1078.Hls/Descriptors/DescriptorBase.cs
@@ -0,0 +1,15 @@
+using JT1078.Hls.Formatters;
+using JT1078.Hls.MessagePack;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT1078.Hls.Descriptors
+{
+ public abstract class DescriptorBase : ITSMessagePackFormatter
+ {
+ public abstract byte Tag { get; set; }
+ public abstract byte Length { get; set; }
+ public abstract void ToBuffer(ref TSMessagePackWriter writer);
+ }
+}
diff --git a/src/JT1078.Hls/Descriptors/ISO_639_Language_Descriptor.cs b/src/JT1078.Hls/Descriptors/ISO_639_Language_Descriptor.cs
new file mode 100644
index 0000000..34cceb7
--- /dev/null
+++ b/src/JT1078.Hls/Descriptors/ISO_639_Language_Descriptor.cs
@@ -0,0 +1,49 @@
+using JT1078.Hls.MessagePack;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT1078.Hls.Descriptors
+{
+ ///
+ /// 2.6.18 ISO 639 language descripto
+ ///
+ public class ISO_639_Language_Descriptor : DescriptorBase
+ {
+ public override byte Tag { get; set; } = 0x0A;
+ public override byte Length { get; set; }
+
+ public List ISO_639_Language_Infos { get; set; }
+
+ public override void ToBuffer(ref TSMessagePackWriter writer)
+ {
+ writer.WriteByte(Tag);
+ if (ISO_639_Language_Infos != null)
+ {
+ writer.Skip(1, out int DescriptorLengthPosition);
+ foreach(var item in ISO_639_Language_Infos)
+ {
+ writer.WriteUInt3(item.ISO_639_Language_Code>> 8);
+ writer.WriteByte(item.Audio_Type);
+ }
+ writer.WriteByteReturn((byte)(writer.GetCurrentPosition()- DescriptorLengthPosition-1), DescriptorLengthPosition);
+ }
+ else
+ {
+ writer.WriteByte(0);
+ }
+ }
+
+ public class ISO_639_Language_Info
+ {
+ ///
+ /// 24bit
+ ///
+ public uint ISO_639_Language_Code { get; set; }
+ ///
+ /// 8bit
+ ///
+ public byte Audio_Type { get; set; }
+ }
+ }
+}
diff --git a/src/JT1078.Hls/ES_Package.cs b/src/JT1078.Hls/ES_Package.cs
index 6059e68..900842b 100644
--- a/src/JT1078.Hls/ES_Package.cs
+++ b/src/JT1078.Hls/ES_Package.cs
@@ -1,6 +1,5 @@
using JT1078.Hls.Formatters;
using JT1078.Hls.MessagePack;
-using JT1078.Protocol.H264;
using System;
using System.Collections.Generic;
using System.Text;
@@ -11,7 +10,7 @@ namespace JT1078.Hls
{
public static byte[] NALU0X09 = new byte[] { 0x00, 0x00, 0x00, 0x01, 0x09, 0xFF };
public byte[] NALU0x09 { get; set; } = NALU0X09;
- public List NALUs { get; set; }
+ public List NALUs { get; set; }
public void ToBuffer(ref TSMessagePackWriter writer)
{
writer.WriteArray(NALU0x09);
@@ -19,8 +18,7 @@ namespace JT1078.Hls
{
foreach(var nalu in NALUs)
{
- writer.WriteArray(nalu.StartCodePrefix);
- writer.WriteArray(nalu.RawData);
+ writer.WriteArray(nalu);
}
}
}
diff --git a/src/JT1078.Hls/Enums/AdaptationFieldControl.cs b/src/JT1078.Hls/Enums/AdaptationFieldControl.cs
index b549a57..1f56ea9 100644
--- a/src/JT1078.Hls/Enums/AdaptationFieldControl.cs
+++ b/src/JT1078.Hls/Enums/AdaptationFieldControl.cs
@@ -4,11 +4,11 @@ using System.Text;
namespace JT1078.Hls.Enums
{
- public enum AdaptationFieldControl
+ public enum AdaptationFieldControl:byte
{
- 保留= 0000_0000,
- 无自适应域_仅含有效负载 = 0001_0000,
- 仅含自适应域_无有效负载 = 0010_0000,
- 同时带有自适应域和有效负载 = 0011_0000,
+ 保留= 0b_0000_0000,
+ 无自适应域_仅含有效负载 = 0b_0001_0000,
+ 仅含自适应域_无有效负载 = 0b_0010_0000,
+ 同时带有自适应域和有效负载 = 0b_0011_0000,
}
}
diff --git a/src/JT1078.Hls/Enums/PCRInclude.cs b/src/JT1078.Hls/Enums/PCRInclude.cs
index dcc21a2..4950a27 100644
--- a/src/JT1078.Hls/Enums/PCRInclude.cs
+++ b/src/JT1078.Hls/Enums/PCRInclude.cs
@@ -6,6 +6,7 @@ namespace JT1078.Hls.Enums
{
///
/// 取0x50表示包含PCR或0x40表示不包含PCR
+ /// 注意:关键帧需要加pcr
///
public enum PCRInclude:byte
{
diff --git a/src/JT1078.Hls/MessagePack/TSMessagePackWriter.cs b/src/JT1078.Hls/MessagePack/TSMessagePackWriter.cs
index a4c3b54..4ae781f 100644
--- a/src/JT1078.Hls/MessagePack/TSMessagePackWriter.cs
+++ b/src/JT1078.Hls/MessagePack/TSMessagePackWriter.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Buffers.Binary;
namespace JT1078.Hls.MessagePack
@@ -127,9 +129,11 @@ namespace JT1078.Hls.MessagePack
}
var crcSpan = writer.Written.Slice(start);
uint crc = 0xFFFFFFFF;
+ byte j = 0;
for (int i = 0; i < crcSpan.Length; i++)
{
- crc = (crc << 8) ^ Util.crcTable[(crc >> 24) ^ crcSpan[i]];
+ j = (byte)(((crc >> 24) ^ crcSpan[i]) & 0xff);
+ crc = (crc << 8) ^ Util.crcTable[j];
}
WriteUInt32(crc);
}
diff --git a/src/JT1078.Hls/TSConstants.cs b/src/JT1078.Hls/TSConstants.cs
new file mode 100644
index 0000000..9f1fff9
--- /dev/null
+++ b/src/JT1078.Hls/TSConstants.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace JT1078.Hls
+{
+ public static class TSConstants
+ {
+ ///
+ /// 固定包长度
+ ///
+ public const int FiexdPackageLength = 188;
+
+ }
+}
diff --git a/src/JT1078.Hls/TS_AdaptationInfo.cs b/src/JT1078.Hls/TS_AdaptationInfo.cs
index b80df07..b70918e 100644
--- a/src/JT1078.Hls/TS_AdaptationInfo.cs
+++ b/src/JT1078.Hls/TS_AdaptationInfo.cs
@@ -3,6 +3,7 @@ using JT1078.Hls.Formatters;
using JT1078.Hls.MessagePack;
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
namespace JT1078.Hls
@@ -19,7 +20,10 @@ namespace JT1078.Hls
/// 5B
///
public long PCR { get; set; }
-
+ ///
+ /// 填充字节大小
+ ///
+ public byte FillSize { get; set; }
public void ToBuffer(ref TSMessagePackWriter writer)
{
writer.WriteByte((byte)PCRIncluded);
@@ -27,6 +31,10 @@ namespace JT1078.Hls
{
writer.WriteInt5(PCR);
}
+ if (FillSize > 0)
+ {
+ writer.WriteArray(Enumerable.Range(0, FillSize).Select(s => (byte)0xFF).ToArray());
+ }
}
}
}
diff --git a/src/JT1078.Hls/TS_Header.cs b/src/JT1078.Hls/TS_Header.cs
index c2b015c..0f41ee7 100644
--- a/src/JT1078.Hls/TS_Header.cs
+++ b/src/JT1078.Hls/TS_Header.cs
@@ -34,7 +34,7 @@ namespace JT1078.Hls
///
public ushort PID { get; set; }
///
- /// 传输优先级,0为低优先级,1为高优先级,通常取0
+ /// 传输加扰控制
/// 2bit
///
internal byte TransportScramblingControl { get; set; } = 0;
@@ -62,8 +62,8 @@ namespace JT1078.Hls
writer.WriteByte(SyncByte);
//TransportErrorIndicator PayloadUnitStartIndicator TransportPriority PID
//0 1 0 0000 0000 0000 0
- writer.WriteUInt16((ushort)(0100_0000_0000_0000 | PID));
- writer.WriteByte((byte)((int)AdaptationFieldControl | ContinuityCounter));
+ writer.WriteUInt16((ushort)(0b_0100_0000_0000_0000 | PID));
+ writer.WriteByte((byte)((byte)AdaptationFieldControl | ContinuityCounter));
if (Adaptation != null)
{
writer.Skip(1, out int AdaptationLengthPosition);
diff --git a/src/JT1078.Hls/TS_PAT_Package.cs b/src/JT1078.Hls/TS_PAT_Package.cs
index 5844524..09e7e20 100644
--- a/src/JT1078.Hls/TS_PAT_Package.cs
+++ b/src/JT1078.Hls/TS_PAT_Package.cs
@@ -2,6 +2,7 @@
using JT1078.Hls.MessagePack;
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
namespace JT1078.Hls
@@ -11,6 +12,7 @@ namespace JT1078.Hls
///
public class TS_PAT_Package : ITSMessagePackFormatter
{
+ public TS_Header Header { get; set; }
///
/// PAT表固定为0x00
/// 8bit
@@ -76,18 +78,17 @@ namespace JT1078.Hls
public void ToBuffer(ref TSMessagePackWriter writer)
{
+ Header.ToBuffer(ref writer);
writer.WriteByte(TableId);
//SectionSyntaxIndicator Zero Reserved1 SectionLength
//1 0 11 0000 0000 0000
- //(ushort)(1011_0000_0000_0000 | SectionLength)
- // todo:
- //writer.WriteUInt16((ushort)(1011_0000_0000_0000 | SectionLength));
+ //(ushort)(0b_1011_0000_0000_0000 | SectionLength)
writer.Skip(2, out int SectionLengthPosition);
writer.WriteUInt16(TransportStreamId);
//Reserved2 VersionNumber CurrentNextIndicator
//11 00000 1
- var a = Reserved2 & 0xC0;
- var b = VersionNumber & 0x3E;
+ var a = 0xC0 & (Reserved2 << 6);
+ var b = 0x3E & (VersionNumber << 3);
var c = (byte)(a | b | CurrentNextIndicator);
writer.WriteByte(c);
writer.WriteByte(SectionNumber);
@@ -99,8 +100,13 @@ namespace JT1078.Hls
program.ToBuffer(ref writer);
}
}
- writer.WriteUInt16Return((ushort)(1011_0000_0000_0000 | (ushort)(writer.GetCurrentPosition() - SectionLengthPosition - 2)), SectionLengthPosition);
- writer.WriteCRC32(SectionLengthPosition);
+ 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_PAT_Program.cs b/src/JT1078.Hls/TS_PAT_Program.cs
index a464fe8..0eb1856 100644
--- a/src/JT1078.Hls/TS_PAT_Program.cs
+++ b/src/JT1078.Hls/TS_PAT_Program.cs
@@ -15,7 +15,7 @@ namespace JT1078.Hls
public ushort ProgramNumber { get; set; }
///
/// 固定为二进制111(7)
- /// 1110_0000_0000_0000
+ /// 0b_1110_0000_0000_0000
/// 3bit
///
internal byte Reserved1 { get; set; } = 0x07;
@@ -28,7 +28,7 @@ namespace JT1078.Hls
public void ToBuffer(ref TSMessagePackWriter writer)
{
writer.WriteUInt16(ProgramNumber);
- writer.WriteUInt16((ushort)(1110_0000_0000_0000 | PID));
+ writer.WriteUInt16((ushort)(0b_1110_0000_0000_0000 | PID));
}
}
}
diff --git a/src/JT1078.Hls/TS_PMT_Component.cs b/src/JT1078.Hls/TS_PMT_Component.cs
index 63af051..09fde58 100644
--- a/src/JT1078.Hls/TS_PMT_Component.cs
+++ b/src/JT1078.Hls/TS_PMT_Component.cs
@@ -1,4 +1,5 @@
-using JT1078.Hls.Enums;
+using JT1078.Hls.Descriptors;
+using JT1078.Hls.Enums;
using JT1078.Hls.Formatters;
using JT1078.Hls.MessagePack;
using System;
@@ -16,7 +17,7 @@ namespace JT1078.Hls
public StreamType StreamType { get; set; }
///
/// 固定为二进制111(7)
- /// 0111_0000_0000_0000
+ /// 0b_1110_0000_0000_0000
/// 3bit
///
internal byte Reserved1 { get; set; } = 0x07;
@@ -27,7 +28,7 @@ namespace JT1078.Hls
public ushort ElementaryPID { get; set; }
///
/// 固定为二进制1111(15)
- /// 1111_0000_0000_0000
+ /// 0b_1111_0000_0000_0000
/// 4bit
///
internal byte Reserved2 { get; set; } = 0x0F;
@@ -36,12 +37,22 @@ namespace JT1078.Hls
/// 12bit
///
internal ushort ESInfoLength { get; set; } = 0x000;
-
+ public DescriptorBase Descriptor { get; set; }
public void ToBuffer(ref TSMessagePackWriter writer)
{
writer.WriteByte((byte)StreamType);
- writer.WriteUInt16((ushort)(0111_0000_0000_0000| ElementaryPID));
- writer.WriteUInt16((ushort)(1111_0000_0000_0000| ESInfoLength));
+ writer.WriteUInt16((ushort)(0b_1110_0000_0000_0000 | ElementaryPID));
+ if (Descriptor == null)
+ {
+ writer.WriteUInt16((ushort)(0b_1111_0000_0000_0000 | ESInfoLength));
+ }
+ else
+ {
+ writer.Skip(2, out int ESInfoLengthPosition);
+ Descriptor.ToBuffer(ref writer);
+ ESInfoLength = (ushort)(writer.GetCurrentPosition() - ESInfoLengthPosition - 2);
+ writer.WriteUInt16Return((ushort)(0b_1111_0000_0000_0000 | ESInfoLength), ESInfoLengthPosition);
+ }
}
}
}
diff --git a/src/JT1078.Hls/TS_PMT_Package.cs b/src/JT1078.Hls/TS_PMT_Package.cs
index 7cbae8c..bb5d601 100644
--- a/src/JT1078.Hls/TS_PMT_Package.cs
+++ b/src/JT1078.Hls/TS_PMT_Package.cs
@@ -2,6 +2,7 @@
using JT1078.Hls.MessagePack;
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
namespace JT1078.Hls
@@ -11,6 +12,7 @@ namespace JT1078.Hls
///
public class TS_PMT_Package : ITSMessagePackFormatter
{
+ public TS_Header Header { get; set; }
///
/// PMT表取值随意
/// 8bit
@@ -93,28 +95,27 @@ namespace JT1078.Hls
public uint CRC32 { get; set; }
public void ToBuffer(ref TSMessagePackWriter writer)
{
+ Header.ToBuffer(ref writer);
writer.WriteByte(TableId);
//SectionSyntaxIndicator Zero Reserved1 SectionLength
//1 0 11 0000 0000 0000
- //(ushort)(1011_0000_0000_0000 | SectionLength)
- // todo:
- //writer.WriteUInt16((ushort)(1011_0000_0000_0000 | SectionLength));
+ //(ushort)(0b_1011_0000_0000_0000 | SectionLength)
writer.Skip(2, out int SectionLengthPosition);
writer.WriteUInt16(ProgramNumber);
//Reserved2 VersionNumber CurrentNextIndicator
//11 00000 1
- var a = Reserved2 & 0xC0;
- var b = VersionNumber & 0x3E;
- var c=(byte)(a | b | CurrentNextIndicator);
+ 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);
//Reserved3 PCR_PID
//111 0000 0000 0000 0
- writer.WriteUInt16((ushort)(0111_0000_0000_0000 | PCR_PID));
+ writer.WriteUInt16((ushort)(0b_1110_0000_0000_0000 | PCR_PID));
//Reserved4 ProgramInfoLength
//1111 0000 0000 0000
- writer.WriteUInt16((ushort)(1111_0000_0000_0000 | ProgramInfoLength));
+ writer.WriteUInt16((ushort)(0b_1111_0000_0000_0000 | ProgramInfoLength));
if (Components != null)
{
foreach(var component in Components)
@@ -122,8 +123,13 @@ namespace JT1078.Hls
component.ToBuffer(ref writer);
}
}
- writer.WriteUInt16Return((ushort)(1011_0000_0000_0000 | (ushort)(writer.GetCurrentPosition() - SectionLengthPosition - 2)), SectionLengthPosition);
- writer.WriteCRC32(SectionLengthPosition);
+ 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_Package.cs b/src/JT1078.Hls/TS_Package.cs
index 7675b44..8686aa9 100644
--- a/src/JT1078.Hls/TS_Package.cs
+++ b/src/JT1078.Hls/TS_Package.cs
@@ -1,17 +1,21 @@
-using JT1078.Protocol.H264;
+using JT1078.Hls.Formatters;
+using JT1078.Hls.MessagePack;
+using JT1078.Protocol.H264;
using System;
using System.Collections.Generic;
using System.Text;
namespace JT1078.Hls
{
- public class TS_Package
+ public class TS_Package : ITSMessagePackFormatter
{
public TS_Header Header { get; set; }
public PES_Package Payload { get; set; }
- ///
- /// 填充字节,取值0xff
- ///
- public byte[] Fill { get; set; }
+
+ public void ToBuffer(ref TSMessagePackWriter writer)
+ {
+ Header.ToBuffer(ref writer);
+ Payload.ToBuffer(ref writer);
+ }
}
}