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  }