110,545
社区成员
发帖
与我相关
我的任务
分享
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace IPClient.Core
{
public class RtmpPusher
{
private int _camId;
private readonly string _ffmpeg_path;
private readonly string _rtmp_url;
private ConcurrentQueue<byte[]> _bgr24Buffer = new ConcurrentQueue<byte[]>();
public RtmpPusher(int camId)
{
this._camId = camId;
this._ffmpeg_path = @"D:\quickhigh\ffmpeg\bin\ffmpeg.exe";
this._rtmp_url = string.Format("rtmp://192.168.1.202/live/{0}", camId);
string pipeName = string.Format("pusher{0}", camId);
Task.Factory.StartNew((p) =>
{
DoWriteWork(p as string);
}, pipeName, TaskCreationOptions.LongRunning);
Task.Factory.StartNew((p) =>
{
DoRunFFMPEG(p as string);
}, pipeName, TaskCreationOptions.LongRunning);
}
public RtmpPusher StartNew(int camId)
{
return new RtmpPusher(camId);
}
public void AddBuffer(byte[] buffer)
{
if (_bgr24Buffer.IsEmpty)
{
int height = 720;
int width = 1280;
int dataLen = width * height * 3;
byte[] rgb24_buffer = new byte[width * height * 3];
//54字节是BMP固定信息
Array.Copy(buffer, 54, rgb24_buffer, 0, dataLen);
//bmp位图数据存储时是B、G、R排列,变成RGB24时G不动调换R、B。
for (int j=0;j< height; j++)
{
for (int i = 0; i < width; i++)
{
byte temp = rgb24_buffer[(j * width + i) * 3 + 2];
rgb24_buffer[(j * width + i) * 3 + 2] = rgb24_buffer[(j * width + i) * 3 + 0];
rgb24_buffer[(j * width + i) * 3 + 0] = temp;
}
}
_bgr24Buffer.Enqueue(rgb24_buffer);
}
}
private void DoWriteWork(string pipeName)
{
byte[] buffer = null;
using (NamedPipeServerStream pipeServer =new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1))
{
pipeServer.WaitForConnection();
do
{
try
{
if (_bgr24Buffer.TryDequeue(out buffer))
{
using (StreamWriter sw = new StreamWriter(pipeServer))
{
Trace.WriteLine("+1");
char[] cBuffer = Encoding.ASCII.GetChars(buffer);
sw.Write(cBuffer, 0, cBuffer.Length);
sw.Flush();
}
}
}
catch
{ }
finally
{
Thread.Sleep(1);
}
}
while (pipeServer.IsConnected);
}
}
private void DoRunFFMPEG(string pipeName)
{
string args = string.Format(@"-y -f rawvideo -vcodec rawvideo -pix_fmt bgr24 -s 1280x720 -r 5 -i \\.\pipe\{0} -c:v libx264 -pix_fmt yuv420p -preset ultrafast -f flv ""{1}""", pipeName, _rtmp_url);
RunFFMPEG(args);
}
private void RunFFMPEG(string args)
{
Process p = new Process();
p.StartInfo.FileName = _ffmpeg_path;
p.StartInfo.Arguments = args;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = false;
p.ErrorDataReceived += new DataReceivedEventHandler(ffmpeg_Output);
p.Start();
p.BeginErrorReadLine();
p.WaitForExit();//阻塞等待进程结束
p.Close();
p.Dispose();
}
private void ffmpeg_Output(object sender, DataReceivedEventArgs e)
{
Trace.WriteLine(e.Data);
}
}
}