-
Notifications
You must be signed in to change notification settings - Fork 61
/
Copy pathmedia_description.go
132 lines (107 loc) · 2.88 KB
/
media_description.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
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
package sdp
import (
"strconv"
)
// MediaDescription represents a media type.
// https://tools.ietf.org/html/rfc4566#section-5.14
type MediaDescription struct {
// m=<media> <port>/<number of ports> <proto> <fmt> ...
// https://tools.ietf.org/html/rfc4566#section-5.14
MediaName MediaName
// i=<session description>
// https://tools.ietf.org/html/rfc4566#section-5.4
MediaTitle *Information
// c=<nettype> <addrtype> <connection-address>
// https://tools.ietf.org/html/rfc4566#section-5.7
ConnectionInformation *ConnectionInformation
// b=<bwtype>:<bandwidth>
// https://tools.ietf.org/html/rfc4566#section-5.8
Bandwidth []Bandwidth
// k=<method>
// k=<method>:<encryption key>
// https://tools.ietf.org/html/rfc4566#section-5.12
EncryptionKey *EncryptionKey
// a=<attribute>
// a=<attribute>:<value>
// https://tools.ietf.org/html/rfc4566#section-5.13
Attributes []Attribute
}
// Attribute returns the value of an attribute and if it exists.
func (d *MediaDescription) Attribute(key string) (string, bool) {
for _, a := range d.Attributes {
if a.Key == key {
return a.Value, true
}
}
return "", false
}
// RangedPort supports special format for the media field "m=" port value. If
// it may be necessary to specify multiple transport ports, the protocol allows
// to write it as: <port>/<number of ports> where number of ports is a an
// offsetting range.
type RangedPort struct {
Value int
Range *int
}
func (p *RangedPort) String() string {
output := strconv.Itoa(p.Value)
if p.Range != nil {
output += "/" + strconv.Itoa(*p.Range)
}
return output
}
func (p RangedPort) marshalInto(b []byte) []byte {
b = strconv.AppendInt(b, int64(p.Value), 10)
if p.Range != nil {
b = append(b, '/')
b = strconv.AppendInt(b, int64(*p.Range), 10)
}
return b
}
func (p RangedPort) marshalSize() (size int) {
size = lenInt(int64(p.Value))
if p.Range != nil {
size += 1 + lenInt(int64(*p.Range))
}
return
}
// MediaName describes the "m=" field storage structure.
type MediaName struct {
Media string
Port RangedPort
Protos []string
Formats []string
}
func (m MediaName) String() string {
return stringFromMarshal(m.marshalInto, m.marshalSize)
}
func (m MediaName) marshalInto(b []byte) []byte {
appendList := func(list []string, sep byte) {
for i, p := range list {
if i != 0 && i != len(list) {
b = append(b, sep)
}
b = append(b, p...)
}
}
b = append(append(b, m.Media...), ' ')
b = append(m.Port.marshalInto(b), ' ')
appendList(m.Protos, '/')
b = append(b, ' ')
appendList(m.Formats, ' ')
return b
}
func (m MediaName) marshalSize() (size int) {
listSize := func(list []string) {
for _, p := range list {
size += 1 + len(p)
}
}
size = len(m.Media)
size += 1 + m.Port.marshalSize()
listSize(m.Protos)
listSize(m.Formats)
return size
}