2020-10-18 10:33:47 +02:00
|
|
|
package main
|
|
|
|
|
|
2020-10-18 15:40:25 +02:00
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"encoding/binary"
|
2020-10-19 09:45:49 +02:00
|
|
|
"errors"
|
2020-10-18 15:40:25 +02:00
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/nonoo/kappanhang/log"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const audioTimeoutDuration = 3 * time.Second
|
2020-10-20 14:14:05 +02:00
|
|
|
const rxSeqBufLength = 100 * time.Millisecond
|
2020-10-18 10:33:47 +02:00
|
|
|
|
|
|
|
|
type audioStream struct {
|
2020-10-18 11:01:53 +02:00
|
|
|
common streamCommon
|
2020-10-18 15:40:25 +02:00
|
|
|
|
|
|
|
|
timeoutTimer *time.Timer
|
2020-10-18 18:59:23 +02:00
|
|
|
receivedAudio bool
|
2020-10-18 15:40:25 +02:00
|
|
|
lastReceivedAudioSeq uint16
|
2020-10-20 14:14:05 +02:00
|
|
|
rxSeqBuf seqBuf
|
|
|
|
|
rxSeqBufEntryChan chan seqBufEntry
|
2020-10-18 20:09:12 +02:00
|
|
|
|
|
|
|
|
audioSendSeq uint16
|
2020-10-18 10:33:47 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-18 13:19:52 +02:00
|
|
|
func (s *audioStream) sendDisconnect() {
|
|
|
|
|
s.common.sendDisconnect()
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-20 14:14:05 +02:00
|
|
|
// sendPart1 expects 1364 bytes of PCM data.
|
|
|
|
|
func (s *audioStream) sendPart1(pcmData []byte) {
|
|
|
|
|
s.common.send(append([]byte{0x6c, 0x05, 0x00, 0x00, 0x00, 0x00, byte(s.audioSendSeq), byte(s.audioSendSeq >> 8),
|
|
|
|
|
byte(s.common.localSID >> 24), byte(s.common.localSID >> 16), byte(s.common.localSID >> 8), byte(s.common.localSID),
|
|
|
|
|
byte(s.common.remoteSID >> 24), byte(s.common.remoteSID >> 16), byte(s.common.remoteSID >> 8), byte(s.common.remoteSID),
|
|
|
|
|
0x80, 0x00, byte((s.audioSendSeq - 1) >> 8), byte(s.audioSendSeq - 1), 0x00, 0x00, byte(len(pcmData) >> 8), byte(len(pcmData))},
|
|
|
|
|
pcmData...))
|
|
|
|
|
s.audioSendSeq++
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sendPart2 expects 556 bytes of PCM data.
|
|
|
|
|
func (s *audioStream) sendPart2(pcmData []byte) {
|
|
|
|
|
s.common.send(append([]byte{0x44, 0x02, 0x00, 0x00, 0x00, 0x00, byte(s.audioSendSeq), byte(s.audioSendSeq >> 8),
|
|
|
|
|
byte(s.common.localSID >> 24), byte(s.common.localSID >> 16), byte(s.common.localSID >> 8), byte(s.common.localSID),
|
|
|
|
|
byte(s.common.remoteSID >> 24), byte(s.common.remoteSID >> 16), byte(s.common.remoteSID >> 8), byte(s.common.remoteSID),
|
|
|
|
|
0x80, 0x00, byte((s.audioSendSeq - 1) >> 8), byte(s.audioSendSeq - 1), 0x00, 0x00, byte(len(pcmData) >> 8), byte(len(pcmData))},
|
|
|
|
|
pcmData...))
|
|
|
|
|
s.audioSendSeq++
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-20 11:44:07 +02:00
|
|
|
func (s *audioStream) sendRetransmitRequest(seqNum uint16) {
|
|
|
|
|
p := []byte{0x10, 0x00, 0x00, 0x00, 0x01, 0x00, byte(seqNum), byte(seqNum >> 8),
|
|
|
|
|
byte(s.common.localSID >> 24), byte(s.common.localSID >> 16), byte(s.common.localSID >> 8), byte(s.common.localSID),
|
|
|
|
|
byte(s.common.remoteSID >> 24), byte(s.common.remoteSID >> 16), byte(s.common.remoteSID >> 8), byte(s.common.remoteSID)}
|
|
|
|
|
s.common.send(p)
|
|
|
|
|
s.common.send(p)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type seqNumRange [2]uint16
|
|
|
|
|
|
|
|
|
|
func (s *audioStream) sendRetransmitRequestForRanges(seqNumRanges []seqNumRange) {
|
|
|
|
|
seqNumBytes := make([]byte, len(seqNumRanges)*4)
|
|
|
|
|
for i := 0; i < len(seqNumRanges); i++ {
|
|
|
|
|
seqNumBytes[i*2] = byte(seqNumRanges[i][0])
|
|
|
|
|
seqNumBytes[i*2+1] = byte(seqNumRanges[i][0] >> 8)
|
|
|
|
|
seqNumBytes[i*2+2] = byte(seqNumRanges[i][1])
|
|
|
|
|
seqNumBytes[i*2+3] = byte(seqNumRanges[i][1] >> 8)
|
|
|
|
|
}
|
|
|
|
|
p := append([]byte{0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
|
|
|
|
|
byte(s.common.localSID >> 24), byte(s.common.localSID >> 16), byte(s.common.localSID >> 8), byte(s.common.localSID),
|
|
|
|
|
byte(s.common.remoteSID >> 24), byte(s.common.remoteSID >> 16), byte(s.common.remoteSID >> 8), byte(s.common.remoteSID)},
|
|
|
|
|
seqNumBytes...)
|
|
|
|
|
s.common.send(p)
|
|
|
|
|
s.common.send(p)
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-20 14:14:05 +02:00
|
|
|
func (s *audioStream) handleRxSeqBufEntry(e seqBufEntry) {
|
|
|
|
|
gotSeq := uint16(e.seq)
|
2020-10-18 18:59:23 +02:00
|
|
|
if s.receivedAudio {
|
|
|
|
|
expectedSeq := s.lastReceivedAudioSeq + 1
|
|
|
|
|
if expectedSeq != gotSeq {
|
|
|
|
|
var missingPkts int
|
|
|
|
|
if gotSeq > expectedSeq {
|
|
|
|
|
missingPkts = int(gotSeq) - int(expectedSeq)
|
|
|
|
|
} else {
|
|
|
|
|
missingPkts = int(gotSeq) + 65536 - int(expectedSeq)
|
|
|
|
|
}
|
|
|
|
|
log.Error("lost ", missingPkts, " audio packets")
|
2020-10-18 15:40:25 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
s.lastReceivedAudioSeq = gotSeq
|
2020-10-18 18:59:23 +02:00
|
|
|
s.receivedAudio = true
|
2020-10-18 15:40:25 +02:00
|
|
|
|
2020-10-20 15:23:12 +02:00
|
|
|
audio.play <- e.data
|
2020-10-18 15:40:25 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-20 14:14:05 +02:00
|
|
|
func (s *audioStream) handleAudioPacket(r []byte) {
|
|
|
|
|
if s.timeoutTimer != nil {
|
|
|
|
|
s.timeoutTimer.Stop()
|
|
|
|
|
s.timeoutTimer.Reset(audioTimeoutDuration)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gotSeq := binary.LittleEndian.Uint16(r[6:8])
|
|
|
|
|
err := s.rxSeqBuf.add(seqNum(gotSeq), r[24:])
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Error(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-18 13:52:38 +02:00
|
|
|
func (s *audioStream) handleRead(r []byte) {
|
2020-10-18 15:40:25 +02:00
|
|
|
if len(r) >= 580 && (bytes.Equal(r[:6], []byte{0x6c, 0x05, 0x00, 0x00, 0x00, 0x00}) || bytes.Equal(r[:6], []byte{0x44, 0x02, 0x00, 0x00, 0x00, 0x00})) {
|
|
|
|
|
s.handleAudioPacket(r)
|
|
|
|
|
}
|
2020-10-18 13:52:38 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-18 18:34:22 +02:00
|
|
|
func (s *audioStream) init() {
|
2020-10-18 11:17:40 +02:00
|
|
|
s.common.open("audio", 50003)
|
2020-10-20 14:14:05 +02:00
|
|
|
s.rxSeqBufEntryChan = make(chan seqBufEntry)
|
|
|
|
|
s.rxSeqBuf.init(rxSeqBufLength, 0xffff, 0, s.rxSeqBufEntryChan)
|
2020-10-18 18:34:22 +02:00
|
|
|
}
|
2020-10-18 10:33:47 +02:00
|
|
|
|
2020-10-18 18:34:22 +02:00
|
|
|
func (s *audioStream) start() {
|
2020-10-18 11:01:53 +02:00
|
|
|
s.common.sendPkt3()
|
2020-10-18 13:52:38 +02:00
|
|
|
s.common.waitForPkt4Answer()
|
2020-10-18 11:01:53 +02:00
|
|
|
s.common.sendPkt6()
|
2020-10-18 13:52:38 +02:00
|
|
|
s.common.waitForPkt6Answer()
|
|
|
|
|
|
2020-10-18 18:34:22 +02:00
|
|
|
log.Print("stream started")
|
2020-10-18 13:52:38 +02:00
|
|
|
|
2020-10-18 15:40:25 +02:00
|
|
|
s.timeoutTimer = time.NewTimer(audioTimeoutDuration)
|
|
|
|
|
|
2020-10-20 19:47:25 +02:00
|
|
|
s.common.pkt7.startPeriodicSend(&s.common, 1, false)
|
2020-10-18 13:52:38 +02:00
|
|
|
|
2020-10-18 20:09:12 +02:00
|
|
|
s.audioSendSeq = 1
|
|
|
|
|
|
2020-10-18 13:52:38 +02:00
|
|
|
for {
|
|
|
|
|
select {
|
2020-10-20 14:14:05 +02:00
|
|
|
case r := <-s.common.readChan:
|
2020-10-18 13:52:38 +02:00
|
|
|
s.handleRead(r)
|
2020-10-18 15:40:25 +02:00
|
|
|
case <-s.timeoutTimer.C:
|
2020-10-20 17:50:50 +02:00
|
|
|
exit(errors.New("audio stream timeout"))
|
2020-10-20 14:14:05 +02:00
|
|
|
case e := <-s.rxSeqBufEntryChan:
|
|
|
|
|
s.handleRxSeqBufEntry(e)
|
2020-10-20 16:04:35 +02:00
|
|
|
case d := <-audio.rec:
|
|
|
|
|
s.sendPart1(d[:1364])
|
|
|
|
|
s.sendPart2(d[1364:1920])
|
2020-10-18 13:52:38 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-10-18 10:33:47 +02:00
|
|
|
}
|