From 2a89459263a718b8c02be6a041aabbc29b12caca Mon Sep 17 00:00:00 2001 From: Kubo Ryosuke Date: Sat, 8 Aug 2020 01:58:10 +0900 Subject: [PATCH] Support sidx and styp --- box_types.go | 63 ++++++++++++++++++++++- box_types_test.go | 127 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 189 insertions(+), 1 deletion(-) diff --git a/box_types.go b/box_types.go index 58cd77c..735961e 100644 --- a/box_types.go +++ b/box_types.go @@ -370,7 +370,7 @@ type Ftyp struct { Box MajorBrand [4]byte `mp4:"size=8,string"` MinorVersion uint32 `mp4:"size=32"` - CompatibleBrands []CompatibleBrandElem `mp4:"size=32"` // to end of the box + CompatibleBrands []CompatibleBrandElem `mp4:"size=32"` // reach to end of the box } type CompatibleBrandElem struct { @@ -963,6 +963,48 @@ func (*Sgpd) GetType() BoxType { return BoxTypeSgpd() } +/*************************** sidx ****************************/ + +func BoxTypeSidx() BoxType { return StrToBoxType("sidx") } + +func init() { + AddBoxDef(&Sidx{}, 0, 1) +} + +type Sidx struct { + FullBox `mp4:"extend"` + ReferenceID uint32 `mp4:"size=32"` + Timescale uint32 `mp4:"size=32"` + EarliestPresentationTimeV0 uint32 `mp4:"size=32,ver=0"` + FirstOffsetV0 uint32 `mp4:"size=32,ver=0"` + EarliestPresentationTimeV1 uint64 `mp4:"size=64,nver=0"` + FirstOffsetV1 uint64 `mp4:"size=64,nver=0"` + Reserved uint16 `mp4:"size=16,const=0"` + ReferenceCount uint16 `mp4:"size=16"` + References []SidxReference `mp4:"size=96,len=dynamic"` +} + +type SidxReference struct { + ReferenceType bool `mp4:"size=1"` + ReferencedSize uint32 `mp4:"size=31"` + SubsegmentDuration uint32 `mp4:"size=32"` + StartsWithSAP bool `mp4:"size=1"` + SAPType uint32 `mp4:"size=3"` + SAPDeltaTime uint32 `mp4:"size=28"` +} + +func (*Sidx) GetType() BoxType { + return BoxTypeSidx() +} + +func (sidx *Sidx) GetFieldLength(name string) uint { + switch name { + case "References": + return uint(sidx.ReferenceCount) + } + panic(fmt.Errorf("invalid name of dynamic-length field: boxType=sidx fieldName=%s", name)) +} + /*************************** smhd ****************************/ func BoxTypeSmhd() BoxType { return StrToBoxType("smhd") } @@ -1178,6 +1220,25 @@ func (stts *Stts) GetFieldLength(name string) uint { panic(fmt.Errorf("invalid name of dynamic-length field: boxType=stts fieldName=%s", name)) } +/*************************** styp ****************************/ + +func BoxTypeStyp() BoxType { return StrToBoxType("styp") } + +func init() { + AddBoxDef(&Styp{}, 0) +} + +type Styp struct { + Box + MajorBrand [4]byte `mp4:"size=8,string"` + MinorVersion uint32 `mp4:"size=32"` + CompatibleBrands []CompatibleBrandElem `mp4:"size=32"` // reach to end of the box +} + +func (*Styp) GetType() BoxType { + return BoxTypeStyp() +} + /*************************** tfdt ****************************/ func BoxTypeTfdt() BoxType { return StrToBoxType("tfdt") } diff --git a/box_types_test.go b/box_types_test.go index 223a4b9..403a29f 100644 --- a/box_types_test.go +++ b/box_types_test.go @@ -1106,6 +1106,114 @@ func TestBoxTypes(t *testing.T) { `EntryCount=2 ` + `Unsupported=[0x11, 0x22, 0x33, 0x44]`, }, + { + name: "sidx: version=0", + src: &Sidx{ + FullBox: FullBox{ + Version: 0, + Flags: [3]byte{0x00, 0x00, 0x00}, + }, + ReferenceID: 0x01234567, + Timescale: 0x23456789, + EarliestPresentationTimeV0: 0x456789ab, + FirstOffsetV0: 0x6789abcd, + ReferenceCount: 2, + References: []SidxReference{ + { + ReferenceType: false, + ReferencedSize: 0x01234567, + SubsegmentDuration: 0x23456789, + StartsWithSAP: true, + SAPType: 6, + SAPDeltaTime: 0x09abcdef, + }, + { + ReferenceType: true, + ReferencedSize: 0x01234567, + SubsegmentDuration: 0x23456789, + StartsWithSAP: false, + SAPType: 5, + SAPDeltaTime: 0x09abcdef, + }, + }, + }, + dst: &Sidx{}, + bin: []byte{ + 0, // version + 0x00, 0x00, 0x00, // flags + 0x01, 0x23, 0x45, 0x67, // ReferenceID + 0x23, 0x45, 0x67, 0x89, // Timescale + 0x45, 0x67, 0x89, 0xab, // EarliestPresentationTimeV0 + 0x67, 0x89, 0xab, 0xcd, // FirstOffsetV0 + 0x00, 0x00, // Reserved + 0x00, 0x2, // ReferenceCount + 0x01, 0x23, 0x45, 0x67, // ReferenceType, ReferencedSize + 0x23, 0x45, 0x67, 0x89, // SubsegmentDuration + 0xe9, 0xab, 0xcd, 0xef, // StartsWithSAP, SAPType, SAPDeltaTime + 0x81, 0x23, 0x45, 0x67, // ReferenceType, ReferencedSize + 0x23, 0x45, 0x67, 0x89, // SubsegmentDuration + 0x59, 0xab, 0xcd, 0xef, // StartsWithSAP, SAPType, SAPDeltaTime + }, + str: `Version=0 Flags=0x000000 ` + + `ReferenceID=19088743 Timescale=591751049 EarliestPresentationTimeV0=1164413355 FirstOffsetV0=1737075661 ` + + `ReferenceCount=2 References=[` + + `{ReferenceType=false ReferencedSize=19088743 SubsegmentDuration=591751049 StartsWithSAP=true SAPType=6 SAPDeltaTime=162254319}, ` + + `{ReferenceType=true ReferencedSize=19088743 SubsegmentDuration=591751049 StartsWithSAP=false SAPType=5 SAPDeltaTime=162254319}]`, + }, + { + name: "sidx: version=1", + src: &Sidx{ + FullBox: FullBox{ + Version: 1, + Flags: [3]byte{0x00, 0x00, 0x00}, + }, + ReferenceID: 0x01234567, + Timescale: 0x23456789, + EarliestPresentationTimeV1: 0x0123456789abcdef, + FirstOffsetV1: 0x23456789abcdef01, + ReferenceCount: 2, + References: []SidxReference{ + { + ReferenceType: false, + ReferencedSize: 0x01234567, + SubsegmentDuration: 0x23456789, + StartsWithSAP: true, + SAPType: 6, + SAPDeltaTime: 0x09abcdef, + }, + { + ReferenceType: true, + ReferencedSize: 0x01234567, + SubsegmentDuration: 0x23456789, + StartsWithSAP: false, + SAPType: 5, + SAPDeltaTime: 0x09abcdef, + }, + }, + }, + dst: &Sidx{}, + bin: []byte{ + 1, // version + 0x00, 0x00, 0x00, // flags + 0x01, 0x23, 0x45, 0x67, // ReferenceID + 0x23, 0x45, 0x67, 0x89, // Timescale + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, // EarliestPresentationTimeV1 + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, // FirstOffsetV1 + 0x00, 0x00, // Reserved + 0x00, 0x2, // ReferenceCount + 0x01, 0x23, 0x45, 0x67, // ReferenceType, ReferencedSize + 0x23, 0x45, 0x67, 0x89, // SubsegmentDuration + 0xe9, 0xab, 0xcd, 0xef, // StartsWithSAP, SAPType, SAPDeltaTime + 0x81, 0x23, 0x45, 0x67, // ReferenceType, ReferencedSize + 0x23, 0x45, 0x67, 0x89, // SubsegmentDuration + 0x59, 0xab, 0xcd, 0xef, // StartsWithSAP, SAPType, SAPDeltaTime + }, + str: `Version=1 Flags=0x000000 ` + + `ReferenceID=19088743 Timescale=591751049 EarliestPresentationTimeV1=81985529216486895 FirstOffsetV1=2541551405711093505 ` + + `ReferenceCount=2 References=[` + + `{ReferenceType=false ReferencedSize=19088743 SubsegmentDuration=591751049 StartsWithSAP=true SAPType=6 SAPDeltaTime=162254319}, ` + + `{ReferenceType=true ReferencedSize=19088743 SubsegmentDuration=591751049 StartsWithSAP=false SAPType=5 SAPDeltaTime=162254319}]`, + }, { name: "smhd", src: &Smhd{ @@ -1285,6 +1393,25 @@ func TestBoxTypes(t *testing.T) { `{SampleCount=19088743 SampleDelta=591751049}, ` + `{SampleCount=1164413355 SampleDelta=1737075661}]`, }, + { + name: "styp", + src: &Styp{ + MajorBrand: [4]byte{'a', 'b', 'e', 'm'}, + MinorVersion: 0x12345678, + CompatibleBrands: []CompatibleBrandElem{ + {CompatibleBrand: [4]byte{'a', 'b', 'c', 'd'}}, + {CompatibleBrand: [4]byte{'e', 'f', 'g', 'h'}}, + }, + }, + dst: &Styp{}, + bin: []byte{ + 'a', 'b', 'e', 'm', // major brand + 0x12, 0x34, 0x56, 0x78, // minor version + 'a', 'b', 'c', 'd', // compatible brand + 'e', 'f', 'g', 'h', // compatible brand + }, + str: `MajorBrand="abem" MinorVersion=305419896 CompatibleBrands=[{CompatibleBrand="abcd"}, {CompatibleBrand="efgh"}]`, + }, { name: "tfdt: version 0", src: &Tfdt{