github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/mpeg4audio/audio_specific_config.go (about) 1 package mpeg4audio 2 3 import ( 4 "fmt" 5 6 "github.com/bluenviron/mediacommon/pkg/bits" 7 ) 8 9 // Config is an alias for AudioSpecificConfig. 10 type Config = AudioSpecificConfig 11 12 // AudioSpecificConfig is an AudioSpecificConfig. 13 // Specification: ISO 14496-3, 1.6.2.1 14 type AudioSpecificConfig struct { 15 Type ObjectType 16 SampleRate int 17 ChannelCount int 18 19 // SBR / PS specific 20 ExtensionType ObjectType 21 ExtensionSampleRate int 22 23 FrameLengthFlag bool 24 DependsOnCoreCoder bool 25 CoreCoderDelay uint16 26 } 27 28 // Unmarshal decodes a Config. 29 func (c *AudioSpecificConfig) Unmarshal(buf []byte) error { 30 pos := 0 31 return c.UnmarshalFromPos(buf, &pos) 32 } 33 34 // UnmarshalFromPos decodes a Config. 35 func (c *AudioSpecificConfig) UnmarshalFromPos(buf []byte, pos *int) error { 36 tmp, err := bits.ReadBits(buf, pos, 5) 37 if err != nil { 38 return err 39 } 40 c.Type = ObjectType(tmp) 41 42 switch c.Type { 43 case ObjectTypeAACLC, ObjectTypeSBR, ObjectTypePS: 44 default: 45 return fmt.Errorf("unsupported object type: %d", c.Type) 46 } 47 48 sampleRateIndex, err := bits.ReadBits(buf, pos, 4) 49 if err != nil { 50 return err 51 } 52 53 switch { 54 case sampleRateIndex <= 12: 55 c.SampleRate = sampleRates[sampleRateIndex] 56 57 case sampleRateIndex == 0x0F: 58 tmp, err := bits.ReadBits(buf, pos, 24) 59 if err != nil { 60 return err 61 } 62 c.SampleRate = int(tmp) 63 64 default: 65 return fmt.Errorf("invalid sample rate index (%d)", sampleRateIndex) 66 } 67 68 channelConfig, err := bits.ReadBits(buf, pos, 4) 69 if err != nil { 70 return err 71 } 72 73 switch { 74 case channelConfig == 0: 75 return fmt.Errorf("not yet supported") 76 77 case channelConfig >= 1 && channelConfig <= 6: 78 c.ChannelCount = int(channelConfig) 79 80 case channelConfig == 7: 81 c.ChannelCount = 8 82 83 default: 84 return fmt.Errorf("invalid channel configuration (%d)", channelConfig) 85 } 86 87 if c.Type == ObjectTypeSBR || c.Type == ObjectTypePS { 88 c.ExtensionType = c.Type 89 90 extensionSamplingFrequencyIndex, err := bits.ReadBits(buf, pos, 4) 91 if err != nil { 92 return err 93 } 94 95 switch { 96 case extensionSamplingFrequencyIndex <= 12: 97 c.ExtensionSampleRate = sampleRates[extensionSamplingFrequencyIndex] 98 99 case extensionSamplingFrequencyIndex == 0x0F: 100 tmp, err := bits.ReadBits(buf, pos, 24) 101 if err != nil { 102 return err 103 } 104 c.ExtensionSampleRate = int(tmp) 105 106 default: 107 return fmt.Errorf("invalid extension sample rate index (%d)", extensionSamplingFrequencyIndex) 108 } 109 110 tmp, err = bits.ReadBits(buf, pos, 5) 111 if err != nil { 112 return err 113 } 114 c.Type = ObjectType(tmp) 115 116 if c.Type != ObjectTypeAACLC { 117 return fmt.Errorf("unsupported object type: %d", c.Type) 118 } 119 } 120 121 c.FrameLengthFlag, err = bits.ReadFlag(buf, pos) 122 if err != nil { 123 return err 124 } 125 126 c.DependsOnCoreCoder, err = bits.ReadFlag(buf, pos) 127 if err != nil { 128 return err 129 } 130 131 if c.DependsOnCoreCoder { 132 tmp, err := bits.ReadBits(buf, pos, 14) 133 if err != nil { 134 return err 135 } 136 c.CoreCoderDelay = uint16(tmp) 137 } 138 139 extensionFlag, err := bits.ReadFlag(buf, pos) 140 if err != nil { 141 return err 142 } 143 144 if extensionFlag { 145 return fmt.Errorf("unsupported") 146 } 147 148 return nil 149 } 150 151 func (c AudioSpecificConfig) marshalSizeBits() int { 152 n := 5 + 4 + 2 + 1 153 154 _, ok := reverseSampleRates[c.SampleRate] 155 if !ok { 156 n += 28 157 } else { 158 n += 4 159 } 160 161 if c.ExtensionType == ObjectTypeSBR || c.ExtensionType == ObjectTypePS { 162 _, ok := reverseSampleRates[c.ExtensionSampleRate] 163 if !ok { 164 n += 28 165 } else { 166 n += 4 167 } 168 n += 5 169 } 170 171 if c.DependsOnCoreCoder { 172 n += 14 173 } 174 175 return n 176 } 177 178 func (c AudioSpecificConfig) marshalSize() int { 179 n := c.marshalSizeBits() 180 181 ret := n / 8 182 if (n % 8) != 0 { 183 ret++ 184 } 185 186 return ret 187 } 188 189 // Marshal encodes a Config. 190 func (c AudioSpecificConfig) Marshal() ([]byte, error) { 191 buf := make([]byte, c.marshalSize()) 192 pos := 0 193 194 err := c.marshalTo(buf, &pos) 195 if err != nil { 196 return nil, err 197 } 198 199 return buf, nil 200 } 201 202 func (c AudioSpecificConfig) marshalTo(buf []byte, pos *int) error { 203 if c.ExtensionType == ObjectTypeSBR || c.ExtensionType == ObjectTypePS { 204 bits.WriteBits(buf, pos, uint64(c.ExtensionType), 5) 205 } else { 206 bits.WriteBits(buf, pos, uint64(c.Type), 5) 207 } 208 209 sampleRateIndex, ok := reverseSampleRates[c.SampleRate] 210 if !ok { 211 bits.WriteBits(buf, pos, uint64(15), 4) 212 bits.WriteBits(buf, pos, uint64(c.SampleRate), 24) 213 } else { 214 bits.WriteBits(buf, pos, uint64(sampleRateIndex), 4) 215 } 216 217 var channelConfig int 218 switch { 219 case c.ChannelCount >= 1 && c.ChannelCount <= 6: 220 channelConfig = c.ChannelCount 221 222 case c.ChannelCount == 8: 223 channelConfig = 7 224 225 default: 226 return fmt.Errorf("invalid channel count (%d)", c.ChannelCount) 227 } 228 bits.WriteBits(buf, pos, uint64(channelConfig), 4) 229 230 if c.ExtensionType == ObjectTypeSBR || c.ExtensionType == ObjectTypePS { 231 sampleRateIndex, ok := reverseSampleRates[c.ExtensionSampleRate] 232 if !ok { 233 bits.WriteBits(buf, pos, uint64(0x0F), 4) 234 bits.WriteBits(buf, pos, uint64(c.ExtensionSampleRate), 24) 235 } else { 236 bits.WriteBits(buf, pos, uint64(sampleRateIndex), 4) 237 } 238 bits.WriteBits(buf, pos, uint64(c.Type), 5) 239 } 240 241 if c.FrameLengthFlag { 242 bits.WriteBits(buf, pos, 1, 1) 243 } else { 244 bits.WriteBits(buf, pos, 0, 1) 245 } 246 247 if c.DependsOnCoreCoder { 248 bits.WriteBits(buf, pos, 1, 1) 249 } else { 250 bits.WriteBits(buf, pos, 0, 1) 251 } 252 253 if c.DependsOnCoreCoder { 254 bits.WriteBits(buf, pos, uint64(c.CoreCoderDelay), 14) 255 } 256 257 *pos++ // extensionFlag 258 259 return nil 260 }