This repository was archived by the owner on Feb 13, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathrtp_parse.go
105 lines (84 loc) · 2.2 KB
/
rtp_parse.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package media
import (
"fmt"
"io"
"github.com/pion/rtcp"
"github.com/pion/rtp"
)
// Experimental
//
// RTPUnmarshal temporarly solution to provide more optimized unmarshal version based on pion/rtp
// it does not preserve any buffer reference which allows reusage
//
// TODO build RTP header unmarshaller for VOIP needs
func RTPUnmarshal(buf []byte, p *rtp.Packet) error {
n, err := p.Header.Unmarshal(buf)
if err != nil {
return err
}
if p.Header.Extension {
// For now eliminate it as it holds reference on buffer
// TODO fix this
p.Header.Extensions = nil
p.Header.Extension = false
}
end := len(buf)
if p.Header.Padding {
p.PaddingSize = buf[end-1]
end -= int(p.PaddingSize)
}
if end < n {
return io.ErrShortBuffer
}
// Payload should be recreated instead referenced
// This allows buf reusage
p.Payload = make([]byte, len(buf[n:end]))
copy(p.Payload, buf[n:end])
return nil
}
// RTCPUnmarshal is improved version based on pion/rtcp where we allow caller to define and control
// buffer of rtcp packets. This also reduces one allocation
// NOTE: data is still referenced in packet buffer
func RTCPUnmarshal(data []byte, packets []rtcp.Packet) (n int, err error) {
for i := 0; i < len(packets) && len(data) != 0; i++ {
var h rtcp.Header
err = h.Unmarshal(data)
if err != nil {
return 0, err
}
pktLen := int(h.Length+1) * 4
if pktLen > len(data) {
return 0, fmt.Errorf("packet too short")
}
inPacket := data[:pktLen]
// Check the type and unmarshal
packet := rtcpTypedPacket(h.Type)
err = packet.Unmarshal(inPacket)
if err != nil {
return 0, err
}
packets[i] = packet
data = data[pktLen:]
n++
}
return n, nil
}
func rtcpMarshal(packets []rtcp.Packet) ([]byte, error) {
return rtcp.Marshal(packets)
}
// TODO this would be nice that pion exports
func rtcpTypedPacket(htype rtcp.PacketType) rtcp.Packet {
// Currently we are not interested
switch htype {
case rtcp.TypeSenderReport:
return new(rtcp.SenderReport)
case rtcp.TypeReceiverReport:
return new(rtcp.ReceiverReport)
case rtcp.TypeSourceDescription:
return new(rtcp.SourceDescription)
case rtcp.TypeGoodbye:
return new(rtcp.Goodbye)
default:
return new(rtcp.RawPacket)
}
}