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