|
@@ -33,25 +33,28 @@ namespace JT1078.Hls |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void CreateTsData(JT1078Package jt1078Package) { |
|
|
public void CreateTsData(JT1078Package jt1078Package) { |
|
|
|
|
|
if (!File.Exists(m3U8Option.M3U8FileName)) File.Create(m3U8Option.M3U8FileName);//创建m3u8文件 |
|
|
string tsFileDirectory = m3U8Option.HlsFileDirectory; |
|
|
string tsFileDirectory = m3U8Option.HlsFileDirectory; |
|
|
string tsNewFileName = $"{m3U8Option.TsFileCount}.ts"; |
|
|
|
|
|
string fileName= Path.Combine(tsFileDirectory, tsNewFileName); |
|
|
|
|
|
var buff = TSArrayPool.Rent(jt1078Package.Bodies.Length + 2048); |
|
|
|
|
|
|
|
|
string tsNewFileName = $"{m3U8Option.TsFileSerialNo}.ts"; |
|
|
|
|
|
string tsFileName= Path.Combine(tsFileDirectory, tsNewFileName); |
|
|
|
|
|
var buff = TSArrayPool.Rent(jt1078Package.Bodies.Length + 1024); |
|
|
TSMessagePackWriter tSMessagePackWriter = new TSMessagePackWriter(buff); |
|
|
TSMessagePackWriter tSMessagePackWriter = new TSMessagePackWriter(buff); |
|
|
if (TsFirst1078PackageDic.TryGetValue(jt1078Package.SIM, out var firstTimespan)) |
|
|
|
|
|
|
|
|
if (TsFirst1078PackageDic.TryGetValue($"{jt1078Package.SIM}_{jt1078Package.LogicChannelNumber}" , out var firstTimespan)) |
|
|
{ |
|
|
{ |
|
|
var pes = tSEncoder.CreatePES(jt1078Package, 188); |
|
|
|
|
|
|
|
|
var pes = tSEncoder.CreatePES(jt1078Package); |
|
|
tSMessagePackWriter.WriteArray(pes); |
|
|
tSMessagePackWriter.WriteArray(pes); |
|
|
CreateTsFile(fileName, tSMessagePackWriter.FlushAndGetArray()); |
|
|
|
|
|
|
|
|
CreateTsFile(tsFileName, tSMessagePackWriter.FlushAndGetArray()); |
|
|
if ((jt1078Package.Timestamp - firstTimespan) > 10 * 1000) |
|
|
if ((jt1078Package.Timestamp - firstTimespan) > 10 * 1000) |
|
|
{ |
|
|
{ |
|
|
//按设定的时间(默认为10秒)切分ts文件 |
|
|
//按设定的时间(默认为10秒)切分ts文件 |
|
|
TsFirst1078PackageDic.TryRemove(jt1078Package.SIM, out var _); |
|
|
|
|
|
tsFileInfoQueue.Enqueue(new TsFileInfo { FileName= tsNewFileName, Duration= (jt1078Package.Timestamp - firstTimespan)/1000.0 }); |
|
|
|
|
|
m3U8Option.TsFileCount++; |
|
|
|
|
|
|
|
|
TsFirst1078PackageDic.TryRemove($"{jt1078Package.SIM}_{jt1078Package.LogicChannelNumber}", out var _); |
|
|
|
|
|
var tsFileInfo = new TsFileInfo { FileName = tsNewFileName, Duration = (jt1078Package.Timestamp - firstTimespan) / 1000.0 }; |
|
|
|
|
|
CreateM3U8File(tsFileInfo); |
|
|
|
|
|
m3U8Option.TsFileSerialNo++; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
|
|
|
if (File.Exists(tsFileName)) File.Delete(tsFileName); |
|
|
var sdt = tSEncoder.CreateSDT(jt1078Package); |
|
|
var sdt = tSEncoder.CreateSDT(jt1078Package); |
|
|
tSMessagePackWriter.WriteArray(sdt); |
|
|
tSMessagePackWriter.WriteArray(sdt); |
|
|
var pat = tSEncoder.CreatePAT(jt1078Package); |
|
|
var pat = tSEncoder.CreatePAT(jt1078Package); |
|
@@ -60,68 +63,54 @@ namespace JT1078.Hls |
|
|
tSMessagePackWriter.WriteArray(pmt); |
|
|
tSMessagePackWriter.WriteArray(pmt); |
|
|
var pes = tSEncoder.CreatePES(jt1078Package); |
|
|
var pes = tSEncoder.CreatePES(jt1078Package); |
|
|
tSMessagePackWriter.WriteArray(pes); |
|
|
tSMessagePackWriter.WriteArray(pes); |
|
|
CreateTsFile(fileName, tSMessagePackWriter.FlushAndGetArray()); |
|
|
|
|
|
TsFirst1078PackageDic.TryAdd(jt1078Package.SIM, jt1078Package.Timestamp); |
|
|
|
|
|
|
|
|
CreateTsFile(tsFileName, tSMessagePackWriter.FlushAndGetArray()); |
|
|
|
|
|
TsFirst1078PackageDic.TryAdd($"{jt1078Package.SIM}_{jt1078Package.LogicChannelNumber}", jt1078Package.Timestamp); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public void CreateM3U8File() |
|
|
|
|
|
|
|
|
private void CreateM3U8File(TsFileInfo tsFileInfo) |
|
|
{ |
|
|
{ |
|
|
//ecode_slice_header error 以非关键帧开始的报错信息 |
|
|
//ecode_slice_header error 以非关键帧开始的报错信息 |
|
|
if (tsFileInfoQueue.TryDequeue(out var tsFileInfo)) |
|
|
|
|
|
|
|
|
string tsFileSerialNo = string.Empty; |
|
|
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
|
|
sb.AppendLine("#EXTM3U");//开始 |
|
|
|
|
|
sb.AppendLine("#EXT-X-VERSION:3");//版本号 |
|
|
|
|
|
sb.AppendLine("#EXT-X-ALLOW-CACHE:NO");//是否允许cache |
|
|
|
|
|
sb.AppendLine($"#EXT-X-TARGETDURATION:{m3U8Option.TsFileMaxSecond}");//第一个TS分片的序列号 |
|
|
|
|
|
sb.AppendLine($"#EXT-X-MEDIA-SEQUENCE:{(m3U8Option.TsFileSerialNo - m3U8Option.TsFileCapacity > 0 ? (m3U8Option.TsFileSerialNo - m3U8Option.TsFileCapacity) : 0)}"); //默认第一个文件为0 |
|
|
|
|
|
Queue<string> fileBody = new Queue<string>(); |
|
|
|
|
|
using (FileStream fs = new FileStream(m3U8Option.M3U8FileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) |
|
|
|
|
|
using (StreamReader sr = new StreamReader(fs)) |
|
|
{ |
|
|
{ |
|
|
string firstTsIndex = string.Empty; |
|
|
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
|
|
List<string> fileHeader = new List<string>() { |
|
|
|
|
|
"#EXTM3U",//开始 |
|
|
|
|
|
"#EXT-X-VERSION:3",//版本号 |
|
|
|
|
|
"#EXT-X-ALLOW-CACHE:NO",//是否允许cache |
|
|
|
|
|
$"#EXT-X-TARGETDURATION:{m3U8Option.TsFileMaxSecond}",//第一个TS分片的序列号 |
|
|
|
|
|
$"#EXT-X-MEDIA-SEQUENCE:firstTsIndex" |
|
|
|
|
|
}; |
|
|
|
|
|
Queue<string> fileBody = new Queue<string>(); |
|
|
|
|
|
if (!File.Exists(m3U8Option.M3U8Filepath)) File.Create(m3U8Option.M3U8Filepath); |
|
|
|
|
|
using(FileStream fs=new FileStream(m3U8Option.M3U8Filepath,FileMode.Open,FileAccess.Read,FileShare.ReadWrite)) |
|
|
|
|
|
using (StreamReader sr = new StreamReader(fs)) |
|
|
|
|
|
|
|
|
while (!sr.EndOfStream) |
|
|
{ |
|
|
{ |
|
|
while (!sr.EndOfStream) |
|
|
|
|
|
{ |
|
|
|
|
|
var text = sr.ReadLine(); |
|
|
|
|
|
if (text.Length == 0) continue; |
|
|
|
|
|
if (fileHeader.Contains(text)) continue; |
|
|
|
|
|
if (text.StartsWith("#EXT-X-MEDIA-SEQUENCE")) continue; |
|
|
|
|
|
fileBody.Enqueue(text); |
|
|
|
|
|
} |
|
|
|
|
|
if (fileBody.Count >= m3U8Option.TsFileCapacity * 2) |
|
|
|
|
|
{ |
|
|
|
|
|
var deleteTsFileName_extraInfo = fileBody.Dequeue(); |
|
|
|
|
|
var deleteTsFileName = fileBody.Dequeue(); |
|
|
|
|
|
tsDelFileNameQueue.Enqueue(deleteTsFileName); |
|
|
|
|
|
|
|
|
|
|
|
fileBody.Enqueue($"#EXTINF:{tsFileInfo.Duration},"); |
|
|
|
|
|
fileBody.Enqueue(tsFileInfo.FileName); |
|
|
|
|
|
|
|
|
|
|
|
firstTsIndex = fileBody.ElementAt(1).Replace(".ts", ""); |
|
|
|
|
|
} |
|
|
|
|
|
else { |
|
|
|
|
|
fileBody.Enqueue($"#EXTINF:{tsFileInfo.Duration},"); |
|
|
|
|
|
fileBody.Enqueue(tsFileInfo.FileName); |
|
|
|
|
|
|
|
|
var text = sr.ReadLine(); |
|
|
|
|
|
if (text.Length == 0) continue; |
|
|
|
|
|
if (sb.ToString().Contains(text.Split(':')[0])) continue; |
|
|
|
|
|
fileBody.Enqueue(text); |
|
|
|
|
|
} |
|
|
|
|
|
if (fileBody.Count >= m3U8Option.TsFileCapacity * 2) |
|
|
|
|
|
{ |
|
|
|
|
|
var deleteTsFileName_extraInfo = fileBody.Dequeue(); |
|
|
|
|
|
var deleteTsFileName = fileBody.Dequeue(); |
|
|
|
|
|
tsDelFileNameQueue.Enqueue(deleteTsFileName); |
|
|
|
|
|
|
|
|
firstTsIndex = fileBody.ElementAt(1).Replace(".ts", ""); |
|
|
|
|
|
} |
|
|
|
|
|
fileHeader.ForEach((m) => { |
|
|
|
|
|
if (m.Contains("firstTsIndex")) m = m.Replace("firstTsIndex", firstTsIndex); |
|
|
|
|
|
sb.AppendLine(m); |
|
|
|
|
|
}); |
|
|
|
|
|
fileBody.ToList().ForEach(m => { |
|
|
|
|
|
sb.AppendLine(m); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
fileBody.Enqueue($"#EXTINF:{tsFileInfo.Duration},"); |
|
|
|
|
|
fileBody.Enqueue(tsFileInfo.FileName); |
|
|
} |
|
|
} |
|
|
using (FileStream fs = new FileStream(m3U8Option.M3U8Filepath, FileMode.Create,FileAccess.Write, FileShare.ReadWrite)) |
|
|
|
|
|
using (StreamWriter sw = new StreamWriter(fs)) |
|
|
|
|
|
|
|
|
else |
|
|
{ |
|
|
{ |
|
|
sw.Write(sb.ToString()); |
|
|
|
|
|
|
|
|
fileBody.Enqueue($"#EXTINF:{tsFileInfo.Duration},"); |
|
|
|
|
|
fileBody.Enqueue(tsFileInfo.FileName); |
|
|
} |
|
|
} |
|
|
|
|
|
fileBody.ToList().ForEach(m => { |
|
|
|
|
|
sb.AppendLine(m); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
using (FileStream fs = new FileStream(m3U8Option.M3U8FileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) |
|
|
|
|
|
using (StreamWriter sw = new StreamWriter(fs)) |
|
|
|
|
|
{ |
|
|
|
|
|
sw.Write(sb.ToString()); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|