diff --git a/go.mod b/go.mod index 6a85a47ac..1ac0bb4a3 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( codeberg.org/superseriousbusiness/exif-terminator v0.7.0 github.com/DmitriyVTitov/size v1.5.0 github.com/KimMachineGun/automemlimit v0.5.0 - github.com/abema/go-mp4 v1.1.1 + github.com/abema/go-mp4 v1.2.0 github.com/buckket/go-blurhash v1.1.0 github.com/coreos/go-oidc/v3 v3.9.0 github.com/disintegration/imaging v1.6.2 diff --git a/go.sum b/go.sum index d512e2b55..2de163572 100644 --- a/go.sum +++ b/go.sum @@ -81,8 +81,8 @@ github.com/DmitriyVTitov/size v1.5.0 h1:/PzqxYrOyOUX1BXj6J9OuVRVGe+66VL4D9FlUaW5 github.com/DmitriyVTitov/size v1.5.0/go.mod h1:le6rNI4CoLQV1b9gzp1+3d7hMAD/uu2QcJ+aYbNgiU0= github.com/KimMachineGun/automemlimit v0.5.0 h1:BeOe+BbJc8L5chL3OwzVYjVzyvPALdd5wxVVOWuUZmQ= github.com/KimMachineGun/automemlimit v0.5.0/go.mod h1:di3GCKiu9Y+1fs92erCbUvKzPkNyViN3mA0vti/ykEQ= -github.com/abema/go-mp4 v1.1.1 h1:OfzkdMO6SWTBR1ltNSVwlTHatrAK9I3iYLQfkdEMMuc= -github.com/abema/go-mp4 v1.1.1/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws= +github.com/abema/go-mp4 v1.2.0 h1:gi4X8xg/m179N/J15Fn5ugywN9vtI6PLk6iLldHGLAk= +github.com/abema/go-mp4 v1.2.0/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= diff --git a/vendor/github.com/abema/go-mp4/README.md b/vendor/github.com/abema/go-mp4/README.md index c876a2166..2f3e690be 100644 --- a/vendor/github.com/abema/go-mp4/README.md +++ b/vendor/github.com/abema/go-mp4/README.md @@ -6,9 +6,14 @@ go-mp4 [![Coverage Status](https://coveralls.io/repos/github/abema/go-mp4/badge.svg)](https://coveralls.io/github/abema/go-mp4) [![Go Report Card](https://goreportcard.com/badge/github.com/abema/go-mp4)](https://goreportcard.com/report/github.com/abema/go-mp4) -go-mp4 is Go library and CLI tool which provide low-level I/O interfaces of MP4. +go-mp4 is Go library which provides low-level I/O interfaces of MP4. This library supports you to parse or build any MP4 boxes(atoms) directly. +go-mp4 provides very flexible interfaces for reading boxes. +If you want to read only specific parts of MP4 file, this library extracts those boxes via io.ReadSeeker interface. + +On the other hand, this library is not suitable for complex data conversions. + ## Integration with your Go application ### Reading diff --git a/vendor/github.com/abema/go-mp4/box_info.go b/vendor/github.com/abema/go-mp4/box_info.go index 402b418ef..1cb4b8aa7 100644 --- a/vendor/github.com/abema/go-mp4/box_info.go +++ b/vendor/github.com/abema/go-mp4/box_info.go @@ -12,6 +12,9 @@ type Context struct { // IsQuickTimeCompatible represents whether ftyp.compatible_brands contains "qt ". IsQuickTimeCompatible bool + // QuickTimeKeysMetaEntryCount the expected number of items under the ilst box as observed from the keys box + QuickTimeKeysMetaEntryCount int + // UnderWave represents whether current box is under the wave box. UnderWave bool diff --git a/vendor/github.com/abema/go-mp4/box_types_iso23001_5.go b/vendor/github.com/abema/go-mp4/box_types_iso23001_5.go new file mode 100644 index 000000000..849411ad1 --- /dev/null +++ b/vendor/github.com/abema/go-mp4/box_types_iso23001_5.go @@ -0,0 +1,35 @@ +package mp4 + +/*************************** ipcm ****************************/ + +func BoxTypeIpcm() BoxType { return StrToBoxType("ipcm") } + +func init() { + AddAnyTypeBoxDef(&AudioSampleEntry{}, BoxTypeIpcm()) +} + +/*************************** fpcm ****************************/ + +func BoxTypeFpcm() BoxType { return StrToBoxType("fpcm") } + +func init() { + AddAnyTypeBoxDef(&AudioSampleEntry{}, BoxTypeFpcm()) +} + +/*************************** pcmC ****************************/ + +func BoxTypePcmC() BoxType { return StrToBoxType("pcmC") } + +func init() { + AddBoxDef(&PcmC{}, 0, 1) +} + +type PcmC struct { + FullBox `mp4:"0,extend"` + FormatFlags uint8 `mp4:"1,size=8"` + PCMSampleSize uint8 `mp4:"1,size=8"` +} + +func (PcmC) GetType() BoxType { + return BoxTypePcmC() +} diff --git a/vendor/github.com/abema/go-mp4/box_types_metadata.go b/vendor/github.com/abema/go-mp4/box_types_metadata.go index de2146975..7baba2242 100644 --- a/vendor/github.com/abema/go-mp4/box_types_metadata.go +++ b/vendor/github.com/abema/go-mp4/box_types_metadata.go @@ -107,6 +107,8 @@ const ( DataTypeFloat64BigEndian = 23 ) +// Data is a Value BoxType +// https://developer.apple.com/documentation/quicktime-file-format/value_atom type Data struct { Box DataType uint32 `mp4:"0,size=32"` @@ -167,6 +169,89 @@ func (sd *StringData) StringifyField(name string, indent string, depth int, ctx return "", false } +/*************************** numbered items ****************************/ + +// Item is a numbered item under an item list atom +// https://developer.apple.com/documentation/quicktime-file-format/metadata_item_list_atom/item_list +type Item struct { + AnyTypeBox + Version uint8 `mp4:"0,size=8"` + Flags [3]byte `mp4:"1,size=8"` + ItemName []byte `mp4:"2,size=8,len=4"` + Data Data `mp4:"3"` +} + +// StringifyField returns field value as string +func (i *Item) StringifyField(name string, indent string, depth int, ctx Context) (string, bool) { + switch name { + case "ItemName": + return fmt.Sprintf("\"%s\"", util.EscapeUnprintables(string(i.ItemName))), true + } + return "", false +} + func isUnderIlstFreeFormat(ctx Context) bool { return ctx.UnderIlstFreeMeta } + +func BoxTypeKeys() BoxType { return StrToBoxType("keys") } + +func init() { + AddBoxDef(&Keys{}) +} + +/*************************** keys ****************************/ + +// Keys is the Keys BoxType +// https://developer.apple.com/documentation/quicktime-file-format/metadata_item_keys_atom +type Keys struct { + FullBox `mp4:"0,extend"` + EntryCount int32 `mp4:"1,size=32"` + Entries []Key `mp4:"2,len=dynamic"` +} + +// GetType implements the IBox interface and returns the BoxType +func (*Keys) GetType() BoxType { + return BoxTypeKeys() +} + +// GetFieldLength implements the ICustomFieldObject interface and returns the length of dynamic fields +func (k *Keys) GetFieldLength(name string, ctx Context) uint { + switch name { + case "Entries": + return uint(k.EntryCount) + } + panic(fmt.Errorf("invalid name of dynamic-length field: boxType=keys fieldName=%s", name)) +} + +/*************************** key ****************************/ + +// Key is a key value field in the Keys BoxType +// https://developer.apple.com/documentation/quicktime-file-format/metadata_item_keys_atom/key_value_key_size-8 +type Key struct { + BaseCustomFieldObject + KeySize int32 `mp4:"0,size=32"` + KeyNamespace []byte `mp4:"1,size=8,len=4"` + KeyValue []byte `mp4:"2,size=8,len=dynamic"` +} + +// GetFieldLength implements the ICustomFieldObject interface and returns the length of dynamic fields +func (k *Key) GetFieldLength(name string, ctx Context) uint { + switch name { + case "KeyValue": + // sizeOf(KeySize)+sizeOf(KeyNamespace) = 8 bytes + return uint(k.KeySize) - 8 + } + panic(fmt.Errorf("invalid name of dynamic-length field: boxType=key fieldName=%s", name)) +} + +// StringifyField returns field value as string +func (k *Key) StringifyField(name string, indent string, depth int, ctx Context) (string, bool) { + switch name { + case "KeyNamespace": + return fmt.Sprintf("\"%s\"", util.EscapeUnprintables(string(k.KeyNamespace))), true + case "KeyValue": + return fmt.Sprintf("\"%s\"", util.EscapeUnprintables(string(k.KeyValue))), true + } + return "", false +} diff --git a/vendor/github.com/abema/go-mp4/mp4.go b/vendor/github.com/abema/go-mp4/mp4.go index 6aa5b307a..2fab24da7 100644 --- a/vendor/github.com/abema/go-mp4/mp4.go +++ b/vendor/github.com/abema/go-mp4/mp4.go @@ -1,6 +1,7 @@ package mp4 import ( + "encoding/binary" "errors" "fmt" "reflect" @@ -19,6 +20,13 @@ func StrToBoxType(code string) BoxType { return BoxType{code[0], code[1], code[2], code[3]} } +// Uint32ToBoxType returns a new BoxType from the provied uint32 +func Uint32ToBoxType(i uint32) BoxType { + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, i) + return BoxType{b[0], b[1], b[2], b[3]} +} + func (boxType BoxType) String() string { if isPrintable(boxType[0]) && isPrintable(boxType[1]) && isPrintable(boxType[2]) && isPrintable(boxType[3]) { s := string([]byte{boxType[0], boxType[1], boxType[2], boxType[3]}) @@ -92,6 +100,8 @@ func AddAnyTypeBoxDefEx(payload IAnyType, boxType BoxType, isTarget func(Context }) } +var itemBoxFields = buildFields(&Item{}) + func (boxType BoxType) getBoxDef(ctx Context) *boxDef { boxDefs := boxMap[boxType] for i := len(boxDefs) - 1; i >= 0; i-- { @@ -100,6 +110,16 @@ func (boxType BoxType) getBoxDef(ctx Context) *boxDef { return boxDef } } + if ctx.UnderIlst { + typeID := int(binary.BigEndian.Uint32(boxType[:])) + if typeID >= 1 && typeID <= ctx.QuickTimeKeysMetaEntryCount { + return &boxDef{ + dataType: reflect.TypeOf(Item{}), + isTarget: isIlstMetaContainer, + fields: itemBoxFields, + } + } + } return nil } diff --git a/vendor/github.com/abema/go-mp4/read.go b/vendor/github.com/abema/go-mp4/read.go index e4fadb121..7118d802a 100644 --- a/vendor/github.com/abema/go-mp4/read.go +++ b/vendor/github.com/abema/go-mp4/read.go @@ -64,6 +64,18 @@ func readBoxStructureFromInternal(r io.ReadSeeker, bi *BoxInfo, path BoxPath, ha } } + // parse numbered ilst items after keys box by saving EntryCount field to context + if bi.Type == BoxTypeKeys() { + var keys Keys + if _, err := Unmarshal(r, bi.Size-bi.HeaderSize, &keys, bi.Context); err != nil { + return nil, err + } + bi.QuickTimeKeysMetaEntryCount = int(keys.EntryCount) + if _, err := bi.SeekToPayload(r); err != nil { + return nil, err + } + } + ctx := bi.Context if bi.Type == BoxTypeWave() { ctx.UnderWave = true @@ -172,6 +184,11 @@ func readBoxStructure(r io.ReadSeeker, totalSize uint64, isRoot bool, path BoxPa if bi.IsQuickTimeCompatible { ctx.IsQuickTimeCompatible = true } + + // preserve keys entry count on context for subsequent ilst number item box + if bi.Type == BoxTypeKeys() { + ctx.QuickTimeKeysMetaEntryCount = bi.QuickTimeKeysMetaEntryCount + } } if totalSize != 0 && !ctx.IsQuickTimeCompatible { diff --git a/vendor/modules.txt b/vendor/modules.txt index 8ad21430c..d7a945da1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -72,7 +72,7 @@ github.com/DmitriyVTitov/size ## explicit; go 1.19 github.com/KimMachineGun/automemlimit github.com/KimMachineGun/automemlimit/memlimit -# github.com/abema/go-mp4 v1.1.1 +# github.com/abema/go-mp4 v1.2.0 ## explicit; go 1.14 github.com/abema/go-mp4 github.com/abema/go-mp4/internal/bitio