diff --git a/src/JT1078.Flv.Test/JT1078.Flv.Test.csproj b/src/JT1078.Flv.Test/JT1078.Flv.Test.csproj
index 938f334..dfff8a5 100644
--- a/src/JT1078.Flv.Test/JT1078.Flv.Test.csproj
+++ b/src/JT1078.Flv.Test/JT1078.Flv.Test.csproj
@@ -5,6 +5,7 @@
+
@@ -16,10 +17,6 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
@@ -51,9 +48,6 @@
Always
-
- Always
-
diff --git a/src/JT1078.Flv.Test/Libs/libfaac.dll b/src/JT1078.Flv.Test/Libs/libfaac.dll
deleted file mode 100644
index a67c71f..0000000
Binary files a/src/JT1078.Flv.Test/Libs/libfaac.dll and /dev/null differ
diff --git a/src/JT1078.Flv/FlvEncoder.cs b/src/JT1078.Flv/FlvEncoder.cs
index ab933db..2328dfe 100644
--- a/src/JT1078.Flv/FlvEncoder.cs
+++ b/src/JT1078.Flv/FlvEncoder.cs
@@ -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);
}
///
diff --git a/src/JT1078.Flv/JT1078.Flv.csproj b/src/JT1078.Flv/JT1078.Flv.csproj
index 2003d3f..2442c56 100644
--- a/src/JT1078.Flv/JT1078.Flv.csproj
+++ b/src/JT1078.Flv/JT1078.Flv.csproj
@@ -14,7 +14,7 @@
https://github.com/SmallChi/JT1078/blob/master/LICENSE
https://github.com/SmallChi/JT1078/blob/master/LICENSE
false
- 1.0.0-preview6
+ 1.0.0-preview7
false
true
LICENSE
diff --git a/src/JT1078.Hls/M3U8FileManage.cs b/src/JT1078.Hls/M3U8FileManage.cs
index 909edf3..260bb6c 100644
--- a/src/JT1078.Hls/M3U8FileManage.cs
+++ b/src/JT1078.Hls/M3U8FileManage.cs
@@ -22,7 +22,6 @@ namespace JT1078.Hls
public readonly M3U8Option m3U8Option;
ConcurrentDictionary curTsFileInfoDic = new ConcurrentDictionary();//当前文件信息
ConcurrentDictionary> tsFileInfoQueueDic = new ConcurrentDictionary>();
- ConcurrentDictionary TsFirst1078PackageDic = new ConcurrentDictionary();
public M3U8FileManage(M3U8Option m3U8Option, TSEncoder tSEncoder)
{
@@ -33,46 +32,51 @@ namespace JT1078.Hls
/// 生成ts和m3u8文件
///
///
- public void CreateTsData(JT1078Package jt1078Package) {
- string key = $"{jt1078Package.SIM}_{jt1078Package.LogicChannelNumber}";
+ public void CreateTsData(JT1078Package jt1078Package)
+ {
+ string key = jt1078Package.GetKey();
string hlsFileDirectory = m3U8Option.HlsFileDirectory;
string m3u8FileName = Path.Combine(hlsFileDirectory, m3U8Option.M3U8FileName);
if (!File.Exists(m3u8FileName)) File.Create(m3u8FileName);//创建m3u8文件
-
var buff = TSArrayPool.Rent(jt1078Package.Bodies.Length + 1024);
TSMessagePackWriter tSMessagePackWriter = new TSMessagePackWriter(buff);
-
- var curTsFileInfo = CreateTsFileInfo(key, jt1078Package);
- if (!curTsFileInfo.IsCreateTsFile)
+ try
{
- var pes = tSEncoder.CreatePES(jt1078Package);
- tSMessagePackWriter.WriteArray(pes);
- CreateTsFile(curTsFileInfo.FileName, tSMessagePackWriter.FlushAndGetArray());
-
- curTsFileInfo.Duration = (jt1078Package.Timestamp - curTsFileInfo.TsFirst1078PackageTimeStamp) / 1000.0;
- //按设定的时间(默认为10秒)切分ts文件
- if (curTsFileInfo.Duration > m3U8Option.TsFileMaxSecond)
+ var curTsFileInfo = CreateTsFileInfo(key);
+ if (!curTsFileInfo.IsCreateTsFile)
+ {
+ var pes = tSEncoder.CreatePES(jt1078Package);
+ tSMessagePackWriter.WriteArray(pes);
+ CreateTsFile(curTsFileInfo.FileName, tSMessagePackWriter.FlushAndGetArray());
+ curTsFileInfo.Duration = (jt1078Package.Timestamp - curTsFileInfo.TsFirst1078PackageTimeStamp) / 1000.0;
+ //按设定的时间(默认为10秒)切分ts文件
+ if (curTsFileInfo.Duration > m3U8Option.TsFileMaxSecond)
+ {
+ var tsFileInfoQueue = ManageTsFileInfo(key, curTsFileInfo);
+ CreateM3U8File(curTsFileInfo, tsFileInfoQueue);
+ var newTsFileInfo = new TsFileInfo { IsCreateTsFile = true, Duration = 0, TsFileSerialNo = ++curTsFileInfo.TsFileSerialNo };
+ curTsFileInfoDic.TryUpdate(key, newTsFileInfo, curTsFileInfo);
+ }
+ }
+ else
{
- var tsFileInfoQueue = ManageTsFileInfo(key, curTsFileInfo);
- CreateM3U8File(key, curTsFileInfo, tsFileInfoQueue);
- var newTsFileInfo = new TsFileInfo { IsCreateTsFile = true, Duration = 0, TsFileSerialNo = ++curTsFileInfo.TsFileSerialNo };
- curTsFileInfoDic.TryUpdate(key, newTsFileInfo, curTsFileInfo);
+ curTsFileInfo.IsCreateTsFile = false;
+ curTsFileInfo.TsFirst1078PackageTimeStamp = jt1078Package.Timestamp;
+ curTsFileInfo.FileName = $"{curTsFileInfo.TsFileSerialNo}.ts";
+ var sdt = tSEncoder.CreateSDT(jt1078Package);
+ tSMessagePackWriter.WriteArray(sdt);
+ var pat = tSEncoder.CreatePAT(jt1078Package);
+ tSMessagePackWriter.WriteArray(pat);
+ var pmt = tSEncoder.CreatePMT(jt1078Package);
+ tSMessagePackWriter.WriteArray(pmt);
+ var pes = tSEncoder.CreatePES(jt1078Package);
+ tSMessagePackWriter.WriteArray(pes);
+ CreateTsFile(curTsFileInfo.FileName, tSMessagePackWriter.FlushAndGetArray());
}
}
- else {
- curTsFileInfo.IsCreateTsFile = false;
- curTsFileInfo.TsFirst1078PackageTimeStamp = jt1078Package.Timestamp;
- curTsFileInfo.FileName = $"{curTsFileInfo.TsFileSerialNo}.ts";
-
- var sdt = tSEncoder.CreateSDT(jt1078Package);
- tSMessagePackWriter.WriteArray(sdt);
- var pat = tSEncoder.CreatePAT(jt1078Package);
- tSMessagePackWriter.WriteArray(pat);
- var pmt = tSEncoder.CreatePMT(jt1078Package);
- tSMessagePackWriter.WriteArray(pmt);
- var pes = tSEncoder.CreatePES(jt1078Package);
- tSMessagePackWriter.WriteArray(pes);
- CreateTsFile(curTsFileInfo.FileName, tSMessagePackWriter.FlushAndGetArray());
+ finally
+ {
+ TSArrayPool.Return(buff);
}
}
///
@@ -81,7 +85,8 @@ namespace JT1078.Hls
///
///
///
- private Queue ManageTsFileInfo(string key, TsFileInfo curTsFileInfo) {
+ private Queue ManageTsFileInfo(string key, TsFileInfo curTsFileInfo)
+ {
if (tsFileInfoQueueDic.TryGetValue(key, out var tsFileInfoQueue))
{
if (tsFileInfoQueue.Count >= m3U8Option.TsFileCapacity)
@@ -103,12 +108,10 @@ namespace JT1078.Hls
///
/// 创建M3U8文件
///
- ///
///
- private void CreateM3U8File(string key,TsFileInfo curTsFileInfo, Queue tsFileInfoQueue)
+ private void CreateM3U8File(TsFileInfo curTsFileInfo, Queue tsFileInfoQueue)
{
//ecode_slice_header error 以非关键帧开始生成的ts,通过ffplay播放会出现报错信息
- string tsFileSerialNo = string.Empty;
StringBuilder sb = new StringBuilder();
sb.AppendLine("#EXTM3U");//开始
sb.AppendLine("#EXT-X-VERSION:3");//版本号
@@ -123,9 +126,9 @@ namespace JT1078.Hls
sb.AppendLine(tsFileInfo.FileName);
}
using (FileStream fs = new FileStream(m3U8Option.M3U8FileName, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
- using (StreamWriter sw = new StreamWriter(fs))
{
- sw.Write(sb.ToString());
+ var buffer = Encoding.UTF8.GetBytes(sb.ToString());
+ fs.Write(buffer,0, buffer.Length);
}
}
@@ -133,9 +136,9 @@ namespace JT1078.Hls
/// 创建TS文件信息
///
///
- ///
///
- private TsFileInfo CreateTsFileInfo(string key,JT1078Package jt1078Package) {
+ private TsFileInfo CreateTsFileInfo(string key)
+ {
if (!curTsFileInfoDic.TryGetValue(key, out var curTsFileInfo))
{
curTsFileInfo = new TsFileInfo();
@@ -157,41 +160,58 @@ namespace JT1078.Hls
}
}
+ /////
+ ///// 添加结束标识
+ ///// 直播流用不到
+ /////
+ /////
+ ////public void AppendM3U8End()
+ ////{
+ //// StringBuilder sb = new StringBuilder();
+ //// sb.AppendLine("#EXT-X-ENDLIST"); //m3u8文件结束符 表示视频已经结束 有这个标志同时也说明当前流是一个非直播流
+ //// //#EXT-X-PLAYLIST-TYPE:VOD/Live //VOD表示当前视频流不是一个直播流,而是点播流(也就是视频的全部ts文件已经生成)
+ ////}
+
///
- /// 添加结束标识
- /// 直播流用不到
- ///
- ///
- //public void AppendM3U8End()
- //{
- // StringBuilder sb = new StringBuilder();
- // sb.AppendLine("#EXT-X-ENDLIST"); //m3u8文件结束符 表示视频已经结束 有这个标志同时也说明当前流是一个非直播流
- // //#EXT-X-PLAYLIST-TYPE:VOD/Live //VOD表示当前视频流不是一个直播流,而是点播流(也就是视频的全部ts文件已经生成)
- //}
- }
- ///
- /// TS文件信息
- ///
- public class TsFileInfo {
- ///
- /// ts文件名
- ///
- public string FileName { get; set; } = "0.ts";
- ///
- /// 持续时间
- ///
- public double Duration { get; set; } = 0;
- ///
- /// 当前ts文件序号
- ///
- public int TsFileSerialNo { get; set; } = 0;
- ///
- /// 是否创建ts文件
+ /// 停止观看直播时清零数据
///
- public bool IsCreateTsFile { get; set; } = true;
+ ///
+ ///
+ public void Clear(string sim,int channelNo)
+ {
+ var key = $"{sim}_{channelNo}";
+ curTsFileInfoDic.TryRemove(key, out _);
+ tsFileInfoQueueDic.TryRemove(key, out _);
+ var directory = Path.Combine(m3U8Option.HlsFileDirectory, key);
+ if (Directory.Exists(directory)) Directory.Delete(directory);
+ }
+
///
- /// ts文件第一个jt1078包的时间戳
+ /// TS文件信息
///
- public ulong TsFirst1078PackageTimeStamp { get; set; } = 0;
+ internal class TsFileInfo
+ {
+ ///
+ /// ts文件名
+ ///
+ public string FileName { get; set; } = "0.ts";
+ ///
+ /// 持续时间
+ ///
+ public double Duration { get; set; } = 0;
+ ///
+ /// 当前ts文件序号
+ ///
+ public int TsFileSerialNo { get; set; } = 0;
+ ///
+ /// 是否创建ts文件
+ ///
+ public bool IsCreateTsFile { get; set; } = true;
+ ///
+ /// ts文件第一个jt1078包的时间戳
+ ///
+ public ulong TsFirst1078PackageTimeStamp { get; set; } = 0;
+ }
}
+
}