github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/mpeg4audio/stream_mux_config.go (about) 1 package mpeg4audio 2 3 import ( 4 "fmt" 5 6 "github.com/bluenviron/mediacommon/pkg/bits" 7 ) 8 9 // StreamMuxConfigLayer is a layer of a StreamMuxConfig. 10 type StreamMuxConfigLayer struct { 11 AudioSpecificConfig *AudioSpecificConfig 12 FrameLengthType uint 13 LatmBufferFullness uint 14 FrameLength uint 15 CELPframeLengthTableIndex uint 16 HVXCframeLengthTableIndex bool 17 } 18 19 // StreamMuxConfigProgram is a program of a StreamMuxConfig. 20 type StreamMuxConfigProgram struct { 21 Layers []*StreamMuxConfigLayer 22 } 23 24 // StreamMuxConfig is a StreamMuxConfig. 25 // Specification: ISO 14496-3, Table 1.42 26 type StreamMuxConfig struct { 27 NumSubFrames uint 28 Programs []*StreamMuxConfigProgram 29 OtherDataPresent bool 30 OtherDataLenBits uint32 31 CRCCheckPresent bool 32 CRCCheckSum uint8 33 } 34 35 // Unmarshal decodes a StreamMuxConfig. 36 func (c *StreamMuxConfig) Unmarshal(buf []byte) error { 37 pos := 0 38 39 err := bits.HasSpace(buf, pos, 12) 40 if err != nil { 41 return err 42 } 43 44 audioMuxVersion := bits.ReadFlagUnsafe(buf, &pos) 45 if audioMuxVersion { 46 return fmt.Errorf("audioMuxVersion = 1 is not supported") 47 } 48 49 allStreamsSameTimeFraming := bits.ReadFlagUnsafe(buf, &pos) 50 if !allStreamsSameTimeFraming { 51 return fmt.Errorf("allStreamsSameTimeFraming = 0 is not supported") 52 } 53 54 c.NumSubFrames = uint(bits.ReadBitsUnsafe(buf, &pos, 6)) 55 numProgram := uint(bits.ReadBitsUnsafe(buf, &pos, 4)) 56 57 c.Programs = make([]*StreamMuxConfigProgram, numProgram+1) 58 59 for prog := uint(0); prog <= numProgram; prog++ { 60 p := &StreamMuxConfigProgram{} 61 c.Programs[prog] = p 62 63 numLayer, err := bits.ReadBits(buf, &pos, 3) 64 if err != nil { 65 return err 66 } 67 68 p.Layers = make([]*StreamMuxConfigLayer, numLayer+1) 69 70 for lay := uint(0); lay <= uint(numLayer); lay++ { 71 l := &StreamMuxConfigLayer{} 72 p.Layers[lay] = l 73 74 var useSameConfig bool 75 76 if prog == 0 && lay == 0 { 77 useSameConfig = false 78 } else { 79 var err error 80 useSameConfig, err = bits.ReadFlag(buf, &pos) 81 if err != nil { 82 return err 83 } 84 } 85 86 if !useSameConfig { 87 l.AudioSpecificConfig = &AudioSpecificConfig{} 88 err := l.AudioSpecificConfig.UnmarshalFromPos(buf, &pos) 89 if err != nil { 90 return err 91 } 92 } 93 94 tmp, err := bits.ReadBits(buf, &pos, 3) 95 if err != nil { 96 // support truncated configs 97 l.LatmBufferFullness = 255 98 return nil //nolint:nilerr 99 } 100 l.FrameLengthType = uint(tmp) 101 102 switch l.FrameLengthType { 103 case 0: 104 tmp, err := bits.ReadBits(buf, &pos, 8) 105 if err != nil { 106 return err 107 } 108 l.LatmBufferFullness = uint(tmp) 109 110 case 1: 111 tmp, err := bits.ReadBits(buf, &pos, 9) 112 if err != nil { 113 return err 114 } 115 l.FrameLength = uint(tmp) 116 117 case 4, 5, 3: 118 tmp, err := bits.ReadBits(buf, &pos, 6) 119 if err != nil { 120 return err 121 } 122 l.CELPframeLengthTableIndex = uint(tmp) 123 124 case 6, 7: 125 var err error 126 l.HVXCframeLengthTableIndex, err = bits.ReadFlag(buf, &pos) 127 if err != nil { 128 return err 129 } 130 } 131 } 132 } 133 134 c.OtherDataPresent, err = bits.ReadFlag(buf, &pos) 135 if err != nil { 136 return err 137 } 138 139 if c.OtherDataPresent { 140 for { 141 c.OtherDataLenBits *= 256 142 143 err := bits.HasSpace(buf, pos, 9) 144 if err != nil { 145 return err 146 } 147 148 otherDataLenEsc := bits.ReadFlagUnsafe(buf, &pos) 149 otherDataLenTmp := uint32(bits.ReadBitsUnsafe(buf, &pos, 8)) 150 c.OtherDataLenBits += otherDataLenTmp 151 152 if !otherDataLenEsc { 153 break 154 } 155 } 156 } 157 158 c.CRCCheckPresent, err = bits.ReadFlag(buf, &pos) 159 if err != nil { 160 return err 161 } 162 163 if c.CRCCheckPresent { 164 tmp, err := bits.ReadBits(buf, &pos, 8) 165 if err != nil { 166 return err 167 } 168 c.CRCCheckSum = uint8(tmp) 169 } 170 171 return nil 172 } 173 174 func (c StreamMuxConfig) marshalSize() int { 175 n := 12 176 177 for prog, p := range c.Programs { 178 n += 3 179 180 for lay, l := range p.Layers { 181 if prog != 0 || lay != 0 { 182 n++ 183 } 184 185 if l.AudioSpecificConfig != nil { 186 n += l.AudioSpecificConfig.marshalSizeBits() 187 } 188 189 n += 3 190 191 switch l.FrameLengthType { 192 case 0: 193 n += 8 194 195 case 1: 196 n += 9 197 198 case 4, 5, 3: 199 n += 6 200 201 case 6, 7: 202 n++ 203 } 204 } 205 } 206 207 n++ // otherDataPresent 208 209 if c.OtherDataPresent { 210 tmp := c.OtherDataLenBits 211 for { 212 tmp /= 256 213 n += 9 214 215 if tmp == 0 { 216 break 217 } 218 } 219 } 220 221 n++ // crcCheckPresent 222 223 if c.CRCCheckPresent { 224 n += 8 225 } 226 227 ret := n / 8 228 if (n % 8) != 0 { 229 ret++ 230 } 231 232 return ret 233 } 234 235 // Marshal encodes a StreamMuxConfig. 236 func (c StreamMuxConfig) Marshal() ([]byte, error) { 237 buf := make([]byte, c.marshalSize()) 238 pos := 0 239 240 bits.WriteBits(buf, &pos, 0, 1) // audioMuxVersion 241 bits.WriteBits(buf, &pos, 1, 1) // allStreamsSameTimeFraming 242 bits.WriteBits(buf, &pos, uint64(c.NumSubFrames), 6) 243 bits.WriteBits(buf, &pos, uint64(len(c.Programs)-1), 4) 244 245 for prog, p := range c.Programs { 246 bits.WriteBits(buf, &pos, uint64(len(p.Layers)-1), 3) 247 248 for lay, l := range p.Layers { 249 if prog != 0 || lay != 0 { 250 if l.AudioSpecificConfig != nil { 251 bits.WriteBits(buf, &pos, 0, 1) 252 } else { 253 bits.WriteBits(buf, &pos, 1, 1) 254 } 255 } 256 257 if l.AudioSpecificConfig != nil { 258 err := l.AudioSpecificConfig.marshalTo(buf, &pos) 259 if err != nil { 260 return nil, err 261 } 262 } 263 264 bits.WriteBits(buf, &pos, uint64(l.FrameLengthType), 3) 265 266 switch l.FrameLengthType { 267 case 0: 268 bits.WriteBits(buf, &pos, uint64(l.LatmBufferFullness), 8) 269 270 case 1: 271 bits.WriteBits(buf, &pos, uint64(l.FrameLength), 9) 272 273 case 4, 5, 3: 274 bits.WriteBits(buf, &pos, uint64(l.CELPframeLengthTableIndex), 6) 275 276 case 6, 7: 277 if l.HVXCframeLengthTableIndex { 278 bits.WriteBits(buf, &pos, 1, 1) 279 } else { 280 bits.WriteBits(buf, &pos, 0, 1) 281 } 282 } 283 } 284 } 285 286 if c.OtherDataPresent { 287 bits.WriteBits(buf, &pos, 1, 1) 288 289 var lenBytes []byte 290 tmp := c.OtherDataLenBits 291 292 for { 293 mod := tmp % 256 294 tmp -= mod 295 tmp /= 256 296 lenBytes = append(lenBytes, uint8(mod)) 297 298 if tmp == 0 { 299 break 300 } 301 } 302 303 for i := len(lenBytes) - 1; i > 0; i-- { 304 bits.WriteBits(buf, &pos, 1, 1) 305 bits.WriteBits(buf, &pos, uint64(lenBytes[i]), 8) 306 } 307 308 bits.WriteBits(buf, &pos, 0, 1) 309 bits.WriteBits(buf, &pos, uint64(lenBytes[0]), 8) 310 } else { 311 bits.WriteBits(buf, &pos, 0, 1) 312 } 313 314 if c.CRCCheckPresent { 315 bits.WriteBits(buf, &pos, 1, 1) 316 bits.WriteBits(buf, &pos, uint64(c.CRCCheckSum), 8) 317 } else { 318 bits.WriteBits(buf, &pos, 0, 1) 319 } 320 321 return buf, nil 322 }