github.com/bluenviron/mediacommon@v1.9.3/pkg/codecs/ac3/bsi.go (about) 1 package ac3 2 3 import ( 4 "fmt" 5 6 "github.com/bluenviron/mediacommon/pkg/bits" 7 ) 8 9 // BSI is a Bit Stream Information. 10 // Specification: ATSC, AC-3, Table 5.2 11 type BSI struct { 12 Bsid uint8 13 Bsmod uint8 14 Acmod uint8 15 LfeOn bool 16 } 17 18 // Unmarshal decodes a BSI. 19 func (b *BSI) Unmarshal(buf []byte) error { 20 if len(buf) < 2 { 21 return fmt.Errorf("not enough bits") 22 } 23 24 b.Bsid = buf[0] >> 3 25 if b.Bsid != 0x08 { 26 return fmt.Errorf("invalid bsid") 27 } 28 29 b.Bsmod = buf[0] & 0b111 30 31 buf = buf[1:] 32 pos := 0 33 34 tmp := bits.ReadBitsUnsafe(buf, &pos, 3) 35 b.Acmod = uint8(tmp) 36 37 if ((b.Acmod & 0x1) != 0) && (b.Acmod != 0x1) { 38 bits.ReadBitsUnsafe(buf, &pos, 2) // cmixlev 39 } 40 41 if (b.Acmod & 0x4) != 0 { 42 bits.ReadBitsUnsafe(buf, &pos, 2) // surmixlev 43 } 44 45 if b.Acmod == 0x2 { 46 bits.ReadBitsUnsafe(buf, &pos, 2) // dsurmod 47 } 48 49 b.LfeOn = bits.ReadFlagUnsafe(buf, &pos) 50 51 return nil 52 } 53 54 // ChannelCount returns the channel count. 55 func (b BSI) ChannelCount() int { 56 var n int 57 switch b.Acmod { 58 case 0b001: 59 n = 1 60 case 0b010, 0b000: 61 n = 2 62 case 0b011, 0b100: 63 n = 3 64 case 0b101, 0b110: 65 n = 4 66 default: 67 n = 5 68 } 69 70 if b.LfeOn { 71 return n + 1 72 } 73 return n 74 }