diff --git a/box_types_vp.go b/box_types_vp.go new file mode 100644 index 0000000..6927b21 --- /dev/null +++ b/box_types_vp.go @@ -0,0 +1,53 @@ +package mp4 + +// https://www.webmproject.org/vp9/mp4/ + +/*************************** vp08 ****************************/ + +func BoxTypeVp08() BoxType { return StrToBoxType("vp08") } + +func init() { + AddAnyTypeBoxDef(&VisualSampleEntry{}, BoxTypeVp08()) +} + +/*************************** vp09 ****************************/ + +func BoxTypeVp09() BoxType { return StrToBoxType("vp09") } + +func init() { + AddAnyTypeBoxDef(&VisualSampleEntry{}, BoxTypeVp09()) +} + +/*************************** VpcC ****************************/ + +func BoxTypeVpcC() BoxType { return StrToBoxType("vpcC") } + +func init() { + AddBoxDef(&VpcC{}) +} + +type VpcC struct { + FullBox `mp4:"0,extend"` + Profile uint8 `mp4:"1,size=8"` + Level uint8 `mp4:"2,size=8"` + BitDepth uint8 `mp4:"3,size=4"` + ChromaSubsampling uint8 `mp4:"4,size=3"` + VideoFullRangeFlag uint8 `mp4:"5,size=1"` + ColourPrimaries uint8 `mp4:"6,size=8"` + TransferCharacteristics uint8 `mp4:"7,size=8"` + MatrixCoefficients uint8 `mp4:"8,size=8"` + CodecInitializationDataSize uint16 `mp4:"9,size=16"` + CodecInitializationData []uint8 `mp4:"10,size=8,len=dynamic"` +} + +func (VpcC) GetType() BoxType { + return BoxTypeVpcC() +} + +func (vpcc VpcC) GetFieldLength(name string, ctx Context) uint { + switch name { + case "CodecInitializationData": + return uint(vpcc.CodecInitializationDataSize) + } + return 0 +} diff --git a/box_types_vp_test.go b/box_types_vp_test.go new file mode 100644 index 0000000..beef336 --- /dev/null +++ b/box_types_vp_test.go @@ -0,0 +1,80 @@ +package mp4 + +import ( + "bytes" + "io" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestBoxTypesVp(t *testing.T) { + testCases := []struct { + name string + src IImmutableBox + dst IBox + bin []byte + str string + ctx Context + }{ + { + name: "vpcC", + src: &VpcC{ + FullBox: FullBox{ + Version: 1, + }, + Profile: 1, + Level: 50, + BitDepth: 10, + ChromaSubsampling: 3, + VideoFullRangeFlag: 1, + ColourPrimaries: 0, + TransferCharacteristics: 1, + MatrixCoefficients: 10, + CodecInitializationDataSize: 3, + CodecInitializationData: []byte{5, 4, 3}, + }, + dst: &VpcC{}, + bin: []byte{ + 0x01, 0x00, 0x00, 0x00, 0x01, 0x32, 0xa7, 0x00, + 0x01, 0x0a, 0x00, 0x03, 0x05, 0x04, 0x03, + }, + str: `Version=1 Flags=0x000000 Profile=0x1 Level=0x32 BitDepth=0xa ChromaSubsampling=0x3 VideoFullRangeFlag=0x1 ColourPrimaries=0x0 TransferCharacteristics=0x1 MatrixCoefficients=0xa CodecInitializationDataSize=3 CodecInitializationData=[0x5, 0x4, 0x3]`, + }, + } + 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) + }) + } +}