在 C# 应用程序中播放 Raspberry Pi h264 流
Posted
技术标签:
【中文标题】在 C# 应用程序中播放 Raspberry Pi h264 流【英文标题】:Play Raspberry Pi h264 stream in C# app 【发布时间】:2014-08-19 12:00:06 【问题描述】:我有一个带有专用摄像头的 Raspberry Pi 板,仅在 h264 中录制视频。我正在寻找在 c# windows forms 应用程序中实时流式传输和播放录制视频的最佳方法(如延迟小于 1 秒)。附加要求是此类流可以在显示之前轻松处理,例如用于搜索图像上的对象。
我尝试过的东西:
- raspi 上的 VLC 服务器和 c# 表单应用程序中的 VLC 控制
- 使用 nc 在 raspi 上创建一个套接字,在 c# 中接收原始 h264 数据并将其传递给 mplayer 前端
- 使用https://github.com/cisco/openh264
h264dec.exe vid.h264 out.yuv
这会产生 0bytes out.yuv 文件,而:
h264dec.exe vid.h264
给我错误消息:“配置文件中没有指定输入文件。”
- ffmpeg
我什至不确定我是否正确地接近了这个主题,所以我非常感谢我能得到的每一条建议。
编辑 这是我试图在 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 完成的(已经尝试过)。
【问题讨论】:
【参考方案1】:好的,所以实际上我设法解决了这个问题:
就像我之前所说的 -fps 120 选项可以让播放器跳过缓冲区中的内容并在收到流时立即播放。 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 是 rasp 正在侦听的端口号。
#!/bin/bash
raspivid --width 1280 --height 720 -t 9999999 --framerate 25 --output - | nc -l PORTNUMBER
【讨论】:
【参考方案2】:我没有使用 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 -
注意:写摄像头连接的树莓派的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 脚本并关闭 mplayer 子进程,我们在 End
函数中调用 pkill。
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 安装单声道:
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
使用此命令(与@CoreMeltdown 相同)在连接相机的 Raspberry Pi 上启动相机流。
raspivid --width 400 --height 300 -t 9999999 --framerate 25 --output - | nc -l 5000
在接收器 Raspberry Pi(带有已编译二进制文件的那个)上,打开终端,使用二进制文件转到目录并执行:
mono MplayerFrontEnd.exe # MplayerFrontEnd is the name of my project, use your own name here.
这是它的样子:
开发愉快:D
【讨论】:
以上是关于在 C# 应用程序中播放 Raspberry Pi h264 流的主要内容,如果未能解决你的问题,请参考以下文章
适用于 Raspberry Pi 的轻量级音频播放和图像显示
如何使用 Python 在 Raspberry Pi 上杀死 omxplayer 播放器
在 Raspberry Pi(Python 和 Socket)上播放 .wav 文件时遇到问题
c# mono raspberry pi GPIO with Raspberry#getting Operation is not valid