@@ -17,4 +17,10 @@ | |||
<ProjectReference Include="..\JT1078.Hls\JT1078.Hls.csproj" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Update="file\demo.264"> | |||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||
</None> | |||
</ItemGroup> | |||
</Project> |
@@ -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 | |||
{ | |||
/// <summary> | |||
/// 使用demo0.ts | |||
/// </summary> | |||
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<TS_PAT_Program>(); | |||
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); | |||
} | |||
} | |||
} |
@@ -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 | |||
{ | |||
/// <summary> | |||
/// 使用demo0.ts | |||
/// </summary> | |||
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<TS_PMT_Component>(); | |||
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<ISO_639_Language_Descriptor.ISO_639_Language_Info>() | |||
{ | |||
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); | |||
} | |||
} | |||
} |
@@ -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 | |||
{ | |||
/// <summary> | |||
/// 使用demo0.ts | |||
/// </summary> | |||
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(); | |||
} | |||
} | |||
} |
@@ -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 | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
using JT1078.Hls.MessagePack; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT1078.Hls.Descriptors | |||
{ | |||
/// <summary> | |||
/// 2.6.18 ISO 639 language descripto | |||
/// </summary> | |||
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_Info> 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 | |||
{ | |||
/// <summary> | |||
/// 24bit | |||
/// </summary> | |||
public uint ISO_639_Language_Code { get; set; } | |||
/// <summary> | |||
/// 8bit | |||
/// </summary> | |||
public byte Audio_Type { get; set; } | |||
} | |||
} | |||
} |
@@ -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<H264NALU> NALUs { get; set; } | |||
public List<byte[]> 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); | |||
} | |||
} | |||
} | |||
@@ -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, | |||
} | |||
} |
@@ -6,6 +6,7 @@ namespace JT1078.Hls.Enums | |||
{ | |||
/// <summary> | |||
/// 取0x50表示包含PCR或0x40表示不包含PCR | |||
/// 注意:关键帧需要加pcr | |||
/// </summary> | |||
public enum PCRInclude:byte | |||
{ | |||
@@ -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); | |||
} | |||
@@ -0,0 +1,15 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT1078.Hls | |||
{ | |||
public static class TSConstants | |||
{ | |||
/// <summary> | |||
/// 固定包长度 | |||
/// </summary> | |||
public const int FiexdPackageLength = 188; | |||
} | |||
} |
@@ -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 | |||
/// </summary> | |||
public long PCR { get; set; } | |||
/// <summary> | |||
/// 填充字节大小 | |||
/// </summary> | |||
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()); | |||
} | |||
} | |||
} | |||
} |
@@ -34,7 +34,7 @@ namespace JT1078.Hls | |||
/// </summary> | |||
public ushort PID { get; set; } | |||
/// <summary> | |||
/// 传输优先级,0为低优先级,1为高优先级,通常取0 | |||
/// 传输加扰控制 | |||
/// 2bit | |||
/// </summary> | |||
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); | |||
@@ -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 | |||
/// </summary> | |||
public class TS_PAT_Package : ITSMessagePackFormatter | |||
{ | |||
public TS_Header Header { get; set; } | |||
/// <summary> | |||
/// 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()); | |||
} | |||
} | |||
} |
@@ -15,7 +15,7 @@ namespace JT1078.Hls | |||
public ushort ProgramNumber { get; set; } | |||
/// <summary> | |||
/// 固定为二进制111(7) | |||
/// 1110_0000_0000_0000 | |||
/// 0b_1110_0000_0000_0000 | |||
/// 3bit | |||
/// </summary> | |||
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)); | |||
} | |||
} | |||
} |
@@ -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; } | |||
/// <summary> | |||
/// 固定为二进制111(7) | |||
/// 0111_0000_0000_0000 | |||
/// 0b_1110_0000_0000_0000 | |||
/// 3bit | |||
/// </summary> | |||
internal byte Reserved1 { get; set; } = 0x07; | |||
@@ -27,7 +28,7 @@ namespace JT1078.Hls | |||
public ushort ElementaryPID { get; set; } | |||
/// <summary> | |||
/// 固定为二进制1111(15) | |||
/// 1111_0000_0000_0000 | |||
/// 0b_1111_0000_0000_0000 | |||
/// 4bit | |||
/// </summary> | |||
internal byte Reserved2 { get; set; } = 0x0F; | |||
@@ -36,12 +37,22 @@ namespace JT1078.Hls | |||
/// 12bit | |||
/// </summary> | |||
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); | |||
} | |||
} | |||
} | |||
} |
@@ -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 | |||
/// </summary> | |||
public class TS_PMT_Package : ITSMessagePackFormatter | |||
{ | |||
public TS_Header Header { get; set; } | |||
/// <summary> | |||
/// 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()); | |||
} | |||
} | |||
} |
@@ -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; } | |||
/// <summary> | |||
/// 填充字节,取值0xff | |||
/// </summary> | |||
public byte[] Fill { get; set; } | |||
public void ToBuffer(ref TSMessagePackWriter writer) | |||
{ | |||
Header.ToBuffer(ref writer); | |||
Payload.ToBuffer(ref writer); | |||
} | |||
} | |||
} |