-
Notifications
You must be signed in to change notification settings - Fork 177
/
mpeg4_audio.go
151 lines (127 loc) · 3.5 KB
/
mpeg4_audio.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
package format
import (
"encoding/hex"
"fmt"
"strconv"
"github.com/pion/rtp"
"github.com/aler9/gortsplib/v2/pkg/codecs/mpeg4audio"
"github.com/aler9/gortsplib/v2/pkg/formatdecenc/rtpmpeg4audio"
)
// MPEG4Audio is a format that uses a MPEG-4 audio codec.
type MPEG4Audio struct {
PayloadTyp uint8
Config *mpeg4audio.Config
SizeLength int
IndexLength int
IndexDeltaLength int
}
// String implements Format.
func (t *MPEG4Audio) String() string {
return "MPEG4-audio"
}
// ClockRate implements Format.
func (t *MPEG4Audio) ClockRate() int {
return t.Config.SampleRate
}
// PayloadType implements Format.
func (t *MPEG4Audio) PayloadType() uint8 {
return t.PayloadTyp
}
func (t *MPEG4Audio) unmarshal(
payloadType uint8, clock string, codec string,
rtpmap string, fmtp map[string]string,
) error {
t.PayloadTyp = payloadType
for key, val := range fmtp {
switch key {
case "config":
enc, err := hex.DecodeString(val)
if err != nil {
return fmt.Errorf("invalid AAC config (%v)", val)
}
t.Config = &mpeg4audio.Config{}
err = t.Config.Unmarshal(enc)
if err != nil {
return fmt.Errorf("invalid AAC config (%v)", val)
}
case "sizelength":
n, err := strconv.ParseUint(val, 10, 64)
if err != nil {
return fmt.Errorf("invalid AAC SizeLength (%v)", val)
}
t.SizeLength = int(n)
case "indexlength":
n, err := strconv.ParseUint(val, 10, 64)
if err != nil {
return fmt.Errorf("invalid AAC IndexLength (%v)", val)
}
t.IndexLength = int(n)
case "indexdeltalength":
n, err := strconv.ParseUint(val, 10, 64)
if err != nil {
return fmt.Errorf("invalid AAC IndexDeltaLength (%v)", val)
}
t.IndexDeltaLength = int(n)
}
}
if t.Config == nil {
return fmt.Errorf("config is missing")
}
if t.SizeLength == 0 {
return fmt.Errorf("sizelength is missing")
}
return nil
}
// Marshal implements Format.
func (t *MPEG4Audio) Marshal() (string, map[string]string) {
enc, err := t.Config.Marshal()
if err != nil {
return "", nil
}
sampleRate := t.Config.SampleRate
if t.Config.ExtensionSampleRate != 0 {
sampleRate = t.Config.ExtensionSampleRate
}
fmtp := make(map[string]string)
fmtp["profile-level-id"] = "1"
fmtp["mode"] = "AAC-hbr"
if t.SizeLength > 0 {
fmtp["sizelength"] = strconv.FormatInt(int64(t.SizeLength), 10)
}
if t.IndexLength > 0 {
fmtp["indexlength"] = strconv.FormatInt(int64(t.IndexLength), 10)
}
if t.IndexDeltaLength > 0 {
fmtp["indexdeltalength"] = strconv.FormatInt(int64(t.IndexDeltaLength), 10)
}
fmtp["config"] = hex.EncodeToString(enc)
return "mpeg4-generic/" + strconv.FormatInt(int64(sampleRate), 10) +
"/" + strconv.FormatInt(int64(t.Config.ChannelCount), 10), fmtp
}
// PTSEqualsDTS implements Format.
func (t *MPEG4Audio) PTSEqualsDTS(*rtp.Packet) bool {
return true
}
// CreateDecoder creates a decoder able to decode the content of the format.
func (t *MPEG4Audio) CreateDecoder() *rtpmpeg4audio.Decoder {
d := &rtpmpeg4audio.Decoder{
SampleRate: t.Config.SampleRate,
SizeLength: t.SizeLength,
IndexLength: t.IndexLength,
IndexDeltaLength: t.IndexDeltaLength,
}
d.Init()
return d
}
// CreateEncoder creates an encoder able to encode the content of the format.
func (t *MPEG4Audio) CreateEncoder() *rtpmpeg4audio.Encoder {
e := &rtpmpeg4audio.Encoder{
PayloadType: t.PayloadTyp,
SampleRate: t.Config.SampleRate,
SizeLength: t.SizeLength,
IndexLength: t.IndexLength,
IndexDeltaLength: t.IndexDeltaLength,
}
e.Init()
return e
}