forked from AlexxIT/go2rtc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaac.go
126 lines (102 loc) · 2.87 KB
/
aac.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
package aac
import (
"encoding/hex"
"fmt"
"github.com/AlexxIT/go2rtc/pkg/bits"
"github.com/AlexxIT/go2rtc/pkg/core"
)
const (
TypeAACMain = 1
TypeAACLC = 2 // Low Complexity
TypeAACLD = 23 // Low Delay (48000, 44100, 32000, 24000, 22050)
TypeESCAPE = 31
TypeAACELD = 39 // Enhanced Low Delay
AUTime = 1024
// FMTP streamtype=5 - audio stream
FMTP = "streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config="
)
var sampleRates = [16]uint32{
96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350,
0, 0, 0, // protection from request sampleRates[15]
}
func ConfigToCodec(conf []byte) *core.Codec {
// https://en.wikipedia.org/wiki/MPEG-4_Part_3#MPEG-4_Audio_Object_Types
rd := bits.NewReader(conf)
codec := &core.Codec{
FmtpLine: FMTP + hex.EncodeToString(conf),
PayloadType: core.PayloadTypeRAW,
}
objType := rd.ReadBits(5)
if objType == TypeESCAPE {
objType = 32 + rd.ReadBits(6)
}
switch objType {
case TypeAACLC, TypeAACLD, TypeAACELD:
codec.Name = core.CodecAAC
default:
codec.Name = fmt.Sprintf("AAC-%X", objType)
}
if sampleRateIdx := rd.ReadBits8(4); sampleRateIdx < 0x0F {
codec.ClockRate = sampleRates[sampleRateIdx]
} else {
codec.ClockRate = rd.ReadBits(24)
}
codec.Channels = rd.ReadBits16(4)
return codec
}
func DecodeConfig(b []byte) (objType, sampleFreqIdx, channels byte, sampleRate uint32) {
rd := bits.NewReader(b)
objType = rd.ReadBits8(5)
if objType == 0b11111 {
objType = 32 + rd.ReadBits8(6)
}
sampleFreqIdx = rd.ReadBits8(4)
if sampleFreqIdx == 0b1111 {
sampleRate = rd.ReadBits(24)
} else {
sampleRate = sampleRates[sampleFreqIdx]
}
channels = rd.ReadBits8(4)
return
}
func EncodeConfig(objType byte, sampleRate uint32, channels byte, shortFrame bool) []byte {
wr := bits.NewWriter(nil)
if objType < TypeESCAPE {
wr.WriteBits8(objType, 5)
} else {
wr.WriteBits8(TypeESCAPE, 5)
wr.WriteBits8(objType-32, 6)
}
i := indexUint32(sampleRates[:], sampleRate)
if i >= 0 {
wr.WriteBits8(byte(i), 4)
} else {
wr.WriteBits8(0xF, 4)
wr.WriteBits(sampleRate, 24)
}
wr.WriteBits8(channels, 4)
switch objType {
case TypeAACLD:
// https://github.com/FFmpeg/FFmpeg/blob/67d392b97941bb51fb7af3a3c9387f5ab895fa46/libavcodec/aacdec_template.c#L841
wr.WriteBool(shortFrame)
wr.WriteBit(0) // dependsOnCoreCoder
wr.WriteBit(0) // extension_flag
wr.WriteBits8(0, 2) // ep_config
case TypeAACELD:
// https://github.com/FFmpeg/FFmpeg/blob/67d392b97941bb51fb7af3a3c9387f5ab895fa46/libavcodec/aacdec_template.c#L922
wr.WriteBool(shortFrame)
wr.WriteBits8(0, 3) // res_flags
wr.WriteBit(0) // ldSbrPresentFlag
wr.WriteBits8(0, 4) // ELDEXT_TERM
wr.WriteBits8(0, 2) // ep_config
}
return wr.Bytes()
}
func indexUint32(s []uint32, v uint32) int {
for i := range s {
if v == s[i] {
return i
}
}
return -1
}