C#FFmpeg视频采集与推送RTMP服务器代码思路整理
C#视频采集与推送RTMP服务器代码思路整理:在看过FFmpeg后是否认为写C#的视频流采集和推送还是一头雾水啊?深有此感。领导是C#的高手,说可以通过C或C++的代码直接复制粘贴到C#工程然后进行适配代码就可以了,因为C#使用ffmpeg的类名和变量、方法等都与C保持高度一致的,经领导这么一说C#里面只需要参考C或C++的实现就可以完成相关的操作了,这样就更容易理解了(涉及到指针问题,C#也支持)。本文旨在分析实现思路,而不提供源代码,敬请谅解!
服务端和客户端的职能
客户端负责视频采集,服务端负责视频转发或播放
整体设计视频传输架构
说明:视频数据发送H264数据包给服务端,服务端获取到数据包进行编解码转成FLV格式的流,而RTMP只支持FLV格式的流。
原理:socket视频数据采集,socket 数据包发送,编解码处理,推流。
视频直播推流效果展示
启动顺序:程序客户端和服务端是两个项目需要分别启动,先启动服务端,再启动客户端,允许多个实例存在。
第一幕:启动视频编解码服务端
第二幕:启动视频采集摄像头客户端
点击开始连接到服务端。
第三幕:服务端处理要连接的客户端并建立数据传输
选择客户端,并开始传输视频,此时会弹出摄像头访问窗口。
第四幕:验证直播是否进行
访问RTMP服务器状态监控地址,如:http://172.16.20.10:1990/stat
第五幕:使用ffplay进行直播流播放
cmd进入ffmpeg的路径执行:ffplay rtmp://172.16.20.10:1935/live/S013333333333
以上就是所有架构实现的效果了。
摄像头视频采集客户端
客户端窗体变量:
// socket数据包封装对象
JTData jtdata = new JTData();
// 数据分包对象
SplitData splitData = new SplitData();
// TCP通信通道
Network.TCPChannel channel;
// 标识用户手机号
string SimKey = "013333333333";
// 线程对象
Thread thVideo;
// Socket实例对象
private Socket send_sock;
private Queue<Bitmap> mQueues = new Queue<Bitmap>();
// 摄像头处理H264对象
Cam2H264 cam2H264 = new Cam2H264();private Setting setting;
IPEndPoint iPEndPoint;
客户端窗体开始录像按钮处理:
private void btnStart_Click(object sender, EventArgs e){channel = new Network.TCPChannel(txtServer.Text.Trim(), Convert.ToInt32(txtPort.Text.Trim()));//实例化TCP连接通道channel.DataReceive = Receive;channel.DataSend = DataSend;channel.ChannelConnect += new EventChannelConnect(channel_ChannelConnect);// 设置通道连接事件channel.Connect();//channel.StartReceiveAsync();btnStart.Enabled = false;btnStop.Enabled = true;}
客户端窗体TCP通道回调函数:
void channel_ChannelConnect(object sender, ChannelConnectArg arg){Console.WriteLine(arg.SocketError.ToString());SendHeart();}private void SendHeart(){var lst = jtdata.Package(0x0002, SimKey);SendAnswer(lst);}#region 链路public void Receive(object sender, ChannelReceiveArg arg){splitData.SplitDataBy7E(arg.Data, ((byte[] bGps) =>{if (bGps.Length > 11 && CheckHelper.CheckXOR(bGps, 0, bGps.Length - 1) == bGps[bGps.Length - 1])//效验通过{var head = JTHeader.NewEntity(bGps);JXData(bGps, head);}}));}public void JXData(byte[] bGps, JTHeader head){switch (head.MsgId){case 0x8001://通用应答break;case 0x8B00://4.1.1 实时音视频传输请求if (thVideo != null && thVideo.IsAlive){Console.WriteLine("已经在传输");}else{BaseLineTime = DateTime.Now;SerialNumber = 0;LastIFrameTime = DateTime.MinValue;LastFrameTime = DateTime.MinValue;var req = JTRealVideoTransferRequest.NewEntity(bGps, head.HeadLen);thVideo = new Thread(StartVideo);thVideo.IsBackground = true;iPEndPoint = new IPEndPoint(IPAddress.Parse(req.IPAddress), req.UdpPort);thVideo.Start(iPEndPoint);}break;default:break;}}public void DataSend(object sender, ChannelSendArg arg){}public bool SendAnswer(JTPData data){foreach (var item in data){channel.Send(item.Data.ToArray());//return true;}return true;}
客户端窗体线程处理视频数据:
unsafe void StartVideo(object ep){try{send_sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);send_sock.SendBufferSize = 1000000;cam2H264.Run(setting.VideoDevice, SendToServer, 0);}catch (Exception ex){}}
具体264的处理基本上可以参考FFmpeg的C实现方式来做,下面是步骤:
请参考:https://github.com/FFmpeg/FFmpeg
视频数据包转发服务端
注:实际服务端未做转码处理,已在客户端线程中处理。
服务端窗体常量:
// 开启本机TCP连接
Network.TCPServer ser = new Network.TCPServer("0.0.0.0", 9700);
// RTP服务端
RTPServer rtServer;
// 连接到的客户端列表
List<VideoClient> lstTCPChannel = new List<VideoClient>();
// 数据包拆分对象
JX.SplitData splitData = new JX.SplitData();
服务端窗体事件绑定与客户端连接自动发现:
#region 窗体事件private void frmServer_FormClosing(object sender, FormClosingEventArgs e){try{ser.Stop();}catch{}try{rtServer.Dispose();}catch{}}private void btnStart_Click(object sender, EventArgs e){var vc = lstTCPChannel[lstBoxTcp.SelectedIndex];//rtServer.AddClient(vc.SimKey, "rtmp://localhost:32768/rtmplive/S" + vc.SimKey);rtServer.AddClient(vc.SimKey, "rtmp://172.16.20.10:1935/live/S" + vc.SimKey);// 添加直播客户端---RTMP推流服务器地址和流名称vc.SendVideoCtrl(new JTRealVideoTransferRequest{IPAddress = "127.0.0.1",UdpPort = 9700,Channel = 0,DataType = 1,StreamType = StreamType.SubStream});}private void frmServer_Load(object sender, EventArgs e){rtServer = new RTPServer(9700, pictureBox1);//RTP服务端图像传输对象rtServer.Start();ser.ChannelConnect += new Network.EventChannelConnect(ser_ChannelConnect);// 通道连接事件ser.ChannelDispose += new Network.EventChannelDispose(ser_ChannelDispose);// 通道连接断开事件ser.Start();Network.Utils.Setup(10);}#endregion
服务端窗体客户端连接列表控制:
#region 列表控制VideoClient AddToList(Channel channel){var item = new VideoClient(channel, splitData);channel.Tag = item;lstTCPChannel.Add(item);//rtServer.AddClient(item.SimKey, "rtmp://localhost:32768/rtmplive/S" + item.SimKey);rtServer.AddClient(item.SimKey, "rtmp://172.16.20.10:1935/live/S" + item.SimKey);// 添加直播客户端---RTMP推流服务器地址和流名称lstBoxTcp.BeginInvoke(new MethodInvoker(() =>{lstBoxTcp.Items.Add(channel.RemoteHost + ":" + channel.RemotePort);}));return item;}void RemoveList(Channel channel){var item = (VideoClient)channel.Tag;lstTCPChannel.Remove(item);rtServer.RemoveClient(item.SimKey);lstBoxTcp.Invoke(new MethodInvoker(() =>{lstBoxTcp.Items.Remove(channel.RemoteHost + ":" + channel.RemotePort);}));}#endregion
服务端窗体通信链路事件方法:
#region 链路相关void ser_ChannelDispose(object sender, Network.ChannelDisposeArg arg){RemoveList(arg.Channel);}void ser_ChannelConnect(object sender, Network.ChannelConnectArg arg){var item = AddToList(arg.Channel);arg.Channel.DataReceive = item.Receive;arg.Channel.DataSend = item.DataSend;arg.Channel.StartReceiveAsync();}#endregion
大致代码的思路都在此了。
需要思考的问题
想达到这样的目的:视频能够一边下载一边播放。如何编程实现服务器端的视频流信息向客户端的发送? 客服端又如何接收并播放视频?
使用System.Net的NetStream和使用System.IO的FileStream、MediaPlayer播放插件。
(1)在服务端建立一个Socket服务,将文件分段放入缓冲区。
(2)在客户端建立一个Socket客户端,读取服务端的缓冲区内容。
(3)将读到的部分发送给MediaPlayer进行播放。
上面的客户端和服务端的情况就是按照这种思路来写的,后续需要加入视频预览、播放的功能。实际上就是将H264流数据转成YUV/RGB->Bitmap前端进行展示,然后加入音频数据传输的线程等进行处理同步播放。
上图是服务器端获取到的H264->YUV播放示例。
C#FFmpeg视频采集与推送RTMP服务器代码思路整理相关推荐
- Android视频采集实时推送RTP/RTSP/RTMP
因为在工作中,接触到了视频相关的开发工作:同时,大多数android处理音视频多半都是有C++工程师提供处理库,所以,在这里记录一下我自己在工作中遇到的问题. 主要功能: 采集Android摄像头数据 ...
- 使用ffmpeg循环推流(循环读取视频文件)推送RTMP服务器的方法
https://blog.csdn.net/cai6811376/article/details/74783269/
- 最简单的基于FFmpeg的推流器(以推送RTMP为例)
===================================================== 最简单的基于FFmpeg的推流器系列文章列表: <最简单的基于FFmpeg的推流器(以 ...
- GDLiveStreaming视频推送RTMP
所谓的视频推送就是把摄像头和麦克风捕获到视频和音频推送到直播服务器上.我们这里使用推送协议是RTMP协议. 扩展:腾讯直播平台,阿里直播平台,百度直播平台提供均为RTMP的推流和HLS/RTMP等拉流 ...
- 腾讯视频怎样关闭推送迷你页面
腾讯视频是一款难得的好软件,本文给大家分享"腾讯视频怎样关闭推送迷你页面",相信大家看完后在使用方面更加得心应手.腾讯视频客户端为您推荐更多精选热门视频,通过多条件筛选快速定位匹配 ...
- Sql 经典题目(视频相同爱好推送)
表 collect_spu id代表用户,spu_id 代表用户浏览的产品 题目则是:向有过历史上完全一样的产品浏览记录的两个用户,推送(两个用户之间)新的浏览记录. 001 A F H 0 ...
- php微信小程序物流进度推送,微信小程序 消息推送php服务器验证实例详解
微信小程序 消息推送php服务器验证实例详解 设置页面("设置">>"开发设置"): 1.设置服务器域名 注意http和https协议的不同. 2. ...
- 极光推送maven与代码,无需修改,粘贴即用
maven: <!-- 极光推送 --> <dependency><groupId>cn.jpush.api</groupId><artifact ...
- java socket 推送机制_Java中websocket消息推送的实现代码
一.服务层 package com.demo.websocket; import java.io.IOException; import java.util.Iterator; import java ...
最新文章
- ubuntu16.0.4 opencv4.0.0 GPU 版本的 SURF
- flv文件转换,完美解决
- VTK修炼之道1_初识VTK
- servlet多重映射_关于多重映射问题,很奇怪
- 解决长email在表格td中不自动换行的问题 CSS强制不换行
- Netty 5.X 官方指南翻译版7
- mac通过android打电话,应用短评:用Mac打电话的意义在哪?
- linux mrtg,鳥哥的 Linux 私房菜 -- MRTG 流量偵測法
- linux debian硬盘安装,Debian硬盘安装方法
- 存储容错:鱼与熊掌可以兼得
- Scale-up and Scale-out
- wps下一步快捷键_WPS快捷键大全(最常用138个办公快捷键)
- 计算机怎么改鼠标标志,鼠标指针怎么换,教您如何更换鼠标指针
- 西数MyBookDuo提供致臻性能、超大容量及综合数据保护
- 淘宝/天猫/京东/拼多多/苏宁易购/小米商城/华为商城/抖音快手直播/茅台抢购助手,宝惠抢购助手/OK助手源码
- 青蛙跳台阶问题(超详解)
- python 特征选择卡方_文本特征选择(信息熵、Gini、IV、卡方值)
- 爱因斯坦《社会和个人 》
- 开发APP的费用是多少?
- Java各种数据类型互转