范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Qt编写视频监控管理平台(支持海康大华宇视华为天地伟业等)

  一、前言
  海康大华等厂家自己的客户端软件,基本上都是支持自家的设备,不支持其他家的摄像机和硬盘录像机,并不是因为技术上做不到,这些大厂要实现支持兼容其他的家的(他们家的服务端或者收费的都是支持其他家的),那都是分分钟的事情,无非就是走通用的标准onvif+rtsp+gb28181,为何目前客户端不兼容其他家的,可能也是由于商业角度考虑,这样可以最大化的绑定自家的硬件一起,毕竟客户端都是免费使用的,仅仅用他们免费的客户端而不用他们的硬件,那就没有太大意义。
  用Qt编写这个视频监控系统,最初的目标就是要实现支持海康/大华/宇视/华为/天地伟业等各个厂家的设备,也一直朝着这个目标前进,好在有onvif+gb28181这种国际标准和国家标准,只要对方的设备支持这两种标准则都可以顺利接入,一般onvif用来搜索和获取设备信息,拿到rtsp地址可以用ffmpeg解码播放,而gb28181主要用来回放视频居多,难易程度上gb28181由于通信复杂更难,onvif相对来说更简单,onvif底层就是用的udp+http,先用udp发组播消息搜索设备,然后用http发送请求拿详细的数据。
  目前市面上绝大部分厂家的设备都是支持onvif和gb28181的,所以这也给专门的软件厂商一个巨大机会,可以将各个硬件厂商的设备集中起来统一管理,除了局域网的设备可以集中管理,广域网的也可以通过各种中转统一管理,甚至推流通过公网管理,只要有权限,想看哪个摄像头哪个设备就调出来查看即可。二、功能特点(一)、软件模块视频监控模块,各种停靠小窗体子模块,包括设备列表、图文警情、窗口信息、云台控制、预置位、巡航设置、设备控制、悬浮地图、网页浏览等。视频回放模块,包括本地回放、远程回放、设备播放、图片回放、视频上传等。电子地图模块,包括图片地图、在线地图、离线地图、路径规划等。日志查询模块,包括本地日志、设备日志等。系统设置模块,包括系统设置(基本设置、视频参数、数据库设置、地图配置、串口配置等)、录像机管理、摄像机管理、轮询配置、录像计划、用户管理等。(二)、基础功能支持各种视频流(rtsp、rtmp、http等)、视频文件(mp4、rmvb、avi等)、本地USB摄像机播放。支持多画面切换,包括1、4、6、8、9、13、16、25、36、64画面切换。支持全屏切换,多种切换方式包括鼠标右键菜单、工具栏按钮、快捷键(alt+enter全屏,esc退出全屏)。支持视频轮询,包括1、4、9、16画面轮询,可设置轮询分组(轮询预案)、轮询间隔、码流类型等。支持onvif协议,包括设备搜索、云台控制、预置位、设备控制(图片参数、校对时间、系统重启,抓拍图片等)。支持权限管理,不同的用户可以对应不同的模块权限,比如删除日志、关闭系统等。数据库支持多种,包括sqlite、mysql、sqlserver、postgresql、oracle、人大金仓等。本地USB摄像机支持设置分辨率、帧率等参数。所有停靠模块都自动生成对应的菜单用来控制显示和隐藏,在标题栏右键可以弹出。支持显示所有模块、隐藏所有模块、复位普通布局、复位全屏布局。双击设备弹出实时预览视频,支持图片地图、在线地图、离线地图等。摄像机节点拖曳到对应窗体播放视频,同时支持拖曳本地文件直接播放。删除视频支持鼠标右键删除、悬浮条关闭删除、拖曳到视频监控面板外删除等多种方式。图片地图上设备按钮可自由拖动,自动保存位置信息。百度地图上可以鼠标单击获取经纬度信息,用来更新设备位置。视频监控面板窗体中任意通道支持拖曳交换,瞬间响应。封装了百度地图,视图切换,运动轨迹,设备点位,鼠标按下获取经纬度等。双击节点、拖曳节点、拖曳窗体交换位置等操作,均自动更新保存最后的播放地址,下次软件打开自动应用。右下角音量条控件,失去焦点自动隐藏,音量条带静音图标。支持视频截图,可指定单个或者对所有通道截图,底部小工具栏也有截图按钮。支持超时自动隐藏鼠标指针、自动全屏机制。支持onvif云台控制,可上下左右移动云台摄像机,包括复位和焦距调整等。支持onvif预置位,可以添加、删除、修改预置位,可以调用起始位。支持onvif图像参数设置,包括明亮度、对比度、饱和度、尖锐度等。支持onvif其他操作,包括抓图、网络设置、校时、重启、事件订阅等。支持任意onvif摄像机,包括但不限于海康、大华、宇视、天地伟业、华为等。可保存视频,可选定时存储或者单文件存储,可选存储间隔时间。可设置视频流通信方式tcp+udp,可设置视频解码是速度优先、质量优先、均衡等。可设置软件中文名称、英文名称、LOGO图标等。存储的视频文件支持导出到指定目录,支持批量上传到服务器。完善的录像计划设置,支持每个通道7乘24小时每半小时设置是否存储录像。(三)、特色功能主界面采用停靠窗体模式,各种组件以小模块的形式加入,可自定义任意模块加入。停靠模块可拖动任意位置嵌入和悬浮,支持最大化全屏,支持多屏幕。双重布局文件存储机制,正常模式、全屏模式都对应不同的布局方案,自动切换和保存,比如全屏模式可以突出几个模块透明显示在指定位置,更具科幻感现代化。原创onvif协议机制,采用底层协议解析(udp广播搜索+http请求执行命令)更轻量易懂易学习拓展,不依赖任何第三方组件比如gsoap。原创数据导入、导出、打印机制,跨平台不依赖任何组件,瞬间导出数据。内置多个原创组件,宇宙超值超级牛逼,包括数据导入导出组件(导出到xls、pdf、打印)、数据库组件(数据库管理线程、自动清理数据线程、万能分页、数据请求等)、地图组件、视频监控组件、文件多线程收发组件、onvif通信组件、通用浏览器内核组件等。自定义信息框+错误框+询问框+右下角提示框(包含多种格式)等。精美换肤,高达17套皮肤样式随意更换,所有样式全部统一,包括菜单等。视频控件悬浮条可以自行增加多个按钮,监控界面底部小工具栏也可自行增加按钮。双击摄像机节点自动播放视频,双击节点自动依次添加视频,会自动跳到下一个,双击父节点自动添加该节点下的所有视频。可选主码流、子码流。录像机管理、摄像机管理,可添加删除修改导入导出打印信息,立即应用新的设备信息生成树状列表,不需重启。可选多种内核自由切换,ffmpeg、vlc、mpv等,均可在pro中设置。推荐用ffmpeg,跨平台最多,默认提供好了linux和mac平台上编译好的库。支持硬解码,可设置硬解码类型(qsv、dxva2、d3d11va等)。默认采用opengl绘制视频,超低的CPU资源占用,支持yuyv和nv12两种格式绘制,很牛逼。高度可定制化,用户可以很方便的在此基础上衍生自己的功能,比如增加自定义模块,增加运行模式、机器人监控、无人机监控、挖掘机监控等。支持xp、win7、win10、win11、linux、mac、各种国产系统(UOS、中标麒麟、银河麒麟等)、嵌入式linux等系统。注释完整,项目结构清晰,超级详细完整的使用开发手册,精确到每个代码文件的功能说明,不断持续迭代版本。三、体验地址体验地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取码:01jf 文件名:bin_video_system.zip。国内站点:https://gitee.com/feiyangqingyun国际站点:https://github.com/feiyangqingyun个人主页:https://blog.csdn.net/feiyangqingyun知乎主页:https://www.zhihu.com/people/feiyangqingyun/在线文档:https://feiyangqingyun.gitee.io/qwidgetdemo/video_system/四、效果图
  五、相关代码#include "deviceonvif.h" #include "quihelper.h" #include "dbquery.h" #include "playwav.h" #include "devicehelper.h" #include "onvifthread.h" #include "videowidgetx.h"  bool DeviceOnvif::checkUrl(const QString &url, OnvifDeviceData &deviceData) {     //不是rtsp开头也不是摄像机,为空也包含在这个判断中     if (!url.startsWith("rtsp")) {         return false;     }      //可能是主码流也可能是子码流     int index1 = DbData::IpcInfo_RtspMain.indexOf(url);     int index2 = DbData::IpcInfo_RtspSub.indexOf(url);     int index = -1;     if (index1 >= 0) {         index = index1;     } else if (index2 >= 0) {         index = index2;     }      //没有码流地址不用继续     if (index < 0) {         return false;     }      //只有onvif地址存在才是onvif设备     QString onvifAddr = DbData::IpcInfo_OnvifAddr.at(index);     if (onvifAddr.isEmpty()) {         return false;     }      //onvif地址中的IP和rtsp地址中的IP必须一致     //为什么会出现这个现象因为用户很可能直接在原来的正确的带有onvif地址的信息中修改了rtsp地址     if (OnvifHelper::getIP(onvifAddr) != OnvifHelper::getIP(url)) {         return false;     }      //对应结构体数据赋值     deviceData.userName = DbData::IpcInfo_UserName.at(index);     deviceData.userPwd = DbData::IpcInfo_UserPwd.at(index);     deviceData.onvifAddr = DbData::IpcInfo_OnvifAddr.at(index);     deviceData.profileToken = DbData::IpcInfo_ProfileToken.at(index);     deviceData.videoSource = DbData::IpcInfo_VideoSource.at(index);     return true; }  bool DeviceOnvif::ptzControl(quint8 type, const QString &url, double x, double y, double z) {     bool result = false;     OnvifDeviceData deviceData;     if (checkUrl(url, deviceData)) {         OnvifDevice *device = OnvifThread::getOnvifDevice(deviceData);         qDebug() << TIMEMS << "执行云台控制" << OnvifHelper::getIP(url);         result = device->ptzControl(type, deviceData.profileToken, x, y, z);     }     return result; }  bool DeviceOnvif::ptzPreset(quint8 type, const QString &url, const QString &presetToken, const QString &presetName) {     bool result = false;     OnvifDeviceData deviceData;     if (checkUrl(url, deviceData)) {         OnvifDevice *device = OnvifThread::getOnvifDevice(deviceData);         qDebug() << TIMEMS << "预置位处理" << OnvifHelper::getIP(url);         result = device->ptzPreset(type, deviceData.profileToken, presetToken, presetName);     }     return result; }  QList DeviceOnvif::getPresets(const QString &url) {     QList presets;     OnvifDeviceData deviceData;     if (checkUrl(url, deviceData)) {         OnvifDevice *device = OnvifThread::getOnvifDevice(deviceData);         qDebug() << TIMEMS << "获取预置位" << OnvifHelper::getIP(url);         presets = device->getPresets(deviceData.profileToken);     }     return presets; }  SINGLETON_IMPL(DeviceOnvif) DeviceOnvif::DeviceOnvif(QObject *parent) : QObject(parent) {     //显示截图的标签     labImage.setWindowFlags(Qt::WindowStaysOnTopHint);     labImage.setFixedSize(QSize(800, 600));     labImage.setWindowTitle("抓拍图片预览");     QUIHelper::setFormInCenter(&labImage);      //关联信号     connect(OnvifThread::Instance(), SIGNAL(receiveImage(QString, QImage)),             this, SLOT(receiveImage(QString, QImage)));     connect(OnvifThread::Instance(), SIGNAL(receiveEvent(QString, OnvifEventInfo)),             this, SLOT(receiveEvent(QString, OnvifEventInfo)));     connect(OnvifThread::Instance(), SIGNAL(receiveResult(QString, QString, QVariant)),             this, SIGNAL(receiveResult(QString, QString, QVariant)));      //启动onvif线程     OnvifThread::Instance()->start();      //启动定时器判断摄像机上下线     QTimer *timerOffline = new QTimer(this);     connect(timerOffline, SIGNAL(timeout()), this, SLOT(checkOffline()));     timerOffline->start(3000); }  void DeviceOnvif::checkOffline() {     for (int i = 0; i < DbData::IpcInfo_Count; ++i) {         QString url = DbData::getRtspAddr(i);         QString ip = OnvifHelper::getIP(url);         int port = OnvifHelper::getPort(url);          //rtsp除外的认为永远存在,可以根据需要自行约定规则         bool online = true;         if (url.startsWith("rtsp")) {             online = QUIHelper::ipLive(ip, port);         }          //过滤下只有当状态变化了才需要         if (online) {             if (!DbData::IpcInfo_IpcOnline.at(i)) {                 DeviceHelper::setVideoIcon2(ip, true);             }         } else {             if (DbData::IpcInfo_IpcOnline.at(i)) {                 DeviceHelper::setVideoIcon2(ip, false);             }         }          DbData::IpcInfo_IpcOnline[i] = online;     } }  void DeviceOnvif::receivePlayStart(int time) {     //轮询阶段不处理     if (AppConfig::Polling) {         //return;     }      //拿到触发信号的控件     VideoWidget *widget = (VideoWidget *)sender();     //先校验当前视频对应的信息是否符合     OnvifDeviceData deviceData;     if (checkUrl(widget->getVideoPara().videoUrl, deviceData)) {         //交给线程执行指令         OnvifThread::Instance()->append(deviceData, "getServices");         if (AppConfig::OnvifNtp) {             OnvifThread::Instance()->append(deviceData, "setDateTime");         }         if (AppConfig::OnvifEvent) {             OnvifThread::Instance()->append(deviceData, "getEvent");         }     } }  void DeviceOnvif::receivePlayFinsh() {     //先校验当前视频对应的信息是否符合     VideoWidget *widget = (VideoWidget *)sender();     OnvifDeviceData deviceData;     if (checkUrl(widget->getVideoPara().videoUrl, deviceData)) {         //交给线程执行指令         OnvifThread::Instance()->append(deviceData, "remove");     } }  void DeviceOnvif::receiveImage(const QString &url, const QImage &image) {     QImage img = image;     if (!img.isNull()) {         //等比例缩放一下         img = img.scaled(labImage.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);         labImage.setPixmap(QPixmap::fromImage(img));         labImage.show();     } }  void DeviceOnvif::receiveEvent(const QString &url, const OnvifEventInfo &event) {     //可能临时关闭了事件订阅     if (!AppConfig::OnvifEvent) {         return;     }      //事件内容存放在结构体数据中     //qDebug() << TIMEMS << event;     QString name = event.dataName;     QVariant value = event.dataValue;     //可能有多种关键字可以自行增加 LogicalState State IsMotion     if (!name.contains("LogicalState") && !name.contains("IsMotion")) {         return;     }      qDebug() << TIMEMS << "收到报警事件" << QUIHelper::getIP(url) << name << value;     //过滤不在本系统中的设备发过来的报警     int index = DbData::IpcInfo_OnvifAddr.indexOf(url);     if (index < 0) {         return;     }      //true false 1 0 字符串转成bool     bool alarm = value.toBool();     QString ipcName = DbData::IpcInfo_IpcName.at(index);     QString info, msg;     if (name.contains("IsMotion")) {         info = (alarm ? "移动侦测" : "移动结束");         msg = QString("%1%2").arg(ipcName).arg(info);         DeviceHelper::addMsg(msg, alarm ? 2 : 0);     } else {         info = (alarm ? "触发报警" : "报警恢复");         msg = QString("%1%2").arg(ipcName).arg(info);         DeviceHelper::addMsg(msg, alarm ? 2 : 0);     }      //播放报警声音     if (alarm) {         DeviceHelper::playAlarm("8.wav");     } else {         DeviceHelper::stopSound();     }      //插入到日志记录数据库     DbQuery::addUserLog("报警日志", msg);     //右下角弹出提示     if (AppConfig::TipInterval != 10000) {         QUIHelper::showTipBox("提示", msg, AppConfig::FullScreen, true, AppConfig::TipInterval);     } }

倒霉的杜锋倒霉的杜锋杜锋之所以倒霉,就是因为他刚上任中国男篮主教练,就碰上了世纪疫情。因为疫情,他带领的中国男篮不但无法进行正常的训练和比赛,而且在参加亚洲杯的时候,部分队员遭受了感染,结果如何在乔卡身边打球?戈登随时准备好投篮与切入要有侵略性直播吧2月14日讯快船新援埃里克戈登今日在球队训练结束后接受了媒体采访。记者问道你和哈登保罗和威少一起打过球,你认为你从中学到了什么,这些东西该如何应用到莱昂纳德与乔治身上?戈登表独处,是女人想离开你的前兆一个女人在和你相处时,真心实意爱上你,往往喜欢和你待在一起,舍不得和你分别,在见不到你的时候,她会觉得孤寂,脑子里总是想着你,难以保持独处,常会找理由和你联系,寻求你的陪伴。换言之赏读相思是苦。相思是毒作者姬晓喃翻阅一段美好的记忆,执笔一段过往,我在蝶恋花的清词里划去忧伤的字眼,写着想你的故事,写着你在时光里拓下的痕迹,写着我浮生若梦的日子我在你的世界和回忆里获得永生的呼吸。都说CBA最新消息姚明职务调整,王芳接管国家队,男篮12人名单敲定姚明职务调整北京时间2月14日,根据新华社发文消息,中国篮协主席姚明已经卸任深蓝体育公司董事长一职,深蓝体育公司是中国篮协旗下全资子公司,主要经营的业务是体育比赛策划和举办,运动服东亚机械,解构倒三角金字塔格局目前,我国空压机竞争格局呈现明显的倒三角金字塔型,国产品牌在国外巨头垄断高端市场的环伺下求生,以东亚机械开山股份鲍斯股份汉钟精机为代表的国产企业在细分市场中精耕细作,渐渐占据一席之当篮球教练还是回家继承公司?太阳队老板的20年NBA梦想2003年,伊什比亚面临一个两难的选择。一边是放弃球员身份,成为密歇根州大的学生助教,那是球队助教离开后主教练伊佐特意为他留的工作另一个则是来自父亲的建议,进入家族企业UWM信贷公哈姆是牛皮大王,也是靠这优势才获得湖人队主教练湖人队主教练哈姆执教水平不高,但是吹牛皮是一把好手,也正是靠这优势才获得湖人队主教练一职。本赛季赛程已过大半,湖人队在哈姆的执教下以26胜31负排在西部第13位,这与球队的实力大相ChatGPT杭州GDP何时可以超越上海?亚运会对杭州会带来哪些影响问杭州GDP什么时候可以超越上海?ChatGPT我不知道杭州的GDP何时会超过上海,因为这取决于许多因素,如两个城市的经济增长率政策产业结构和自然灾害等。预测未来的经济趋势是一项复比特币正在进入新的牛市吗?在最近发布的通胀数据之后,比特币对上行做出了积极反应。市场参与者预计通胀率为6。2,但美国政府公布的通胀率为6。4。PanteraCapital在最近的一份时事通讯中查看了比特币的痴了退了红了一群普通戏迷和他们的互联网20年1995年深秋,北京海淀区白颐路南街角,一块巨大的广告牌树起,上面写着中国人离信息高速公路有多远,向北1500米。这被视作中国互联网发展的一个起点。虽然彼时中国硅谷中关村还不叫中关
三狮军团后防全是坑,伊朗坐拥亚洲最强锋线天团能否爆冷?世界杯看球指南第2夜11月21日2100英格兰VS伊朗11月22日0000塞内加尔VS荷兰11月22日0300美国VS威尔士11月16日,英格兰队球员在训练中。新华社发北京时间11探访扬州个园感悟春夏秋冬山光异趣风晴月露竹影多姿的故事我作为民俗文化体验工作者,行走在民间探寻民俗文化与各地地方小吃,探秘城市里街巷文化元素符号,发现一些新奇美的故事,十年前,我去扬州个园寻找楹联故事,走进个园北大门,便可以观赏到一副怒放的生命,怒放的菊花一场突如其来的疫情,让福州西湖公园菊花展延迟了观赏期。目前已开放,爱花的小伙伴们依然可以来打卡。扫码进入公园11月17日随着公共场所公园等开放,周末福州西湖公园迎来乐此不疲,观赏菊家有栀子院有蝶连绵疫情,让众多游客错过了诸多美景。我时常自问,人间最美的风景到底在哪?宅居的我,一直在苦苦寻觅着,寻觅我心中最美的风景。漫步长廊,回眸光阴,在我记忆深处,有这么一幅画面,每当忆起老白茶陈放太久,煮茶之前需要洗茶吗?里面会不会有灰尘和细菌?丨本文由小陈茶事原创丨首发于头条号小陈茶事丨作者村姑陈1很想念能说走就走的时候。开车几个小时到海边,看月亮,吃大餐。李麻花在朋友圈看到海边一家民宿,重新开业,绿码通行,还能在附近的少年军神霍去病军神霍去病(前140年前117年),河东郡平阳县人(今山西临汾),卫青将军的外甥,霍光之兄,十九岁封为骠骑大将军,是汉武帝对抗匈奴的悍将。元狩六年因病去世,年仅二十三岁。霍去病霍去清朝的一张老照片,房间好像出现幽灵,你知道是为什么吗?天地合而万物生,阴阳接而变化起。荀子这句话是战国末期著名的教育家思想家荀子所说,意为会见万物的出现和变化自有天意,而非是人力可操控或者是带有一些其他目的的。也被大家奉为是唯物主义的北京一日游特色游自驾游,哪些坑别踩?北京消协旅游消费体验调查结果来了为进一步保护消费者合法权益,规范旅游消费市场秩序,促进旅游业健康发展,北京市消费者协会自2016年开始,连续七年开展北京旅游消费市场体验式调查,相关体验指标大部分都保持了一致,尤其实锤!北京信托原董事长和总经理双双被查11月18日,北京市纪委发布消息,北京信托原董事长周瑞明和北京信托原总经理何晓峰涉嫌严重违纪违法,目前正接受纪律审查和监察调查。周瑞明,2001年进入北京信托,曾任北京信托党委副书奚美娟罕见走机场,一身极简穿搭充满品味,身姿挺拔更出众在娱乐圈当中有很多德艺双馨的艺人,奚美娟老师就是其中之一,获得了金鸡奖影后后仍然十分的低调,罕见走机场,身着极简风格搭配,十分有品味,紧跟时尚潮流的同时又不浮夸,67岁的奚美娟老师湖北十堰五龙宫遗址考古出土文物千余件水池底部发现三组浮雕来源央视新闻客户端五龙宫,位于湖北省十堰市武当山旅游经济特区五龙村。是武当山古建筑群九宫八观之一。作为武当山古建筑群组成部分,被联合国科教文组织列入世界文化遗产。根据文献记载,五龙