@@ -1,11 +1,22 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | <Project Sdk="Microsoft.NET.Sdk"> | ||||
<Import Project="..\SharedProperties.props" /> | |||||
<Import Project="..\Version.props" /> | |||||
<PropertyGroup> | <PropertyGroup> | ||||
<TargetFramework>netstandard2.0</TargetFramework> | <TargetFramework>netstandard2.0</TargetFramework> | ||||
<LangVersion>7.3</LangVersion> | |||||
<Copyright>Copyright 2019.</Copyright> | |||||
<Authors>SmallChi(Koike)</Authors> | |||||
<PackageId>JT1078.DotNetty.Core</PackageId> | <PackageId>JT1078.DotNetty.Core</PackageId> | ||||
<Product>JT1078.DotNetty.Core</Product> | <Product>JT1078.DotNetty.Core</Product> | ||||
<Description>基于DotNetty实现的JT1078DotNetty的核心库</Description> | <Description>基于DotNetty实现的JT1078DotNetty的核心库</Description> | ||||
<PackageReleaseNotes>基于DotNetty实现的JT1078DotNetty的核心库</PackageReleaseNotes> | <PackageReleaseNotes>基于DotNetty实现的JT1078DotNetty的核心库</PackageReleaseNotes> | ||||
<RepositoryUrl>https://github.com/SmallChi/JT1078DotNetty</RepositoryUrl> | |||||
<PackageProjectUrl>https://github.com/SmallChi/JT1078DotNetty</PackageProjectUrl> | |||||
<licenseUrl>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</licenseUrl> | |||||
<license>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</license> | |||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> | |||||
<SignAssembly>false</SignAssembly> | |||||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | |||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
@@ -21,6 +32,10 @@ | |||||
<PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" /> | <PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | |||||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | <ItemGroup> | ||||
<Folder Include="Properties\" /> | <Folder Include="Properties\" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
@@ -1,7 +1,10 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | <Project Sdk="Microsoft.NET.Sdk"> | ||||
<Import Project="..\SharedProperties.props" /> | |||||
<Import Project="..\Version.props" /> | |||||
<PropertyGroup> | <PropertyGroup> | ||||
<TargetFramework>netstandard2.0</TargetFramework> | <TargetFramework>netstandard2.0</TargetFramework> | ||||
<LangVersion>7.3</LangVersion> | |||||
<Copyright>Copyright 2019.</Copyright> | |||||
<Authors>SmallChi(Koike)</Authors> | |||||
<PackageId>JT1078.DotNetty.Tcp</PackageId> | <PackageId>JT1078.DotNetty.Tcp</PackageId> | ||||
<Product>JT1078.DotNetty.Tcp</Product> | <Product>JT1078.DotNetty.Tcp</Product> | ||||
<Description>基于DotNetty实现的JT1078DotNetty的Tcp服务</Description> | <Description>基于DotNetty实现的JT1078DotNetty的Tcp服务</Description> | ||||
@@ -10,12 +13,19 @@ | |||||
<PackageProjectUrl>https://github.com/SmallChi/JT1078DotNetty</PackageProjectUrl> | <PackageProjectUrl>https://github.com/SmallChi/JT1078DotNetty</PackageProjectUrl> | ||||
<licenseUrl>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</licenseUrl> | <licenseUrl>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</licenseUrl> | ||||
<license>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</license> | <license>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</license> | ||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> | |||||
<SignAssembly>false</SignAssembly> | |||||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | |||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\JT1078.DotNetty.Core\JT1078.DotNetty.Core.csproj" /> | <ProjectReference Include="..\JT1078.DotNetty.Core\JT1078.DotNetty.Core.csproj" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | |||||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="DotNetty.Handlers" Version="0.6.0" /> | <PackageReference Include="DotNetty.Handlers" Version="0.6.0" /> | ||||
@@ -0,0 +1,53 @@ | |||||
using DotNetty.Buffers; | |||||
using DotNetty.Codecs.Http.WebSockets; | |||||
using JT1078.DotNetty.Core.Session; | |||||
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; | |||||
namespace JT1078.DotNetty.TestHosting | |||||
{ | |||||
class FFMPEGHTTPFLVPHostedService : IHostedService | |||||
{ | |||||
private readonly JT1078DataService jT1078DataService; | |||||
private readonly FFMPEGHTTPFLVPipingService fFMPEGHTTPFLVPipingService; | |||||
public FFMPEGHTTPFLVPHostedService( | |||||
JT1078DataService jT1078DataService) | |||||
{ | |||||
this.jT1078DataService = jT1078DataService; | |||||
fFMPEGHTTPFLVPipingService = new FFMPEGHTTPFLVPipingService("demo2"); | |||||
} | |||||
public Task StartAsync(CancellationToken cancellationToken) | |||||
{ | |||||
Task.Run(() => | |||||
{ | |||||
try | |||||
{ | |||||
foreach (var item in jT1078DataService.DataBlockingCollection.GetConsumingEnumerable(cancellationToken)) | |||||
{ | |||||
fFMPEGHTTPFLVPipingService.Wirte(item); | |||||
} | |||||
} | |||||
catch(Exception ex) | |||||
{ | |||||
Console.WriteLine(ex); | |||||
} | |||||
}, cancellationToken); | |||||
return Task.CompletedTask; | |||||
} | |||||
public Task StopAsync(CancellationToken cancellationToken) | |||||
{ | |||||
return Task.CompletedTask; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,94 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.IO.Pipes; | |||||
using System.Text; | |||||
using System.Threading.Tasks; | |||||
namespace JT1078.DotNetty.TestHosting | |||||
{ | |||||
public class FFMPEGHTTPFLVPipingService : IDisposable | |||||
{ | |||||
private readonly Process process; | |||||
private readonly NamedPipeServerStream pipeServer; | |||||
private readonly NamedPipeServerStream pipeServerOut; | |||||
public FFMPEGHTTPFLVPipingService(string pipeName) | |||||
{ | |||||
pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); | |||||
pipeServerOut = new NamedPipeServerStream(pipeName+ "out", PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous); | |||||
process = new Process | |||||
{ | |||||
StartInfo = | |||||
{ | |||||
FileName = @"C:\ffmpeg\bin\ffmpeg.exe", | |||||
Arguments = $@"-i \\.\pipe\{pipeName} -c copy -f flv -y \\.\pipe\{pipeName}out", | |||||
UseShellExecute = false, | |||||
CreateNoWindow = true, | |||||
RedirectStandardError = true | |||||
} | |||||
}; | |||||
process.Start(); | |||||
process.ErrorDataReceived += ErrorDataReceived; | |||||
pipeServer.WaitForConnection(); | |||||
Task.Run(() => | |||||
{ | |||||
while (true) | |||||
{ | |||||
try | |||||
{ | |||||
if (pipeServerOut.IsConnected) | |||||
{ | |||||
if (pipeServerOut.CanRead) | |||||
{ | |||||
var value = pipeServerOut.ReadByte(); | |||||
Console.WriteLine(value); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
pipeServerOut.WaitForConnectionAsync(); | |||||
} | |||||
} | |||||
catch (Exception ex) | |||||
{ | |||||
Console.WriteLine(ex); | |||||
} | |||||
} | |||||
}); | |||||
} | |||||
public void ErrorDataReceived(object sender, DataReceivedEventArgs e) | |||||
{ | |||||
Console.WriteLine(e.Data); | |||||
} | |||||
public void OutputDataReceived(object sender, DataReceivedEventArgs e) | |||||
{ | |||||
Console.WriteLine(e.Data); | |||||
} | |||||
public void Wirte(byte[] buffer) | |||||
{ | |||||
if (pipeServer.IsConnected) | |||||
pipeServer.WriteAsync(buffer); | |||||
} | |||||
public void Dispose() | |||||
{ | |||||
try | |||||
{ | |||||
process.WaitForExit(); | |||||
pipeServer.Flush(); | |||||
} | |||||
catch | |||||
{ | |||||
} | |||||
process.Dispose(); | |||||
pipeServer.Dispose(); | |||||
} | |||||
} | |||||
} |
@@ -29,7 +29,7 @@ namespace JT1078.DotNetty.TestHosting.Handlers | |||||
{ | { | ||||
logger.LogInformation(JsonConvert.SerializeObject(request.Package)); | logger.LogInformation(JsonConvert.SerializeObject(request.Package)); | ||||
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)}"); | 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)}"); | ||||
jT1078DataService.DataBlockingCollection.TryAdd(request.Package); | |||||
jT1078DataService.DataBlockingCollection.TryAdd(request.Src); | |||||
return Task.FromResult<JT1078Response>(default); | return Task.FromResult<JT1078Response>(default); | ||||
} | } | ||||
} | } | ||||
@@ -24,6 +24,9 @@ | |||||
<None Update="2019-07-12.log"> | <None Update="2019-07-12.log"> | ||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
</None> | </None> | ||||
<None Update="2019-08-27-1.log"> | |||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | |||||
</None> | |||||
<None Update="appsettings.json"> | <None Update="appsettings.json"> | ||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> | <CopyToOutputDirectory>Always</CopyToOutputDirectory> | ||||
</None> | </None> | ||||
@@ -1,8 +1,10 @@ | |||||
using JT1078.Protocol; | using JT1078.Protocol; | ||||
using JT1078.Protocol.Enums; | |||||
using System; | using System; | ||||
using System.Collections.Concurrent; | using System.Collections.Concurrent; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.IO; | using System.IO; | ||||
using System.Linq; | |||||
using System.Text; | using System.Text; | ||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
@@ -11,12 +13,14 @@ namespace JT1078.DotNetty.TestHosting | |||||
{ | { | ||||
public class JT1078DataService | public class JT1078DataService | ||||
{ | { | ||||
public BlockingCollection<JT1078Package> DataBlockingCollection { get; } | |||||
public BlockingCollection<byte[]> DataBlockingCollection { get; } | |||||
private readonly ConcurrentDictionary<string, byte[]> SubcontractKey; | |||||
public JT1078DataService() | public JT1078DataService() | ||||
{ | { | ||||
DataBlockingCollection = new BlockingCollection<JT1078Package>(60000); | |||||
var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "2019-07-15.log")); | |||||
DataBlockingCollection = new BlockingCollection<byte[]>(60000); | |||||
SubcontractKey = new ConcurrentDictionary<string, byte[]>(StringComparer.OrdinalIgnoreCase); | |||||
var lines = File.ReadAllLines(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "2019-08-27-1.log")); | |||||
Task.Run(() => | Task.Run(() => | ||||
{ | { | ||||
while (true) | while (true) | ||||
@@ -25,9 +29,30 @@ namespace JT1078.DotNetty.TestHosting | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
var package = JT1078Serializer.Deserialize(lines[i].Split(',')[6].ToHexBytes()); | |||||
DataBlockingCollection.Add(package); | |||||
Thread.Sleep(300); | |||||
var item = JT1078Serializer.Deserialize(lines[i].Split(',')[6].ToHexBytes()); | |||||
if (item.Label3.SubpackageType == JT1078SubPackageType.分包处理时的第一个包) | |||||
{ | |||||
SubcontractKey.TryRemove(item.SIM, out _); | |||||
SubcontractKey.TryAdd(item.SIM, item.Bodies); | |||||
} | |||||
else if (item.Label3.SubpackageType == JT1078SubPackageType.分包处理时的中间包) | |||||
{ | |||||
if (SubcontractKey.TryGetValue(item.SIM, out var buffer)) | |||||
{ | |||||
SubcontractKey[item.SIM] = buffer.Concat(item.Bodies).ToArray(); | |||||
} | |||||
} | |||||
else if (item.Label3.SubpackageType == JT1078SubPackageType.分包处理时的最后一个包) | |||||
{ | |||||
if (SubcontractKey.TryGetValue(item.SIM, out var buffer)) | |||||
{ | |||||
DataBlockingCollection.Add(buffer.Concat(item.Bodies).ToArray()); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
DataBlockingCollection.Add(item.Bodies); | |||||
} | |||||
} | } | ||||
catch | catch | ||||
{ | { | ||||
@@ -20,6 +20,7 @@ namespace JT1078.DotNetty.TestHosting | |||||
JT1078WebSocketSessionManager jT1078WebSocketSessionManager; | JT1078WebSocketSessionManager jT1078WebSocketSessionManager; | ||||
private readonly JT1078DataService jT1078DataService; | private readonly JT1078DataService jT1078DataService; | ||||
private readonly ConcurrentDictionary<string, byte[]> SubcontractKey; | private readonly ConcurrentDictionary<string, byte[]> SubcontractKey; | ||||
public JT1078WebSocketPushHostedService( | public JT1078WebSocketPushHostedService( | ||||
JT1078DataService jT1078DataService, | JT1078DataService jT1078DataService, | ||||
JT1078WebSocketSessionManager jT1078WebSocketSessionManager) | JT1078WebSocketSessionManager jT1078WebSocketSessionManager) | ||||
@@ -32,59 +33,24 @@ namespace JT1078.DotNetty.TestHosting | |||||
{ | { | ||||
Task.Run(() => | Task.Run(() => | ||||
{ | { | ||||
while (true) | |||||
while (!cancellationToken.IsCancellationRequested) | |||||
{ | { | ||||
try | try | ||||
{ | { | ||||
foreach (var item in jT1078DataService.DataBlockingCollection.GetConsumingEnumerable()) | |||||
foreach (var item in jT1078DataService.DataBlockingCollection.GetConsumingEnumerable(cancellationToken)) | |||||
{ | { | ||||
//if (jT1078WebSocketSessionManager.GetAll().Count() > 0) | |||||
//{ | |||||
// Parallel.ForEach(jT1078WebSocketSessionManager.GetAll(), new ParallelOptions { MaxDegreeOfParallelism = 5 }, session => | |||||
// { | |||||
// //if (item.Label3.SubpackageType == JT1078SubPackageType.分包处理时的第一个包) | |||||
// //{ | |||||
// // SubcontractKey.TryRemove(item.SIM, out _); | |||||
// // SubcontractKey.TryAdd(item.SIM, item.Bodies); | |||||
// //} | |||||
// //else if (item.Label3.SubpackageType == JT1078SubPackageType.分包处理时的中间包) | |||||
// //{ | |||||
// // if (SubcontractKey.TryGetValue(item.SIM, out var buffer)) | |||||
// // { | |||||
// // SubcontractKey[item.SIM] = buffer.Concat(item.Bodies).ToArray(); | |||||
// // } | |||||
// //} | |||||
// //else if (item.Label3.SubpackageType == JT1078SubPackageType.分包处理时的最后一个包) | |||||
// //{ | |||||
// // if (SubcontractKey.TryGetValue(item.SIM, out var buffer)) | |||||
// // { | |||||
// // session.Channel.WriteAndFlushAsync(new BinaryWebSocketFrame(Unpooled.WrappedBuffer(buffer.Concat(item.Bodies).ToArray()))); | |||||
// // } | |||||
// //} | |||||
// //else | |||||
// //{ | |||||
// session.Channel.WriteAndFlushAsync(new BinaryWebSocketFrame(Unpooled.WrappedBuffer(item.Bodies))); | |||||
// // } | |||||
// }); | |||||
//} | |||||
if (jT1078WebSocketSessionManager.GetAll().Count() > 0) | |||||
Parallel.ForEach(jT1078WebSocketSessionManager.GetAll(), new ParallelOptions { MaxDegreeOfParallelism = 5 }, session => | |||||
{ | { | ||||
Parallel.ForEach(jT1078WebSocketSessionManager.GetAll(), new ParallelOptions { MaxDegreeOfParallelism = 5 }, session => | |||||
{ | |||||
session.Channel.WriteAndFlushAsync(new BinaryWebSocketFrame(Unpooled.WrappedBuffer(item.Bodies))); | |||||
}); | |||||
} | |||||
session.Channel.WriteAndFlushAsync(new BinaryWebSocketFrame(Unpooled.WrappedBuffer(item))); | |||||
}); | |||||
} | } | ||||
} | } | ||||
catch | catch | ||||
{ | { | ||||
} | } | ||||
Thread.Sleep(10000); | |||||
} | } | ||||
}); | |||||
}, cancellationToken); | |||||
return Task.CompletedTask; | return Task.CompletedTask; | ||||
} | } | ||||
@@ -58,17 +58,19 @@ namespace JT1078.DotNetty.TestHosting | |||||
services.AddSingleton<ILoggerFactory, LoggerFactory>(); | services.AddSingleton<ILoggerFactory, LoggerFactory>(); | ||||
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); | ||||
services.AddSingleton<JT1078DataService>(); | services.AddSingleton<JT1078DataService>(); | ||||
services.AddJT1078Core(hostContext.Configuration) | |||||
.AddJT1078TcpHost() | |||||
.Replace<JT1078TcpMessageHandlers>() | |||||
.Builder() | |||||
//.AddJT1078UdpHost() | |||||
//.Replace<JT1078UdpMessageHandlers>() | |||||
//.Builder() | |||||
.AddJT1078WebSocketHost() | |||||
services.AddJT1078Core(hostContext.Configuration); | |||||
// .AddJT1078TcpHost() | |||||
// .Replace<JT1078TcpMessageHandlers>() | |||||
// .Builder() | |||||
// .AddJT1078UdpHost() | |||||
// .Replace<JT1078UdpMessageHandlers>() | |||||
// .Builder() | |||||
// .AddJT1078WebSocketHost() | |||||
// .Replace() | // .Replace() | ||||
.Builder(); | |||||
services.AddHostedService<JT1078WebSocketPushHostedService>(); | |||||
// .Builder(); | |||||
//services.AddHostedService<JT1078WebSocketPushHostedService>(); | |||||
//services.AddHostedService<FFMPEGRTMPHostedService>(); | |||||
services.AddHostedService<FFMPEGHTTPFLVPHostedService>(); | |||||
}); | }); | ||||
await serverHostBuilder.RunConsoleAsync(); | await serverHostBuilder.RunConsoleAsync(); | ||||
@@ -0,0 +1,54 @@ | |||||
using DotNetty.Buffers; | |||||
using DotNetty.Codecs.Http.WebSockets; | |||||
using JT1078.DotNetty.Core.Session; | |||||
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; | |||||
namespace JT1078.DotNetty.TestHosting | |||||
{ | |||||
class FFMPEGRTMPHostedService : IHostedService | |||||
{ | |||||
private readonly JT1078DataService jT1078DataService; | |||||
private readonly FFMPEGRTMPPipingService fFMPEGPipingService; | |||||
public FFMPEGRTMPHostedService( | |||||
JT1078DataService jT1078DataService) | |||||
{ | |||||
this.jT1078DataService = jT1078DataService; | |||||
fFMPEGPipingService = new FFMPEGRTMPPipingService("demo1"); | |||||
} | |||||
public Task StartAsync(CancellationToken cancellationToken) | |||||
{ | |||||
Task.Run(() => | |||||
{ | |||||
try | |||||
{ | |||||
foreach (var item in jT1078DataService.DataBlockingCollection.GetConsumingEnumerable(cancellationToken)) | |||||
{ | |||||
fFMPEGPipingService.Wirte(item); | |||||
} | |||||
} | |||||
catch(Exception ex) | |||||
{ | |||||
Console.WriteLine(ex); | |||||
} | |||||
}, cancellationToken); | |||||
return Task.CompletedTask; | |||||
} | |||||
public Task StopAsync(CancellationToken cancellationToken) | |||||
{ | |||||
return Task.CompletedTask; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,71 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Diagnostics; | |||||
using System.IO; | |||||
using System.IO.Pipes; | |||||
using System.Text; | |||||
namespace JT1078.DotNetty.TestHosting | |||||
{ | |||||
/// <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> | |||||
public class FFMPEGRTMPPipingService : IDisposable | |||||
{ | |||||
private readonly Process process; | |||||
private readonly NamedPipeServerStream pipeServer; | |||||
public FFMPEGRTMPPipingService(string pipeName) | |||||
{ | |||||
pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.WriteThrough, 10000, 10000); | |||||
string rtmp = "rtmp://127.0.0.1/living/streamName"; | |||||
process = new Process | |||||
{ | |||||
StartInfo = | |||||
{ | |||||
FileName = @"C:\ffmpeg\bin\ffmpeg.exe", | |||||
Arguments = $@"-i \\.\pipe\{pipeName} -c copy -f flv {rtmp}", | |||||
UseShellExecute = false, | |||||
CreateNoWindow = true, | |||||
RedirectStandardError = true | |||||
} | |||||
}; | |||||
process.Start(); | |||||
process.ErrorDataReceived += ErrorDataReceived; | |||||
pipeServer.WaitForConnection(); | |||||
} | |||||
public void ErrorDataReceived(object sender, DataReceivedEventArgs e) | |||||
{ | |||||
Console.WriteLine(e.Data); | |||||
} | |||||
public void Wirte(byte[] buffer) | |||||
{ | |||||
if (pipeServer.IsConnected) | |||||
pipeServer.WriteAsync(buffer); | |||||
} | |||||
public void Dispose() | |||||
{ | |||||
try | |||||
{ | |||||
process.Kill(); | |||||
pipeServer.Flush(); | |||||
} | |||||
catch | |||||
{ | |||||
} | |||||
process.Dispose(); | |||||
pipeServer.Dispose(); | |||||
} | |||||
} | |||||
} |
@@ -1,15 +1,28 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | <Project Sdk="Microsoft.NET.Sdk"> | ||||
<Import Project="..\SharedProperties.props" /> | |||||
<Import Project="..\Version.props" /> | |||||
<PropertyGroup> | <PropertyGroup> | ||||
<TargetFramework>netstandard2.0</TargetFramework> | <TargetFramework>netstandard2.0</TargetFramework> | ||||
<LangVersion>7.3</LangVersion> | |||||
<Copyright>Copyright 2019.</Copyright> | |||||
<Authors>SmallChi(Koike)</Authors> | |||||
<PackageId>JT1078.DotNetty.Udp</PackageId> | <PackageId>JT1078.DotNetty.Udp</PackageId> | ||||
<Product>JT1078.DotNetty.Udp</Product> | <Product>JT1078.DotNetty.Udp</Product> | ||||
<Description>基于DotNetty实现的JT1078DotNetty的Udp服务</Description> | <Description>基于DotNetty实现的JT1078DotNetty的Udp服务</Description> | ||||
<PackageReleaseNotes>基于DotNetty实现的JT1078DotNetty的Udp服务</PackageReleaseNotes> | <PackageReleaseNotes>基于DotNetty实现的JT1078DotNetty的Udp服务</PackageReleaseNotes> | ||||
<RepositoryUrl>https://github.com/SmallChi/JT1078DotNetty</RepositoryUrl> | |||||
<PackageProjectUrl>https://github.com/SmallChi/JT1078DotNetty</PackageProjectUrl> | |||||
<licenseUrl>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</licenseUrl> | |||||
<license>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</license> | |||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> | |||||
<SignAssembly>false</SignAssembly> | |||||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | |||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\JT1078.DotNetty.Core\JT1078.DotNetty.Core.csproj" /> | <ProjectReference Include="..\JT1078.DotNetty.Core\JT1078.DotNetty.Core.csproj" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | |||||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" /> | |||||
</ItemGroup> | |||||
</Project> | </Project> |
@@ -1,11 +1,22 @@ | |||||
<Project Sdk="Microsoft.NET.Sdk"> | <Project Sdk="Microsoft.NET.Sdk"> | ||||
<Import Project="..\SharedProperties.props" /> | |||||
<Import Project="..\Version.props" /> | |||||
<PropertyGroup> | <PropertyGroup> | ||||
<TargetFramework>netstandard2.0</TargetFramework> | <TargetFramework>netstandard2.0</TargetFramework> | ||||
<LangVersion>7.3</LangVersion> | |||||
<Copyright>Copyright 2019.</Copyright> | |||||
<Authors>SmallChi(Koike)</Authors> | |||||
<PackageId>JT1078.DotNetty.WebSocket</PackageId> | <PackageId>JT1078.DotNetty.WebSocket</PackageId> | ||||
<Product>JT1078.DotNetty.WebSocket</Product> | <Product>JT1078.DotNetty.WebSocket</Product> | ||||
<Description>基于DotNetty实现的JT1078DotNetty的WebSocket服务</Description> | <Description>基于DotNetty实现的JT1078DotNetty的WebSocket服务</Description> | ||||
<PackageReleaseNotes>基于DotNetty实现的JT1078DotNetty的WebSocket服务</PackageReleaseNotes> | <PackageReleaseNotes>基于DotNetty实现的JT1078DotNetty的WebSocket服务</PackageReleaseNotes> | ||||
<RepositoryUrl>https://github.com/SmallChi/JT1078DotNetty</RepositoryUrl> | |||||
<PackageProjectUrl>https://github.com/SmallChi/JT1078DotNetty</PackageProjectUrl> | |||||
<licenseUrl>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</licenseUrl> | |||||
<license>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</license> | |||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> | |||||
<SignAssembly>false</SignAssembly> | |||||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | |||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
@@ -18,5 +29,7 @@ | |||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\JT1078.DotNetty.Core\JT1078.DotNetty.Core.csproj" /> | <ProjectReference Include="..\JT1078.DotNetty.Core\JT1078.DotNetty.Core.csproj" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | |||||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" /> | |||||
</ItemGroup> | |||||
</Project> | </Project> |
@@ -1,19 +0,0 @@ | |||||
<Project> | |||||
<PropertyGroup> | |||||
<LangVersion>7.3</LangVersion> | |||||
<Copyright>Copyright 2019.</Copyright> | |||||
<Authors>SmallChi(Koike)</Authors> | |||||
<RepositoryUrl>https://github.com/SmallChi/JT1078DotNetty</RepositoryUrl> | |||||
<PackageProjectUrl>https://github.com/SmallChi/JT1078DotNetty</PackageProjectUrl> | |||||
<licenseUrl>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</licenseUrl> | |||||
<license>https://github.com/SmallChi/JT1078DotNetty/blob/master/LICENSE</license> | |||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> | |||||
<Version>1.0.0-preview2</Version> | |||||
<SignAssembly>false</SignAssembly> | |||||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | |||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||||
</PropertyGroup> | |||||
<ItemGroup> | |||||
<None Include="..\..\LICENSE" Pack="true" PackagePath="" /> | |||||
</ItemGroup> | |||||
</Project> |
@@ -0,0 +1,5 @@ | |||||
<Project> | |||||
<PropertyGroup> | |||||
<JT1078DotNettyPackageVersion>1.0.0-preview2</JT1078DotNettyPackageVersion> | |||||
</PropertyGroup> | |||||
</Project> |