Skip to content

Commit

Permalink
Merge pull request #142 from aler9/patch-opus
Browse files Browse the repository at this point in the history
add Opus boxes
  • Loading branch information
sunfish-shogi committed Aug 6, 2023
2 parents cfe3146 + d4444a6 commit a091b3a
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 0 deletions.
54 changes: 54 additions & 0 deletions box_types_opus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package mp4

/*************************** Opus ****************************/

// https://opus-codec.org/docs/opus_in_isobmff.html

func BoxTypeOpus() BoxType { return StrToBoxType("Opus") }

func init() {
AddAnyTypeBoxDef(&AudioSampleEntry{}, BoxTypeOpus())
}

/*************************** dOps ****************************/

// https://opus-codec.org/docs/opus_in_isobmff.html

func BoxTypeDOps() BoxType { return StrToBoxType("dOps") }

func init() {
AddBoxDef(&DOps{})
}

type DOps struct {
Box
Version uint8 `mp4:"0,size=8"`
OutputChannelCount uint8 `mp4:"1,size=8"`
PreSkip uint16 `mp4:"2,size=16"`
InputSampleRate uint32 `mp4:"3,size=32"`
OutputGain int16 `mp4:"4,size=16"`
ChannelMappingFamily uint8 `mp4:"5,size=8"`
StreamCount uint8 `mp4:"6,opt=dynamic,size=8"`
CoupledCount uint8 `mp4:"7,opt=dynamic,size=8"`
ChannelMapping []uint8 `mp4:"8,opt=dynamic,size=8,len=dynamic"`
}

func (DOps) GetType() BoxType {
return BoxTypeDOps()
}

func (dops DOps) IsOptFieldEnabled(name string, ctx Context) bool {
switch name {
case "StreamCount", "CoupledCount", "ChannelMapping":
return dops.ChannelMappingFamily != 0
}
return false
}

func (ops DOps) GetFieldLength(name string, ctx Context) uint {
switch name {
case "ChannelMapping":
return uint(ops.OutputChannelCount)
}
return 0
}
75 changes: 75 additions & 0 deletions box_types_opus_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package mp4

import (
"bytes"
"io"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestBoxTypesOpus(t *testing.T) {
testCases := []struct {
name string
src IImmutableBox
dst IBox
bin []byte
str string
ctx Context
}{
{
name: "dOps",
src: &DOps{
OutputChannelCount: 2,
PreSkip: 312,
InputSampleRate: 48000,
OutputGain: 0,
ChannelMappingFamily: 2,
StreamCount: 1,
CoupledCount: 1,
ChannelMapping: []uint8{1, 2},
},
dst: &DOps{},
bin: []byte{
0x00, 0x02, 0x01, 0x38, 0x00, 0x00, 0xbb, 0x80,
0x00, 0x00, 0x02, 0x01, 0x01, 0x01, 0x02,
},
str: `Version=0 OutputChannelCount=0x2 PreSkip=312 InputSampleRate=48000 OutputGain=0 ChannelMappingFamily=0x2 StreamCount=0x1 CoupledCount=0x1 ChannelMapping=[0x1, 0x2]`,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Marshal
buf := bytes.NewBuffer(nil)
n, err := Marshal(buf, tc.src, tc.ctx)
require.NoError(t, err)
assert.Equal(t, uint64(len(tc.bin)), n)
assert.Equal(t, tc.bin, buf.Bytes())

// Unmarshal
r := bytes.NewReader(tc.bin)
n, err = Unmarshal(r, uint64(len(tc.bin)), tc.dst, tc.ctx)
require.NoError(t, err)
assert.Equal(t, uint64(buf.Len()), n)
assert.Equal(t, tc.src, tc.dst)
s, err := r.Seek(0, io.SeekCurrent)
require.NoError(t, err)
assert.Equal(t, int64(buf.Len()), s)

// UnmarshalAny
dst, n, err := UnmarshalAny(bytes.NewReader(tc.bin), tc.src.GetType(), uint64(len(tc.bin)), tc.ctx)
require.NoError(t, err)
assert.Equal(t, uint64(buf.Len()), n)
assert.Equal(t, tc.src, dst)
s, err = r.Seek(0, io.SeekCurrent)
require.NoError(t, err)
assert.Equal(t, int64(buf.Len()), s)

// Stringify
str, err := Stringify(tc.src, tc.ctx)
require.NoError(t, err)
assert.Equal(t, tc.str, str)
})
}
}

0 comments on commit a091b3a

Please sign in to comment.