mediamtx/internal/aac/adts.go
2021-04-18 23:02:19 +02:00

192 lines
3.9 KiB
Go

package aac
import (
"fmt"
)
// ADTSPacket is an ADTS packet
type ADTSPacket struct {
SampleRate int
ChannelCount int
Frame []byte
}
// 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 {
return nil, fmt.Errorf("ADTS with CRC is not supported")
}
pkt := &ADTSPacket{}
profile := (byts[2] >> 6)
if profile != 0 {
return nil, fmt.Errorf("only AAC-LC is supported")
}
sampleRateIndex := (byts[2] >> 2) & 0x0F
switch sampleRateIndex {
case 0:
pkt.SampleRate = 96000
case 1:
pkt.SampleRate = 88200
case 2:
pkt.SampleRate = 64000
case 3:
pkt.SampleRate = 48000
case 4:
pkt.SampleRate = 44100
case 5:
pkt.SampleRate = 32000
case 6:
pkt.SampleRate = 24000
case 7:
pkt.SampleRate = 22050
case 8:
pkt.SampleRate = 16000
case 9:
pkt.SampleRate = 12000
case 10:
pkt.SampleRate = 11025
case 11:
pkt.SampleRate = 8000
case 12:
pkt.SampleRate = 7350
default:
return nil, fmt.Errorf("invalid sample rate index: %d", sampleRateIndex)
}
channelConfig := ((byts[2] & 0x01) << 2) | ((byts[3] >> 6) & 0x03)
switch channelConfig {
case 1:
pkt.ChannelCount = 1
case 2:
pkt.ChannelCount = 2
case 3:
pkt.ChannelCount = 3
case 4:
pkt.ChannelCount = 4
case 5:
pkt.ChannelCount = 5
case 6:
pkt.ChannelCount = 6
case 7:
pkt.ChannelCount = 8
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
fullness := ((uint16(byts[5]) & 0x1F) << 6) | ((uint16(byts[6]) >> 2) & 0x3F)
if fullness != 1800 {
return nil, fmt.Errorf("fullness not supported")
}
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")
}
pkt.Frame = byts[7 : 7+frameLen]
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 {
frameLen := len(pkt.Frame) + 7
fullness := 1800
var channelConf uint8
switch pkt.ChannelCount {
case 1:
channelConf = 1
case 2:
channelConf = 2
case 3:
channelConf = 3
case 4:
channelConf = 4
case 5:
channelConf = 5
case 6:
channelConf = 6
case 8:
channelConf = 7
default:
return nil, fmt.Errorf("invalid channel count: %v", pkt.ChannelCount)
}
var sampleRateIndex uint8
switch pkt.SampleRate {
case 96000:
sampleRateIndex = 0
case 88200:
sampleRateIndex = 1
case 64000:
sampleRateIndex = 2
case 48000:
sampleRateIndex = 3
case 44100:
sampleRateIndex = 4
case 32000:
sampleRateIndex = 5
case 24000:
sampleRateIndex = 6
case 22050:
sampleRateIndex = 7
case 16000:
sampleRateIndex = 8
case 12000:
sampleRateIndex = 9
case 11025:
sampleRateIndex = 10
case 8000:
sampleRateIndex = 11
case 7350:
sampleRateIndex = 12
default:
return nil, fmt.Errorf("invalid sample rate: %v", pkt.SampleRate)
}
header := make([]byte, 7)
header[0] = 0xFF
header[1] = 0xF1
header[2] = (sampleRateIndex << 2) | ((channelConf >> 2) & 0x01)
header[3] = (channelConf&0x03)<<6 | uint8((frameLen>>11)&0x03)
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...)
ret = append(ret, pkt.Frame...)
}
return ret, nil
}