Browse Source

优化一下m3u8

tags/v1.1.0
waterliu99 4 years ago
parent
commit
01e8ebac23
5 changed files with 56 additions and 68 deletions
  1. +1
    -1
      src/JT1078.Flv/FlvEncoder.cs
  2. +2
    -3
      src/JT1078.Hls.Test/M3U8_Test.cs
  3. +49
    -60
      src/JT1078.Hls/M3U8FileManage.cs
  4. +3
    -3
      src/JT1078.Hls/Options/M3U8Option.cs
  5. +1
    -1
      src/JT1078.Hls/TSEncoder.cs

+ 1
- 1
src/JT1078.Flv/FlvEncoder.cs View File

@@ -41,7 +41,7 @@ namespace JT1078.Flv
readonly H264Decoder h264Decoder = new H264Decoder();
public FlvEncoder(int sampleRate = 8000, int channels = 1, int sampleBit = 16, bool adts = false)
{
faacEncoder = new FaacEncoder(sampleRate, channels, sampleBit, adts);
//faacEncoder = new FaacEncoder(sampleRate, channels, sampleBit, adts);
}

/// <summary>


+ 2
- 3
src/JT1078.Hls.Test/M3U8_Test.cs View File

@@ -20,9 +20,9 @@ namespace JT1078.Hls.Test
{
var hls_file_directory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "terminalno");
if (!File.Exists(hls_file_directory)) Directory.CreateDirectory(hls_file_directory);
var m3u8_filepath = Path.Combine(hls_file_directory, "live.m3u8");
var m3u8_filename = Path.Combine(hls_file_directory, "live.m3u8");
TSEncoder tSEncoder = new TSEncoder();
var m3u8Manage = new M3U8FileManage(new Options.M3U8Option { HlsFileDirectory = hls_file_directory, M3U8Filepath = m3u8_filepath }, tSEncoder);
var m3u8Manage = new M3U8FileManage(new Options.M3U8Option { HlsFileDirectory = hls_file_directory, M3U8FileName = m3u8_filename }, tSEncoder);
var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "H264", "JT1078_3.txt"));
foreach (var line in lines)
@@ -34,7 +34,6 @@ namespace JT1078.Hls.Test
if (fullpackage != null)
{
m3u8Manage.CreateTsData(fullpackage);
m3u8Manage.CreateM3U8File();
}
}
}


+ 49
- 60
src/JT1078.Hls/M3U8FileManage.cs View File

@@ -33,25 +33,28 @@ namespace JT1078.Hls
}

public void CreateTsData(JT1078Package jt1078Package) {
if (!File.Exists(m3U8Option.M3U8FileName)) File.Create(m3U8Option.M3U8FileName);//创建m3u8文件
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);
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);
CreateTsFile(fileName, tSMessagePackWriter.FlushAndGetArray());
CreateTsFile(tsFileName, tSMessagePackWriter.FlushAndGetArray());
if ((jt1078Package.Timestamp - firstTimespan) > 10 * 1000)
{
//按设定的时间(默认为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 {
if (File.Exists(tsFileName)) File.Delete(tsFileName);
var sdt = tSEncoder.CreateSDT(jt1078Package);
tSMessagePackWriter.WriteArray(sdt);
var pat = tSEncoder.CreatePAT(jt1078Package);
@@ -60,68 +63,54 @@ namespace JT1078.Hls
tSMessagePackWriter.WriteArray(pmt);
var pes = tSEncoder.CreatePES(jt1078Package);
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 以非关键帧开始的报错信息
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());
}
}



+ 3
- 3
src/JT1078.Hls/Options/M3U8Option.cs View File

@@ -18,13 +18,13 @@ namespace JT1078.Hls.Options
/// </summary>
public int TsFileMaxSecond { get; set; } = 10;
/// <summary>
/// ts文件个数
/// 当前ts文件序号
/// </summary>
public int TsFileCount { get; set; } = 0;
public int TsFileSerialNo { get; set; } = 0;
/// <summary>
/// m3u8文件
/// </summary>
public string M3U8Filepath { get; set; }
public string M3U8FileName { get; set; }
/// <summary>
/// hls文件路径
/// </summary>


+ 1
- 1
src/JT1078.Hls/TSEncoder.cs View File

@@ -139,7 +139,7 @@ namespace JT1078.Hls
TSArrayPool.Return(buffer);
}
}
public byte[] CreatePES(JT1078Package jt1078Package, int minBufferSize = 188)
public byte[] CreatePES(JT1078Package jt1078Package, int minBufferSize = 1024)
{
//将1078一帧的数据拆分成一小段一小段的PES包
byte[] buffer = TSArrayPool.Rent(jt1078Package.Bodies.Length + minBufferSize);


Loading…
Cancel
Save