github.com/cnotch/ipchub@v1.1.0/av/codec/aac/asc.go (about) 1 // Copyright (c) 2019,CAOHONGJU All rights reserved. 2 // Use of this source code is governed by a MIT-style 3 // license that can be found in the LICENSE file. 4 // 5 // Translate from FFmpeg mpeg4audio.h mpeg4audio.c 6 // 7 package aac 8 9 import ( 10 "encoding/binary" 11 "encoding/hex" 12 "errors" 13 "fmt" 14 "runtime/debug" 15 16 "github.com/cnotch/ipchub/utils/bits" 17 ) 18 19 // RawSps AudioSpecificConfig 的别名 20 type RawSPS = AudioSpecificConfig 21 22 // AudioSpecificConfig . 23 type AudioSpecificConfig struct { 24 ObjectType uint8 25 SamplingIndex uint8 26 SampleRate int 27 ChannelConfig uint8 28 Sbr int ///< -1 implicit, 1 presence 29 ExtObjectType uint8 30 ExtSamplingIndex uint8 31 ExtSampleRate int 32 ExtChannelConfig uint8 33 Channels uint8 34 Ps int ///< -1 implicit, 1 presence 35 FrameLengthShort int 36 } 37 38 // DecodeString 从 hex 字串解码 sps 39 func (asc *AudioSpecificConfig) DecodeString(config string) error { 40 data, err := hex.DecodeString(config) 41 if err != nil { 42 return err 43 } 44 return asc.Decode(data) 45 } 46 47 // Decode 从字节序列中解码 sps 48 func (asc *AudioSpecificConfig) Decode(config []byte) (err error) { 49 defer func() { 50 if r := recover(); r != nil { 51 err = fmt.Errorf("AudioSpecificConfig decode panic;r = %v \n %s", r, debug.Stack()) 52 } 53 }() 54 55 r := bits.NewReader(config) 56 57 asc.ObjectType = getObjectType(r) 58 asc.SamplingIndex, asc.SampleRate = getSampleRate(r) 59 asc.ChannelConfig = r.ReadUint8(4) 60 if int(asc.ChannelConfig) < len(aacAudioChannels) { 61 asc.Channels = aacAudioChannels[asc.ChannelConfig] 62 } 63 asc.Sbr = -1 64 asc.Ps = -1 65 if asc.ObjectType == AOT_SBR || (asc.ObjectType == AOT_PS && 66 0 == r.Peek(3)&0x03 && 0 == r.Peek(9)&0x3F) { // check for W6132 Annex YYYY draft MP3onMP4 67 if asc.ObjectType == AOT_PS { 68 asc.Ps = 1 69 } 70 asc.ExtObjectType = AOT_SBR 71 asc.Sbr = 1 72 asc.ExtSamplingIndex, asc.ExtSampleRate = getSampleRate(r) 73 asc.ObjectType = getObjectType(r) 74 if asc.ObjectType == AOT_ER_BSAC { 75 asc.ExtChannelConfig = r.ReadUint8(4) 76 } 77 } else { 78 asc.ExtObjectType = AOT_NULL 79 asc.ExtSampleRate = 0 80 } 81 82 if asc.ObjectType == AOT_ALS { 83 r.Skip(5) 84 if uint32(r.Peek(24)) != binary.BigEndian.Uint32([]byte{0, 'A', 'L', 'S'}) { 85 r.Skip(24) 86 } 87 88 if err = asc.parseConfigALS(r); err != nil { 89 return 90 } 91 } 92 93 if asc.ExtObjectType != AOT_SBR { 94 for r.BitsLeft() > 15 { 95 if r.Peek(11) == 0x2b7 { // sync extension 96 r.Skip(11) 97 asc.ExtObjectType = getObjectType(r) 98 if asc.ExtObjectType == AOT_SBR { 99 asc.Sbr = int(r.ReadBit()) 100 if asc.Sbr == 1 { 101 asc.ExtSamplingIndex, asc.ExtSampleRate = getSampleRate(r) 102 if asc.ExtSampleRate == asc.SampleRate { 103 asc.Sbr = -1 104 } 105 } 106 107 } 108 if r.BitsLeft() > 11 && r.Read(11) == 0x548 { 109 asc.Ps = int(r.ReadBit()) 110 } 111 112 break 113 } else { 114 r.Skip(1) // skip 1 bit 115 } 116 } 117 } 118 119 //PS requires SBR 120 if asc.Sbr == 0 { 121 asc.Ps = 0 122 } 123 //Limit implicit PS to the HE-AACv2 Profile 124 if (asc.Ps == -1 && asc.ObjectType != AOT_AAC_LC) || (asc.Channels&^0x01) != 0 { 125 asc.Ps = 0 126 } 127 return 128 } 129 130 func (asc *AudioSpecificConfig) ToAdtsHeader(payloadSize int) ADTSHeader { 131 sampleRateIdx := asc.SamplingIndex 132 if asc.ExtSampleRate > 0 { 133 sampleRateIdx = asc.ExtSamplingIndex 134 } 135 136 return NewADTSHeader(asc.ObjectType-1, sampleRateIdx, asc.ChannelConfig, payloadSize) 137 } 138 139 func Encode2BytesASC(objType, samplingIdx, channelConfig byte) []byte { 140 var config = make([]byte, 2) 141 config[0] = objType<<3 | (samplingIdx>>1)&0x07 142 config[1] = samplingIdx<<7 | (channelConfig&0x0f)<<3 143 return config 144 } 145 146 var errInvalidData = errors.New("Invalid data found when processing input") 147 148 func (asc *AudioSpecificConfig) parseConfigALS(r *bits.Reader) (err error) { 149 if r.BitsLeft() < 112 { 150 return errInvalidData 151 } 152 153 if r.Read(32) != binary.BigEndian.Uint32([]byte{'A', 'L', 'S', 0}) { 154 return errInvalidData 155 } 156 157 // override AudioSpecificConfig channel configuration and sample rate 158 // which are buggy in old ALS conformance files 159 asc.SampleRate = r.ReadInt(32) 160 161 if asc.SampleRate <= 0 { 162 return errInvalidData 163 } 164 165 // skip number of samples 166 r.Skip(32) 167 168 // read number of channels 169 asc.ChannelConfig = 0 170 asc.Channels = uint8(r.ReadInt(16) + 1) 171 return 172 } 173 174 func getObjectType(r *bits.Reader) (objType uint8) { 175 objType = r.ReadUint8(5) 176 177 if AOT_ESCAPE == objType { 178 objType = r.ReadUint8(6) + 32 179 } 180 return 181 } 182 183 func getSampleRate(r *bits.Reader) (sampleRateIdx uint8, sampleRate int) { 184 sampleRateIdx = r.ReadUint8(4) 185 if sampleRateIdx == 0xf { 186 sampleRate = r.ReadInt(24) 187 } else { 188 sampleRate = SampleRate(int(sampleRateIdx)) 189 } 190 return 191 }