Golang 使用 Channel 控制数据帧发送的开始和结束

本文介绍如何使用 Golang 的 channel 机制来控制数据帧的开始和结束发送。通过修改 OnDriverStartOnDriverStop 函数,以及 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)
}

代码解释

  1. OnDriverStart 函数中,调用 GetOrCreateDriver 函数将 startCh channel 传入,用于发送开始信号。
  2. OnDriverStop 函数中,调用 SetSig 函数将 stopCh channel 传入,用于发送停止信号。
  3. HandelModelDataV2 函数中,使用 select 语句监听 startSigstopSig 两个 channel。
  4. 当收到 startSig 信号时,开始发送数据帧。
  5. 当收到 stopSig 信号时,停止发送数据帧并退出循环。

总结

通过使用 Golang 的 channel 机制,可以方便地控制数据帧的开始和结束发送。这种方法简单易懂,并且可以有效地提高代码的灵活性和可维护性。

Golang 使用 Channel 控制数据帧发送的开始和结束

原文地址: https://www.cveoy.top/t/topic/p4nu 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录