QT下的udp视频传输系统
前段时间工作著
本文只为记录思路,若想认真学会开发请参考 参考资料和官方文档
@[toc]
总体框图
框图是从需求里面来的,那我自然是奔着视频流传输去的,但是在底层的硬件配置摄像头的过程中,我们可以通过IIC去重设一些参数,比如宽高啊,白平衡啊什么的.所以我在这里的设计是这样的.
就是分两条线程去写,主线程ui,新建一条UDP线程,不然在视频流传输的时候程序会很容易crash.
然后由于我想在一个路由器中搞完,不用自己指定ip,所以获取一下ip地址这样子
帧结构(帧头)
帧结构最初可见参考资料,我增删了一些东西
1 | struct ImageFrameHead{ |
这里我们跟当初学UDP一样进行分片处理,然后用片偏移分段写入到图片的Buffer中,然后CmdFrameHead里面是可以动态配置摄像头的,但是因为当时赶工程,这里就用从机ip打回来了(文末有点说明),而且保持了命令帧跟视频帧头等长
所以整个帧就是帧头加数据组成,总的传输长度由TRANS_SIZE 控制
1 |
类UdpThread
由于在这里需要再拉一条线程干活,新建一个UDPSocket,不断接收消息和接收视频流.那就干脆新建一个类.
1 | class UdpThread : public QThread |
这里需要注册两个信号两个槽:
- 信号sigRecvok(char *buf, int len)记录已经传输完一帧
- 信号cmdRecvok(CmdFrameHead *buf) 下位机发来贺电
- 槽slotRecv(),在网卡上截获到UDP信息(即readyRead())
- 槽slotChangewh(),上位机希望改变宽高
另外需要注意的就是,在构折函数里面,要关掉UDPSocket和free掉m_buf(^_^我炸了)
槽slotRecv()
在这里我们需要对接收到的帧进行处理:
1 | void UdpThread::slotRecv() |
槽slotChangewh(int w,int h)
在这里由于重设了宽和高,所以我们需要重设m_buf的大小,这里乘3是因为我用的是RGB888,所以需要考虑3通道,如果是ycr422的话就不需要这么大了
1 | void UdpThread::slotChangewh(int w,int h) |
图片显示
其实在上面注册完信号和槽之后思路就很清晰了,这里要处理的主要是底层摄像头传回来的byte数据我们要怎么”显示”.
因为不同于其他抽象层次的传输,我们传上来的数据是没有编码的.看见有用opencv来干的,但是想想又要编译感觉好麻烦,我就去翻了一下官方手册,才发现官方是提供方法编码的.
核心代码见:
1 | void Udp_Widget::slotRecv(char* buf,int len) |
那顺便记录一下,QT还支持多少这些像素格式编码.哎啊自己看手册吧
这里也引来一个毛病,就是如果也只是在一个线程中来编码的话,有时候会因为fps过高而爆炸,正常做法是做一个队列,再动态新建线程来处理,但是 赶工程 然后当时也没这个需求就没做了:)
一些设计细节
绑定的端口是8080,用之前要改win的防火墙规则
用udp发送数据的方法是:
1
2m_udpThread->m_udpSocket->writeDatagram(m_sendBuf, TRANS_SIZE,
QHostAddress::Broadcast,8080);其实拿从机的ip地址不需要自己傻乎乎整个命令帧,在处理帧的时候就可以直接拿了
1
2
3
4
5char buf[1024] = {0};
QHostAddress addr; //对方的ip
quint16 port; //对方的端口
qint64 len;
len = udpsocket->readDatagram(buf, sizeof(buf), &addr, &port);
这样做的原因是因为在zynq中的lwip也是我设计的,当时在做的时候不知道发点啥,就回传一下ip看看误码怎么样
4. 功能码funcode我的定义是这样的
- funcode = 24 从->主,视频帧
- funcode = 25 主->从,命令帧
- funcode = 26 从->主,回复帧
5. 做了个截图功能,会保存在当前目录下
成果
由于赶工原因,界面ui我们就不讲究了吧…
版本信息
设计环境 | 版本号 |
---|---|
QT creator | 4.10.1 |
QT(版本号) | 5.13 |
结语
之前想着用mfc来写的,但是考虑到mfc那个socket是真的过时,就放弃了
这个因为不是开发重点(硬件那边的设计难多了…),所以这个就是一直保持 能用就行的状态.但是还是记录一下,需要源码的可以联系我.
我还单独写了收发端,有需要的朋友也可以联系我,那个做的就是为了模拟硬件环境的收发,因为当时联调BUG太多了,不知道是哪方出了问题
另 接fpga,qt,嵌入式的外包,有兴趣可联系.
如果你觉得有丶收获的话
参考资料
Qt5&OpenCV3 UDP协议实现实时视频传输与通信
Qt学习之路十二——利用UDP进行通信
Qt通过UDP传图片,实现自定义分包和组包
Qt5–UDP图片传输并显示