标题:Qt编写安防视频监控系统40-onvif线程处理
作者:liudianwu
日期:2021-07-05 08:20
内容:
## 一、前言
整个onvif模块大部分的功能都有了以后,除了在demo上点点按钮可以执行获取结果显示外,最终还是要应用到视频监控中,在按钮上点点和系统中后台自动运行是两码事,比如onvif校时和事件订阅,不会说是傻到在监控系统界面上提供按钮给用户点击才去执行,最多做的应该是系统设置中提供两个开关比如自动校时、事件订阅,可以方便的开启这几个功能。开启以后等监控系统启动后自动去处理,比如挨个对摄像机进行校时处理以及订阅事件,为了能够做到添加摄像机后自动立即应用,特意改成了在打开摄像机视频画面的时候,主动去实例化DeviceOnvif类(每个摄像机都对应一个实例)
最开始的做法是采用定时器去处理要指定的指令队列,后面发现速度不好控制,毕竟网络请求受网速和网络环境的影响,有时候100毫秒就执行完成了,有时候又需要300毫秒不等,尽管网络请求的时候已经设置了超时时间(这个时间一般设置成2-3秒,保证请求有足够的时候返回),这个时间有点大,如果按照这个网络请求超时时间来设定定时器,设备数量很多的时候太慢了,监控系统一般几十个设备是有的,这蜗牛一样的速度要处理到何年马月,而且每个摄像机有多个指令需要处理比如自动校时、事件订阅等。
那有没有一种机制可以尽最快的速度排队处理呢,答案是当然,这不就是线程擅长干的事情吗,使劲的干,休息多久自由msleep控制即可,网络环境好的情况下,20个设备的指令基本上在1s内完成的,这就能够满足用户的需求,毕竟用户打开软件后,大概率不想等待太长时间,就像能够看到所有摄像机时间自动校准好了,搞个摄像机报警也能立即通过onvif协议上报,该处理的都尽快处理完了。
QNetworkAccessManager类如果一开始不是在线程中new出来的,会提示不能在其他线程执行,这就需要在线程的run函数中调用QMetaObject::invokeMethod来执行对应的处理,一个万能的处理方法就是将需要执行的全部放在work函数中,搞个iswork标志位,进入该开始的时候将标志位iswork=true,处理结束后iswork=false,在run中先判断标志位是否为假,为假表示当前不在工作,则去调用work函数处理。这就规避了在线程中执行其他线程类对象函数的错误提示。
基本的处理思路
- 查询出所有的摄像机信息。
- 过滤摄像机信息,找出所有具备onvif地址的,只有具备onvif地址的才是需要去处理的。
- 从deviceonvif链表中找到当前onvif地址的设备类对象,该方法同时肩带new出实例在没有找到对应实例的情况下。
- 将对应的 ..