国标GB28181协议视频人脸识别/车牌识别平台EasyCVR设定好录像计划重启后通道不录像原因排查

TSINGSEE青犀视频开发的视频智能分析平台EasyCVR支持像国标EasyGBS平台一样开启录像计划进行录像。正常情况下不同通道同时开启录像计划的话,通道之间的录像计划不会被影响或者混乱,但是我们测试时却发现了异常。

当我们测试EasyCVR的两路设备同时开启设备录像时,随后重启EasyCVR服务后,会发现设备录像只有一路在录像,另外一路不录像。

因此我们先排查程序启动时候云端录像相关代码:

var channel []models.Channel
db.SQLite.Where("Ondemand=?", false).Find(&channel)
for _, v := range channel {
       AutoTouchStream(&v, true)
       if v.Record > 0 && v.RecordPlanSwitch {
              go v.DoTicker()
       }
}
func (channel *Channel) DoTicker() {
       defer func() {
              if err := recover(); err != nil {
                     err_logger.Error(fmt.Sprintf("%s\n", err))
                     err_logger.Error(fmt.Sprintln(string(debug.Stack())))
              }
       }()
       if channel.quit == nil {
              channel.quit = make(chan bool)
       } else {
              return
       }
       channel.cleanRecordTime = time.Now()
       ticker := time.NewTicker(10 * time.Second)
       defer ticker.Stop()
       for {
              select {
              case <-ticker.C:
                     //发送通知更新云端录像状态
                     //uax.ChannelDispatcher.Dispatch(fmt.Sprintf("cloud_record_%s_%s", channel.DeviceID, channel.ID), uint(channel.Record))
                     if CheckChannelRecordPlan(channel.DeviceID, channel.ID) {
                            uax.ChannelDispatcher.Dispatch(fmt.Sprintf("cloud_record_%s_%s", channel.DeviceID, channel.ID), uint(channel.Record))

通过排查代码发现,在程序启动时,会自动初始化开启录像计划的设备,让其继续录像,但是在doticker方法中使用的是*channel指针类型的通道数据,犹豫指针类型的特性(指向值的内存地址,当修改指针值时,底层的数据也会发生变化),导致在循环遍历所有开启录像计划的设备中,指针指向的数值永远都是最后一个设备的数据。

这就能够理解为什么两台设备开启录像计划,却在程序重启后只有一台在录像了。

我们将代码做如下修改:

func (channel Channel) DoTicker() {
       defer func() {
              if err := recover(); err != nil {
                     err_logger.Error(fmt.Sprintf("%s\n", err))
                     err_logger.Error(fmt.Sprintln(string(debug.Stack())))
              }
       }()
       //if channel.quit == nil {
       //     channel.quit = make(chan bool)
       //} else {
       //     return
       //}
       key := fmt.Sprintf("%s_%s", channel.DeviceID, channel.ID)
       fmt.Println("======", key)
       if _, ok := atsMap.Load(key); !ok {
              atsMap.Store(key, true)
       } else {
              return
       }
       channel.cleanRecordTime = time.Now()
       ticker := time.NewTicker(10 * time.Second)
       defer ticker.Stop()

再次重启程序测试,可以看到两台设备都在正常录像。

对于录像计划的开发,TSINGSEE青犀视频团队首先是从EasyNVR开始的,如果对录像计划的开发有兴趣,可以阅读我们之前写过的博客:EasyNVR录像计划模块开发过程。如果想对EasyCVR进行测试,欢迎联系我们了解。

posted on 2020-12-31 16:59  TSINGSEE  阅读(121)  评论(0编辑  收藏  举报