-
Notifications
You must be signed in to change notification settings - Fork 1
/
frame.go
63 lines (58 loc) · 1.39 KB
/
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
package rtsp
import (
"bufio"
"encoding/binary"
"fmt"
"io"
"math"
)
// Frame of interleaved binary data.
// This is encoded in RTP format.
type Frame struct {
Channel int
Data []byte
}
// Write the interleaved frame to the provided writer.
func (f Frame) Write(w io.Writer) error {
if f.Channel < 0 || f.Channel > math.MaxUint8 {
return fmt.Errorf("invalid channel: %d", f.Channel)
}
var hdr [4]byte
hdr[0] = '$'
hdr[1] = uint8(f.Channel)
binary.BigEndian.PutUint16(hdr[2:], uint16(len(f.Data)))
if _, err := w.Write(hdr[:]); err != nil {
return err
}
if _, err := w.Write(f.Data); err != nil {
return err
}
return nil
}
// ReadFrame reads an interleaved binary frame from the reader.
func ReadFrame(r io.Reader) (Frame, error) {
var hdr [4]byte
if _, err := io.ReadFull(r, hdr[:]); err != nil {
return Frame{}, err
}
if hdr[0] != '$' {
return Frame{}, fmt.Errorf("invalid magic prefix: %v", hdr[0])
}
data := make([]byte, binary.BigEndian.Uint16(hdr[2:]))
if _, err := io.ReadFull(r, data); err != nil {
return Frame{}, err
}
return Frame{
Channel: int(hdr[1]),
Data: data,
}, nil
}
// IsFrame returns true when the next message is an interleaved frame.
// This will block until at least one byte is available in the reader
func IsFrame(r *bufio.Reader) (bool, error) {
first, err := r.Peek(1)
if err != nil {
return false, err
}
return first[0] == '$', nil
}