diff --git a/handler/tool.go b/handler/tool.go index d7db1fa..28c453b 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -34,7 +34,7 @@ func SetUpToolGroup(router *gin.Engine) { } // 跨域访问:cross origin resource share -func CrosHandler() gin.HandlerFunc { +func CorsHandler() gin.HandlerFunc { return func(context *gin.Context) { //method := context.Request.Method context.Writer.Header().Set("Access-Control-Allow-Origin", "*") @@ -68,17 +68,17 @@ func GetVideoStream(c *gin.Context) { var req videoStreamReq id, _ := c.Get("id") id1 := id.(int) - //校验权限 - device := service.GetDevice(req.ID, id1) - if device.ID == 0 { - c.JSON(400, gin.H{"error": "device not exist"}) - return - } - + //将query参数绑定到结构体 if err := c.ShouldBind(&req); err != nil { c.JSON(400, gin.H{"error": err.Error()}) return } else { + //校验权限 + device := service.GetDevice(req.ID, id1) + if device.ID == 0 { + c.JSON(400, gin.H{"error": "device not exist"}) + return + } //查看id是否存在 index := -1 for _, device := range proto.Config.DeviceInfo { @@ -99,14 +99,20 @@ func GetVideoStream(c *gin.Context) { //设备流 c.Stream(func(w io.Writer) bool { var count int + var frame gocv.Mat for { - frame, cnt := service.GetDeviceCurrentFrame(req.ID) + cnt := service.GetDeviceCurrentFrameV2(&frame, req.ID) if cnt == count { time.Sleep(50 * time.Millisecond) continue } //gocv.Matrix转为jpeg - img, err := gocv.IMEncode(".jpg", frame) + img, err2 := gocv.IMEncode(".jpg", frame) + if err2 != nil { + fmt.Printf("img encode err:%v", err2) + time.Sleep(50 * time.Millisecond) + continue + } frame_ := img.GetBytes() _, err = w.Write([]byte("--frame\r\nContent-Type: image/jpeg\r\n\r\n")) @@ -161,22 +167,22 @@ func subscribeAndHandleMessagesV3(ws *websocket.Conn, device_id int) { //图片计数器 count := 0 //定时器,发送计数器 - t_count := 0 + tCount := 0 + //从service获取当前帧 + var img gocv.Mat for { - //从service获取当前帧 - var img gocv.Mat c := service.GetDeviceCurrentFrameV2(&img, device_id) if c != count { //将img转[]byte if img.Empty() { - log.Printf("device:%d img is empty!", device_id) + log.Printf("device:%d img is empty! count=%d", device_id, c) } else { //gocv.Matrix转为jpeg buf, err := gocv.IMEncode(".jpg", img) if err != nil { log.Printf("img encode err:%v", err) worker.SetRedisSetRemove(online_conn_key, con_id) - goto end + break } buf1 := buf.GetBytes() @@ -184,7 +190,7 @@ func subscribeAndHandleMessagesV3(ws *websocket.Conn, device_id int) { if err2 != nil { log.Printf("send message to client err:%v", err2) worker.SetRedisSetRemove(online_conn_key, con_id) - goto end + break } c = count err4 := img.Close() @@ -194,20 +200,25 @@ func subscribeAndHandleMessagesV3(ws *websocket.Conn, device_id int) { } } else { //每秒发送一次心跳检测 - if t_count%10 == 0 { + if tCount%10 == 0 { err := ws.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(time.Second)) if err != nil { log.Printf("Connection check failed:%v", err) worker.SetRedisSetRemove(online_conn_key, con_id) - goto end + break } } } time.Sleep(100 * time.Millisecond) - t_count++ + tCount++ + } + + //关闭img + err := img.Close() + if err != nil { + log.Printf("img close err:%v", err) } -end: // 查看是否还有其他连接,没有则设置 is_play 为 0 if worker.IsContainKey(online_conn_key) == false { worker.SetRedisWithExpire(strconv.Itoa(device_id)+"_is_play", "1", time.Minute*5) diff --git a/main.go b/main.go index 21ef9d6..60146be 100644 --- a/main.go +++ b/main.go @@ -35,7 +35,7 @@ func main() { if err0 != nil { panic("failed to connect redis:" + err0.Error()) } - r.Use(handler.CrosHandler()) + r.Use(handler.CorsHandler()) r.Use(JWTAuthMiddleware()) // 使用 JWT 认证中间件 handler.SetUpToolGroup(r) // Tool err := worker.InitRedis() diff --git a/service/tool.go b/service/tool.go index b8081e0..88e1018 100644 --- a/service/tool.go +++ b/service/tool.go @@ -16,10 +16,13 @@ import ( var DeviceRWMap = &sync.Map{} var DeviceCurrentFrameMap = &sync.Map{} -var DeviceFrameCount = &sync.Map{} +var DeviceFrameCount map[int]int var DeviceIsGettingFrame = &sync.Map{} +var Device1CurrentFrame gocv.Mat +var Device50CurrentFrame gocv.Mat +var Device73CurrentFrame gocv.Mat -func SetDeviceCurrentFrame(frame gocv.Mat, device_id int) error { +func SetDeviceCurrentFrame(frame *gocv.Mat, device_id int) error { //获取读写锁 mutex_, ok := DeviceRWMap.Load(device_id) if !ok { @@ -28,26 +31,31 @@ func SetDeviceCurrentFrame(frame gocv.Mat, device_id int) error { mutex := mutex_.(*sync.RWMutex) mutex.Lock() defer mutex.Unlock() - //获取前一帧,将前一帧释放 - framePrev, ok := DeviceCurrentFrameMap.Load(device_id) - if ok { - frame_, ok2 := framePrev.(gocv.Mat) - if ok2 { - err2 := frame_.Close() - if err2 != nil { - log.Printf("设备:%d, 错误: 无法关闭帧\n", device_id) - } - } - } //设置当前帧 - DeviceCurrentFrameMap.Store(device_id, frame) - frame_count, ok := DeviceFrameCount.Load(device_id) + switch device_id { + case 1: + if Device1CurrentFrame.Empty() { + Device1CurrentFrame = gocv.NewMatWithSize((*frame).Rows(), (*frame).Cols(), (*frame).Type()) + } + (*frame).CopyTo(&Device1CurrentFrame) + case 50: + if Device50CurrentFrame.Empty() { + Device50CurrentFrame = gocv.NewMatWithSize((*frame).Rows(), (*frame).Cols(), (*frame).Type()) + } + (*frame).CopyTo(&Device50CurrentFrame) + case 73: + if Device73CurrentFrame.Empty() { + Device73CurrentFrame = gocv.NewMatWithSize((*frame).Rows(), (*frame).Cols(), (*frame).Type()) + } + (*frame).CopyTo(&Device73CurrentFrame) + } + + frameCount, ok := DeviceFrameCount[device_id] if !ok { return fmt.Errorf("设备:%s 当前帧计数不存在", device_id) } - frame_count_ := frame_count.(int) - frame_count_++ - DeviceFrameCount.Store(device_id, frame_count_) + frameCount++ + DeviceFrameCount[device_id] = frameCount return nil } @@ -70,26 +78,31 @@ func GetDeviceCurrentFrameV2(frame *gocv.Mat, deviceId int) int { } mutex.RLock() defer mutex.RUnlock() - var frame_ gocv.Mat //获取当前帧 - frameIface, ok := DeviceCurrentFrameMap.Load(deviceId) + switch deviceId { + case 1: + if frame.Empty() { + *frame = gocv.NewMatWithSize(Device1CurrentFrame.Rows(), Device1CurrentFrame.Cols(), Device1CurrentFrame.Type()) + } + Device1CurrentFrame.CopyTo(frame) + case 50: + if frame.Empty() { + *frame = gocv.NewMatWithSize(Device50CurrentFrame.Rows(), Device50CurrentFrame.Cols(), Device50CurrentFrame.Type()) + } + Device50CurrentFrame.CopyTo(frame) + case 73: + if frame.Empty() { + *frame = gocv.NewMatWithSize(Device73CurrentFrame.Rows(), Device73CurrentFrame.Cols(), Device73CurrentFrame.Type()) + } + Device73CurrentFrame.CopyTo(frame) + + } + + frameCount, ok := DeviceFrameCount[deviceId] if !ok { return -1 } - frame_, ok = frameIface.(gocv.Mat) - if !ok { - log.Printf("DeviceCurrentFrameMap 存储的不是 gocv.Mat 类型,device_id: %d \n", deviceId) - } - *frame = frame_ - frame_countIface, ok := DeviceFrameCount.Load(deviceId) - if !ok { - return -1 - } - frame_count, ok := frame_countIface.(int) - if !ok { - log.Printf("DeviceFrameCount 存储的不是 int 类型,device_id: %d", deviceId) - } - return frame_count + return frameCount } func GetDeviceCurrentFrame(deviceId int) (gocv.Mat, int) { @@ -112,24 +125,34 @@ func GetDeviceCurrentFrame(deviceId int) (gocv.Mat, int) { } mutex.RLock() defer mutex.RUnlock() + var ret gocv.Mat + if ret.Empty() { + + } //获取当前帧 - frameIface, ok := DeviceCurrentFrameMap.Load(deviceId) - if !ok { - return gocv.NewMat(), -1 + switch deviceId { + case 1: + if ret.Empty() { + ret = gocv.NewMatWithSize(Device1CurrentFrame.Rows(), Device1CurrentFrame.Cols(), Device1CurrentFrame.Type()) + } + Device1CurrentFrame.CopyTo(&ret) + case 50: + if ret.Empty() { + ret = gocv.NewMatWithSize(Device50CurrentFrame.Rows(), Device50CurrentFrame.Cols(), Device50CurrentFrame.Type()) + } + Device50CurrentFrame.CopyTo(&ret) + case 73: + if ret.Empty() { + ret = gocv.NewMatWithSize(Device73CurrentFrame.Rows(), Device73CurrentFrame.Cols(), Device73CurrentFrame.Type()) + } + Device73CurrentFrame.CopyTo(&ret) } - frame, ok := frameIface.(gocv.Mat) + frameCount, ok := DeviceFrameCount[deviceId] if !ok { - log.Printf("DeviceCurrentFrameMap 存储的不是 gocv.Mat 类型,device_id: %d \n", deviceId) + log.Printf("设备:%d 当前帧计数不存在\n", deviceId) + frameCount = -1 } - frame_countIface, ok := DeviceFrameCount.Load(deviceId) - if !ok { - return gocv.NewMat(), -1 - } - frame_count, ok := frame_countIface.(int) - if !ok { - log.Printf("DeviceFrameCount 存储的不是 int 类型,device_id: %d", deviceId) - } - return frame, frame_count + return ret, frameCount } func getVideoFrame(device proto.DeviceInfo) { @@ -185,7 +208,7 @@ func getVideoFrame(device proto.DeviceInfo) { currentTime := time.Now().Format("2006-01-02 15:04:05") gocv.PutText(&frame, currentTime, image.Point{10, 20}, font, fontScale, fontColor, lineType) //需要将帧付给全局变量 - err3 := SetDeviceCurrentFrame(frame, device.ID) + err3 := SetDeviceCurrentFrame(&frame, device.ID) if err3 != nil { log.Printf("设备:%d 错误: 无法设置当前帧,err:%s \n", device.ID, err3.Error()) }