123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- package aac
- import (
- "encoding/hex"
- "github.com/AlexxIT/go2rtc/pkg/bits"
- "github.com/AlexxIT/go2rtc/pkg/core"
- "github.com/pion/rtp"
- )
- func IsADTS(b []byte) bool {
- return len(b) > 7 && b[0] == 0xFF && b[1]&0xF6 == 0xF0
- }
- func ADTSToCodec(b []byte) *core.Codec {
- // 1. Check ADTS header
- if !IsADTS(b) {
- return nil
- }
- // 2. Decode ADTS params
- // https://wiki.multimedia.cx/index.php/ADTS
- rd := bits.NewReader(b)
- _ = rd.ReadBits(12) // Syncword, all bits must be set to 1
- _ = rd.ReadBit() // MPEG Version, set to 0 for MPEG-4 and 1 for MPEG-2
- _ = rd.ReadBits(2) // Layer, always set to 0
- _ = rd.ReadBit() // Protection absence, set to 1 if there is no CRC and 0 if there is CRC
- objType := rd.ReadBits8(2) + 1 // Profile, the MPEG-4 Audio Object Type minus 1
- sampleRateIdx := rd.ReadBits8(4) // MPEG-4 Sampling Frequency Index
- _ = rd.ReadBit() // Private bit, guaranteed never to be used by MPEG, set to 0 when encoding, ignore when decoding
- channels := rd.ReadBits16(3) // MPEG-4 Channel Configuration
- //_ = rd.ReadBit() // Originality, set to 1 to signal originality of the audio and 0 otherwise
- //_ = rd.ReadBit() // Home, set to 1 to signal home usage of the audio and 0 otherwise
- //_ = rd.ReadBit() // Copyright ID bit
- //_ = rd.ReadBit() // Copyright ID start
- //_ = rd.ReadBits(13) // Frame length
- //_ = rd.ReadBits(11) // Buffer fullness
- //_ = rd.ReadBits(2) // Number of AAC frames (Raw Data Blocks) in ADTS frame minus 1
- //_ = rd.ReadBits(16) // CRC check
- // 3. Encode RTP config
- wr := bits.NewWriter(nil)
- wr.WriteBits8(objType, 5)
- wr.WriteBits8(sampleRateIdx, 4)
- wr.WriteBits16(channels, 4)
- conf := wr.Bytes()
- codec := &core.Codec{
- Name: core.CodecAAC,
- ClockRate: sampleRates[sampleRateIdx],
- Channels: channels,
- FmtpLine: FMTP + hex.EncodeToString(conf),
- }
- return codec
- }
- func ReadADTSSize(b []byte) uint16 {
- // AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM MMMMMMMM MMMOOOOO OOOOOOPP (QQQQQQQQ QQQQQQQQ)
- _ = b[5] // bounds
- return uint16(b[3]&0x03)<<(8+3) | uint16(b[4])<<3 | uint16(b[5]>>5)
- }
- func WriteADTSSize(b []byte, size uint16) {
- // AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM MMMMMMMM MMMOOOOO OOOOOOPP (QQQQQQQQ QQQQQQQQ)
- _ = b[5] // bounds
- b[3] |= byte(size >> (8 + 3))
- b[4] = byte(size >> 3)
- b[5] |= byte(size << 5)
- return
- }
- func ADTSTimeSize(b []byte) uint32 {
- var units uint32
- for len(b) > ADTSHeaderSize {
- auSize := ReadADTSSize(b)
- b = b[auSize:]
- units++
- }
- return units * AUTime
- }
- func CodecToADTS(codec *core.Codec) []byte {
- s := core.Between(codec.FmtpLine, "config=", ";")
- conf, err := hex.DecodeString(s)
- if err != nil {
- return nil
- }
- objType, sampleFreqIdx, channels, _ := DecodeConfig(conf)
- profile := objType - 1
- wr := bits.NewWriter(nil)
- wr.WriteAllBits(1, 12) // Syncword, all bits must be set to 1
- wr.WriteBit(0) // MPEG Version, set to 0 for MPEG-4 and 1 for MPEG-2
- wr.WriteBits8(0, 2) // Layer, always set to 0
- wr.WriteBit(1) // Protection absence, set to 1 if there is no CRC and 0 if there is CRC
- wr.WriteBits8(profile, 2) // Profile, the MPEG-4 Audio Object Type minus 1
- wr.WriteBits8(sampleFreqIdx, 4) // MPEG-4 Sampling Frequency Index
- wr.WriteBit(0) // Private bit, guaranteed never to be used by MPEG, set to 0 when encoding, ignore when decoding
- wr.WriteBits8(channels, 3) // MPEG-4 Channel Configuration
- wr.WriteBit(0) // Originality, set to 1 to signal originality of the audio and 0 otherwise
- wr.WriteBit(0) // Home, set to 1 to signal home usage of the audio and 0 otherwise
- wr.WriteBit(0) // Copyright ID bit
- wr.WriteBit(0) // Copyright ID start
- wr.WriteBits16(0, 13) // Frame length
- wr.WriteAllBits(1, 11) // Buffer fullness (variable bitrate)
- wr.WriteBits8(0, 2) // Number of AAC frames (Raw Data Blocks) in ADTS frame minus 1
- return wr.Bytes()
- }
- func EncodeToADTS(codec *core.Codec, handler core.HandlerFunc) core.HandlerFunc {
- adts := CodecToADTS(codec)
- return func(packet *rtp.Packet) {
- if !IsADTS(packet.Payload) {
- b := make([]byte, ADTSHeaderSize+len(packet.Payload))
- copy(b, adts)
- copy(b[ADTSHeaderSize:], packet.Payload)
- WriteADTSSize(b, uint16(len(b)))
- clone := *packet
- clone.Payload = b
- handler(&clone)
- } else {
- handler(packet)
- }
- }
- }
|