Qt编写安防视频监控系统15-远程回放
一、前言
远程回放有两种处理方式,一种是采用NVR厂家提供的SDK开发包来登录到NVR上,然后根据SDK的函数接口指定的视频文件,当然也有接口查询视频文件列表等;一种是采用视频监控行业的国标GB28181协议,来注册到NVR上然后查询和播放视频文件。两种处理方式各有优缺点,用SDK的话,接口比较丰富,有很多特殊的处理都在SDK的函数中可以看到,相对来说速度和清晰度会更快一点,操作的友好性高,毕竟是自家的SDK,肯定对自家的设备支持非常好,缺点就是每个厂家都有一个SDK开发包,如果第三方集成厂家需要兼容多个厂家的话,就需要针对每个厂家的SDK都要来一遍,这个对于开发人员来说,厂家越多越崩溃,而国标GB28181的出现就是为了规范这些厂家,类似于onvif一样,约定厂家都按照一个统一的标准来回放视频,这对于广大开发者来说是福音,一般视频监控设备厂家除了支持自家的SDK以外,肯定都会支持onvif和gb28181,不过检测的产品除外。正常来说过检测的产品价格会贵一些,毕竟检测成本摆在那。
皮肤开源:https://gitee.com/feiyangqingyun/QWidgetDemo https://github.com/feiyangqingyun/QWidgetDemo
文件名称:styledemo
体验地址:https://gitee.com/feiyangqingyun/QWidgetExe https://github.com/feiyangqingyun/QWidgetExe
文件名称:bin_video_system.zip
二、功能特点
- 支持16画面切换,全屏切换等,包括1+4+6+8+9+13+16画面切换。
- 支持alt+enter全屏,esc退出全屏。
- 自定义信息框+错误框+询问框+右下角提示框。
- 17套皮肤样式随意更换,所有样式全部统一,包括菜单等。
- 云台仪表盘鼠标移上去高亮,八个方位精准识别。
- 底部画面工具栏(画面分割切换+截图声音等设置)移上去高亮。
- 可在配置文件更改左上角logo+中文软件名称+英文软件名称。
- 封装了百度地图,三维切换,设备点位,鼠标按下获取经纬度等。
- 堆栈窗体,每个窗体都是个单独的qwidget,方便编写自己的代码。
- 顶部鼠标右键菜单,可动态控制时间CPU+左上角面板+左下角面板+右上角面板+右下角面板的显示和隐藏,支持恢复默认布局。
- 工具栏可以放置多个小图标和关闭图标。
- 左侧右侧可拖动拉伸,并自动记忆宽高位置,重启后恢复。
- 双击摄像机节点自动播放视频,双击节点自动依次添加视频,会自动跳到下一个,双击父节点自动添加该节点下的所有视频。
- 摄像机节点拖曳到对应窗体播放视频,同时支持拖曳本地文件直接播放。
- 视频画面窗体支持拖曳交换,瞬间响应。
- 双击节点+拖曳节点+拖曳窗体交换位置,均自动更新url.txt。
- 支持从url.txt中加载16通道视频播放,自动记忆最后通道对应的视频,软件启动后自动打开播放。
- 右下角音量条控件,失去焦点自动隐藏,音量条带静音图标。
- 集成百度地图,可以添加设备对应位置,自动生成地图,支持缩放和三维地图,提供地图风格选择,共12种风格。
- 视频拖动到通道窗体外自动删除视频。
- 鼠标右键可删除当前+所有视频,截图当前+所有视频。
- 录像机管理、摄像机管理,可添加删除修改导入导出打印信息,立即应用新的设备信息生成树状列表,不需重启。
- 在pro文件中可以自由开启是否加载地图。
- 视频播放可选四种内核自由切换,vlc+ffmpeg+easyplayer+海康sdk,均可在pro中设置。
- 可设置1+4+9+16画面轮询,可设置轮询间隔以及轮询码流类型等,直接在主界面底部工具栏右侧单击启动轮询按钮即可,再次单击停止轮询。
- 默认超过10秒钟未操作自动隐藏鼠标指针。
- 支持onvif搜素设备,支持任意onvif摄像机,包括但不限于海康大华宇视天地伟业华为等,支持onvif云台控制。
- 高度可定制化,用户可以很方便的在此基础上衍生自己的功能,支持linux系统。
三、效果图


四、核心代码
void Demo::on_pushButtonLogin_clicked()
{
UNS_INT32 ret;
mDeviceType = ui->comboBoxProtocol->currentData().toInt();
mDeviceIP = ui->lineEditAddress->text();
mDevicePort = ui->lineEditPort->text().toInt();
mUsername = ui->lineEditUsername->text();
mPassword = ui->lineEditPassword->text();
QByteArray username = mUsername.toLatin1();
QByteArray password = mPassword.toLatin1();
QByteArray ipaddr = mDeviceIP.toLatin1();
QString result;
ret = DeviceInterface::login(mDeviceType, username.data(), password.data(), ipaddr.data(), mDevicePort, mLoginHandle);
if (ret != UNS_ESUCCESS) {
result = QString::fromLocal8Bit("登录失败,错误码 ") + QString::number(ret, 10);
QMessageBox::question(this, QString::fromLocal8Bit("提示框"), result, QMessageBox::Yes);
} else {
result = QString::fromLocal8Bit("登录成功");
updateChannelList();
}
}
void Demo::on_pushButtonLogout_clicked()
{
if (!checkLogin()) {
return;
}
DeviceInterface::logout(mLoginHandle);
mLoginHandle = NULL;
}
void Demo::onStartPlayLive()
{
UNS_INT32 ret;
if (!checkLogin()) {
return;
}
updatePlayLiveData(NULL);
UNS_LIVEPLAY_PARAMETER_T param;
param.channel = 0;//mPlayLiveChannel;
param.stream_type = mStreamType;
param.play_wnd = (void *)(ui->videoFrame->winId());
mPlayType = 0;
ret = DeviceInterface::startLivePlay(mLoginHandle, ¶m, liveDataCallback, this, mPlayHandle);
if (ret != UNS_ESUCCESS) {
QString result = QString::fromLocal8Bit("预览失败,错误码 ") + QString::number(ret, 10);
QMessageBox::question(this, QString::fromLocal8Bit("提示框"), result, QMessageBox::Yes);
}
}
void Demo::onStopPlayLive()
{
if (!checkLogin()) {
return;
}
if (mPlayType != 0) {
return;
}
UNS_INT32 ret;
ret = DeviceInterface::stopLivePlay(mPlayHandle);
ui->videoFrame->update();
}
void Demo::onStartPlayback()
{
UNS_INT32 ret;
if (!checkLogin()) {
return;
}
updatePlaybackData();
UNS_PLAYBACK_PARAMETER_T param;
param.channel = mPlaybackChannel;
param.type = 0;
param.method = 0;
param.start = mStartTime;
param.end = mEndTime;
param.play_wnd = (void *)(ui->videoFrame->winId());
mPlayType = 1;
ret = DeviceInterface::startPlayBack(mLoginHandle, ¶m, backDataCallback, this, mPlayHandle);
if (ret != UNS_ESUCCESS) {
QString result = QString::fromLocal8Bit("回放失败,错误码 ") + QString::number(ret, 10);
QMessageBox::question(this, QString::fromLocal8Bit("提示框"), result, QMessageBox::Yes);
}
}
void Demo::onStopPlayback()
{
if (!checkLogin()) {
return;
}
if (mPlayType != 1) {
return;
}
UNS_INT32 ret;
ret = DeviceInterface::stopPlayBack(mPlayHandle);
ui->videoFrame->update();
}
void Demo::onFastPlayback()
{
if (!checkPlayer()) {
return;
}
mPlayScale++;
UNS_INT32 ret = DeviceInterface::scalePlayBack(mPlayHandle, mPlayScale);
//CHECK_RESULT(ret);
}
void Demo::onSlowPlayback()
{
if (!checkPlayer()) {
return;
}
mPlayScale--;
UNS_INT32 ret = DeviceInterface::scalePlayBack(mPlayHandle, mPlayScale);
//CHECK_RESULT(ret);
}
void Demo::onPausePlayback()
{
if (!checkPlayer()) {
return;
}
UNS_INT32 ret = DeviceInterface::pausePlayBack(mPlayHandle);
// CHECK_RESULT(ret);
}
void Demo::onResumePlayback()
{
if (!checkPlayer()) {
return;
}
UNS_INT32 ret = DeviceInterface::resumePlayBack(mPlayHandle);
// CHECK_RESULT(ret);
}
Qt编写安防视频监控系统15-远程回放的更多相关文章
- Qt编写安防视频监控系统5-视频回放
一.前言 一般视频回放都会采用GB28181国标来处理,这样可以保证兼容国内各大厂家的NVR,毕竟在同一的国家标准下,大家都会统一支持国标的,就不需要根据各个厂家的SDK来做兼容处理,烦得很,厂家越来 ...
- Qt编写安防视频监控系统14-本地回放
一.前言 在上一篇文章将视频文件存储好了,需要提供界面方便用户查询视频文件进行回放,其实这个回放就是播放历史存储的视频文件,并不是什么高大上的东西,视频回放在这个系统中分三种,第一种是本地回放,回放存 ...
- Qt编写安防视频监控系统(界面很漂亮)
一.前言 视频监控系统在整个安防领域,已经做到了烂大街的程序,全国起码几百家公司做过类似的系统,当然这一方面的需求量也是非常旺盛的,各种定制化的需求越来越多,尤其是这几年借着人脸识别的东风,发展更加迅 ...
- Qt编写安防视频监控系统12-异形布局
一.前言 视频监控系统中,除了常规的1画面.4画面.9画面.16画面以外,还有几个布局比较另类,比如6画面.8画面.13画面,有些通道需要占据不同的行列,4画面.9画面.16画面都是非常对称的布局,行 ...
- Qt编写安防视频监控系统1-通道切换
一.前言 通道切换在视频监控系统中是最基础的必备功能,一般都会提供1通道+4通道+6通道+8通道+9通道+16通道这几个通道切换,可能做得比较好的还会提供24通道+32通道的,这个可能对电脑的配置就有 ...
- Qt编写安防视频监控系统18-云台控制
一.前言 云台控制是视频监控系统中必备的一个功能,对球机进行上下左右的移动,还有焦距的控制,其实核心就是控制XYZ三个坐标轴,为了开发这个模块,特意研究了各种云台控制的方法和开源库比如soap,有些厂 ...
- Qt编写安防视频监控系统11-动态换肤
一.前言 Qt中的动态换肤技术是非常一流的,直接调用qApp->setStyleSheet(qss);就可以对整个应用程序进行换肤,如果样式表内容不多,或者对应的贴图不对,效率还是蛮好的,不过据 ...
- Qt编写安防视频监控系统9-自动隐藏光标
一.前言 这个效果的灵感来自于大屏电子看板系统,在很多系统中尤其是上了大屏的时候,其实在用户不在操作的时候,是很不希望看到那个鼠标箭头指针的,只有当用户操作的时候才显示出来,这个就需要开个定时器定时计 ...
- Qt编写安防视频监控系统8-双击节点
一.前言 在所有的视频监控系统中,双击摄像机的节点,对应摄像机加载到当前焦点通道显示,这个都是必须具备的功能,还有一些厂家会做双击NVR节点,自动加载该NVR下的所有摄像机全部显示,从通道1开始到通道 ...
随机推荐
- JVM垃圾收集算法之清除算法
最近看了一些大佬的博文,文中提到说:学习知识不能一味的死学滥学,在学之前要明白为什么要学这个知识,在实际的应用中怎么运用这个知识.我觉得说的很对,很多时候我学习确实是了解了这是什么原理,但是要说到实际 ...
- C#和PHP加密结果一致的DES加密解密算法。php实现和c#一致的DES加密解密
DES加密算法 des对称加密,是一种比较传统的加密方式,其加密运算.解密运算使用的是同样的密钥,信息的发送者和信息的接收者在进行信息的传输与处理时,必须共同持有该密码(称为对称密码),是一种对称加密 ...
- 第一篇 -- XML基础
一.XML简介 XML是一种标记语言,用于描述数据,它提供一种标准化的方式来来表示文本数据.XML文档以.xml为后缀.需要彻底注意的是XML是区分大小写的. 先从一个简单的XML例子来了解下xml基 ...
- 项目Beta冲刺(团队)--7/7
课程名称:软件工程1916|W(福州大学) 作业要求:项目Beta冲刺 团队名称:葫芦娃队 作业目标:进行新一轮的项目冲刺,尽力完成并完善项目 团队博客 队员学号 队员昵称 博客地址 04160242 ...
- 项目Alpha冲刺随笔集合
班级:软件工程1916|W 作业:项目Alpha冲刺 团队名称:SkyReach 目标:完成项目Alpha版本 项目Github地址 评审表 团队博客汇总 队员学号 队员姓名 个人博客地址 备注 22 ...
- getLog(this.getClass()) 与 getLog(XXX.class) 的区别
在实例方法中引用Log,通常定义一个实例变量: // 在实例方法中引用Log: public class Person { protected final Log log = LogFactory.g ...
- scala简单的功能实现~weekone
以下是scala简单的入门题~ 1.⼀个数字如果为正数,则它的signum为1:如果是负数,怎么signum为-1:如果是0,则signum 为0.编写⼀个函数来计算这个值. object Test ...
- 数组中有一个数字出现的次数超过数组长度的一半(C、Python)
C语言 1 /* 2 ----------------------------------- 3 动态分配需要的内存大小 4 输入数组元素的值 5 通过函数调用,传地址对数组排序 6 循环每个元素,当 ...
- openstack环境下搭建的keepalived 两台服务器直接无法ping通VIP ALLOWED-ADDRESS-PAIRS
真的是搞了很久 结果一问人才知道真的是neutron的问题 当然前提是设置unicast 而不是默认设置 先贴出来后面再更新图片 [root@haproxy1 ~]# cat /etc/keepali ...
- JSE,JEE,JME三者之间有什么区别
JAVA是一种面向对象语言由SUN公司出品 J针对不同的使用方向规划出J2SE,J2EE,J2ME三个版本 J2SE 指标准版一般用于用户学习JAVA语言的基础也是使用其他两个版本的基础主要用于编写C ...