本帖最后由 酷洵软件 于 2019-6-11 16:00 编辑
一、 概述
应用QT 和C++技术,采集视频设备的数据流,通过分发技术方案,可以使多个终端设备接收该视频流;视频器材可以是任何基于IP网络的视频设备,如视频眼镜、摄像机等。接收分发视频流的终端基本支持所有设备,如PC机、IOS手机、Android手机等;该技术方案主要用来解决两个问题:视频安全可控【防止视频数据泄露】;大幅度节约视频应用成本【目前使用视频云服务的成本相当高昂】。
二、 技术方案总览图框架图
总体分三层结构,视频采集层、数据源管理层和终端接收层,如下图所示:
三、 视频源采集技术
可以通过如下步骤采集视频流(本例以广播包形式说明),视频采集设备可以是PC或者手机终端【本例以Android手机端作为视频采集端,如何编译FFMPEG Android,请参考:https://www.apps121.com/2019/03/11/ffmpeg4-1-androidlibwindows_compile_successfully/】
1、 启动采集设备上的视频采集程序,搜素网络中的视频设备:
2、 捕获搜索到视频设备中的视频流;
代码说明如下:
A、 创建QudpSocket 对象,使用bind绑定端口
B、 定时发送网络广播包
C、解析出RTSP 视频流的地址
D、拉取设备视频流数据
a) 循环使用函数 av_read_frame 读取视频流中的数据到AVPacket ,AVPacket结构特别重要【可以作为未解码的原始数据包直接转发到服务端;根据需求再次编码;直接在设备采集端解码并播放视频;可以进行视频的数据的录制等】;
b) 需要设置关键帧信息 : AVCodecContext中的两个参数分别为time_base.num 和time_base.den
3、 分发的数据流采集
设备采集端需要制作两路视频,一路视频用于采集端播放;另一路用于传到服务端,用于分发使用;
采集端播放代码比较简单:
首先avcodec_decode_video2解码视频流数据,使用sws_scale适配出合适的帧数据,最后创建Qimage对象显示就可以的
注释:Android 显示帧数据使用Image对象就可以的,通过QquickImageProvider格式化显示的帧数据
用于服务端分发流主要有三种方式:
a) 直接使用解码之后的帧数据
首先把帧数据写入QbyteArray对象,再压缩,最后通过网络传输到服务端
QImage image;
this->OpQueue(image,1);
QByteArray byte;
QBuffer buffer(&byte);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "JPG", g_nFrameLevelTmp);
byte = qCompress(byte);
b) 使用未解码的原始数据
把通过函数av_read_frame读取原始数据流AVPacket做个数据拷贝,再把数据写入QbyteArray中同时进行压缩,最后通过网络传输到服务器。
c) 重新编码视频流数据【Android系统FFMPEG编译的时候需要添加H264支持的,默认只支持解码的,不支持编码的,需要特别主要】
创建H264编码器,主要是如下三个函数 avcodec_find_decoder(AV_CODEC_ID_H264)
avcodec_alloc_context3
avcodec_open2
解码器主要参数设置如下:
m_pVideoEnCtx->codec_id = AV_CODEC_ID_H264;
m_pVideoEnCtx->codec_type = AVMEDIA_TYPE_VIDEO;
m_pVideoEnCtx->pix_fmt = AV_PIX_FMT_YUV420P;
m_pVideoEnCtx->width = 1280;
m_pVideoEnCtx->height = 720;
m_pVideoEnCtx->bit_rate = 400000;
m_pVideoEnCtx->gop_size = 75 ;
m_pVideoEnCtx->time_base.num = 1;
m_pVideoEnCtx->time_base.den = 25;
m_pVideoEnCtx->max_b_frames = 0;
m_pVideoEnCtx->has_b_frames = 0;
m_pVideoEnCtx->i_quant_factor = 2;
av_opt_set(m_pVideoEnCtx->priv_data, "preset", "slow", 0);
av_opt_set(m_pVideoEnCtx->priv_data, "tune", "zerolatency", 0);
重新编码视频流数据,这一步可以设置码率、大小等定制化参数;编码之序列化数据到QbyteArray中并且压缩,最后通过网络传输到服务端
d) 三种方式的比较
直接传输视频帧数据,逻辑简单,针对小分辨率和局域网网比较实用;
传输未解码的视频包,逻辑相当复杂点,但是数据压缩率极高,能很好的满足公网传输
重新编码方式,主要应用于多功能定制用途,灵活性特别好,满足不同的视频质量和网络带宽要求
四、 服务端分发技术
服务端主要用户账号管理,提供访问视频数据权限;视频源数据管理,数据存档、过滤以及 以及视频数据下发给各个终端设备。
服务端流程示意图:
五、 接收视频流的终端设备
视频终端设备,连接服务端并接收视频数据,视频终端设备有可能需要处理视频数据,如未解码的原始视频数据,需要终端解码并显示;针对Android视频库的的编译方式,请参照:https://www.apps121.com/2019/03/11/ffmpeg4-1-androidlibwindows_compile_successfully/
六、 结束语
Qt&C++ 基于FFMPEG库的视频流分发技术方案可以有效的节约成本,保证对视频数据的绝对控制和处理;
详细的代码细节,如有兴趣,可以私聊沟通,谢谢!
原文参考了:https://www.apps121.com/2019/06/11/qtcffmpeg_slu/ |