@@ -158,7 +158,7 @@ namespace JT1078.Hls.Test | |||
} | |||
} | |||
} | |||
catch (Exception ex) | |||
catch (Exception ex) | |||
{ | |||
Assert.Throws<Exception>(() => { }); | |||
} | |||
@@ -47,7 +47,6 @@ namespace JT1078.Hls | |||
sb.AppendLine("#EXTM3U");//开始 | |||
sb.AppendLine("#EXT-X-VERSION:3");//版本号 | |||
sb.AppendLine("#EXT-X-ALLOW-CACHE:NO");//是否允许cache | |||
sb.AppendLine($"#EXT-X-TARGETDURATION:{fileMaxSecond}");//每个分片TS的最大的时长 | |||
sb.AppendLine($"#EXT-X-MEDIA-SEQUENCE:{firstTSSerialno}");//第一个TS分片的序列号 | |||
using (StreamWriter sw = new StreamWriter(m3U8Option.M3U8Filepath, true)) | |||
@@ -75,6 +75,16 @@ namespace JT1078.Hls.MessagePack | |||
writer.Free[5] = (byte)(value); | |||
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) | |||
{ | |||
writer.Free[0] = (byte)(value >> 16); | |||
@@ -20,9 +20,10 @@ using System.Buffers; | |||
namespace JT1078.Hls | |||
{ | |||
/// <summary> | |||
/// 1.PAT | |||
/// 2.PMT | |||
/// 3.PES | |||
/// 1.SDT | |||
/// 2.PAT | |||
/// 3.PMT | |||
/// 4.PES | |||
/// </summary> | |||
public class TSEncoder | |||
{ | |||
@@ -31,8 +32,9 @@ namespace JT1078.Hls | |||
private const string ServiceProvider = "JTT1078"; | |||
private const string ServiceName = "Koike&TK"; | |||
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(); | |||
byte[] fileData; | |||
int fileIndex = 0; | |||
@@ -43,31 +45,37 @@ namespace JT1078.Hls | |||
this.m3U8FileManage = m3U8FileManage; | |||
fileData = arrayPool.Rent(2500000); | |||
} | |||
private Dictionary<string, byte> VideoCounter; | |||
/// <summary> | |||
/// 创建m3u8文件 和 ts文件 | |||
/// </summary> | |||
/// <param name="jt1078Package"></param> | |||
public void CreateM3U8File(JT1078Package jt1078Package) { | |||
public void CreateM3U8File(JT1078Package 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()); | |||
arrayPool.Return(fileData); | |||
fileData = arrayPool.Rent(2500000); | |||
fileIndex = 0; | |||
} | |||
} | |||
/// <summary> | |||
/// m3u8文件 追加结束标识 | |||
/// </summary> | |||
public void AppendM3U8End() { | |||
public void AppendM3U8End() | |||
{ | |||
m3U8FileManage.AppendM3U8End(); | |||
} | |||
/// <summary> | |||
/// 按 设定的时间(默认为10秒)切分ts文件 | |||
/// 按设定的时间(默认为10秒)切分ts文件 | |||
/// </summary> | |||
/// <param name="jt1078Package"></param> | |||
private void CombinedTSData(JT1078Package jt1078Package) { | |||
private void CombinedTSData(JT1078Package jt1078Package) | |||
{ | |||
if (m3U8FileManage.m3U8Option.TimestampMilliSecond == 0) | |||
{ | |||
m3U8FileManage.m3U8Option.TimestampMilliSecond = jt1078Package.Timestamp; | |||
@@ -105,8 +113,6 @@ namespace JT1078.Hls | |||
fileIndex = fileIndex + pes.Length; | |||
} | |||
} | |||
//private ConcurrentDictionary<string, byte> AudioCounter = new ConcurrentDictionary<string, byte>(); | |||
public byte[] CreateSDT(JT1078Package jt1078Package, int minBufferSize = 188) | |||
{ | |||
byte[] buffer = TSArrayPool.Rent(minBufferSize); | |||
@@ -205,7 +211,6 @@ namespace JT1078.Hls | |||
TSArrayPool.Return(buffer); | |||
} | |||
} | |||
public byte[] CreatePES(JT1078Package jt1078Package, int minBufferSize = 188) | |||
{ | |||
//将1078一帧的数据拆分成一小段一小段的PES包 | |||
@@ -256,7 +261,7 @@ namespace JT1078.Hls | |||
package.Header.Adaptation.PCRIncluded = PCRInclude.包含; | |||
package.Header.Adaptation.Timestamp = timestamp; | |||
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帧) | |||
{ | |||
@@ -266,7 +271,7 @@ namespace JT1078.Hls | |||
totalLength += 1; | |||
package.Header.Adaptation.PCRIncluded = PCRInclude.不包含; | |||
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 | |||
//1 + 1 + 5 + 5 = 12 | |||
@@ -31,7 +31,7 @@ namespace JT1078.Hls | |||
writer.WriteByte((byte)PCRIncluded); | |||
if (PCRIncluded == PCRInclude.包含) | |||
{ | |||
writer.WriteInt6(ToPCR()); | |||
writer.WritePCR(Timestamp); | |||
} | |||
if (FillSize > 0) | |||
{ | |||
@@ -47,9 +47,9 @@ namespace JT1078.Hls | |||
/// } | |||
/// </summary> | |||
/// <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 | |||
EndProjectSection | |||
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}" | |||
EndProject | |||
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}.Release|Any CPU.ActiveCfg = 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.Build.0 = Debug|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} | |||
{E9FF2716-EF30-4180-879B-E8AB979ACFF3} = {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} | |||
{5564C20B-BFF4-4A2A-BDF2-C7427E93E993} = {0655AF84-E578-409F-AB0E-B47E0D2F6814} | |||
EndGlobalSection | |||