File: media_description.go

package info (click to toggle)
golang-github-pion-sdp 3.0.10-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, sid, trixie
  • size: 304 kB
  • sloc: makefile: 2
file content (132 lines) | stat: -rw-r--r-- 2,950 bytes parent folder | download
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
}