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进行测试,欢迎联系我们了解。