浏览代码

1.修复http-flv跨域问题

2.完善发布包和文档
3.去掉无用项目
master
SmallChi(Koike) 4 年前
父节点
当前提交
bc55418bce
共有 34 个文件被更改,包括 37 次插入4282 次删除
  1. +13
    -5
      README.md
  2. +1
    -0
      nuget.bat
  3. +5
    -0
      publish.bat
  4. +3
    -1
      src/JT1078.Gateway.InMemoryMQ/JT1078.Gateway.InMemoryMQ.csproj
  5. +0
    -3106
      src/JT1078.Gateway.SimpleServer/Configs/NLog.xsd
  6. +0
    -56
      src/JT1078.Gateway.SimpleServer/Configs/nlog.unix.config
  7. +0
    -48
      src/JT1078.Gateway.SimpleServer/Configs/nlog.win.config
  8. +0
    -18
      src/JT1078.Gateway.SimpleServer/CustomHttpMiddleware.cs
  9. +0
    -107
      src/JT1078.Gateway.SimpleServer/HLS/FFMPEGHLSHostedService.cs
  10. +0
    -25
      src/JT1078.Gateway.SimpleServer/HLS/Startup.cs
  11. +0
    -9
      src/JT1078.Gateway.SimpleServer/HLS/appsettings.json
  12. +0
    -25
      src/JT1078.Gateway.SimpleServer/HLS/hls.html
  13. +0
    -2
      src/JT1078.Gateway.SimpleServer/HLS/hls.min.js
  14. +0
    -134
      src/JT1078.Gateway.SimpleServer/HTTPFLV/FFMPEGHTTPFLVHostedService.cs
  15. +0
    -26
      src/JT1078.Gateway.SimpleServer/HTTPFLV/flv.html
  16. +0
    -7
      src/JT1078.Gateway.SimpleServer/HTTPFLV/flv.min.js
  17. +0
    -54
      src/JT1078.Gateway.SimpleServer/Handlers/JT1078TcpMessageHandlers.cs
  18. +0
    -25
      src/JT1078.Gateway.SimpleServer/Handlers/JT1078UdpMessageHandlers.cs
  19. +0
    -24
      src/JT1078.Gateway.SimpleServer/HardwareCamera.cs
  20. +0
    -80
      src/JT1078.Gateway.SimpleServer/HexExtensions.cs
  21. +0
    -26
      src/JT1078.Gateway.SimpleServer/JT1078.Gateway.SimpleServer.csproj
  22. +0
    -17
      src/JT1078.Gateway.SimpleServer/JT1078WSFlv/JT1078WSFlvDataService.cs
  23. +0
    -108
      src/JT1078.Gateway.SimpleServer/JT1078WSFlv/JT1078WSFlvHostedService.cs
  24. +0
    -7
      src/JT1078.Gateway.SimpleServer/JT1078WSFlv/flv.min.js
  25. +0
    -41
      src/JT1078.Gateway.SimpleServer/JT1078WSFlv/index.html
  26. +0
    -86
      src/JT1078.Gateway.SimpleServer/Program.cs
  27. +0
    -58
      src/JT1078.Gateway.SimpleServer/RTMP/FFMPEGRTMPHostedService.cs
  28. +0
    -129
      src/JT1078.Gateway.SimpleServer/WSFLV/FFMPEGWSFLVHostedService.cs
  29. +0
    -7
      src/JT1078.Gateway.SimpleServer/WSFLV/flv.min.js
  30. +0
    -26
      src/JT1078.Gateway.SimpleServer/WSFLV/index.html
  31. +0
    -23
      src/JT1078.Gateway.SimpleServer/appsettings.json
  32. +2
    -1
      src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/index.html
  33. +12
    -0
      src/JT1078.Gateway/Extensions/JT1078HttpContextExtensions.cs
  34. +1
    -1
      src/Version.props

+ 13
- 5
README.md 查看文件

@@ -5,12 +5,20 @@
1. [熟悉JT1078协议](https://github.com/SmallChi/JT1078)
2. 了解Http Chunked编码
3. 了解WebSocket消息推送
4. [了解Flv.js](https://github.com/bilibili/flv.js)
4. [了解flv.js](https://github.com/bilibili/flv.js)
5. [了解hls.js](https://github.com/video-dev/hls.js)

目前只支持Http-Flv、WebSocket-Flv两种方式推流,经过一小时的测试延迟在3秒这样。
> 注意:暂不支持音频

| av | video | audio |test|request|
| --- | ---| --- |---|---|
| flv | 😀| ☹ |😀|http-flv、ws-flv|
| m3u8 | 😀| ☹ |☹|http|

## NuGet安装

| Package Name | Version | Downloads |
| --------------------- | -------------------------------------------------- | --------------------------------------------------- |
| Install-Package JT1078.Gateway | ![JT1078.Gateway](https://img.shields.io/nuget/v/JT1078.Gateway.svg) | ![JT1078.Gateway](https://img.shields.io/nuget/dt/JT1078.Gateway.svg) |
| Package Name | Version |Pre Version|Downloads|
| --- | ---| --- | --- |
| Install-Package JT1078.Gateway.Abstractions | ![JT1078.Gateway.Abstractions](https://img.shields.io/nuget/v/JT1078.Gateway.Abstractions.svg) | ![JT1078.Gateway.Abstractions](https://img.shields.io/nuget/vpre/JT1078.Gateway.Abstractions.svg) | ![JT1078.Gateway.Abstractions](https://img.shields.io/nuget/dt/JT1078.Gateway.Abstractions.svg) |
| Install-Package JT1078.Gateway | ![JT1078.Gateway](https://img.shields.io/nuget/v/JT1078.Gateway.svg) | ![JT1078.Gateway](https://img.shields.io/nuget/vpre/JT1078.Gateway.svg)|![JT1078.Gateway](https://img.shields.io/nuget/dt/JT1078.Gateway.svg) |
| Install-Package JT1078.Gateway.InMemoryMQ | ![JT1078.Gateway.InMemoryMQ](https://img.shields.io/nuget/v/JT1078.Gateway.InMemoryMQ.svg) | ![JT1078.Gateway.InMemoryMQ](https://img.shields.io/nuget/vpre/JT1078.Gateway.InMemoryMQ.svg) | ![JT1078.Gateway.InMemoryMQ](https://img.shields.io/nuget/dt/JT1078.Gateway.InMemoryMQ.svg) |

+ 1
- 0
nuget.bat 查看文件

@@ -0,0 +1 @@
dotnet nuget push .\nupkgs\*.nupkg -k apikey -s https://api.nuget.org/v3/index.json

+ 5
- 0
publish.bat 查看文件

@@ -0,0 +1,5 @@
dotnet pack .\src\JT1078.Gateway\JT1078.Gateway.csproj --no-build --output .\nupkgs
dotnet pack .\src\JT1078.Gateway.Abstractions\JT1078.Gateway.Abstractions.csproj --no-build --output .\nupkgs
dotnet pack .\src\JT1078.Gateway.InMemoryMQ\JT1078.Gateway.InMemoryMQ.csproj --no-build --output .\nupkgs

pause

+ 3
- 1
src/JT1078.Gateway.InMemoryMQ/JT1078.Gateway.InMemoryMQ.csproj 查看文件

@@ -23,7 +23,9 @@
<ItemGroup>
<PackageReference Include="System.Threading.Channels" Version="4.7.1" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\LICENSE" Pack="true" PackagePath="" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JT1078.Gateway.Abstractions\JT1078.Gateway.Abstractions.csproj" />
</ItemGroup>


+ 0
- 3106
src/JT1078.Gateway.SimpleServer/Configs/NLog.xsd
文件差异内容过多而无法显示
查看文件


+ 0
- 56
src/JT1078.Gateway.SimpleServer/Configs/nlog.unix.config 查看文件

@@ -1,56 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
参考:http://www.cnblogs.com/fuchongjundream/p/3936431.html
autoReload:自动再配置
internalLogFile:可以让NLog把内部的调试和异常信息都写入指定文件里程序没问题了,日志却出了问题。这个该怎么办,到底是哪里不正确了?假如日志本身除了bug该如何解决?这就需要日志排错。把日志的错误信息写入日志。
<nlog throwExceptions="true" />
<nlog internalLogFile="file.txt" />- 设置internalLogFile属性可以让NLog把内部的调试和异常信息都写入指定文件里。
<nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" /> - 决定内部日志的级别,级别越高,输出的日志信息越简洁。
<nlog internalLogToConsole="false|true" /> - 是否把内部日志输出到标准控制台。
<nlog internalLogToConsoleError="false|true" /> - 是否把内部日志输出到标准错误控制台 (stderr)。
设置throwExceptions属性为“true”可以让NLog不再阻挡这类异常,而是把它们抛给调用者。在部署是这样做可以帮我们快速定位问题。一旦应用程序已经正确配置了,我们建议把throwExceptions的值设为“false”,这样由于日志引发的问题不至于导致应用程序的崩溃。
-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogFile="wwwroot/logs/internalLog.txt"
internalLogLevel="Debug" >
<variable name="Directory" value="/data/logs/JT1078.Gateway"/>
<targets>
<target name="all" xsi:type="File"
fileName="${Directory}/all/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss} ${callsite} ${level}:${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}"/>
<target name="flvencoding" xsi:type="File"
fileName="${Directory}/flvencoding/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss}:${message}"/>
<target name="JT1078TcpMessageHandlers" xsi:type="File"
fileName="${Directory}/JT1078TcpMessageHandlers/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="JT1078TcpMessageHandlersHex" xsi:type="File"
fileName="${Directory}/JT1078TcpMessageHandlersHex/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="FlvEncoder" xsi:type="File"
fileName="${Directory}/FlvEncoder/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="JT1078TcpConnectionHandler" xsi:type="File"
fileName="${Directory}/JT1078TcpConnectionHandler/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="console" xsi:type="ColoredConsole"
useDefaultRowHighlightingRules="false"
layout="${date:format=yyyyMMddHHmmss} ${callsite} ${level} ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}">
<highlight-row condition="level == LogLevel.Debug" foregroundColor="DarkGray" />
<highlight-row condition="level == LogLevel.Info" foregroundColor="Gray" />
<highlight-row condition="level == LogLevel.Warn" foregroundColor="Yellow" />
<highlight-row condition="level == LogLevel.Error" foregroundColor="Red" />
<highlight-row condition="level == LogLevel.Fatal" foregroundColor="Red" backgroundColor="White" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Error" maxlevel="Fatal" writeTo="all"/>
<logger name="FlvEncoding" minlevel="Debug" maxlevel="Fatal" writeTo="flvencoding"/>
<logger name="JT1078.DotNetty.Tcp.Handlers.JT1078TcpConnectionHandler" minlevel="Debug" maxlevel="Fatal" writeTo="JT1078TcpConnectionHandler,console"/>
<logger name="JT1078TcpMessageHandlers" minlevel="Debug" maxlevel="Fatal" writeTo="JT1078TcpMessageHandlers"/>
<logger name="JT1078TcpMessageHandlersHex" minlevel="Debug" maxlevel="Fatal" writeTo="JT1078TcpMessageHandlersHex"/>
<logger name="FlvEncoder" minlevel="Debug" maxlevel="Fatal" writeTo="FlvEncoder"/>
</rules>
</nlog>

+ 0
- 48
src/JT1078.Gateway.SimpleServer/Configs/nlog.win.config 查看文件

@@ -1,48 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<!--
参考:http://www.cnblogs.com/fuchongjundream/p/3936431.html
autoReload:自动再配置
internalLogFile:可以让NLog把内部的调试和异常信息都写入指定文件里程序没问题了,日志却出了问题。这个该怎么办,到底是哪里不正确了?假如日志本身除了bug该如何解决?这就需要日志排错。把日志的错误信息写入日志。
<nlog throwExceptions="true" />
<nlog internalLogFile="file.txt" />- 设置internalLogFile属性可以让NLog把内部的调试和异常信息都写入指定文件里。
<nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" /> - 决定内部日志的级别,级别越高,输出的日志信息越简洁。
<nlog internalLogToConsole="false|true" /> - 是否把内部日志输出到标准控制台。
<nlog internalLogToConsoleError="false|true" /> - 是否把内部日志输出到标准错误控制台 (stderr)。
设置throwExceptions属性为“true”可以让NLog不再阻挡这类异常,而是把它们抛给调用者。在部署是这样做可以帮我们快速定位问题。一旦应用程序已经正确配置了,我们建议把throwExceptions的值设为“false”,这样由于日志引发的问题不至于导致应用程序的崩溃。
-->
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xsi:schemaLocation="NLog NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogFile="wwwroot/logs/internalLog.txt"
internalLogLevel="Debug" >
<variable name="Directory" value="${basedir}/wwwroot/logs/JT1078.Gateway"/>
<targets>
<target name="all" xsi:type="File"
fileName="${Directory}/all/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss} ${callsite} ${level}:${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}"/>
<target name="JT1078TcpMessageHandlers" xsi:type="File"
fileName="${Directory}/JT1078TcpMessageHandlers/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="JT1078TcpMessageHandlersHex" xsi:type="File"
fileName="${Directory}/JT1078TcpMessageHandlersHex/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="JT1078TcpConnectionHandler" xsi:type="File"
fileName="${Directory}/JT1078TcpConnectionHandler/${shortdate}.log"
layout="${date:format=yyyyMMddHHmmss},${message}"/>
<target name="console" xsi:type="ColoredConsole"
useDefaultRowHighlightingRules="false"
layout="${date:format=yyyyMMddHHmmss} ${callsite} ${level} ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}">
<highlight-row condition="level == LogLevel.Debug" foregroundColor="DarkGray" />
<highlight-row condition="level == LogLevel.Info" foregroundColor="Gray" />
<highlight-row condition="level == LogLevel.Warn" foregroundColor="Yellow" />
<highlight-row condition="level == LogLevel.Error" foregroundColor="Red" />
<highlight-row condition="level == LogLevel.Fatal" foregroundColor="Red" backgroundColor="White" />
</target>
</targets>
<rules>
<logger name="*" minlevel="Debug" maxlevel="Fatal" writeTo="all,console"/>
<logger name="JT1078.DotNetty.Tcp.Handlers.JT1078TcpConnectionHandler" minlevel="Debug" maxlevel="Fatal" writeTo="JT1078TcpConnectionHandler,console"/>
<logger name="JT1078TcpMessageHandlers" minlevel="Debug" maxlevel="Fatal" writeTo="JT1078TcpMessageHandlers,console"/>
<logger name="JT1078TcpMessageHandlersHex" minlevel="Debug" maxlevel="Fatal" writeTo="JT1078TcpMessageHandlersHex,console"/>
</rules>
</nlog>

+ 0
- 18
src/JT1078.Gateway.SimpleServer/CustomHttpMiddleware.cs 查看文件

@@ -1,18 +0,0 @@
using DotNetty.Codecs.Http;
using DotNetty.Transport.Channels;
using JT1078.Gateway.Interfaces;
using System;
using System.Collections.Generic;
using System.Security.Principal;
using System.Text;

namespace JT1078.Gateway.SimpleServer
{
public class CustomHttpMiddleware : IHttpMiddleware
{
public void Next(IChannelHandlerContext ctx, IFullHttpRequest req, IPrincipal principal)
{
Console.WriteLine("CustomHttpMiddleware");
}
}
}

+ 0
- 107
src/JT1078.Gateway.SimpleServer/HLS/FFMPEGHLSHostedService.cs 查看文件

@@ -1,107 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs.Http.WebSockets;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JT1078.Protocol;
using System.Collections.Concurrent;
using JT1078.Protocol.Enums;
using System.Diagnostics;
using System.IO.Pipes;
using Newtonsoft.Json;
using DotNetty.Common.Utilities;
using DotNetty.Codecs.Http;
using DotNetty.Handlers.Streams;
using DotNetty.Transport.Channels;
using Microsoft.AspNetCore.Hosting;
using System.Net;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Cors;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Logging;

namespace JT1078.Gateway.SimpleServer.HLS
{
/// <summary>
///
/// -hls_list_size 10 m3u8内部文件内部保留10个集合
/// -segment_time 10秒切片
/// -hls_wrap 可以让切片文件进行循环 就不会导致产生很多文件了 占用很多空间
/// ./ffmpeg -f dshow -i video="USB2.0 PC CAMERA" -hls_wrap 20 -start_number 0 -hls_list_size 10 -f hls "D:\v\sample.m3u8 -segment_time 10"
/// </summary>
class FFMPEGHLSHostedService : IHostedService
{
private readonly Process process;
private const string FileName= "hls_ch1.m3u8";
private const string DirectoryName = "hlsvideo";
private readonly IWebHost webHost;
public FFMPEGHLSHostedService()
{
string directoryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DirectoryName);
if (Directory.Exists(directoryPath))
{
Directory.Delete(directoryPath,true);
Directory.CreateDirectory(directoryPath);
}
else
{
Directory.CreateDirectory(directoryPath);
}
string filePath =$"\"{Path.Combine(directoryPath, FileName)}\"";
process = new Process
{
StartInfo =
{
FileName = @"C:\ffmpeg\bin\ffmpeg.exe",
Arguments = $@"-f dshow -i video={HardwareCamera.CameraName} -vcodec h264 -hls_wrap 10 -start_number 0 -hls_list_size 10 -f hls {filePath} -segment_time 10",
UseShellExecute = false,
CreateNoWindow = true
}
};
webHost= new WebHostBuilder()
.ConfigureLogging((_, factory) =>
{
factory.SetMinimumLevel(LogLevel.Debug);
factory.AddConsole();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,"HLS"));
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.UseKestrel(ksOptions =>
{
ksOptions.ListenAnyIP(5001);
})
.UseWebRoot(AppDomain.CurrentDomain.BaseDirectory)
.UseStartup<Startup>()
.Build();
}

public Task StartAsync(CancellationToken cancellationToken)
{
process.Start();
webHost.RunAsync(cancellationToken);
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
try
{
process.Kill();
}
catch
{
}
webHost.WaitForShutdownAsync();
return Task.CompletedTask;
}
}
}

+ 0
- 25
src/JT1078.Gateway.SimpleServer/HLS/Startup.cs 查看文件

@@ -1,25 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.Gateway.SimpleServer.HLS
{
public class Startup
{
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
//mime
//https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/DeployingHTTPLiveStreaming/DeployingHTTPLiveStreaming.html
var Provider = new FileExtensionContentTypeProvider();
Provider.Mappings[".m3u8"] = "application/x-mpegURL,vnd.apple.mpegURL";
Provider.Mappings[".ts"] = "video/MP2T";
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider = Provider
});
}
}
}

+ 0
- 9
src/JT1078.Gateway.SimpleServer/HLS/appsettings.json 查看文件

@@ -1,9 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug" //Warning
}
},
"AllowedHosts": "*",
"AllowedOrigins": "*"
}

+ 0
- 25
src/JT1078.Gateway.SimpleServer/HLS/hls.html 查看文件

@@ -1,25 +0,0 @@
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>hls demo</title>
<script src="hls.min.js"></script>
</head>
<body>
<h6>https://poanchen.github.io/blog/2016/11/17/how-to-play-mp4-video-using-hls</h6>
<video muted="muted" webkit-playsinline="true" autoplay="true" id="player"></video>
<script type="text/javascript">
var video = document.getElementById("player");
var videoSrcHls = "/hlsvideo/hls_ch1.m3u8";
if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource(videoSrcHls);
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, function () {
video.play();
});
}
</script>
</body>
</html>

+ 0
- 2
src/JT1078.Gateway.SimpleServer/HLS/hls.min.js
文件差异内容过多而无法显示
查看文件


+ 0
- 134
src/JT1078.Gateway.SimpleServer/HTTPFLV/FFMPEGHTTPFLVHostedService.cs 查看文件

@@ -1,134 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs.Http.WebSockets;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JT1078.Protocol;
using System.Collections.Concurrent;
using JT1078.Protocol.Enums;
using System.Diagnostics;
using System.IO.Pipes;
using Newtonsoft.Json;
using DotNetty.Common.Utilities;
using DotNetty.Codecs.Http;
using DotNetty.Handlers.Streams;
using DotNetty.Transport.Channels;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using JT1078.Gateway.Extensions;
using JT1078.Gateway.Session;

namespace JT1078.Gateway.SimpleServer.HTTPFLV
{
class FFMPEGHTTPFLVHostedService : IHostedService,IDisposable
{
private readonly Process process;
private readonly NamedPipeServerStream pipeServerOut;
private const string PipeNameOut = "demo1serverout";

private readonly JT1078HttpSessionManager jT1078HttpSessionManager;

/// <summary>
/// 需要缓存flv的第一包数据,当新用户进来先推送第一包的数据
/// </summary>
private byte[] flvFirstPackage;
private ConcurrentDictionary<string, byte> exists = new ConcurrentDictionary<string, byte>();
public FFMPEGHTTPFLVHostedService(JT1078HttpSessionManager jT1078HttpSessionManager)
{
pipeServerOut = new NamedPipeServerStream(PipeNameOut, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous,10240,10240);
process = new Process
{
StartInfo =
{
FileName = @"C:\ffmpeg\bin\ffmpeg.exe",
Arguments = $@"-f dshow -i video={HardwareCamera.CameraName} -c copy -f flv -vcodec h264 -y \\.\pipe\{PipeNameOut}",
UseShellExecute = false,
CreateNoWindow = true
}
};
this.jT1078HttpSessionManager = jT1078HttpSessionManager;
}
public Task StartAsync(CancellationToken cancellationToken)
{
process.Start();
Task.Run(() =>
{
while (true)
{
try
{
Console.WriteLine("IsConnected>>>" + pipeServerOut.IsConnected);
if (pipeServerOut.IsConnected)
{
if (pipeServerOut.CanRead)
{
Span<byte> v1 = new byte[2048];
var length = pipeServerOut.Read(v1);
var realValue = v1.Slice(0, length).ToArray();
if (realValue.Length <= 0) continue;
if (flvFirstPackage == null)
{
flvFirstPackage = realValue;
}
if (jT1078HttpSessionManager.GetAll().Count() > 0)
{
foreach (var session in jT1078HttpSessionManager.GetAll())
{
if (!exists.ContainsKey(session.Channel.Id.AsShortText()))
{
session.SendHttpFirstChunkAsync(flvFirstPackage);
exists.TryAdd(session.Channel.Id.AsShortText(), 0);
}
session.SendHttpOtherChunkAsync(realValue);
}
}
//Console.WriteLine(JsonConvert.SerializeObject(realValue)+"-"+ length.ToString());
}
}
else
{
if (!pipeServerOut.IsConnected)
{
Console.WriteLine("WaitForConnection Star...");
pipeServerOut.WaitForConnectionAsync().Wait(300);
Console.WriteLine("WaitForConnection End...");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
});
return Task.CompletedTask;
}
public void Dispose()
{
pipeServerOut.Dispose();
}
public Task StopAsync(CancellationToken cancellationToken)
{
try
{
process.Kill();
pipeServerOut.Flush();
pipeServerOut.Close();
}
catch
{


}
return Task.CompletedTask;
}
}
}

+ 0
- 26
src/JT1078.Gateway.SimpleServer/HTTPFLV/flv.html 查看文件

@@ -1,26 +0,0 @@
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="flv.min.js"></script>
</head>
<body>
<video muted="muted" webkit-playsinline="true" autoplay="true" id="player"></video>
<script>

if (flvjs.isSupported()) {
var player = document.getElementById('player');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
isLive: true,
url: "http://127.0.0.1:1818/demo.flv?token=" + Math.floor((Math.random() * 1000000) + 1)
});
flvPlayer.attachMediaElement(player);
flvPlayer.load();
flvPlayer.play();
}
</script>
</body>
</html>

+ 0
- 7
src/JT1078.Gateway.SimpleServer/HTTPFLV/flv.min.js
文件差异内容过多而无法显示
查看文件


+ 0
- 54
src/JT1078.Gateway.SimpleServer/Handlers/JT1078TcpMessageHandlers.cs 查看文件

@@ -1,54 +0,0 @@
using DotNetty.Buffers;
using JT1078.Gateway.Interfaces;
using JT1078.Gateway.Metadata;
using JT1078.Gateway.SimpleServer.JT1078WSFlv;
using JT1078.Protocol;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace JT1078.Gateway.SimpleServer.Handlers
{
public class JT1078TcpMessageHandlers : IJT1078TcpMessageHandlers
{
private readonly ILogger logger;
private readonly ILogger hexLogger;
private readonly JT1078WSFlvDataService jT1078WSFlvDataService;
public JT1078TcpMessageHandlers(
JT1078WSFlvDataService jT1078WSFlvDataServic,
ILoggerFactory loggerFactory)
{
this.jT1078WSFlvDataService = jT1078WSFlvDataServic;
logger = loggerFactory.CreateLogger("JT1078TcpMessageHandlers");
hexLogger = loggerFactory.CreateLogger("JT1078TcpMessageHandlersHex");
//var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "h264", "demo.h264");
//if (!File.Exists(path))
//{
// File.Create(path);
//}
}

public Task<JT1078Response> Processor(JT1078Request request)
{
//var path=Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "h264", $"demo.h264");
//using (FileStream fs = new FileStream(path, FileMode.Append, FileAccess.Write))
//{
// fs.Write(request.Src);
// fs.Close();
//}
logger.LogInformation(JsonConvert.SerializeObject(request.Package));
//hexLogger.LogInformation($"{request.Package.SIM},{request.Package.Label3.DataType.ToString()},{request.Package.LastFrameInterval},{request.Package.LastIFrameInterval},{request.Package.Timestamp},{request.Package.SN},{request.Package.LogicChannelNumber},{request.Package.Label3.SubpackageType.ToString()},{ByteBufferUtil.HexDump(request.Src)}");
hexLogger.LogInformation($"{request.Package.SIM},{request.Package.SN},{request.Package.LogicChannelNumber},{request.Package.Label3.DataType.ToString()},{request.Package.Label3.SubpackageType.ToString()},{ByteBufferUtil.HexDump(request.Src)}");
var mergePackage = JT1078Serializer.Merge(request.Package);
if (mergePackage != null)
{
jT1078WSFlvDataService.JT1078Packages.Add(mergePackage);
}
return Task.FromResult<JT1078Response>(default);
}
}
}

+ 0
- 25
src/JT1078.Gateway.SimpleServer/Handlers/JT1078UdpMessageHandlers.cs 查看文件

@@ -1,25 +0,0 @@
using JT1078.Gateway.Interfaces;
using JT1078.Gateway.Metadata;
using JT1078.Protocol;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Threading.Tasks;

namespace JT1078.Gateway.SimpleServer.Handlers
{
public class JT1078UdpMessageHandlers : IJT1078UdpMessageHandlers
{
private readonly ILogger<JT1078UdpMessageHandlers> logger;

public JT1078UdpMessageHandlers(ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<JT1078UdpMessageHandlers>();
}

public Task<JT1078Response> Processor(JT1078Request request)
{
logger.LogDebug(JsonConvert.SerializeObject(request.Package));
return Task.FromResult<JT1078Response>(default);
}
}
}

+ 0
- 24
src/JT1078.Gateway.SimpleServer/HardwareCamera.cs 查看文件

@@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace JT1078.Gateway.SimpleServer
{
/// <summary>
///
/// .\ffmpeg -list_options true -f dshow -i video = "USB2.0 PC CAMERA"
/// .\ffmpeg -f dshow -i video = "USB2.0 PC CAMERA" -vcodec libx264 "D:\mycamera.flv"
///
/// .\ffmpeg -f dshow -i video = "USB2.0 PC CAMERA" - c copy -f flv -vcodec h264 "rtmp://127.0.0.1/living/streamName"
/// .\ffplay rtmp://127.0.0.1/living/streamName
///
/// .\ffmpeg -f dshow -i video = "USB2.0 PC CAMERA" - c copy -f -y flv -vcodec h264 "pipe://demoserverout"
///
/// ref:https://www.cnblogs.com/lidabo/p/8662955.html
/// </summary>
public static class HardwareCamera
{
public const string CameraName = "\"USB2.0 PC CAMERA\"";
public const string RTMPURL = "rtmp://127.0.0.1/living/streamName";
}
}

+ 0
- 80
src/JT1078.Gateway.SimpleServer/HexExtensions.cs 查看文件

@@ -1,80 +0,0 @@
using System;

namespace JT1078.Gateway.SimpleServer
{
public static partial class BinaryExtensions
{
public static string ToHexString(this byte[] source)
{
return HexUtil.DoHexDump(source, 0, source.Length).ToUpper();
}
/// <summary>
/// 16进制字符串转16进制数组
/// </summary>
/// <param name="hexString"></param>
/// <param name="separator"></param>
/// <returns></returns>
public static byte[] ToHexBytes(this string hexString)
{
hexString = hexString.Replace(" ", "");
byte[] buf = new byte[hexString.Length / 2];
ReadOnlySpan<char> readOnlySpan = hexString.AsSpan();
for (int i = 0; i < hexString.Length; i++)
{
if (i % 2 == 0)
{
buf[i / 2] = Convert.ToByte(readOnlySpan.Slice(i, 2).ToString(), 16);
}
}
return buf;
}
}

public static class HexUtil
{
static readonly char[] HexdumpTable = new char[256 * 4];
static HexUtil()
{
char[] digits = "0123456789ABCDEF".ToCharArray();
for (int i = 0; i < 256; i++)
{
HexdumpTable[i << 1] = digits[(int)((uint)i >> 4 & 0x0F)];
HexdumpTable[(i << 1) + 1] = digits[i & 0x0F];
}
}

public static string DoHexDump(ReadOnlySpan<byte> buffer, int fromIndex, int length)
{
if (length == 0)
{
return "";
}
int endIndex = fromIndex + length;
var buf = new char[length << 1];
int srcIdx = fromIndex;
int dstIdx = 0;
for (; srcIdx < endIndex; srcIdx++, dstIdx += 2)
{
Array.Copy(HexdumpTable, buffer[srcIdx] << 1, buf, dstIdx, 2);
}
return new string(buf);
}

public static string DoHexDump(byte[] array, int fromIndex, int length)
{
if (length == 0)
{
return "";
}
int endIndex = fromIndex + length;
var buf = new char[length << 1];
int srcIdx = fromIndex;
int dstIdx = 0;
for (; srcIdx < endIndex; srcIdx++, dstIdx += 2)
{
Array.Copy(HexdumpTable, (array[srcIdx] & 0xFF) << 1, buf, dstIdx, 2);
}
return new string(buf);
}
}
}

+ 0
- 26
src/JT1078.Gateway.SimpleServer/JT1078.Gateway.SimpleServer.csproj 查看文件

@@ -1,26 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JT1078.Flv" Version="1.0.0-preview4" />
<PackageReference Include="Microsoft.AspNetCore.Cors" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.6.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\JT1078.Gateway\JT1078.Gateway.csproj" />
</ItemGroup>

</Project>

+ 0
- 17
src/JT1078.Gateway.SimpleServer/JT1078WSFlv/JT1078WSFlvDataService.cs 查看文件

@@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Concurrent;
using JT1078.Protocol;

namespace JT1078.Gateway.SimpleServer.JT1078WSFlv
{
public class JT1078WSFlvDataService
{
public JT1078WSFlvDataService()
{
JT1078Packages = new BlockingCollection<JT1078Package>();
}
public BlockingCollection<JT1078Package> JT1078Packages { get; set; }
}
}

+ 0
- 108
src/JT1078.Gateway.SimpleServer/JT1078WSFlv/JT1078WSFlvHostedService.cs 查看文件

@@ -1,108 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs.Http.WebSockets;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JT1078.Protocol;
using System.Collections.Concurrent;
using JT1078.Protocol.Enums;
using System.Diagnostics;
using System.IO.Pipes;
using Newtonsoft.Json;
using JT1078.Flv;
using Microsoft.Extensions.Logging;
using JT1078.Gateway.Session;
using JT1078.Gateway.Extensions;

namespace JT1078.Gateway.SimpleServer.JT1078WSFlv
{
/// <summary>
///
/// </summary>
class JT1078WSFlvHostedService : IHostedService
{
private readonly JT1078HttpSessionManager jT1078HttpSessionManager;

private ConcurrentDictionary<string, byte> exists = new ConcurrentDictionary<string, byte>();

private readonly JT1078WSFlvDataService jT1078WSFlvDataService;
private readonly FlvEncoder FlvEncoder;
private readonly ILogger logger;
private readonly ILogger flvEncodingLogger;
public JT1078WSFlvHostedService(
ILoggerFactory loggerFactory,
JT1078WSFlvDataService jT1078WSFlvDataServic,
JT1078HttpSessionManager jT1078HttpSessionManager)
{
logger = loggerFactory.CreateLogger("JT1078WSFlvHostedService");
flvEncodingLogger = loggerFactory.CreateLogger("FlvEncoding");
this.jT1078WSFlvDataService = jT1078WSFlvDataServic;
this.jT1078HttpSessionManager = jT1078HttpSessionManager;
FlvEncoder = new FlvEncoder(loggerFactory);
}

public Task StartAsync(CancellationToken cancellationToken)
{
Task.Run(() =>
{
try
{
Stopwatch stopwatch = new Stopwatch();
foreach (var item in jT1078WSFlvDataService.JT1078Packages.GetConsumingEnumerable())
{
stopwatch.Start();
var flv3 = FlvEncoder.CreateFlvFrame(item);
stopwatch.Stop();
if(flvEncodingLogger.IsEnabled(LogLevel.Debug))
{
long times = stopwatch.ElapsedMilliseconds;
flvEncodingLogger.LogDebug($"flv encoding {times.ToString()}ms");
}
stopwatch.Reset();
if (flv3 == null) continue;
if (jT1078HttpSessionManager.GetAll().Count() > 0)
{
foreach (var session in jT1078HttpSessionManager.GetAll())
{
if (!exists.ContainsKey(session.Channel.Id.AsShortText()))
{
exists.TryAdd(session.Channel.Id.AsShortText(), 0);
string key = item.GetKey();
//ws-flv
//session.SendBinaryWebSocketAsync(FlvEncoder.GetFirstFlvFrame(key, flv3));
//http-flv
var buffer = FlvEncoder.GetFirstFlvFrame(key, flv3);
if (buffer != null)
{
flvEncodingLogger.LogDebug(JsonConvert.SerializeObject(buffer));
session.SendHttpFirstChunkAsync(buffer);
}
continue;
}
//ws-flv
//session.SendBinaryWebSocketAsync(flv3);
//http-flv
session.SendHttpOtherChunkAsync(flv3);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
});
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}

+ 0
- 7
src/JT1078.Gateway.SimpleServer/JT1078WSFlv/flv.min.js
文件差异内容过多而无法显示
查看文件


+ 0
- 41
src/JT1078.Gateway.SimpleServer/JT1078WSFlv/index.html 查看文件

@@ -1,41 +0,0 @@
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="flv.min.js"></script>
</head>
<body>
<video muted="muted" webkit-playsinline="true" autoplay="true" id="player"></video>
<script>
if (flvjs.isSupported()) {
var player = document.getElementById('player');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
isLive: true,
url: "ws://127.0.0.1:1818/jt1078live?token=" + Math.floor((Math.random() * 1000000) + 1)
});
flvPlayer.attachMediaElement(player);
flvPlayer.load();
flvPlayer.play();
function componentDidMount() {
this.cleanBuff = setInterval(function () {
let buffered = player.buffered
console.log("start...")
if (buffered.length > 0) {
let end = buffered.end(0)
if (end - player.currentTime > 0.15) {
player.currentTime = end - 0.1;
console.log("exe... start")
}
}
console.log("end...")
}, 3 * 10 * 1000)
};
componentDidMount();
}
</script>
</body>
</html>

+ 0
- 86
src/JT1078.Gateway.SimpleServer/Program.cs 查看文件

@@ -1,86 +0,0 @@
using JT1078.Gateway.SimpleServer.Handlers;
using JT1078.Gateway.SimpleServer.JT1078WSFlv;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NLog.Extensions.Logging;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;


namespace JT1078.Gateway.SimpleServer
{
class Program
{
static Program()
{
Newtonsoft.Json.JsonSerializerSettings setting = new Newtonsoft.Json.JsonSerializerSettings();
JsonConvert.DefaultSettings = new Func<JsonSerializerSettings>(() =>
{
setting.Converters.Add(new StringEnumConverter());
return setting;
});
}
static async Task Main(string[] args)
{
//3031636481E2108801123456781001100000016BB392CA7C02800028002E0000000161E1A2BF0098CFC0EE1E17283407788E39A403FDDBD1D546BFB063013F59AC34C97A021AB96A28A42C08
var serverHostBuilder = new HostBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory);
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
})
.ConfigureLogging((context, logging) =>
{
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
NLog.LogManager.LoadConfiguration("Configs/nlog.unix.config");
}
else
{
NLog.LogManager.LoadConfiguration("Configs/nlog.win.config");
}
logging.AddNLog(new NLogProviderOptions { CaptureMessageTemplates = true, CaptureMessageProperties = true });
logging.SetMinimumLevel(LogLevel.Trace);
})
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<JT1078WSFlvDataService>();
services.AddSingleton<ILoggerFactory, LoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
services.AddJT1078Gateway(hostContext.Configuration)
.AddTcpHost()
.Replace<JT1078TcpMessageHandlers>()
.Builder()
//.AddJT1078UdpHost()
//.Replace<JT1078UdpMessageHandlers>()
// .Builder()
.AddHttpHost()
//.UseHttpMiddleware<CustomHttpMiddleware>()
//.Builder()
;
//使用ffmpeg工具
//1.success
//services.AddHostedService<FFMPEGRTMPHostedService>();
//2.success
//services.AddHostedService<FFMPEGHTTPFLVHostedService>();
//3.success
//services.AddHostedService<FFMPEGWSFLVPHostedService>();
//4.success
//http://127.0.0.1:5001/HLS/hls.html
//services.AddHostedService<FFMPEGHLSHostedService>();

services.AddHostedService<JT1078WSFlvHostedService>();
});
await serverHostBuilder.RunConsoleAsync();
}
}
}

+ 0
- 58
src/JT1078.Gateway.SimpleServer/RTMP/FFMPEGRTMPHostedService.cs 查看文件

@@ -1,58 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs.Http.WebSockets;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JT1078.Protocol;
using System.Collections.Concurrent;
using JT1078.Protocol.Enums;
using System.Diagnostics;

namespace JT1078.Gateway.SimpleServer.RTMP
{
/// <summary>
/// 1.部署 RTMP 服务器 https://github.com/a1q123456/Harmonic
/// 2.使用ffplay播放器查看 ./ffplay rtmp://127.0.0.1/living/streamName
/// ref:
/// https://stackoverflow.com/questions/32157774/ffmpeg-output-pipeing-to-named-windows-pipe
/// https://mathewsachin.github.io/blog/2017/07/28/ffmpeg-pipe-csharp.html
/// https://csharp.hotexamples.com/examples/-/NamedPipeServerStream/-/php-namedpipeserverstream-class-examples.html
///
/// ffmpeg pipe作为客户端
/// NamedPipeServerStream作为服务端
/// </summary>
class FFMPEGRTMPHostedService : IHostedService
{
private readonly Process process;
public FFMPEGRTMPHostedService()
{
process = new Process
{
StartInfo =
{
FileName = @"C:\ffmpeg\bin\ffmpeg.exe",
Arguments = $@"-f dshow -i video={HardwareCamera.CameraName} -c copy -f flv -vcodec h264 {HardwareCamera.RTMPURL}",
UseShellExecute = false,
CreateNoWindow = true
}
};
}

public Task StartAsync(CancellationToken cancellationToken)
{
process.Start();
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
process.Kill();
return Task.CompletedTask;
}
}
}

+ 0
- 129
src/JT1078.Gateway.SimpleServer/WSFLV/FFMPEGWSFLVHostedService.cs 查看文件

@@ -1,129 +0,0 @@
using DotNetty.Buffers;
using DotNetty.Codecs.Http.WebSockets;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using JT1078.Protocol;
using System.Collections.Concurrent;
using JT1078.Protocol.Enums;
using System.Diagnostics;
using System.IO.Pipes;
using Newtonsoft.Json;
using JT1078.Gateway.Session;
using JT1078.Gateway.Extensions;

namespace JT1078.Gateway.SimpleServer.WSFLV
{
/// <summary>
///
/// </summary>
class FFMPEGWSFLVHostedService : IHostedService,IDisposable
{
private readonly Process process;
private readonly NamedPipeServerStream pipeServerOut;
private const string PipeNameOut = "demo2serverout";
private readonly JT1078HttpSessionManager jT1078HttpSessionManager;
/// <summary>
/// 需要缓存flv的第一包数据,当新用户进来先推送第一包的数据
/// </summary>
private byte[] flvFirstPackage;
private ConcurrentDictionary<string,byte> exists = new ConcurrentDictionary<string, byte>();
public FFMPEGWSFLVHostedService(
JT1078HttpSessionManager jT1078HttpSessionManager)
{
pipeServerOut = new NamedPipeServerStream(PipeNameOut, PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous,102400,102400);
process = new Process
{
StartInfo =
{
FileName = @"C:\ffmpeg\bin\ffmpeg.exe",
Arguments = $@"-f dshow -i video={HardwareCamera.CameraName} -c copy -f flv -vcodec h264 -y \\.\pipe\{PipeNameOut}",
UseShellExecute = false,
CreateNoWindow = true,
}
};
this.jT1078HttpSessionManager = jT1078HttpSessionManager;
}

public void Dispose()
{
pipeServerOut.Dispose();
}

public Task StartAsync(CancellationToken cancellationToken)
{
process.Start();
Task.Run(() =>
{
while (true)
{
try
{
Console.WriteLine("IsConnected>>>" + pipeServerOut.IsConnected);
if (pipeServerOut.IsConnected)
{
if (pipeServerOut.CanRead)
{
Span<byte> v1 = new byte[2048];
var length = pipeServerOut.Read(v1);
var realValue = v1.Slice(0, length).ToArray();
if (realValue.Length <= 0) continue;
if (flvFirstPackage == null)
{
flvFirstPackage = realValue;
}
if (jT1078HttpSessionManager.GetAll().Count() > 0)
{
foreach (var session in jT1078HttpSessionManager.GetAll())
{
if (!exists.ContainsKey(session.Channel.Id.AsShortText()))
{
session.SendBinaryWebSocketAsync(flvFirstPackage);
exists.TryAdd(session.Channel.Id.AsShortText(), 0);
}
session.SendBinaryWebSocketAsync(realValue);
}
}
}
}
else
{
if (!pipeServerOut.IsConnected)
{
Console.WriteLine("WaitForConnection Star...");
pipeServerOut.WaitForConnectionAsync().Wait(300);
Console.WriteLine("WaitForConnection End...");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
});
return Task.CompletedTask;
}

public Task StopAsync(CancellationToken cancellationToken)
{
try
{
process.Kill();
pipeServerOut.Flush();
pipeServerOut.Close();
}
catch
{

}
return Task.CompletedTask;
}
}
}

+ 0
- 7
src/JT1078.Gateway.SimpleServer/WSFLV/flv.min.js
文件差异内容过多而无法显示
查看文件


+ 0
- 26
src/JT1078.Gateway.SimpleServer/WSFLV/index.html 查看文件

@@ -1,26 +0,0 @@
<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="flv.min.js"></script>
</head>
<body>
<video muted="muted" webkit-playsinline="true" autoplay="true" id="player"></video>
<script>
if (flvjs.isSupported()) {
var player = document.getElementById('player');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
isLive: true,
url: "ws://127.0.0.1:1818/jt1078live?token=" + Math.floor((Math.random() * 1000000) + 1)
});
flvPlayer.attachMediaElement(player);
flvPlayer.load();
flvPlayer.play();
}
</script>
</body>
</html>

+ 0
- 23
src/JT1078.Gateway.SimpleServer/appsettings.json 查看文件

@@ -1,23 +0,0 @@
{
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Trace"
}
},
"Console": {
"LogLevel": {
"Default": "Trace"
}
}
},
"JT1078Configuration": {
"TcpPort": 1808,
"UdpPort": 1808,
"HttpPort": 1818,
"RemoteServerOptions": {

}
}
}

+ 2
- 1
src/JT1078.Gateway.Tests/JT1078.Gateway.TestNormalHosting/wwwroot/index.html 查看文件

@@ -15,7 +15,8 @@
var flvPlayer = flvjs.createPlayer({
type: 'flv',
isLive: true,
url: "ws://127.0.0.1:15555/?sim=11234567810&channel=1&token=123456"
//url: "http://127.0.0.1:15555/?sim=1901305037&channel=3&token=123456"
//url: "ws://127.0.0.1:15555/?sim=11234567810&channel=1&token=123456"
});
flvPlayer.attachMediaElement(player);
flvPlayer.load();


+ 12
- 0
src/JT1078.Gateway/Extensions/JT1078HttpContextExtensions.cs 查看文件

@@ -14,6 +14,8 @@ namespace JT1078.Gateway.Extensions
public static async ValueTask Http401(this HttpListenerContext context)
{
byte[] b = Encoding.UTF8.GetBytes("auth error");
context.Response.AddHeader("Access-Control-Allow-Headers", "*");
context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
context.Response.KeepAlive = false;
context.Response.ContentLength64 = b.Length;
@@ -26,6 +28,8 @@ namespace JT1078.Gateway.Extensions
public static async ValueTask Http400(this HttpListenerContext context)
{
byte[] b = Encoding.UTF8.GetBytes($"sim and channel parameter required.");
context.Response.AddHeader("Access-Control-Allow-Headers", "*");
context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
context.Response.KeepAlive = false;
context.Response.ContentLength64 = b.Length;
@@ -37,6 +41,8 @@ namespace JT1078.Gateway.Extensions

public static void Http404(this HttpListenerContext context)
{
context.Response.AddHeader("Access-Control-Allow-Headers", "*");
context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
context.Response.StatusCode = (int)HttpStatusCode.NotFound;
context.Response.KeepAlive = false;
context.Response.OutputStream.Close();
@@ -46,6 +52,8 @@ namespace JT1078.Gateway.Extensions
public static async ValueTask Http500(this HttpListenerContext context)
{
byte[] b = Encoding.UTF8.GetBytes("inner error");
context.Response.AddHeader("Access-Control-Allow-Headers", "*");
context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.KeepAlive = false;
context.Response.ContentLength64 = b.Length;
@@ -57,6 +65,8 @@ namespace JT1078.Gateway.Extensions

public static async ValueTask HttpSendFirstChunked(this JT1078HttpContext context, ReadOnlyMemory<byte> buffer)
{
context.Context.Response.AddHeader("Access-Control-Allow-Headers", "*");
context.Context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
context.Context.Response.StatusCode = (int)HttpStatusCode.OK;
context.Context.Response.SendChunked = true;
await context.Context.Response.OutputStream.WriteAsync(buffer);
@@ -71,6 +81,8 @@ namespace JT1078.Gateway.Extensions
public static async ValueTask HttpClose(this JT1078HttpContext context)
{
byte[] b = Encoding.UTF8.GetBytes("close");
context.Context.Response.AddHeader("Access-Control-Allow-Headers", "*");
context.Context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
context.Context.Response.StatusCode = (int)HttpStatusCode.OK;
context.Context.Response.KeepAlive = false;
context.Context.Response.ContentLength64 = b.Length;


+ 1
- 1
src/Version.props 查看文件

@@ -1,5 +1,5 @@
<Project>
<PropertyGroup>
<JT1078PackageVersion>1.0.0-preview3</JT1078PackageVersion>
<JT1078PackageVersion>1.0.0-preview2</JT1078PackageVersion>
</PropertyGroup>
</Project>

正在加载...
取消
保存