// Copyright 2019, Chef. All rights reserved. // https://github.com/q191201771/lal // // Use of this source code is governed by a MIT-style license // that can be found in the License file. // // Author: Chef (191201771@qq.com) package aac import ( "errors" "github.com/q191201771/naza/pkg/nazabits" "github.com/q191201771/naza/pkg/nazalog" ) // AudioSpecificConfig(asc) // keywords: Seq Header, // e.g. rtmp, flv // // ADTS(Audio Data Transport Stream) // e.g. es, ts // // StreamMuxConfig // var ErrAac = errors.New("lal.aac: fxxk") const ( AdtsHeaderLength = 7 AscSamplingFrequencyIndex48000 = 3 AscSamplingFrequencyIndex44100 = 4 ) const ( minAscLength = 2 ) // // <1.6.2.1 AudioSpecificConfig>, // <1.5.1.1 Audio Object type definition>, // <1.6.3.3 samplingFrequencyIndex>, // <1.6.3.4 channelConfiguration> // -------------------------------------------------------- // audio object type [5b] 1=AAC MAIN 2=AAC LC // samplingFrequencyIndex [4b] 3=48000 4=44100 6=24000 5=32000 11=11025 // channelConfiguration [4b] 1=center front speaker 2=left, right front speakers type AscContext struct { AudioObjectType uint8 // [5b] SamplingFrequencyIndex uint8 // [4b] ChannelConfiguration uint8 // [4b] } func NewAscContext(asc []byte) (*AscContext, error) { var ascCtx AscContext if err := ascCtx.Unpack(asc); err != nil { return nil, err } return &ascCtx, nil } // @param asc: 2字节的AAC Audio Specifc Config // 注意,如果是rtmp/flv的message/tag,应去除Seq Header头部的2个字节 // 函数调用结束后,内部不持有该内存块 // func (ascCtx *AscContext) Unpack(asc []byte) error { if len(asc) < minAscLength { nazalog.Warnf("aac seq header length invalid. len=%d", len(asc)) return ErrAac } br := nazabits.NewBitReader(asc) ascCtx.AudioObjectType, _ = br.ReadBits8(5) ascCtx.SamplingFrequencyIndex, _ = br.ReadBits8(4) ascCtx.ChannelConfiguration, _ = br.ReadBits8(4) return nil } // @return asc: 内存块为独立新申请;函数调用结束后,内部不持有该内存块 // func (ascCtx *AscContext) Pack() (asc []byte) { asc = make([]byte, minAscLength) bw := nazabits.NewBitWriter(asc) bw.WriteBits8(5, ascCtx.AudioObjectType) bw.WriteBits8(4, ascCtx.SamplingFrequencyIndex) bw.WriteBits8(4, ascCtx.ChannelConfiguration) return } // 获取ADTS头,由于ADTS头中的字段依赖包的长度,而每个包的长度可能不同,所以每个包的ADTS头都需要独立生成 // // @param frameLength: raw aac frame的大小 // 注意,如果是rtmp/flv的message/tag,应去除Seq Header头部的2个字节 // // @return h: 内存块为独立新申请;函数调用结束后,内部不持有该内存块 // func (ascCtx *AscContext) PackAdtsHeader(frameLength int) (out []byte) { out = make([]byte, AdtsHeaderLength) _ = ascCtx.PackToAdtsHeader(out, frameLength) return } // @param out: 函数调用结束后,内部不持有该内存块 // func (ascCtx *AscContext) PackToAdtsHeader(out []byte, frameLength int) error { if len(out) < AdtsHeaderLength { return ErrAac } // // <1.A.2.2.1 Fixed Header of ADTS>, // <1.A.2.2.2 Variable Header of ADTS>, // <1.A.3.2.1 Definitions: Bitstream elements for ADTS> // ---------------------------------------------------- // Syncword [12b] '1111 1111 1111' // ID [1b] 1=MPEG-2 AAC 0=MPEG-4 // Layer [2b] // protection_absent [1b] 1=no crc check // Profile_ObjectType [2b] // sampling_frequency_index [4b] // private_bit [1b] // channel_configuration [3b] // origin/copy [1b] // home [1b] // Emphasis??? // ------------------------------------ // copyright_identification_bit [1b] // copyright_identification_start [1b] // aac_frame_length [13b] // adts_buffer_fullness [11b] // no_raw_data_blocks_in_frame [2b] bw := nazabits.NewBitWriter(out) // Syncword 0(8) 1(4) bw.WriteBits16(12, 0xFFF) // ID, Layer, protection_absent 1(4) bw.WriteBits8(4, 0x1) // 2(2) bw.WriteBits8(2, ascCtx.AudioObjectType-1) // 2(4) bw.WriteBits8(4, ascCtx.SamplingFrequencyIndex) // private_bit 2(1) bw.WriteBits8(1, 0) // 2(1) 3(2) bw.WriteBits8(3, ascCtx.ChannelConfiguration) // origin/copy, home, copyright_identification_bit, copyright_identification_start 3(4) bw.WriteBits8(4, 0) // 3(2) 4(8) 5(3) bw.WriteBits16(13, uint16(frameLength+AdtsHeaderLength)) // adts_buffer_fullness 5(5) 6(6) bw.WriteBits16(11, 0x7FF) // no_raw_data_blocks_in_frame 6(2) bw.WriteBits8(2, 0) return nil } func (ascCtx *AscContext) GetSamplingFrequency() (int, error) { switch ascCtx.SamplingFrequencyIndex { case AscSamplingFrequencyIndex48000: return 48000, nil case AscSamplingFrequencyIndex44100: return 44100, nil } return -1, ErrAac } type AdtsHeaderContext struct { AscCtx AscContext AdtsLength uint16 // 字段中的值,包含了adts header + adts frame } func NewAdtsHeaderContext(adtsHeader []byte) (*AdtsHeaderContext, error) { var ctx AdtsHeaderContext if err := ctx.Unpack(adtsHeader); err != nil { return nil, err } return &ctx, nil } // @param adtsHeader: 函数调用结束后,内部不持有该内存块 // func (ctx *AdtsHeaderContext) Unpack(adtsHeader []byte) error { if len(adtsHeader) < AdtsHeaderLength { return ErrAac } br := nazabits.NewBitReader(adtsHeader) _ = br.SkipBits(16) v, _ := br.ReadBits8(2) ctx.AscCtx.AudioObjectType = v + 1 ctx.AscCtx.SamplingFrequencyIndex, _ = br.ReadBits8(4) _ = br.SkipBits(1) ctx.AscCtx.ChannelConfiguration, _ = br.ReadBits8(3) _ = br.SkipBits(4) ctx.AdtsLength, _ = br.ReadBits16(13) return nil } // @param adtsHeader: 函数调用结束后,内部不持有该内存块 // // @return asc: 内存块为独立新申请;函数调用结束后,内部不持有该内存块 // func MakeAscWithAdtsHeader(adtsHeader []byte) (asc []byte, err error) { var ctx *AdtsHeaderContext if ctx, err = NewAdtsHeaderContext(adtsHeader); err != nil { return nil, err } return ctx.AscCtx.Pack(), nil }