github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/mpeg4audio/adts.go (about) 1 package mpeg4audio 2 3 import ( 4 "fmt" 5 ) 6 7 // ADTSPacket is an ADTS frame. 8 // Specification: ISO 14496-3, Table 1.A.5 9 type ADTSPacket struct { 10 Type ObjectType 11 SampleRate int 12 ChannelCount int 13 AU []byte 14 } 15 16 // ADTSPackets is a group od ADTS packets. 17 type ADTSPackets []*ADTSPacket 18 19 // Unmarshal decodes an ADTS stream into ADTS packets. 20 func (ps *ADTSPackets) Unmarshal(buf []byte) error { 21 // refs: https://wiki.multimedia.cx/index.php/ADTS 22 23 bl := len(buf) 24 pos := 0 25 26 for { 27 if (bl - pos) < 8 { 28 return fmt.Errorf("invalid length") 29 } 30 31 syncWord := (uint16(buf[pos]) << 4) | (uint16(buf[pos+1]) >> 4) 32 if syncWord != 0xfff { 33 return fmt.Errorf("invalid syncword") 34 } 35 36 protectionAbsent := buf[pos+1] & 0x01 37 if protectionAbsent != 1 { 38 return fmt.Errorf("CRC is not supported") 39 } 40 41 pkt := &ADTSPacket{} 42 43 pkt.Type = ObjectType((buf[pos+2] >> 6) + 1) 44 switch pkt.Type { 45 case ObjectTypeAACLC: 46 default: 47 return fmt.Errorf("unsupported audio type: %d", pkt.Type) 48 } 49 50 sampleRateIndex := (buf[pos+2] >> 2) & 0x0F 51 switch { 52 case sampleRateIndex <= 12: 53 pkt.SampleRate = sampleRates[sampleRateIndex] 54 55 default: 56 return fmt.Errorf("invalid sample rate index: %d", sampleRateIndex) 57 } 58 59 channelConfig := ((buf[pos+2] & 0x01) << 2) | ((buf[pos+3] >> 6) & 0x03) 60 switch { 61 case channelConfig >= 1 && channelConfig <= 6: 62 pkt.ChannelCount = int(channelConfig) 63 64 case channelConfig == 7: 65 pkt.ChannelCount = 8 66 67 default: 68 return fmt.Errorf("invalid channel configuration: %d", channelConfig) 69 } 70 71 frameLen := int(((uint16(buf[pos+3])&0x03)<<11)| 72 (uint16(buf[pos+4])<<3)| 73 ((uint16(buf[pos+5])>>5)&0x07)) - 7 74 75 if frameLen <= 0 { 76 return fmt.Errorf("invalid FrameLen") 77 } 78 79 if frameLen > MaxAccessUnitSize { 80 return fmt.Errorf("access unit size (%d) is too big, maximum is %d", frameLen, MaxAccessUnitSize) 81 } 82 83 frameCount := buf[pos+6] & 0x03 84 if frameCount != 0 { 85 return fmt.Errorf("frame count greater than 1 is not supported") 86 } 87 88 if len(buf[pos+7:]) < frameLen { 89 return fmt.Errorf("invalid frame length") 90 } 91 92 pkt.AU = buf[pos+7 : pos+7+frameLen] 93 pos += 7 + frameLen 94 95 *ps = append(*ps, pkt) 96 97 if (bl - pos) == 0 { 98 break 99 } 100 } 101 102 return nil 103 } 104 105 func (ps ADTSPackets) marshalSize() int { 106 n := 0 107 for _, pkt := range ps { 108 n += 7 + len(pkt.AU) 109 } 110 return n 111 } 112 113 // Marshal encodes ADTS packets into an ADTS stream. 114 func (ps ADTSPackets) Marshal() ([]byte, error) { 115 buf := make([]byte, ps.marshalSize()) 116 pos := 0 117 118 for _, pkt := range ps { 119 sampleRateIndex, ok := reverseSampleRates[pkt.SampleRate] 120 if !ok { 121 return nil, fmt.Errorf("invalid sample rate: %d", pkt.SampleRate) 122 } 123 124 var channelConfig int 125 switch { 126 case pkt.ChannelCount >= 1 && pkt.ChannelCount <= 6: 127 channelConfig = pkt.ChannelCount 128 129 case pkt.ChannelCount == 8: 130 channelConfig = 7 131 132 default: 133 return nil, fmt.Errorf("invalid channel count (%d)", pkt.ChannelCount) 134 } 135 136 frameLen := len(pkt.AU) + 7 137 138 fullness := 0x07FF // like ffmpeg does 139 140 buf[pos+0] = 0xFF 141 buf[pos+1] = 0xF1 142 buf[pos+2] = uint8((int(pkt.Type-1) << 6) | (sampleRateIndex << 2) | ((channelConfig >> 2) & 0x01)) 143 buf[pos+3] = uint8((channelConfig&0x03)<<6 | (frameLen>>11)&0x03) 144 buf[pos+4] = uint8((frameLen >> 3) & 0xFF) 145 buf[pos+5] = uint8((frameLen&0x07)<<5 | ((fullness >> 6) & 0x1F)) 146 buf[pos+6] = uint8((fullness & 0x3F) << 2) 147 pos += 7 148 149 pos += copy(buf[pos:], pkt.AU) 150 } 151 152 return buf, nil 153 }