@@ -158,7 +158,7 @@ namespace JT1078.Hls.Test | |||||
} | } | ||||
} | } | ||||
} | } | ||||
catch (Exception ex) | |||||
catch (Exception ex) | |||||
{ | { | ||||
Assert.Throws<Exception>(() => { }); | Assert.Throws<Exception>(() => { }); | ||||
} | } | ||||
@@ -47,7 +47,6 @@ namespace JT1078.Hls | |||||
sb.AppendLine("#EXTM3U");//开始 | sb.AppendLine("#EXTM3U");//开始 | ||||
sb.AppendLine("#EXT-X-VERSION:3");//版本号 | sb.AppendLine("#EXT-X-VERSION:3");//版本号 | ||||
sb.AppendLine("#EXT-X-ALLOW-CACHE:NO");//是否允许cache | sb.AppendLine("#EXT-X-ALLOW-CACHE:NO");//是否允许cache | ||||
sb.AppendLine($"#EXT-X-TARGETDURATION:{fileMaxSecond}");//每个分片TS的最大的时长 | sb.AppendLine($"#EXT-X-TARGETDURATION:{fileMaxSecond}");//每个分片TS的最大的时长 | ||||
sb.AppendLine($"#EXT-X-MEDIA-SEQUENCE:{firstTSSerialno}");//第一个TS分片的序列号 | sb.AppendLine($"#EXT-X-MEDIA-SEQUENCE:{firstTSSerialno}");//第一个TS分片的序列号 | ||||
using (StreamWriter sw = new StreamWriter(m3U8Option.M3U8Filepath, true)) | using (StreamWriter sw = new StreamWriter(m3U8Option.M3U8Filepath, true)) | ||||
@@ -75,6 +75,16 @@ namespace JT1078.Hls.MessagePack | |||||
writer.Free[5] = (byte)(value); | writer.Free[5] = (byte)(value); | ||||
writer.Advance(6); | writer.Advance(6); | ||||
} | } | ||||
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.Free[5] = 0x00; | |||||
writer.Advance(6); | |||||
} | |||||
public void WriteUInt3(uint value) | public void WriteUInt3(uint value) | ||||
{ | { | ||||
writer.Free[0] = (byte)(value >> 16); | writer.Free[0] = (byte)(value >> 16); | ||||
@@ -20,9 +20,10 @@ using System.Buffers; | |||||
namespace JT1078.Hls | namespace JT1078.Hls | ||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// 1.PAT | |||||
/// 2.PMT | |||||
/// 3.PES | |||||
/// 1.SDT | |||||
/// 2.PAT | |||||
/// 3.PMT | |||||
/// 4.PES | |||||
/// </summary> | /// </summary> | ||||
public class TSEncoder | public class TSEncoder | ||||
{ | { | ||||
@@ -31,8 +32,9 @@ namespace JT1078.Hls | |||||
private const string ServiceProvider = "JTT1078"; | private const string ServiceProvider = "JTT1078"; | ||||
private const string ServiceName = "Koike&TK"; | private const string ServiceName = "Koike&TK"; | ||||
private const int H264DefaultHZ = 90; | private const int H264DefaultHZ = 90; | ||||
private Dictionary<string, byte> VideoCounter; | |||||
//todo:音频同步 | |||||
//private Dictionary<string, byte> AudioCounter = new Dictionary<string, byte>(); | |||||
ArrayPool<byte> arrayPool = ArrayPool<byte>.Create(); | ArrayPool<byte> arrayPool = ArrayPool<byte>.Create(); | ||||
byte[] fileData; | byte[] fileData; | ||||
int fileIndex = 0; | int fileIndex = 0; | ||||
@@ -43,31 +45,37 @@ namespace JT1078.Hls | |||||
this.m3U8FileManage = m3U8FileManage; | this.m3U8FileManage = m3U8FileManage; | ||||
fileData = arrayPool.Rent(2500000); | fileData = arrayPool.Rent(2500000); | ||||
} | } | ||||
private Dictionary<string, byte> VideoCounter; | |||||
/// <summary> | /// <summary> | ||||
/// 创建m3u8文件 和 ts文件 | /// 创建m3u8文件 和 ts文件 | ||||
/// </summary> | /// </summary> | ||||
/// <param name="jt1078Package"></param> | /// <param name="jt1078Package"></param> | ||||
public void CreateM3U8File(JT1078Package jt1078Package) { | |||||
public void CreateM3U8File(JT1078Package jt1078Package) | |||||
{ | |||||
CombinedTSData(jt1078Package); | CombinedTSData(jt1078Package); | ||||
if (m3U8FileManage.m3U8Option.AccumulateSeconds >= m3U8FileManage.m3U8Option.TsFileMaxSecond) { | |||||
if (m3U8FileManage.m3U8Option.AccumulateSeconds >= m3U8FileManage.m3U8Option.TsFileMaxSecond) | |||||
{ | |||||
m3U8FileManage.CreateM3U8File(jt1078Package, fileData.AsSpan().Slice(0,fileIndex).ToArray()); | m3U8FileManage.CreateM3U8File(jt1078Package, fileData.AsSpan().Slice(0,fileIndex).ToArray()); | ||||
arrayPool.Return(fileData); | arrayPool.Return(fileData); | ||||
fileData = arrayPool.Rent(2500000); | fileData = arrayPool.Rent(2500000); | ||||
fileIndex = 0; | fileIndex = 0; | ||||
} | } | ||||
} | } | ||||
/// <summary> | /// <summary> | ||||
/// m3u8文件 追加结束标识 | /// m3u8文件 追加结束标识 | ||||
/// </summary> | /// </summary> | ||||
public void AppendM3U8End() { | |||||
public void AppendM3U8End() | |||||
{ | |||||
m3U8FileManage.AppendM3U8End(); | m3U8FileManage.AppendM3U8End(); | ||||
} | } | ||||
/// <summary> | /// <summary> | ||||
/// 按 设定的时间(默认为10秒)切分ts文件 | |||||
/// 按设定的时间(默认为10秒)切分ts文件 | |||||
/// </summary> | /// </summary> | ||||
/// <param name="jt1078Package"></param> | /// <param name="jt1078Package"></param> | ||||
private void CombinedTSData(JT1078Package jt1078Package) { | |||||
private void CombinedTSData(JT1078Package jt1078Package) | |||||
{ | |||||
if (m3U8FileManage.m3U8Option.TimestampMilliSecond == 0) | if (m3U8FileManage.m3U8Option.TimestampMilliSecond == 0) | ||||
{ | { | ||||
m3U8FileManage.m3U8Option.TimestampMilliSecond = jt1078Package.Timestamp; | m3U8FileManage.m3U8Option.TimestampMilliSecond = jt1078Package.Timestamp; | ||||
@@ -105,8 +113,6 @@ namespace JT1078.Hls | |||||
fileIndex = fileIndex + pes.Length; | fileIndex = fileIndex + pes.Length; | ||||
} | } | ||||
} | } | ||||
//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) | ||||
{ | { | ||||
byte[] buffer = TSArrayPool.Rent(minBufferSize); | byte[] buffer = TSArrayPool.Rent(minBufferSize); | ||||
@@ -205,7 +211,6 @@ namespace JT1078.Hls | |||||
TSArrayPool.Return(buffer); | TSArrayPool.Return(buffer); | ||||
} | } | ||||
} | } | ||||
public byte[] CreatePES(JT1078Package jt1078Package, int minBufferSize = 188) | public byte[] CreatePES(JT1078Package jt1078Package, int minBufferSize = 188) | ||||
{ | { | ||||
//将1078一帧的数据拆分成一小段一小段的PES包 | //将1078一帧的数据拆分成一小段一小段的PES包 | ||||
@@ -256,7 +261,7 @@ namespace JT1078.Hls | |||||
package.Header.Adaptation.PCRIncluded = PCRInclude.包含; | package.Header.Adaptation.PCRIncluded = PCRInclude.包含; | ||||
package.Header.Adaptation.Timestamp = timestamp; | package.Header.Adaptation.Timestamp = timestamp; | ||||
package.Payload.DTS = timestamp * H264DefaultHZ; | package.Payload.DTS = timestamp * H264DefaultHZ; | ||||
package.Payload.PTS = package.Payload.DTS + jt1078Package.LastIFrameInterval * H264DefaultHZ; | |||||
package.Payload.PTS = timestamp * H264DefaultHZ; | |||||
} | } | ||||
else if(jt1078Package.Label3.DataType == JT1078DataType.视频P帧) | else if(jt1078Package.Label3.DataType == JT1078DataType.视频P帧) | ||||
{ | { | ||||
@@ -266,7 +271,7 @@ namespace JT1078.Hls | |||||
totalLength += 1; | totalLength += 1; | ||||
package.Header.Adaptation.PCRIncluded = PCRInclude.不包含; | package.Header.Adaptation.PCRIncluded = PCRInclude.不包含; | ||||
package.Payload.DTS = timestamp * H264DefaultHZ; | package.Payload.DTS = timestamp * H264DefaultHZ; | ||||
package.Payload.PTS = package.Payload.DTS + jt1078Package.LastFrameInterval * H264DefaultHZ; | |||||
package.Payload.PTS = timestamp * H264DefaultHZ; | |||||
} | } | ||||
//Flag1 + PTS_DTS_Flag + DTS + PTS | //Flag1 + PTS_DTS_Flag + DTS + PTS | ||||
//1 + 1 + 5 + 5 = 12 | //1 + 1 + 5 + 5 = 12 | ||||
@@ -31,7 +31,7 @@ namespace JT1078.Hls | |||||
writer.WriteByte((byte)PCRIncluded); | writer.WriteByte((byte)PCRIncluded); | ||||
if (PCRIncluded == PCRInclude.包含) | if (PCRIncluded == PCRInclude.包含) | ||||
{ | { | ||||
writer.WriteInt6(ToPCR()); | |||||
writer.WritePCR(Timestamp); | |||||
} | } | ||||
if (FillSize > 0) | if (FillSize > 0) | ||||
{ | { | ||||
@@ -47,9 +47,9 @@ namespace JT1078.Hls | |||||
/// } | /// } | ||||
/// </summary> | /// </summary> | ||||
/// <returns></returns> | /// <returns></returns> | ||||
private long ToPCR() | |||||
{ | |||||
return (Timestamp / 300 << 15 | 0x7E00); | |||||
} | |||||
//private long ToPCR() | |||||
//{ | |||||
// return (Timestamp / 300 << 15 | 0x7E00); | |||||
//} | |||||
} | } | ||||
} | } |
@@ -24,8 +24,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution | |||||
..\README.md = ..\README.md | ..\README.md = ..\README.md | ||||
EndProjectSection | EndProjectSection | ||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT808.Protocol.Extensions.WebApiTest", "JT808.Protocol.Extensions.WebApiTest\JT808.Protocol.Extensions.WebApiTest.csproj", "{9DB37370-AC73-434B-9CE2-6659321858C8}" | |||||
EndProject | |||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.Flv", "JT1078.Flv\JT1078.Flv.csproj", "{33E54FFC-7D91-42E5-9DC1-853738AB8980}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.Flv", "JT1078.Flv\JT1078.Flv.csproj", "{33E54FFC-7D91-42E5-9DC1-853738AB8980}" | ||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.Flv.Test", "JT1078.Flv.Test\JT1078.Flv.Test.csproj", "{D13FE092-1D11-4545-A322-9F06BCDAC0FD}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JT1078.Flv.Test", "JT1078.Flv.Test\JT1078.Flv.Test.csproj", "{D13FE092-1D11-4545-A322-9F06BCDAC0FD}" | ||||
@@ -70,10 +68,6 @@ Global | |||||
{77402142-54E5-4E64-8F9E-BCAAC2CD0E8D}.Debug|Any CPU.Build.0 = Debug|Any CPU | {77402142-54E5-4E64-8F9E-BCAAC2CD0E8D}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
{77402142-54E5-4E64-8F9E-BCAAC2CD0E8D}.Release|Any CPU.ActiveCfg = Release|Any CPU | {77402142-54E5-4E64-8F9E-BCAAC2CD0E8D}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
{77402142-54E5-4E64-8F9E-BCAAC2CD0E8D}.Release|Any CPU.Build.0 = Release|Any CPU | {77402142-54E5-4E64-8F9E-BCAAC2CD0E8D}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
{9DB37370-AC73-434B-9CE2-6659321858C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | |||||
{9DB37370-AC73-434B-9CE2-6659321858C8}.Debug|Any CPU.Build.0 = Debug|Any CPU | |||||
{9DB37370-AC73-434B-9CE2-6659321858C8}.Release|Any CPU.ActiveCfg = Release|Any CPU | |||||
{9DB37370-AC73-434B-9CE2-6659321858C8}.Release|Any CPU.Build.0 = Release|Any CPU | |||||
{33E54FFC-7D91-42E5-9DC1-853738AB8980}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | {33E54FFC-7D91-42E5-9DC1-853738AB8980}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
{33E54FFC-7D91-42E5-9DC1-853738AB8980}.Debug|Any CPU.Build.0 = Debug|Any CPU | {33E54FFC-7D91-42E5-9DC1-853738AB8980}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
{33E54FFC-7D91-42E5-9DC1-853738AB8980}.Release|Any CPU.ActiveCfg = Release|Any CPU | {33E54FFC-7D91-42E5-9DC1-853738AB8980}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
@@ -102,7 +96,6 @@ Global | |||||
{C6A43FDF-C609-40BB-B598-87F0BF7B944B} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | {C6A43FDF-C609-40BB-B598-87F0BF7B944B} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | ||||
{E9FF2716-EF30-4180-879B-E8AB979ACFF3} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | {E9FF2716-EF30-4180-879B-E8AB979ACFF3} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | ||||
{9ADD82F9-E0B2-4263-8573-151F673BB33F} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | {9ADD82F9-E0B2-4263-8573-151F673BB33F} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | ||||
{9DB37370-AC73-434B-9CE2-6659321858C8} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | |||||
{D13FE092-1D11-4545-A322-9F06BCDAC0FD} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | {D13FE092-1D11-4545-A322-9F06BCDAC0FD} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | ||||
{5564C20B-BFF4-4A2A-BDF2-C7427E93E993} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | {5564C20B-BFF4-4A2A-BDF2-C7427E93E993} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | ||||
EndGlobalSection | EndGlobalSection | ||||