forked from pion/webrtc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.go
168 lines (142 loc) · 3.72 KB
/
util.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package sdp
import (
"bufio"
"fmt"
"io"
"math/rand"
"strconv"
"strings"
"time"
"github.com/pkg/errors"
)
// ConnectionRole indicates which of the end points should initiate the connection establishment
type ConnectionRole int
const (
// ConnectionRoleActive indicates the endpoint will initiate an outgoing connection.
ConnectionRoleActive ConnectionRole = iota + 1
// ConnectionRolePassive indicates the endpoint will accept an incoming connection.
ConnectionRolePassive
// ConnectionRoleActpass indicates the endpoint is willing to accept an incoming connection or to initiate an outgoing connection.
ConnectionRoleActpass
// ConnectionRoleHoldconn indicates the endpoint does not want the connection to be established for the time being.
ConnectionRoleHoldconn
)
func (t ConnectionRole) String() string {
switch t {
case ConnectionRoleActive:
return "active"
case ConnectionRolePassive:
return "passive"
case ConnectionRoleActpass:
return "actpass"
case ConnectionRoleHoldconn:
return "holdconn"
default:
return "Unknown"
}
}
func newSessionID() uint64 {
r := rand.New(rand.NewSource(time.Now().UnixNano()))
return uint64(r.Uint32()*2) >> 2
}
// Codec represents a codec
type Codec struct {
PayloadType uint8
Name string
ClockRate uint32
EncodingParameters string
Fmtp string
}
func (c Codec) String() string {
return fmt.Sprintf("%d %s/%d/%s", c.PayloadType, c.Name, c.ClockRate, c.EncodingParameters)
}
// GetCodecForPayloadType scans the SessionDescription for the given payloadType and returns the codec
func (s *SessionDescription) GetCodecForPayloadType(payloadType uint8) (Codec, error) {
codec := Codec{
PayloadType: payloadType,
}
found := false
payloadTypeString := strconv.Itoa(int(payloadType))
rtpmapPrefix := "rtpmap:" + payloadTypeString
fmtpPrefix := "fmtp:" + payloadTypeString
for _, m := range s.MediaDescriptions {
for _, a := range m.Attributes {
if strings.HasPrefix(*a.String(), rtpmapPrefix) {
found = true
// a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]
split := strings.Split(*a.String(), " ")
if len(split) == 2 {
split = strings.Split(split[1], "/")
codec.Name = split[0]
parts := len(split)
if parts > 1 {
rate, err := strconv.Atoi(split[1])
if err != nil {
return codec, err
}
codec.ClockRate = uint32(rate)
}
if parts > 2 {
codec.EncodingParameters = split[2]
}
}
} else if strings.HasPrefix(*a.String(), fmtpPrefix) {
// a=fmtp:<format> <format specific parameters>
split := strings.Split(*a.String(), " ")
if len(split) == 2 {
codec.Fmtp = split[1]
}
}
}
if found {
return codec, nil
}
}
return codec, errors.New("payload type not found")
}
type lexer struct {
desc *SessionDescription
input *bufio.Reader
}
type stateFn func(*lexer) (stateFn, error)
func readType(input *bufio.Reader) (string, error) {
key, err := input.ReadString('=')
if err != nil {
return key, err
}
if len(key) != 2 {
return key, errors.Errorf("sdp: invalid syntax `%v`", key)
}
return key, nil
}
func readValue(input *bufio.Reader) (string, error) {
line, err := input.ReadString('\n')
if err != nil && err != io.EOF {
return line, err
}
if len(line) == 0 {
return line, nil
}
if line[len(line)-1] == '\n' {
drop := 1
if len(line) > 1 && line[len(line)-2] == '\r' {
drop = 2
}
line = line[:len(line)-drop]
}
return line, nil
}
func indexOf(element string, data []string) int {
for k, v := range data {
if element == v {
return k
}
}
return -1
}
func keyValueBuild(key string, value *string) string {
if value != nil {
return key + *value + "\r\n"
}
return ""
}