-
Notifications
You must be signed in to change notification settings - Fork 173
/
interleaved_frame.go
72 lines (56 loc) · 1.59 KB
/
interleaved_frame.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package base
import (
"bufio"
"fmt"
"io"
)
const (
// InterleavedFrameMagicByte is the first byte of an interleaved frame.
InterleavedFrameMagicByte = 0x24
)
// InterleavedFrame is an interleaved frame, and allows to transfer binary data
// within RTSP/TCP connections. It is used to send and receive RTP and RTCP packets with TCP.
type InterleavedFrame struct {
// channel ID
Channel int
// payload
Payload []byte
}
// Unmarshal decodes an interleaved frame.
func (f *InterleavedFrame) Unmarshal(br *bufio.Reader) error {
var header [4]byte
_, err := io.ReadFull(br, header[:])
if err != nil {
return err
}
if header[0] != InterleavedFrameMagicByte {
return fmt.Errorf("invalid magic byte (0x%.2x)", header[0])
}
// it's useless to check payloadLen since it's limited to 65535
payloadLen := int(uint16(header[2])<<8 | uint16(header[3]))
f.Channel = int(header[1])
f.Payload = make([]byte, payloadLen)
_, err = io.ReadFull(br, f.Payload)
return err
}
// MarshalSize returns the size of an InterleavedFrame.
func (f InterleavedFrame) MarshalSize() int {
return 4 + len(f.Payload)
}
// MarshalTo writes an InterleavedFrame.
func (f InterleavedFrame) MarshalTo(buf []byte) (int, error) {
pos := 0
pos += copy(buf[pos:], []byte{0x24, byte(f.Channel)})
payloadLen := len(f.Payload)
buf[pos] = byte(payloadLen >> 8)
buf[pos+1] = byte(payloadLen)
pos += 2
pos += copy(buf[pos:], f.Payload)
return pos, nil
}
// Marshal writes an InterleavedFrame.
func (f InterleavedFrame) Marshal() ([]byte, error) {
buf := make([]byte, f.MarshalSize())
_, err := f.MarshalTo(buf)
return buf, err
}