VideoStream/service/tool.go

203 lines
4.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"VideoStream/dao"
"VideoStream/proto"
"VideoStream/worker"
"fmt"
"gocv.io/x/gocv"
"image"
"image/color"
"log"
"net/http"
"sync"
"time"
)
var DeviceRWMap = &sync.Map{}
var DeviceCurrentFrameMap = &sync.Map{}
var DeviceFrameCount = &sync.Map{}
var DeviceIsGettingFrame = &sync.Map{}
func SetDeviceCurrentFrame(frame gocv.Mat, device_id int) error {
//获取读写锁
mutex_, ok := DeviceRWMap.Load(device_id)
if !ok {
return fmt.Errorf("设备:%s 读写锁不存在", device_id)
}
mutex := mutex_.(*sync.RWMutex)
mutex.Lock()
defer mutex.Unlock()
//设置当前帧
DeviceCurrentFrameMap.Store(device_id, frame)
frame_count, ok := DeviceFrameCount.Load(device_id)
if !ok {
return fmt.Errorf("设备:%s 当前帧计数不存在", device_id)
}
frame_count_ := frame_count.(int)
frame_count_++
DeviceFrameCount.Store(device_id, frame_count_)
return nil
}
func GetDeviceCurrentFrame(device_id int) (gocv.Mat, int) {
//获取读写锁
mutex_, ok := DeviceRWMap.Load(device_id)
if !ok {
return gocv.NewMat(), -1
}
mutex, ok := mutex_.(*sync.RWMutex)
if !ok {
log.Fatalf("DeviceRWMap 存储的不是 *sync.RWMutex 类型device_id: %d", device_id)
}
mutex.RLock()
defer mutex.RUnlock()
//获取当前帧
frameIface, ok := DeviceCurrentFrameMap.Load(device_id)
if !ok {
return gocv.NewMat(), -1
}
frame, ok := frameIface.(gocv.Mat)
if !ok {
log.Fatalf("DeviceCurrentFrameMap 存储的不是 gocv.Mat 类型device_id: %d", device_id)
}
frame_countIface, ok := DeviceFrameCount.Load(device_id)
if !ok {
return gocv.NewMat(), -1
}
frame_count, ok := frame_countIface.(int)
if !ok {
log.Fatalf("DeviceFrameCount 存储的不是 int 类型device_id: %d", device_id)
}
return frame, frame_count
}
func getVideoFrame(device proto.DeviceInfo) {
webcam, err := gocv.OpenVideoCapture(device.Stream)
if err != nil {
fmt.Printf("设备:%s 错误: 无法打开视频流err: %v\n", device.ID, err)
return
}
defer webcam.Close()
// 字体相关设置对应OpenCV默认字体等这里简化处理实际可按需求调整
font := gocv.FontHersheySimplex
fontScale := 0.5
fontColor := color.RGBA{G: 255}
lineType := 2
z := 0
for {
if device.LogFrame > 0 && z%device.LogFrame == 0 {
fmt.Printf("设备:%d 当前帧: %d\n", device.ID, z)
}
if device.NextStop {
break
}
frame := gocv.NewMat()
ok := webcam.Read(&frame)
if !ok {
fmt.Printf("设备 错误: 无法从视频流中读取帧:", device, "\n")
break
}
if frame.Empty() {
fmt.Printf("设备:%s 错误: 无法从视频流中读取帧\n", device)
//等待50ms
time.Sleep(50 * time.Millisecond)
continue
}
height := frame.Rows()
width := frame.Cols()
if height < device.CheckFrameHeight || width < device.CheckFrameWidth {
fmt.Printf("设备:%s 帧尺寸已改变\n", device)
break
}
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)
if err3 != nil {
fmt.Printf("设备:%d 错误: 无法设置当前帧,err:%s \n", device.ID, err3.Error())
}
z++
err2 := frame.Close()
if err2 != nil {
fmt.Println("设备:%d,计数z=%d, 错误: 无法关闭帧", device.ID, z)
}
}
}
// 发起get请求,返回响应状态码
func Get(url string) int {
req, err := http.NewRequest("GET", url, nil)
var client = &http.Client{}
if err != nil {
return 500
}
resp, err := client.Do(req)
if err != nil {
return 500
}
return resp.StatusCode
}
func GetVideoStream(id int) {
is_get, ok := DeviceIsGettingFrame.Load(id)
if !ok {
fmt.Println("device:", id, " not found")
return
}
if is_get == true {
fmt.Println("device:", id, " is running!")
return
}
for {
var device proto.DeviceInfo
var index int
//获取设备信息
for i, device1 := range proto.Config.DeviceInfo {
if device1.ID == id {
device = device1
break
}
index = i
}
if index == len(proto.Config.DeviceInfo) {
//设备不存在
log.Println("device:", id, " not found")
break
}
is_get, ok = DeviceIsGettingFrame.Load(id)
if is_get == true {
log.Println("for device:", id, " is running!")
break
}
if device.NextStop {
DeviceIsGettingFrame.Store(id, false)
break
}
//设置设备控制信息
status := Get(device.Control)
DeviceIsGettingFrame.Store(id, true)
log.Println("device:", device.ID, " set control info status:", status)
getVideoFrame(device)
DeviceIsGettingFrame.Store(id, false)
//等待1s
time.Sleep(1 * time.Second)
}
}
func DoGetVideoStream() {
for _, device := range proto.Config.DeviceInfo {
go GetVideoStream(device.ID)
}
}
func GetDevice(id, auth_id int) dao.Device {
return dao.FindDeviceByID(id, auth_id)
}
func SetConfigRedis(key, config string) {
worker.SetRedis(key, config)
}