Skip to content

Commit

Permalink
feat: support for weird dac3 reported in Issue #395
Browse files Browse the repository at this point in the history
  • Loading branch information
tobbee committed Dec 25, 2024
1 parent e8067d2 commit 3677740
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- mp4.SetUUID() can take base64 string as well as hex-encoded.
- Support for weird dac3 box with initial 4 zero bytes (Issue #395)

### Fixed

Expand Down
41 changes: 29 additions & 12 deletions mp4/dac3.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,16 @@ var AC3BitrateCodesKbps = []uint16{
}

// Dac3Box - AC3SpecificBox from ETSI TS 102 366 V1.4.1 F.4 (2017)
// Extra b
type Dac3Box struct {
FSCod byte
BSID byte
BSMod byte
ACMod byte
LFEOn byte
BitRateCode byte
FSCod byte
BSID byte
BSMod byte
ACMod byte
LFEOn byte
BitRateCode byte
Reserved byte
InitialZeroes byte // Should be zero
}

// DecodeDac3 - box-specific decode
Expand All @@ -78,20 +81,25 @@ func DecodeDac3SR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, err
}

func decodeDac3FromData(data []byte) (Box, error) {
if len(data) != 3 {
return nil, fmt.Errorf("not 3 bytes payload in dac3 box")
b := Dac3Box{}
if len(data) > 3 {
b.InitialZeroes = byte(len(data) - 3)
}
buf := bytes.NewBuffer(data)
br := bits.NewReader(buf)
b := Dac3Box{}
for i := 0; i < int(b.InitialZeroes); i++ {
if zero := br.Read(8); zero != 0 {
return nil, fmt.Errorf("dac3 box, extra initial bytes are not zero")
}
}
b.FSCod = byte(br.Read(2))
b.BSID = byte(br.Read(5))
b.BSMod = byte(br.Read(3))
b.ACMod = byte(br.Read(3))
b.LFEOn = byte(br.Read(1))
b.BitRateCode = byte(br.Read(5))
// 5 bits reserved follows
_ = br.Read(5)
b.Reserved = byte(br.Read(5))
return &b, nil
}

Expand All @@ -102,7 +110,7 @@ func (b *Dac3Box) Type() string {

// Size - calculated size of box
func (b *Dac3Box) Size() uint64 {
return uint64(boxHeaderSize + 3)
return uint64(boxHeaderSize + 3 + uint(b.InitialZeroes))
}

// Encode - write box to w
Expand All @@ -122,13 +130,16 @@ func (b *Dac3Box) EncodeSW(sw bits.SliceWriter) error {
if err != nil {
return err
}
for i := 0; i < int(b.InitialZeroes); i++ {
sw.WriteBits(0, 8)
}
sw.WriteBits(uint(b.FSCod), 2)
sw.WriteBits(uint(b.BSID), 5)
sw.WriteBits(uint(b.BSMod), 3)
sw.WriteBits(uint(b.ACMod), 3)
sw.WriteBits(uint(b.LFEOn), 1)
sw.WriteBits(uint(b.BitRateCode), 5)
sw.WriteBits(0, 5) // 5-bits padding
sw.WriteBits(uint(b.Reserved), 5) // 5-bits reserved
return sw.AccError()
}

Expand All @@ -154,6 +165,12 @@ func (b *Dac3Box) Info(w io.Writer, specificBoxLevels, indent, indentStep string
bd.write(" - bitRateCode=%d => bitrate=%dkbps", b.BitRateCode, AC3BitrateCodesKbps[b.BitRateCode])
nrChannels, chanmap := b.ChannelInfo()
bd.write(" - nrChannels=%d, chanmap=%04x", nrChannels, chanmap)
if b.Reserved != 0 {
bd.write(" - reserved=%d", b.Reserved)
}
if b.InitialZeroes > 0 {
bd.write(" - weird initial zero bytes=%d", b.InitialZeroes)
}
return bd.err
}

Expand Down
10 changes: 8 additions & 2 deletions mp4/dac3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ import (
)

func TestEncodeDedodeAC3(t *testing.T) {
dac3 := &Dac3Box{FSCod: 1, BSID: 2, ACMod: 3, LFEOn: 1, BitRateCode: 7}
boxDiffAfterEncodeAndDecode(t, dac3)
t.Run("normal-dac3", func(t *testing.T) {
dac3 := &Dac3Box{FSCod: 1, BSID: 2, ACMod: 3, LFEOn: 1, BitRateCode: 7}
boxDiffAfterEncodeAndDecode(t, dac3)
})
t.Run("weird-dac3", func(t *testing.T) {
dac3 := &Dac3Box{FSCod: 1, BSID: 2, ACMod: 3, LFEOn: 1, BitRateCode: 7, InitialZeroes: 4}
boxDiffAfterEncodeAndDecode(t, dac3)
})
}

func TestGetChannelInfo(t *testing.T) {
Expand Down

0 comments on commit 3677740

Please sign in to comment.