[英]Play Raspberry Pi h264 stream in C# app
我有一个带有专用摄像头的Raspberry Pi板,只能在h264中录制视频。 我正在寻找在c#windows forms app中实时流式传输和播放录制视频的最佳方法(例如,延迟不到1秒)。 附加要求是在显示之前可以容易地处理这样的流,例如用于搜索图像上的对象。
我试过的东西:
- 使用radi上的VLC服务器和c#中的VLC控制形成app < - 简单的解决方案,使用RTSP,但是有一个严重的缺陷,即显示的图像延迟约3秒。 我无法用buffor size / options等修复它。
- 使用nc在raspi上创建套接字,在c#中接收原始h264数据并将其传递给mplayer前端 < - 如果我只是启动raspotion | nc和笔记本电脑上的nc | mplayer,我得到我想要的结果,我得到的视频几乎是实时的,但是当我尝试在c#中创建mplayer前端并模拟nc.exe时出现问题。 也许我正在传递h264数据错误(只是将它们写入stdin)或者其他东西。
- 使用https://github.com/cisco/openh264 < - 我编译了所有内容,但我甚至无法解码使用h264dec.exe在raspi上录制的样本vid.h264,更不用说在c#中使用它了。
h264dec.exe vid.h264 out.yuv
这会产生0bytes out.yuv文件,而:
h264dec.exe vid.h264
给我错误消息:“配置文件中没有指定输入文件。”
- ffmpeg < - 我在c#app中实现了ffplay.exe播放,但缺少简单的方法来获取screencaps等,这使我无法进一步调查和开发。
我甚至不确定我是否正确地接近这个主题,所以我真的很感谢我能得到的每一条建议。
编辑这是我试图在c#中实现的“工作”解决方案
raspivid --width 400 --height 300 -t 9999999 --framerate 25 --output - | nc -l 5884
nc ip_addr 5884 | mplayer -nosound -fps 100 -demuxer +h264es -cache 1024 -
这里的关键是FPS 100,因为mplayer跳过滞后并以正常速度播放它立即收到的视频。 这里的问题是我不知道如何通过c#将视频数据从socket传递到mplayer,因为我猜它不是通过stdin完成的(已经尝试过了)。
好的,实际上我设法解决了这个问题:
就像我之前说的那样-fps 120选项是让玩家在收到它后立即跳过buffor和播放流中的内容。 PanelId是一个面板的句柄,其中mplayer是嵌套的。
class Mplayer
{
Process mplayer;
public Mplayer(string path, string pipeName, int panelId)
{
String args = "";
mplayer = new Process();
mplayer.StartInfo.UseShellExecute = false;
mplayer.StartInfo.RedirectStandardInput = true;
mplayer.StartInfo.FileName = path;
args = @"\\.\pipe\" + pipeName + " -demuxer +h264es -fps 120 -nosound -cache 512";
args += " -nofs -noquiet -identify -slave ";
args += " -nomouseinput -sub-fuzziness 1 ";
args += " -vo direct3d, -ao dsound -wid ";
args += panelId;
mplayer.StartInfo.Arguments = args;
}
public void Start()
{
mplayer.Start();
}
public void End()
{
mplayer.Kill();
}
}
后台工作者从套接字读取东西:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
try
{
pipeServ.WaitForConnection(); //opcjonalne?
StreamWriter sw = new StreamWriter(pipeServ);
sw.AutoFlush = true;
tcpCamera = new TcpClient();
tcpCamera.Connect(ipAddress, camPort);
NetworkStream camStream = tcpCamera.GetStream();
int read = 0;
byte[] bytes = new byte[tcpCamera.ReceiveBufferSize];
while (tcpCamera.Connected)
{
read = camStream.Read(bytes, 0, tcpCamera.ReceiveBufferSize);
if (read > 0)
pipeServ.Write(bytes, 0, read);
}
}
catch (IOException ex)
{
//Broken pipe - result of Mplayer exit
//MessageBox.Show(ex.Message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
在RaspberryPi上运行的脚本。 Portnumber是锉刀正在监听的端口号。
#!/bin/bash
raspivid --width 1280 --height 720 -t 9999999 --framerate 25 --output - | nc -l PORTNUMBER
我在不使用NamedPipes的情况下解决了它。 方法如下:
注意:此解决方案仅适用于Linux。
首先创建一个bash脚本VideoStreamRecv.bash
。 $1
是WindowID的参数,我们将WinForm面板ID传递给此bash脚本。
#!/bin/bash -e
nc 127.0.0.1 5000 | mplayer -nosound -fps 120 -demuxer h264es -cache 1024 -wid $1 -
注意:写入相机所连接的Raspberry Pi的IP代替127.0.0.1
。
创建您的C#项目。 我在Visual Studio中创建了一个简单的Windows窗体应用程序项目。 这是整体外观。
以下是课程:
Base.cs
public partial class Base : Form
{
private MPlayer Player;
private StreamWriter PlayerInput;
public Base()
{
InitializeComponent();
}
private void Base_Load(object sender, EventArgs e)
{
Player = new MPlayer((int)Video.Handle);
Player.Start();
}
private void Stop_Click(object sender, EventArgs e)
{
Player.End();
}
}
MPlayer.cs
它就像@CoreMeltdown但在这里我们正在调用bash脚本并关闭我们在End
函数中调用pkill的mplayer子进程。
class MPlayer
{
Process mplayer;
public MPlayer(int PanelID)
{
mplayer = new Process();
mplayer.StartInfo.UseShellExecute = false;
mplayer.StartInfo.RedirectStandardInput = true;
mplayer.StartInfo.FileName = "VideoStreamRecv.bash";
mplayer.StartInfo.Arguments = PanelID.ToString();
}
public void Start()
{
mplayer.Start();
}
public void End()
{
mplayer.Kill();
Process.Start("pkill mplayer");
}
}
编译项目并将所有二进制文件和VideoStreamRecv.bash
复制到与Raspberry Pi中的二进制文件相同的目录中。
使用以下命令为Raspberry Pi安装mono:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
echo "deb http://download.mono-project.com/repo/debian raspbianstretch main" | sudo tee /etc/apt/sources.list.d/mono-official.list
sudo apt-get update
sudo apt-get install mono-devel --yes --allow-unauthenticated
使用此命令在Raspberry Pi上启动相机流,并使用此命令连接相机(与@CoreMeltdown相同)。
raspivid --width 400 --height 300 -t 9999999 --framerate 25 --output - | nc -l 5000
在接收器Raspberry Pi(带有编译的二进制文件的那个)上,打开终端,用二进制文件转到dir并执行:
mono MplayerFrontEnd.exe # MplayerFrontEnd is the name of my project, use your own name here.
这是它的样子:
快乐开发:D
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.