diff --git a/README.md b/README.md
index 5af94bd..c3a6453 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,7 @@
3. 了解WebSocket消息推送
4. [了解flv.js](https://github.com/bilibili/flv.js)
5. [了解hls.js](https://github.com/video-dev/hls.js)
+6. 了解fmp4
> 注意:暂不支持音频
@@ -14,6 +15,7 @@
| --- | ---| --- |---|---|
| flv | 😀| ☹ |😀|http-flv、ws-flv|
| m3u8 | 😀| ☹ |😀|http|
+| fmp4 | 😀| ☹ |☹|http-fmp4、ws-fmp4|
## NuGet安装
diff --git a/src/JT1078.Gateway.Abstractions/IJT1078MsgProducer.cs b/src/JT1078.Gateway.Abstractions/IJT1078MsgProducer.cs
index 4abab68..07d889c 100644
--- a/src/JT1078.Gateway.Abstractions/IJT1078MsgProducer.cs
+++ b/src/JT1078.Gateway.Abstractions/IJT1078MsgProducer.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
namespace JT1078.Gateway.Abstractions
@@ -12,6 +13,7 @@ namespace JT1078.Gateway.Abstractions
///
/// 设备sim终端号
/// jt1078 hex data
- ValueTask ProduceAsync(string sim, byte[] data);
+ /// cts
+ ValueTask ProduceAsync(string sim, byte[] data, CancellationToken cancellationToken = default);
}
}
diff --git a/src/JT1078.Gateway.Abstractions/JT1078.Gateway.Abstractions.csproj b/src/JT1078.Gateway.Abstractions/JT1078.Gateway.Abstractions.csproj
index 2da8e4e..de064f4 100644
--- a/src/JT1078.Gateway.Abstractions/JT1078.Gateway.Abstractions.csproj
+++ b/src/JT1078.Gateway.Abstractions/JT1078.Gateway.Abstractions.csproj
@@ -33,7 +33,7 @@
-
+
diff --git a/src/JT1078.Gateway.Abstractions/JT1078.Gateway.Abstractions.xml b/src/JT1078.Gateway.Abstractions/JT1078.Gateway.Abstractions.xml
index d46ec53..23c27a9 100644
--- a/src/JT1078.Gateway.Abstractions/JT1078.Gateway.Abstractions.xml
+++ b/src/JT1078.Gateway.Abstractions/JT1078.Gateway.Abstractions.xml
@@ -9,12 +9,13 @@
传输协议类型
-
+
设备sim终端号
jt1078 hex data
+ cts
diff --git a/src/JT1078.Gateway.InMemoryMQ/JT1078MsgProducer.cs b/src/JT1078.Gateway.InMemoryMQ/JT1078MsgProducer.cs
index 1b93f42..85b9d87 100644
--- a/src/JT1078.Gateway.InMemoryMQ/JT1078MsgProducer.cs
+++ b/src/JT1078.Gateway.InMemoryMQ/JT1078MsgProducer.cs
@@ -3,6 +3,7 @@ using JT1078.Protocol;
using System;
using System.Collections.Generic;
using System.Text;
+using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
@@ -24,9 +25,9 @@ namespace JT1078.Gateway.InMemoryMQ
}
- public async ValueTask ProduceAsync(string sim, byte[] data)
+ public async ValueTask ProduceAsync(string sim, byte[] data, CancellationToken cancellationToken = default)
{
- await Channel.Channel.Writer.WriteAsync((sim, data));
+ await Channel.Channel.Writer.WriteAsync((sim, data), cancellationToken);
}
}
}
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/JT1078.Gateway.TestNormalHosting.csproj b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/JT1078.Gateway.TestNormalHosting.csproj
index f799921..1ff238f 100644
--- a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/JT1078.Gateway.TestNormalHosting.csproj
+++ b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/JT1078.Gateway.TestNormalHosting.csproj
@@ -31,11 +31,13 @@
Always
-
+
Always
-
+
Always
+
+
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Program.cs b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Program.cs
index 58172b1..f74782a 100644
--- a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Program.cs
+++ b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Program.cs
@@ -1,8 +1,10 @@
using JT1078.Flv;
+using JT1078.FMp4;
using JT1078.Gateway.InMemoryMQ;
using JT1078.Gateway.TestNormalHosting.Services;
using JT1078.Hls;
using JT1078.Hls.Options;
+using JT1078.Protocol.H264;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@@ -35,20 +37,19 @@ namespace JT1078.Gateway.TestNormalHosting
.ConfigureServices((hostContext, services) =>
{
services.AddMemoryCache();
- services.AddSingleton();
- services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
//flv视频解码器
services.AddSingleton();
//hls视频解码器
services.AddSingleton();
services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
//添加hls依赖项
services.AddHlsGateway(hostContext.Configuration);
services.Configure(hostContext.Configuration.GetSection("M3U8Option"));
var m3u8Option = services.BuildServiceProvider().GetRequiredService>().Value;
services.AddSingleton(m3u8Option);
-
//使用内存队列实现会话通知
services.AddJT1078Gateway(hostContext.Configuration)
.AddTcp()
@@ -60,6 +61,7 @@ namespace JT1078.Gateway.TestNormalHosting
//内存队列没有做分发,可以自己实现。
services.AddHostedService();
services.AddHostedService();
+ services.AddHostedService();
services.AddSingleton();
services.AddHostedService();
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Services/JT1078FMp4NormalMsgHostedService.cs b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Services/JT1078FMp4NormalMsgHostedService.cs
index b0461b1..a68f836 100644
--- a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Services/JT1078FMp4NormalMsgHostedService.cs
+++ b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Services/JT1078FMp4NormalMsgHostedService.cs
@@ -15,33 +15,37 @@ using JT1078.Protocol;
using System.Text.Json;
using System.Text.Json.Serialization;
using JT1078.FMp4;
+using JT1078.Protocol.H264;
+using System.Collections.Concurrent;
namespace JT1078.Gateway.TestNormalHosting.Services
{
public class JT1078FMp4NormalMsgHostedService : BackgroundService
{
- private IJT1078MsgConsumer JT1078MsgConsumer;
private JT1078HttpSessionManager HttpSessionManager;
private FMp4Encoder FM4Encoder;
+ private readonly H264Decoder H264Decoder;
private ILogger Logger;
private IMemoryCache memoryCache;
- private const string ikey = "IKEY";
+ private const string ikey = "IFMp4KEY";
private MessageDispatchDataService messageDispatchDataService;
+ private ConcurrentDictionary> avFrameDict;
public JT1078FMp4NormalMsgHostedService(
MessageDispatchDataService messageDispatchDataService,
IMemoryCache memoryCache,
ILoggerFactory loggerFactory,
+ H264Decoder h264Decoder,
FMp4Encoder fM4Encoder,
- JT1078HttpSessionManager httpSessionManager,
- IJT1078MsgConsumer msgConsumer)
+ JT1078HttpSessionManager httpSessionManager)
{
Logger = loggerFactory.CreateLogger();
- JT1078MsgConsumer = msgConsumer;
HttpSessionManager = httpSessionManager;
FM4Encoder = fM4Encoder;
+ H264Decoder = h264Decoder;
this.memoryCache = memoryCache;
this.messageDispatchDataService = messageDispatchDataService;
+ avFrameDict = new ConcurrentDictionary>();
}
protected async override Task ExecuteAsync(CancellationToken stoppingToken)
{
@@ -49,7 +53,8 @@ namespace JT1078.Gateway.TestNormalHosting.Services
{
var data = await messageDispatchDataService.FlvChannel.Reader.ReadAsync();
try
- {
+ {
+ var nalus = H264Decoder.ParseNALU(data);
if (Logger.IsEnabled(LogLevel.Debug))
{
Logger.LogDebug(JsonSerializer.Serialize(HttpSessionManager.GetAll()));
@@ -58,30 +63,66 @@ namespace JT1078.Gateway.TestNormalHosting.Services
string key = $"{data.GetKey()}_{ikey}";
if (data.Label3.DataType == Protocol.Enums.JT1078DataType.视频I帧)
{
- memoryCache.Set(key, data);
+ var moov = FM4Encoder.EncoderMoovBox(nalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.SPS),
+ nalus.FirstOrDefault(f => f.NALUHeader.NalUnitType == NalUnitType.PPS));
+ memoryCache.Set(key, moov);
}
var httpSessions = HttpSessionManager.GetAllBySimAndChannelNo(data.SIM.TrimStart('0'), data.LogicChannelNumber);
var firstHttpSessions = httpSessions.Where(w => !w.FirstSend).ToList();
if (firstHttpSessions.Count > 0)
{
- if (memoryCache.TryGetValue(key, out JT1078Package idata))
+ try
{
- try
- {
-
- }
- catch (Exception ex)
+ var flvVideoBuffer = FM4Encoder.EncoderFtypBox();
+ memoryCache.TryGetValue(key, out byte[] moovBuffer);
+ foreach (var session in firstHttpSessions)
{
- Logger.LogError(ex, $"{data.SIM},{true},{data.SN},{data.LogicChannelNumber},{data.Label3.DataType.ToString()},{data.Label3.SubpackageType.ToString()},{data.Bodies.ToHexString()}");
+ HttpSessionManager.SendAVData(session, flvVideoBuffer, true);
+ if (moovBuffer != null)
+ {
+ HttpSessionManager.SendAVData(session, moovBuffer, false);
+ }
}
}
+ catch (Exception ex)
+ {
+ Logger.LogError(ex, $"{data.SIM},{true},{data.SN},{data.LogicChannelNumber},{data.Label3.DataType.ToString()},{data.Label3.SubpackageType.ToString()},{data.Bodies.ToHexString()}");
+ }
}
var otherHttpSessions = httpSessions.Where(w => w.FirstSend).ToList();
if (otherHttpSessions.Count > 0)
{
try
{
-
+ if(!avFrameDict.TryGetValue(key, out List frames))
+ {
+ frames = new List();
+ avFrameDict.TryAdd(key, frames);
+ }
+ foreach (var nalu in nalus)
+ {
+ if (nalu.Slice)
+ {
+ //H264 NALU slice first_mb_in_slice
+ frames.Add(nalu);
+ }
+ else
+ {
+ if (nalus.Count > 0)
+ {
+ var otherBuffer = FM4Encoder.EncoderOtherVideoBox(frames);
+ foreach (var session in otherHttpSessions)
+ {
+ if (otherBuffer != null)
+ {
+ HttpSessionManager.SendAVData(session, otherBuffer, false);
+ }
+ }
+ frames.Clear();
+ }
+ frames.Add(nalu);
+ }
+ }
}
catch (Exception ex)
{
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Services/MessageDispatchDataService.cs b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Services/MessageDispatchDataService.cs
index 07c81d4..5f37a7a 100644
--- a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Services/MessageDispatchDataService.cs
+++ b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Services/MessageDispatchDataService.cs
@@ -12,5 +12,6 @@ namespace JT1078.Gateway.TestNormalHosting.Services
{
public Channel HlsChannel = Channel.CreateUnbounded();
public Channel FlvChannel = Channel.CreateUnbounded();
+ public Channel FMp4Channel = Channel.CreateUnbounded();
}
}
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Services/MessageDispatchHostedService.cs b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Services/MessageDispatchHostedService.cs
index 06624ef..96acf3c 100644
--- a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Services/MessageDispatchHostedService.cs
+++ b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/Services/MessageDispatchHostedService.cs
@@ -20,7 +20,7 @@ namespace JT1078.Gateway.TestNormalHosting.Services
private readonly MessageDispatchDataService messageDispatchDataService;
public MessageDispatchHostedService(IJT1078MsgConsumer JT1078MsgConsumer,
- MessageDispatchDataService messageDispatchDataService) {
+ MessageDispatchDataService messageDispatchDataService) {
this.JT1078MsgConsumer = JT1078MsgConsumer;
this.messageDispatchDataService = messageDispatchDataService;
}
@@ -33,8 +33,9 @@ namespace JT1078.Gateway.TestNormalHosting.Services
var merge = JT1078.Protocol.JT1078Serializer.Merge(package);
if (merge != null)
{
- await messageDispatchDataService.HlsChannel.Writer.WriteAsync(merge);
- await messageDispatchDataService.FlvChannel.Writer.WriteAsync(merge);
+ await messageDispatchDataService.HlsChannel.Writer.WriteAsync(merge, stoppingToken);
+ await messageDispatchDataService.FlvChannel.Writer.WriteAsync(merge, stoppingToken);
+ await messageDispatchDataService.FMp4Channel.Writer.WriteAsync(merge, stoppingToken);
}
});
return Task.CompletedTask;
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/flv.min.js b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/flv_demo/flv.min.js
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/flv.min.js
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/flv_demo/flv.min.js
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/index.html b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/flv_demo/index.html
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/index.html
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/flv_demo/index.html
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/fmp4_demo/index.html b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/fmp4_demo/index.html
new file mode 100644
index 0000000..6d0c1e4
--- /dev/null
+++ b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/fmp4_demo/index.html
@@ -0,0 +1,201 @@
+
+
+
+
+
+ WebSocket MSE Fmp4 demo
+
+
+ MSE FMp4 Demo
+
+
+
+
+
\ No newline at end of file
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/10.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/10.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/10.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/10.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/11.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/11.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/11.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/11.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/12.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/12.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/12.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/12.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/13.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/13.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/13.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/13.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/14.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/14.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/14.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/14.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/15.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/15.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/15.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/15.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/16.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/16.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/16.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/16.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/17.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/17.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/17.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/17.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/7.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/7.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/7.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/7.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/8.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/8.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/8.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/8.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/9.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/9.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/9.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/9.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo.m3u8 b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/demo.m3u8
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo.m3u8
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/demo.m3u8
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/demo.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/demo.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo0.ts b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/demo0.ts
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/demo0.ts
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/demo0.ts
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/index.html b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/index.html
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/index.html
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/index.html
diff --git a/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/live.m3u8 b/src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/live.m3u8
similarity index 100%
rename from src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/demo/live.m3u8
rename to src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/hls_demo/live.m3u8