Golang 使用 Channel 控制数据帧发送的开始和结束
Golang 使用 Channel 控制数据帧发送的开始和结束
本文介绍如何使用 Golang 的 channel 机制来控制数据帧的开始和结束发送。通过修改 OnDriverStart 和 OnDriverStop 函数,以及 HandelModelDataV2 函数,可以实现根据需求灵活控制数据帧的发送。
修改 OnDriverStart 和 OnDriverStop 函数
func (this *NoticeDetectionCtl) OnDriverStop() {
SetSig(this.Token, stopCh, 'OnDriverStop,getback to stop driver')
result := make(map[string]interface{})
this.OnSuccess(result)
}
func (this *NoticeDetectionCtl) OnDriverStart() {
var req protocol.StartDriver
err := this.UnMarshal(&req)
if err != nil {
logs.Error('ReNewModel, %s err = %v', string(this.Ctx.Input.RequestBody), err)
this.OnError(errno.EC_InnerError, errno.EM_InnerError)
return
}
commonInfo := fmt.Sprintf('OnDriverStart, userid = %d', this.Session.Id)
if req.StartTime == 0 {
logs.Error('%s,start_time is 0', commonInfo)
this.OnError(errno.EC_InvalidArg, errno.EM_InvalidArg)
return
}
now := time.Now()
timestamp := now.UnixNano()
val := req.StartTime - timestamp
if val == 0 {
GetOrCreateDriver(this.Token, startCh)
} else if val > 0 {
time.Sleep(time.Duration(val) * time.Millisecond)
GetOrCreateDriver(this.Token, startCh)
} else {
logs.Error('%s,start_time is end', commonInfo)
this.OnError(errno.EC_InvalidArg, '当前时间已过音频播放开始时间')
return
}
result := make(map[string]interface{})
this.OnSuccess(result)
}
修改 HandelModelDataV2 函数
func HandelModelDataV2(frames [][]int32, coefl float32, token string, commonInfo string, duration float64, startSig chan int, stopSig chan string) {
defer closeDriver(token, startSig, commonInfo)
streamInfoRes, err := getStreamInfo(token, commonInfo)
if err != nil {
logs.Error('%s, err = %v', commonInfo, err)
return
}
socket, err := getUDPSocket(streamInfoRes.Data.Ip, 11111)
if err != nil {
logs.Error('%s, ip = %s, port = %d, err = %v', commonInfo, streamInfoRes.Data.Ip, 11111, err)
return
}
defer socket.Close()
err = StartBSDriverV1(token)
if err != nil {
logs.Error('%s, StartBSDriver failed, err = %v', commonInfo, err)
return
}
averageDuration := float64(duration) * 1000 / float64(len(frames)) // 平均每帧的时长(毫秒)
frameDuration := time.Duration(averageDuration * 1000 * 1000)
var sumTime = time.Duration(0)
var sTime time.Duration
var allDuration time.Duration
startTime := time.Now()
Loop:
for i := 0; i < len(frames); i++ {
frameTime := time.Now()
frameBs := make([]float32, 61)
for j := 0; j < 51; j++ {
frameBs[j] = float32(frames[i][j]) / coefl
}
var num time.Duration
if i%2 == 0 {
num = 480 * time.Microsecond
}
select {
case <-stopSig:
logs.Info('%s, recv quit sig, quit now', commonInfo)
close(stopSig)
break Loop
case <-startSig:
data := MakeBSFrame(frameBs)
err = sendData(socket, data)
if err != nil {
logs.Error('%s, sendData failed, err = %v', commonInfo, err)
return
}
//400字的较好效果的帧率
//time.Sleep(16*time.Millisecond + 176*time.Microsecond)
sTime = time.Since(frameTime)
waitTime := frameDuration - sTime - 320*time.Microsecond - num
time.Sleep(waitTime)
sumTime = sumTime + waitTime
logs.Info('i:%d,sTime: %v,frameDuration:%v,num:%v,waitTime: %v', i, sTime, frameDuration, num, waitTime)
default:
logs.Info('%s,wait start sig', commonInfo)
}
}
allDuration = time.Since(startTime)
logs.Info(' len: %d , duration: %5.8f, allDuration:%v, averageDuration: %v,time.Duration(averageDuration):%v, time.Duration(averageDuration*1000):%v,'+
'frameDuration * time.Microsecond:%v,duration_len:%5.8f, all_len: %5.8f,frameDuration: %v,实际累计时间和:%v,总帧累计时间和:%v',
len(frames), duration, allDuration, averageDuration, time.Duration(averageDuration), time.Duration(averageDuration*1000), frameDuration*time.Microsecond,
float64(frameDuration)*float64(len(frames)), float64(frameDuration)*float64(len(frames)), frameDuration, allDuration, sumTime)
err = StopBSDriverV1(token)
if err != nil {
logs.Error('%s, StopBSDriver failed, err = %v', commonInfo, err)
return
}
logs.Info('%s, finish', commonInfo)
}
代码解释
- 在
OnDriverStart函数中,调用GetOrCreateDriver函数将startChchannel 传入,用于发送开始信号。 - 在
OnDriverStop函数中,调用SetSig函数将stopChchannel 传入,用于发送停止信号。 - 在
HandelModelDataV2函数中,使用select语句监听startSig和stopSig两个 channel。 - 当收到
startSig信号时,开始发送数据帧。 - 当收到
stopSig信号时,停止发送数据帧并退出循环。
总结
通过使用 Golang 的 channel 机制,可以方便地控制数据帧的开始和结束发送。这种方法简单易懂,并且可以有效地提高代码的灵活性和可维护性。
原文地址: https://www.cveoy.top/t/topic/p4nu 著作权归作者所有。请勿转载和采集!