Skip to content

Commit

Permalink
mpeg4audio: support otherDataPresent and crcCheckPresent of StreamMux…
Browse files Browse the repository at this point in the history
  • Loading branch information
aler9 authored May 31, 2023
1 parent b3b72ee commit e8717ec
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 13 deletions.
4 changes: 2 additions & 2 deletions pkg/codecs/mpeg2audio/frame_header.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ var sampleRates = map[uint8]int{
0b10: 32000,
}

// ChannelMode is a channel mode of a MPEG-2 or MPEG-2 audio frame.
// ChannelMode is a channel mode of a MPEG-1/2 audio frame.
type ChannelMode int

// standard channel modes.
Expand All @@ -57,7 +57,7 @@ const (
ChannelModeMono ChannelMode = 3
)

// FrameHeader is the header of a MPEG-1 or MPEG-2 audio frame.
// FrameHeader is the header of a MPEG-1/2 audio frame.
type FrameHeader struct {
MPEG2 bool
Layer uint8
Expand Down
2 changes: 1 addition & 1 deletion pkg/codecs/mpeg2audio/mpeg2audio.go
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
// Package mpeg2audio contains utilities to work with MPEG-1 and MPEG-2 audio codecs.
// Package mpeg2audio contains utilities to work with MPEG-1/2 audio codecs.
package mpeg2audio
99 changes: 89 additions & 10 deletions pkg/codecs/mpeg4audio/stream_mux_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ type StreamMuxConfigProgram struct {

// StreamMuxConfig is a StreamMuxConfig as defined in ISO 14496-3.
type StreamMuxConfig struct {
NumSubFrames uint
Programs []*StreamMuxConfigProgram
NumSubFrames uint
Programs []*StreamMuxConfigProgram
OtherDataPresent bool
OtherDataLenBits uint32
CRCCheckPresent bool
CRCCheckSum uint8
}

// Unmarshal decodes a StreamMuxConfig.
Expand Down Expand Up @@ -126,19 +130,41 @@ func (c *StreamMuxConfig) Unmarshal(buf []byte) error {
}
}

err = bits.HasSpace(buf, pos, 2)
c.OtherDataPresent, err = bits.ReadFlag(buf, &pos)
if err != nil {
return err
}

otherDataPresent := bits.ReadFlagUnsafe(buf, &pos)
if otherDataPresent {
return fmt.Errorf("otherDataPresent is not supported")
if c.OtherDataPresent {
for {
c.OtherDataLenBits *= 256

err := bits.HasSpace(buf, pos, 9)
if err != nil {
return err
}

otherDataLenEsc := bits.ReadFlagUnsafe(buf, &pos)
otherDataLenTmp := uint32(bits.ReadBitsUnsafe(buf, &pos, 8))
c.OtherDataLenBits += otherDataLenTmp

if !otherDataLenEsc {
break
}
}
}

crcCheckPresent := bits.ReadFlagUnsafe(buf, &pos)
if crcCheckPresent {
return fmt.Errorf("crcCheckPresent is not supported")
c.CRCCheckPresent, err = bits.ReadFlag(buf, &pos)
if err != nil {
return err
}

if c.CRCCheckPresent {
tmp, err := bits.ReadBits(buf, &pos, 8)
if err != nil {
return err
}
c.CRCCheckSum = uint8(tmp)
}

return nil
Expand Down Expand Up @@ -177,7 +203,25 @@ func (c StreamMuxConfig) marshalSize() int {
}
}

n += 2
n++ // otherDataPresent

if c.OtherDataPresent {
tmp := c.OtherDataLenBits
for {
tmp /= 256
n += 9

if tmp == 0 {
break
}
}
}

n++ // crcCheckPresent

if c.CRCCheckPresent {
n += 8
}

ret := n / 8
if (n % 8) != 0 {
Expand Down Expand Up @@ -238,5 +282,40 @@ func (c StreamMuxConfig) Marshal() ([]byte, error) {
}
}

if c.OtherDataPresent {
bits.WriteBits(buf, &pos, 1, 1)

var lenBytes []byte
tmp := c.OtherDataLenBits

for {
mod := tmp % 256
tmp -= mod
tmp /= 256
lenBytes = append(lenBytes, uint8(mod))

if tmp == 0 {
break
}
}

for i := len(lenBytes) - 1; i > 0; i-- {
bits.WriteBits(buf, &pos, 1, 1)
bits.WriteBits(buf, &pos, uint64(lenBytes[i]), 8)
}

bits.WriteBits(buf, &pos, 0, 1)
bits.WriteBits(buf, &pos, uint64(lenBytes[0]), 8)
} else {
bits.WriteBits(buf, &pos, 0, 1)
}

if c.CRCCheckPresent {
bits.WriteBits(buf, &pos, 1, 1)
bits.WriteBits(buf, &pos, uint64(c.CRCCheckSum), 8)
} else {
bits.WriteBits(buf, &pos, 0, 1)
}

return buf, nil
}
40 changes: 40 additions & 0 deletions pkg/codecs/mpeg4audio/stream_mux_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,46 @@ var streamMuxConfigCases = []struct {
}},
},
},
{
"other data and checksum",
[]byte{0x40, 0x00, 0x24, 0x10, 0xad, 0xca, 0x00},
StreamMuxConfig{
Programs: []*StreamMuxConfigProgram{{
Layers: []*StreamMuxConfigLayer{{
AudioSpecificConfig: &AudioSpecificConfig{
Type: 2,
SampleRate: 44100,
ChannelCount: 1,
},
FrameLengthType: 2,
}},
}},
OtherDataPresent: true,
OtherDataLenBits: 220,
CRCCheckPresent: true,
CRCCheckSum: 64,
},
},
{
"other data > 256 and checksum",
[]byte{0x40, 0x00, 0x24, 0x10, 0xb0, 0x33, 0x85, 0x0},
StreamMuxConfig{
Programs: []*StreamMuxConfigProgram{{
Layers: []*StreamMuxConfigLayer{{
AudioSpecificConfig: &AudioSpecificConfig{
Type: 2,
SampleRate: 44100,
ChannelCount: 1,
},
FrameLengthType: 2,
}},
}},
OtherDataPresent: true,
OtherDataLenBits: 880,
CRCCheckPresent: true,
CRCCheckSum: 64,
},
},
}

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

0 comments on commit e8717ec

Please sign in to comment.