mediamtx/internal/aac/adts.go

167 lines
3.2 KiB
Go
Raw Normal View History

2021-04-11 17:05:08 +00:00
package aac
import (
"fmt"
)
2021-09-05 15:35:04 +00:00
const (
mpegAudioTypeAACLLC = 2
)
var sampleRates = []int{
96000,
88200,
64000,
48000,
44100,
32000,
24000,
22050,
16000,
12000,
11025,
8000,
7350,
}
var channelCounts = []int{
1,
2,
3,
4,
5,
6,
8,
}
2021-04-11 17:05:08 +00:00
// ADTSPacket is an ADTS packet
type ADTSPacket struct {
2021-09-05 15:35:04 +00:00
Type int
2021-04-11 17:05:08 +00:00
SampleRate int
ChannelCount int
2021-09-05 15:35:04 +00:00
AU []byte
2021-04-11 17:05:08 +00:00
}
// DecodeADTS decodes an ADTS stream into ADTS packets.
func DecodeADTS(byts []byte) ([]*ADTSPacket, error) {
// refs: https://wiki.multimedia.cx/index.php/ADTS
var ret []*ADTSPacket
for len(byts) > 0 {
syncWord := (uint16(byts[0]) << 4) | (uint16(byts[1]) >> 4)
if syncWord != 0xfff {
return nil, fmt.Errorf("invalid syncword")
}
protectionAbsent := byts[1] & 0x01
if protectionAbsent != 1 {
2021-09-05 15:35:04 +00:00
return nil, fmt.Errorf("CRC is not supported")
2021-04-11 17:05:08 +00:00
}
pkt := &ADTSPacket{}
2021-09-05 15:35:04 +00:00
pkt.Type = int((byts[2] >> 6) + 1)
switch pkt.Type {
case mpegAudioTypeAACLLC:
default:
return nil, fmt.Errorf("unsupported object type: %d", pkt.Type)
2021-04-11 17:05:08 +00:00
}
sampleRateIndex := (byts[2] >> 2) & 0x0F
2021-09-05 15:35:04 +00:00
switch {
case sampleRateIndex <= 12:
pkt.SampleRate = sampleRates[sampleRateIndex]
2021-04-11 17:05:08 +00:00
default:
return nil, fmt.Errorf("invalid sample rate index: %d", sampleRateIndex)
}
channelConfig := ((byts[2] & 0x01) << 2) | ((byts[3] >> 6) & 0x03)
2021-09-05 15:35:04 +00:00
switch {
case channelConfig >= 1 && channelConfig <= 7:
pkt.ChannelCount = channelCounts[channelConfig-1]
2021-04-11 17:05:08 +00:00
default:
return nil, fmt.Errorf("invalid channel configuration: %d", channelConfig)
}
frameLen := int(((uint16(byts[3])&0x03)<<11)|
(uint16(byts[4])<<3)|
((uint16(byts[5])>>5)&0x07)) - 7
2021-09-05 15:35:04 +00:00
// fullness := ((uint16(byts[5]) & 0x1F) << 6) | ((uint16(byts[6]) >> 2) & 0x3F)
2021-04-11 17:05:08 +00:00
frameCount := byts[6] & 0x03
if frameCount != 0 {
return nil, fmt.Errorf("multiple frame count not supported")
}
if len(byts[7:]) < frameLen {
return nil, fmt.Errorf("invalid frame length")
}
2021-09-05 15:35:04 +00:00
pkt.AU = byts[7 : 7+frameLen]
2021-04-11 17:05:08 +00:00
byts = byts[7+frameLen:]
ret = append(ret, pkt)
}
return ret, nil
}
// EncodeADTS encodes ADTS packets into an ADTS stream.
func EncodeADTS(pkts []*ADTSPacket) ([]byte, error) {
var ret []byte
for _, pkt := range pkts {
2021-09-05 15:35:04 +00:00
sampleRateIndex := func() int {
for i, s := range sampleRates {
if s == pkt.SampleRate {
return i
}
}
return -1
}()
if sampleRateIndex == -1 {
return nil, fmt.Errorf("invalid sample rate: %d", pkt.SampleRate)
2021-04-11 17:05:08 +00:00
}
2021-09-05 15:35:04 +00:00
channelConfig := func() int {
for i, co := range channelCounts {
if co == pkt.ChannelCount {
return i + 1
}
}
return -1
}()
if channelConfig == -1 {
return nil, fmt.Errorf("invalid channel count: %d", pkt.ChannelCount)
2021-04-11 17:05:08 +00:00
}
2021-09-05 15:35:04 +00:00
frameLen := len(pkt.AU) + 7
fullness := 0x07FF // like ffmpeg does
2021-04-11 17:05:08 +00:00
header := make([]byte, 7)
header[0] = 0xFF
header[1] = 0xF1
2021-09-05 15:35:04 +00:00
header[2] = uint8(((pkt.Type - 1) << 6) | (sampleRateIndex << 2) | ((channelConfig >> 2) & 0x01))
header[3] = uint8((channelConfig&0x03)<<6 | (frameLen>>11)&0x03)
2021-04-11 17:05:08 +00:00
header[4] = uint8((frameLen >> 3) & 0xFF)
header[5] = uint8((frameLen&0x07)<<5 | ((fullness >> 6) & 0x1F))
header[6] = uint8((fullness & 0x3F) << 2)
ret = append(ret, header...)
2021-09-05 15:35:04 +00:00
ret = append(ret, pkt.AU...)
2021-04-11 17:05:08 +00:00
}
return ret, nil
}