golanggohlsrtmpwebrtcmedia-serverobs-studiortcprtmp-proxyrtmp-serverrtprtsprtsp-proxyrtsp-relayrtsp-serversrtstreamingwebrtc-proxy
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
3.9 KiB
191 lines
3.9 KiB
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 |
|
}
|
|
|