From 996ef32bff961167629e258fe68f941f37ac2293 Mon Sep 17 00:00:00 2001 From: Justine Alexandra Roberts Tunney Date: Wed, 22 Jul 2015 04:42:21 -0400 Subject: [PATCH] Use fancy slicing for RTP buffer. --- fone/main.go | 1 + rtp/rtp.go | 40 +++++++++++++++++++++------------------- rtp/session.go | 49 +++++++++++++++++++++++++------------------------ 3 files changed, 47 insertions(+), 43 deletions(-) diff --git a/fone/main.go b/fone/main.go index a95ce11..3eb9a66 100644 --- a/fone/main.go +++ b/fone/main.go @@ -180,6 +180,7 @@ func main() { case ch := <-keyboard: if err := rs.SendDTMF(ch); err != nil { log.Printf("DTMF: %s\r\n", err.Error()) + break } log.Printf("DTMF: %c\r\n", ch) diff --git a/rtp/rtp.go b/rtp/rtp.go index 0dffeb8..7b05fa0 100755 --- a/rtp/rtp.go +++ b/rtp/rtp.go @@ -93,31 +93,33 @@ type EventHeader struct { Duration uint16 } -// Writes an rtp header to a buffer. You need 12 bytes. -func (h *Header) Write(b []byte) { - b[0] = (Version & mask2) << 6 +// Write appends an RTP header to a byte slice. +func (h *Header) Write(b []byte) []byte { + var b0, b1 byte + b0 = (Version & mask2) << 6 if h.Pad { - b[0] |= (1 & mask1) << 5 + b0 |= (1 & mask1) << 5 } - // if extend { b[0] |= (1 & mask1) << 4 } - // b[0] |= (csrcCount & mask4) << 0 - b[1] = (h.PT & mask7) << 0 + // if extend { b0 |= (1 & mask1) << 4 } + // b0 |= (csrcCount & mask4) << 0 + b1 = (h.PT & mask7) << 0 if h.Mark { - b[1] |= (1 & mask1) << 7 + b1 |= (1 & mask1) << 7 } - b[2] = byte(h.Seq >> 8) - b[3] = byte(h.Seq) - b[4] = byte(h.TS >> 24) - b[5] = byte(h.TS >> 16) - b[6] = byte(h.TS >> 8) - b[7] = byte(h.TS) - b[8] = byte(h.Ssrc >> 24) - b[9] = byte(h.Ssrc >> 16) - b[10] = byte(h.Ssrc >> 8) - b[11] = byte(h.Ssrc) + return append(b, b0, b1, + byte(h.Seq>>8), + byte(h.Seq), + byte(h.TS>>24), + byte(h.TS>>16), + byte(h.TS>>8), + byte(h.TS), + byte(h.Ssrc>>24), + byte(h.Ssrc>>16), + byte(h.Ssrc>>8), + byte(h.Ssrc)) } -// Reads header bits from buffer. +// Read extracts an RTP header from a byte slice. func (h *Header) Read(b []byte) error { if b[0]>>6 != Version { return ErrBadVersion diff --git a/rtp/session.go b/rtp/session.go index 2bc271b..4254468 100644 --- a/rtp/session.go +++ b/rtp/session.go @@ -17,10 +17,13 @@ const ( rtpBindMaxAttempts = 10 rtpBindPortMin = 16384 rtpBindPortMax = 32768 + dtmfVolume = 6 + dtmfDuration = 400 + dtmfInterval = 100 ) var ( - dtmfCodes = map[byte]byte{'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '*': 10, '#': 11, 'a': 12, 'A': 12, 'b': 13, 'B': 13, 'c': 14, 'C': 14, 'd': 15, 'D': 15, '!': 16} + dtmfCodes = [256]byte{'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '*': 10, '#': 11, 'a': 12, 'A': 12, 'b': 13, 'B': 13, 'c': 14, 'C': 14, 'd': 15, 'D': 15, '!': 16} ) type Frame [160]int16 @@ -70,7 +73,7 @@ func NewSession(host string) (rs *Session, err error) { TS: 0, Ssrc: rand.Uint32(), }, - obuf: make([]byte, HeaderSize+160), + obuf: make([]byte, 0, 1500), }, nil } @@ -79,13 +82,14 @@ func (rs *Session) Send(frame *Frame) (err error) { return nil } rs.Header.PT = sdp.ULAWCodec.PT - rs.Header.Write(rs.obuf) + buf := rs.Header.Write(rs.obuf) + buf = buf[0 : len(buf)+160] rs.Header.TS += 160 rs.Header.Seq++ for n := 0; n < 160; n++ { - rs.obuf[HeaderSize+n] = byte(dsp.LinearToUlaw(int64(frame[n]))) + buf[HeaderSize+n] = byte(dsp.LinearToUlaw(int64(frame[n]))) } - _, err = rs.Sock.WriteTo(rs.obuf[:HeaderSize+160], rs.Peer) + _, err = rs.Sock.WriteTo(buf, rs.Peer) return } @@ -94,19 +98,16 @@ func (rs *Session) SendRaw(pt uint8, data []byte, samps uint32) (err error) { return nil } rs.Header.PT = pt - rs.Header.Write(rs.obuf) + buf := rs.Header.Write(rs.obuf) rs.Header.TS += samps rs.Header.Seq++ - _, err = rs.Sock.WriteTo(append(rs.obuf[:HeaderSize], data...), rs.Peer) + _, err = rs.Sock.WriteTo(append(buf, data...), rs.Peer) return } func (rs *Session) SendDTMF(digit byte) error { - const volume = 6 - const duration = 1600 - const interval = 400 - code, ok := dtmfCodes[digit] - if !ok { + code := dtmfCodes[digit] + if code == 0 && digit != '0' { return errors.New("Invalid DTMF digit: " + string(digit)) } if rs == nil || rs.Sock == nil || rs.Peer == nil { @@ -114,30 +115,30 @@ func (rs *Session) SendDTMF(digit byte) error { } rs.Header.PT = sdp.DTMFCodec.PT rs.Header.Mark = true - rs.obuf[HeaderSize+0] = code - rs.obuf[HeaderSize+1] = volume & 0x3f + var event [4]byte + event[0] = code + event[1] = dtmfVolume & 0x3f dur := uint16(1) for { - rs.obuf[HeaderSize+2] = byte(dur >> 8) - rs.obuf[HeaderSize+3] = byte(dur & 0xff) - rs.Header.Write(rs.obuf) - _, err := rs.Sock.WriteTo(rs.obuf[:HeaderSize+4], rs.Peer) + event[2] = byte(dur >> 8) + event[3] = byte(dur & 0xff) + _, err := rs.Sock.WriteTo(append(rs.Header.Write(rs.obuf), event[:]...), rs.Peer) if err != nil { return err } rs.Header.Seq++ rs.Header.Mark = false - dur += interval - if dur >= duration { + dur += dtmfInterval + if dur >= dtmfDuration { break } } - rs.obuf[HeaderSize+1] |= 0x80 - rs.obuf[HeaderSize+2] = byte(duration >> 8) - rs.obuf[HeaderSize+3] = byte(duration & 0xff) + event[1] |= 0x80 + event[2] = byte(dtmfDuration >> 8) + event[3] = byte(dtmfDuration & 0xff) for n := 0; n < 3; n++ { rs.Header.Write(rs.obuf) - _, err := rs.Sock.WriteTo(rs.obuf[:HeaderSize+4], rs.Peer) + _, err := rs.Sock.WriteTo(append(rs.Header.Write(rs.obuf), event[:]...), rs.Peer) if err != nil { return err }