diff --git a/go.mod b/go.mod index 617beca55..8064de4bc 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( codeberg.org/gruf/go-store/v2 v2.2.2 github.com/DmitriyVTitov/size v1.5.0 github.com/KimMachineGun/automemlimit v0.2.6 - github.com/abema/go-mp4 v0.11.0 + github.com/abema/go-mp4 v0.12.0 github.com/buckket/go-blurhash v1.1.0 github.com/coreos/go-oidc/v3 v3.6.0 github.com/disintegration/imaging v1.6.2 diff --git a/go.sum b/go.sum index 4dbde05e7..c752f797e 100644 --- a/go.sum +++ b/go.sum @@ -92,8 +92,8 @@ github.com/DmitriyVTitov/size v1.5.0/go.mod h1:le6rNI4CoLQV1b9gzp1+3d7hMAD/uu2Qc github.com/KimMachineGun/automemlimit v0.2.6 h1:tQFriVTcIteUkV5EgU9iz03eDY36T8JU5RAjP2r6Kt0= github.com/KimMachineGun/automemlimit v0.2.6/go.mod h1:pJhTW/nWJMj6SnWSU2TEKSlCaM+1N5Mej+IfS/5/Ol0= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/abema/go-mp4 v0.11.0 h1:XJfpSmEdUBMvWnDKIiNznLGZPpeDxJ/qDdN6Ust1ADk= -github.com/abema/go-mp4 v0.11.0/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws= +github.com/abema/go-mp4 v0.12.0 h1:XI9PPt1BpjB3wFl18oFiX6C99uesx7F/X13Z+ga8bYY= +github.com/abema/go-mp4 v0.12.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/box_types_3gpp.go b/vendor/github.com/abema/go-mp4/box_types_3gpp.go new file mode 100644 index 000000000..d19640c51 --- /dev/null +++ b/vendor/github.com/abema/go-mp4/box_types_3gpp.go @@ -0,0 +1,24 @@ +package mp4 + +var udta3GppMetaBoxTypes = []BoxType{ + StrToBoxType("titl"), + StrToBoxType("dscp"), + StrToBoxType("cprt"), + StrToBoxType("perf"), + StrToBoxType("auth"), + StrToBoxType("gnre"), +} + +func init() { + for _, bt := range udta3GppMetaBoxTypes { + AddAnyTypeBoxDefEx(&Udta3GppString{}, bt, isUnderUdta, 0) + } +} + +type Udta3GppString struct { + AnyTypeBox + FullBox `mp4:"0,extend"` + Pad bool `mp4:"1,size=1,hidden"` + Language [3]byte `mp4:"2,size=5,iso639-2"` // ISO-639-2/T language code + Data []byte `mp4:"3,size=8,string"` +} diff --git a/vendor/github.com/abema/go-mp4/box_types_av1.go b/vendor/github.com/abema/go-mp4/box_types_av1.go new file mode 100644 index 000000000..7b929e72b --- /dev/null +++ b/vendor/github.com/abema/go-mp4/box_types_av1.go @@ -0,0 +1,44 @@ +package mp4 + +/*************************** av01 ****************************/ + +// https://aomediacodec.github.io/av1-isobmff + +func BoxTypeAv01() BoxType { return StrToBoxType("av01") } + +func init() { + AddAnyTypeBoxDef(&VisualSampleEntry{}, BoxTypeAv01()) +} + +/*************************** av1C ****************************/ + +// https://aomediacodec.github.io/av1-isobmff + +func BoxTypeAv1C() BoxType { return StrToBoxType("av1C") } + +func init() { + AddBoxDef(&Av1C{}) +} + +type Av1C struct { + Box + Marker uint8 `mp4:"0,size=1,const=1"` + Version uint8 `mp4:"1,size=7,const=1"` + SeqProfile uint8 `mp4:"2,size=3"` + SeqLevelIdx0 uint8 `mp4:"3,size=5"` + SeqTier0 uint8 `mp4:"4,size=1"` + HighBitdepth uint8 `mp4:"5,size=1"` + TwelveBit uint8 `mp4:"6,size=1"` + Monochrome uint8 `mp4:"7,size=1"` + ChromaSubsamplingX uint8 `mp4:"8,size=1"` + ChromaSubsamplingY uint8 `mp4:"9,size=1"` + ChromaSamplePosition uint8 `mp4:"10,size=2"` + Reserved uint8 `mp4:"11,size=3,const=0"` + InitialPresentationDelayPresent uint8 `mp4:"12,size=1"` + InitialPresentationDelayMinusOne uint8 `mp4:"13,size=4"` + ConfigOBUs []uint8 `mp4:"14,size=8"` +} + +func (Av1C) GetType() BoxType { + return BoxTypeAv1C() +} diff --git a/vendor/github.com/abema/go-mp4/box_types.go b/vendor/github.com/abema/go-mp4/box_types_iso14496_12.go similarity index 85% rename from vendor/github.com/abema/go-mp4/box_types.go rename to vendor/github.com/abema/go-mp4/box_types_iso14496_12.go index dc4231e3a..b3e46fd75 100644 --- a/vendor/github.com/abema/go-mp4/box_types.go +++ b/vendor/github.com/abema/go-mp4/box_types_iso14496_12.go @@ -1,14 +1,12 @@ package mp4 import ( - "bytes" "errors" "fmt" "io" "github.com/abema/go-mp4/bitio" "github.com/abema/go-mp4/util" - "github.com/google/uuid" ) /*************************** btrt ****************************/ @@ -468,129 +466,6 @@ func (*Emsg) GetType() BoxType { return BoxTypeEmsg() } -/*************************** esds ****************************/ - -// https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html - -func BoxTypeEsds() BoxType { return StrToBoxType("esds") } - -func init() { - AddBoxDef(&Esds{}, 0) -} - -const ( - ESDescrTag = 0x03 - DecoderConfigDescrTag = 0x04 - DecSpecificInfoTag = 0x05 - SLConfigDescrTag = 0x06 -) - -// Esds is ES descripter box -type Esds struct { - FullBox `mp4:"0,extend"` - Descriptors []Descriptor `mp4:"1,array"` -} - -// GetType returns the BoxType -func (*Esds) GetType() BoxType { - return BoxTypeEsds() -} - -type Descriptor struct { - BaseCustomFieldObject - Tag int8 `mp4:"0,size=8"` // must be 0x03 - Size uint32 `mp4:"1,varint"` - ESDescriptor *ESDescriptor `mp4:"2,extend,opt=dynamic"` - DecoderConfigDescriptor *DecoderConfigDescriptor `mp4:"3,extend,opt=dynamic"` - Data []byte `mp4:"4,size=8,opt=dynamic,len=dynamic"` -} - -// GetFieldLength returns length of dynamic field -func (ds *Descriptor) GetFieldLength(name string, ctx Context) uint { - switch name { - case "Data": - return uint(ds.Size) - } - panic(fmt.Errorf("invalid name of dynamic-length field: boxType=esds fieldName=%s", name)) -} - -func (ds *Descriptor) IsOptFieldEnabled(name string, ctx Context) bool { - switch ds.Tag { - case ESDescrTag: - return name == "ESDescriptor" - case DecoderConfigDescrTag: - return name == "DecoderConfigDescriptor" - default: - return name == "Data" - } -} - -// StringifyField returns field value as string -func (ds *Descriptor) StringifyField(name string, indent string, depth int, ctx Context) (string, bool) { - switch name { - case "Tag": - switch ds.Tag { - case ESDescrTag: - return "ESDescr", true - case DecoderConfigDescrTag: - return "DecoderConfigDescr", true - case DecSpecificInfoTag: - return "DecSpecificInfo", true - case SLConfigDescrTag: - return "SLConfigDescr", true - default: - return "", false - } - default: - return "", false - } -} - -type ESDescriptor struct { - BaseCustomFieldObject - ESID uint16 `mp4:"0,size=16"` - StreamDependenceFlag bool `mp4:"1,size=1"` - UrlFlag bool `mp4:"2,size=1"` - OcrStreamFlag bool `mp4:"3,size=1"` - StreamPriority int8 `mp4:"4,size=5"` - DependsOnESID uint16 `mp4:"5,size=16,opt=dynamic"` - URLLength uint8 `mp4:"6,size=8,opt=dynamic"` - URLString []byte `mp4:"7,size=8,len=dynamic,opt=dynamic,string"` - OCRESID uint16 `mp4:"8,size=16,opt=dynamic"` -} - -func (esds *ESDescriptor) GetFieldLength(name string, ctx Context) uint { - switch name { - case "URLString": - return uint(esds.URLLength) - } - panic(fmt.Errorf("invalid name of dynamic-length field: boxType=ESDescriptor fieldName=%s", name)) -} - -func (esds *ESDescriptor) IsOptFieldEnabled(name string, ctx Context) bool { - switch name { - case "DependsOnESID": - return esds.StreamDependenceFlag - case "URLLength", "URLString": - return esds.UrlFlag - case "OCRESID": - return esds.OcrStreamFlag - default: - return false - } -} - -type DecoderConfigDescriptor struct { - BaseCustomFieldObject - ObjectTypeIndication byte `mp4:"0,size=8"` - StreamType int8 `mp4:"1,size=6"` - UpStream bool `mp4:"2,size=1"` - Reserved bool `mp4:"3,size=1"` - BufferSizeDB uint32 `mp4:"4,size=24"` - MaxBitrate uint32 `mp4:"5,size=32"` - AvgBitrate uint32 `mp4:"6,size=32"` -} - /*************************** fiel ****************************/ func BoxTypeFiel() BoxType { return StrToBoxType("fiel") } @@ -865,171 +740,6 @@ func (hvcc HvcC) GetFieldLength(name string, ctx Context) uint { return 0 } -/*************************** ilst ****************************/ - -func BoxTypeIlst() BoxType { return StrToBoxType("ilst") } -func BoxTypeData() BoxType { return StrToBoxType("data") } - -var ilstMetaBoxTypes = []BoxType{ - StrToBoxType("----"), - StrToBoxType("aART"), - StrToBoxType("akID"), - StrToBoxType("apID"), - StrToBoxType("atID"), - StrToBoxType("cmID"), - StrToBoxType("cnID"), - StrToBoxType("covr"), - StrToBoxType("cpil"), - StrToBoxType("cprt"), - StrToBoxType("desc"), - StrToBoxType("disk"), - StrToBoxType("egid"), - StrToBoxType("geID"), - StrToBoxType("gnre"), - StrToBoxType("pcst"), - StrToBoxType("pgap"), - StrToBoxType("plID"), - StrToBoxType("purd"), - StrToBoxType("purl"), - StrToBoxType("rtng"), - StrToBoxType("sfID"), - StrToBoxType("soaa"), - StrToBoxType("soal"), - StrToBoxType("soar"), - StrToBoxType("soco"), - StrToBoxType("sonm"), - StrToBoxType("sosn"), - StrToBoxType("stik"), - StrToBoxType("tmpo"), - StrToBoxType("trkn"), - StrToBoxType("tven"), - StrToBoxType("tves"), - StrToBoxType("tvnn"), - StrToBoxType("tvsh"), - StrToBoxType("tvsn"), - {0xA9, 'A', 'R', 'T'}, - {0xA9, 'a', 'l', 'b'}, - {0xA9, 'c', 'm', 't'}, - {0xA9, 'c', 'o', 'm'}, - {0xA9, 'd', 'a', 'y'}, - {0xA9, 'g', 'e', 'n'}, - {0xA9, 'g', 'r', 'p'}, - {0xA9, 'n', 'a', 'm'}, - {0xA9, 't', 'o', 'o'}, - {0xA9, 'w', 'r', 't'}, -} - -func IsIlstMetaBoxType(boxType BoxType) bool { - for _, bt := range ilstMetaBoxTypes { - if boxType == bt { - return true - } - } - return false -} - -func init() { - AddBoxDef(&Ilst{}) - AddBoxDefEx(&Data{}, isUnderIlstMeta) - for _, bt := range ilstMetaBoxTypes { - AddAnyTypeBoxDefEx(&IlstMetaContainer{}, bt, isIlstMetaContainer) - } - AddAnyTypeBoxDefEx(&StringData{}, StrToBoxType("mean"), isUnderIlstFreeFormat) - AddAnyTypeBoxDefEx(&StringData{}, StrToBoxType("name"), isUnderIlstFreeFormat) -} - -type Ilst struct { - Box -} - -// GetType returns the BoxType -func (*Ilst) GetType() BoxType { - return BoxTypeIlst() -} - -type IlstMetaContainer struct { - AnyTypeBox -} - -func isIlstMetaContainer(ctx Context) bool { - return ctx.UnderIlst && !ctx.UnderIlstMeta -} - -const ( - DataTypeBinary = 0 - DataTypeStringUTF8 = 1 - DataTypeStringUTF16 = 2 - DataTypeStringMac = 3 - DataTypeStringJPEG = 14 - DataTypeSignedIntBigEndian = 21 - DataTypeFloat32BigEndian = 22 - DataTypeFloat64BigEndian = 23 -) - -type Data struct { - Box - DataType uint32 `mp4:"0,size=32"` - DataLang uint32 `mp4:"1,size=32"` - Data []byte `mp4:"2,size=8"` -} - -// GetType returns the BoxType -func (*Data) GetType() BoxType { - return BoxTypeData() -} - -func isUnderIlstMeta(ctx Context) bool { - return ctx.UnderIlstMeta -} - -// StringifyField returns field value as string -func (data *Data) StringifyField(name string, indent string, depth int, ctx Context) (string, bool) { - switch name { - case "DataType": - switch data.DataType { - case DataTypeBinary: - return "BINARY", true - case DataTypeStringUTF8: - return "UTF8", true - case DataTypeStringUTF16: - return "UTF16", true - case DataTypeStringMac: - return "MAC_STR", true - case DataTypeStringJPEG: - return "JPEG", true - case DataTypeSignedIntBigEndian: - return "INT", true - case DataTypeFloat32BigEndian: - return "FLOAT32", true - case DataTypeFloat64BigEndian: - return "FLOAT64", true - } - case "Data": - switch data.DataType { - case DataTypeStringUTF8: - return fmt.Sprintf("\"%s\"", util.EscapeUnprintables(string(data.Data))), true - } - } - return "", false -} - -type StringData struct { - AnyTypeBox - Data []byte `mp4:"0,size=8"` -} - -// StringifyField returns field value as string -func (sd *StringData) StringifyField(name string, indent string, depth int, ctx Context) (string, bool) { - if name == "Data" { - return fmt.Sprintf("\"%s\"", util.EscapeUnprintables(string(sd.Data))), true - } - return "", false -} - -func isUnderIlstFreeFormat(ctx Context) bool { - return ctx.UnderIlstFreeMeta -} - /*************************** mdat ****************************/ func BoxTypeMdat() BoxType { return StrToBoxType("mdat") } @@ -1408,64 +1118,6 @@ func (mvhd *Mvhd) GetRateInt() int16 { return int16(mvhd.Rate >> 16) } -/*************************** pssh ****************************/ - -func BoxTypePssh() BoxType { return StrToBoxType("pssh") } - -func init() { - AddBoxDef(&Pssh{}, 0, 1) -} - -// Pssh is ISOBMFF pssh box type -type Pssh struct { - FullBox `mp4:"0,extend"` - SystemID [16]byte `mp4:"1,size=8,uuid"` - KIDCount uint32 `mp4:"2,size=32,nver=0"` - KIDs []PsshKID `mp4:"3,nver=0,len=dynamic,size=128"` - DataSize int32 `mp4:"4,size=32"` - Data []byte `mp4:"5,size=8,len=dynamic"` -} - -type PsshKID struct { - KID [16]byte `mp4:"0,size=8,uuid"` -} - -// GetFieldLength returns length of dynamic field -func (pssh *Pssh) GetFieldLength(name string, ctx Context) uint { - switch name { - case "KIDs": - return uint(pssh.KIDCount) - case "Data": - return uint(pssh.DataSize) - } - panic(fmt.Errorf("invalid name of dynamic-length field: boxType=pssh fieldName=%s", name)) -} - -// StringifyField returns field value as string -func (pssh *Pssh) StringifyField(name string, indent string, depth int, ctx Context) (string, bool) { - switch name { - case "KIDs": - buf := bytes.NewBuffer(nil) - buf.WriteString("[") - for i, e := range pssh.KIDs { - if i != 0 { - buf.WriteString(", ") - } - buf.WriteString(uuid.UUID(e.KID).String()) - } - buf.WriteString("]") - return buf.String(), true - - default: - return "", false - } -} - -// GetType returns the BoxType -func (*Pssh) GetType() BoxType { - return BoxTypePssh() -} - /*************************** saio ****************************/ func BoxTypeSaio() BoxType { return StrToBoxType("saio") } @@ -1608,7 +1260,7 @@ type AudioSampleEntry struct { SampleSize uint16 `mp4:"4,size=16,opt=dynamic"` PreDefined uint16 `mp4:"5,size=16,opt=dynamic"` Reserved2 uint16 `mp4:"6,size=16,opt=dynamic,const=0"` - SampleRate uint32 `mp4:"7,size=32,opt=dynamic"` + SampleRate uint32 `mp4:"7,size=32,opt=dynamic"` // fixed-point 16.16 QuickTimeData []byte `mp4:"8,size=8,opt=dynamic,len=dynamic"` } @@ -1635,6 +1287,24 @@ func (ase *AudioSampleEntry) GetFieldLength(name string, ctx Context) uint { return 0 } +// StringifyField returns field value as string +func (ase *AudioSampleEntry) StringifyField(name string, indent string, depth int, ctx Context) (string, bool) { + switch name { + case "SampleRate": + return util.FormatUnsignedFixedFloat1616(ase.SampleRate), true + default: + return "", false + } +} + +func (ase *AudioSampleEntry) GetSampleRate() float64 { + return float64(ase.SampleRate) / (1 << 16) +} + +func (ase *AudioSampleEntry) GetSampleRateInt() uint16 { + return uint16(ase.SampleRate >> 16) +} + const ( AVCBaselineProfile uint8 = 66 // 0x42 AVCMainProfile uint8 = 77 // 0x4d @@ -2307,48 +1977,6 @@ func (*Styp) GetType() BoxType { return BoxTypeStyp() } -/*************************** tenc ****************************/ - -func BoxTypeTenc() BoxType { return StrToBoxType("tenc") } - -func init() { - AddBoxDef(&Tenc{}, 0, 1) -} - -// Tenc is ISOBMFF tenc box type -type Tenc struct { - FullBox `mp4:"0,extend"` - Reserved uint8 `mp4:"1,size=8,dec"` - DefaultCryptByteBlock uint8 `mp4:"2,size=4,dec"` // always 0 on version 0 - DefaultSkipByteBlock uint8 `mp4:"3,size=4,dec"` // always 0 on version 0 - DefaultIsProtected uint8 `mp4:"4,size=8,dec"` - DefaultPerSampleIVSize uint8 `mp4:"5,size=8,dec"` - DefaultKID [16]byte `mp4:"6,size=8,uuid"` - DefaultConstantIVSize uint8 `mp4:"7,size=8,opt=dynamic,dec"` - DefaultConstantIV []byte `mp4:"8,size=8,opt=dynamic,len=dynamic"` -} - -func (tenc *Tenc) IsOptFieldEnabled(name string, ctx Context) bool { - switch name { - case "DefaultConstantIVSize", "DefaultConstantIV": - return tenc.DefaultIsProtected == 1 && tenc.DefaultPerSampleIVSize == 0 - } - return false -} - -func (tenc *Tenc) GetFieldLength(name string, ctx Context) uint { - switch name { - case "DefaultConstantIV": - return uint(tenc.DefaultConstantIVSize) - } - panic(fmt.Errorf("invalid name of dynamic-length field: boxType=tenc fieldName=%s", name)) -} - -// GetType returns the BoxType -func (*Tenc) GetType() BoxType { - return BoxTypeTenc() -} - /*************************** tfdt ****************************/ func BoxTypeTfdt() BoxType { return StrToBoxType("tfdt") } @@ -2769,20 +2397,8 @@ func (trun *Trun) GetSampleCompositionTimeOffset(index int) int64 { func BoxTypeUdta() BoxType { return StrToBoxType("udta") } -var udta3GppMetaBoxTypes = []BoxType{ - StrToBoxType("titl"), - StrToBoxType("dscp"), - StrToBoxType("cprt"), - StrToBoxType("perf"), - StrToBoxType("auth"), - StrToBoxType("gnre"), -} - func init() { AddBoxDef(&Udta{}) - for _, bt := range udta3GppMetaBoxTypes { - AddAnyTypeBoxDefEx(&Udta3GppString{}, bt, isUnderUdta, 0) - } } // Udta is ISOBMFF udta box type @@ -2795,14 +2411,6 @@ func (*Udta) GetType() BoxType { return BoxTypeUdta() } -type Udta3GppString struct { - AnyTypeBox - FullBox `mp4:"0,extend"` - Pad bool `mp4:"1,size=1,hidden"` - Language [3]byte `mp4:"2,size=5,iso639-2"` // ISO-639-2/T language code - Data []byte `mp4:"3,size=8,string"` -} - func isUnderUdta(ctx Context) bool { return ctx.UnderUdta } diff --git a/vendor/github.com/abema/go-mp4/box_types_iso14496_14.go b/vendor/github.com/abema/go-mp4/box_types_iso14496_14.go new file mode 100644 index 000000000..fe9880ca0 --- /dev/null +++ b/vendor/github.com/abema/go-mp4/box_types_iso14496_14.go @@ -0,0 +1,126 @@ +package mp4 + +import "fmt" + +/*************************** esds ****************************/ + +// https://developer.apple.com/library/content/documentation/QuickTime/QTFF/QTFFChap3/qtff3.html + +func BoxTypeEsds() BoxType { return StrToBoxType("esds") } + +func init() { + AddBoxDef(&Esds{}, 0) +} + +const ( + ESDescrTag = 0x03 + DecoderConfigDescrTag = 0x04 + DecSpecificInfoTag = 0x05 + SLConfigDescrTag = 0x06 +) + +// Esds is ES descripter box +type Esds struct { + FullBox `mp4:"0,extend"` + Descriptors []Descriptor `mp4:"1,array"` +} + +// GetType returns the BoxType +func (*Esds) GetType() BoxType { + return BoxTypeEsds() +} + +type Descriptor struct { + BaseCustomFieldObject + Tag int8 `mp4:"0,size=8"` // must be 0x03 + Size uint32 `mp4:"1,varint"` + ESDescriptor *ESDescriptor `mp4:"2,extend,opt=dynamic"` + DecoderConfigDescriptor *DecoderConfigDescriptor `mp4:"3,extend,opt=dynamic"` + Data []byte `mp4:"4,size=8,opt=dynamic,len=dynamic"` +} + +// GetFieldLength returns length of dynamic field +func (ds *Descriptor) GetFieldLength(name string, ctx Context) uint { + switch name { + case "Data": + return uint(ds.Size) + } + panic(fmt.Errorf("invalid name of dynamic-length field: boxType=esds fieldName=%s", name)) +} + +func (ds *Descriptor) IsOptFieldEnabled(name string, ctx Context) bool { + switch ds.Tag { + case ESDescrTag: + return name == "ESDescriptor" + case DecoderConfigDescrTag: + return name == "DecoderConfigDescriptor" + default: + return name == "Data" + } +} + +// StringifyField returns field value as string +func (ds *Descriptor) StringifyField(name string, indent string, depth int, ctx Context) (string, bool) { + switch name { + case "Tag": + switch ds.Tag { + case ESDescrTag: + return "ESDescr", true + case DecoderConfigDescrTag: + return "DecoderConfigDescr", true + case DecSpecificInfoTag: + return "DecSpecificInfo", true + case SLConfigDescrTag: + return "SLConfigDescr", true + default: + return "", false + } + default: + return "", false + } +} + +type ESDescriptor struct { + BaseCustomFieldObject + ESID uint16 `mp4:"0,size=16"` + StreamDependenceFlag bool `mp4:"1,size=1"` + UrlFlag bool `mp4:"2,size=1"` + OcrStreamFlag bool `mp4:"3,size=1"` + StreamPriority int8 `mp4:"4,size=5"` + DependsOnESID uint16 `mp4:"5,size=16,opt=dynamic"` + URLLength uint8 `mp4:"6,size=8,opt=dynamic"` + URLString []byte `mp4:"7,size=8,len=dynamic,opt=dynamic,string"` + OCRESID uint16 `mp4:"8,size=16,opt=dynamic"` +} + +func (esds *ESDescriptor) GetFieldLength(name string, ctx Context) uint { + switch name { + case "URLString": + return uint(esds.URLLength) + } + panic(fmt.Errorf("invalid name of dynamic-length field: boxType=ESDescriptor fieldName=%s", name)) +} + +func (esds *ESDescriptor) IsOptFieldEnabled(name string, ctx Context) bool { + switch name { + case "DependsOnESID": + return esds.StreamDependenceFlag + case "URLLength", "URLString": + return esds.UrlFlag + case "OCRESID": + return esds.OcrStreamFlag + default: + return false + } +} + +type DecoderConfigDescriptor struct { + BaseCustomFieldObject + ObjectTypeIndication byte `mp4:"0,size=8"` + StreamType int8 `mp4:"1,size=6"` + UpStream bool `mp4:"2,size=1"` + Reserved bool `mp4:"3,size=1"` + BufferSizeDB uint32 `mp4:"4,size=24"` + MaxBitrate uint32 `mp4:"5,size=32"` + AvgBitrate uint32 `mp4:"6,size=32"` +} diff --git a/vendor/github.com/abema/go-mp4/box_types_iso23001_7.go b/vendor/github.com/abema/go-mp4/box_types_iso23001_7.go new file mode 100644 index 000000000..766c348b0 --- /dev/null +++ b/vendor/github.com/abema/go-mp4/box_types_iso23001_7.go @@ -0,0 +1,108 @@ +package mp4 + +import ( + "bytes" + "fmt" + + "github.com/google/uuid" +) + +/*************************** pssh ****************************/ + +func BoxTypePssh() BoxType { return StrToBoxType("pssh") } + +func init() { + AddBoxDef(&Pssh{}, 0, 1) +} + +// Pssh is ISOBMFF pssh box type +type Pssh struct { + FullBox `mp4:"0,extend"` + SystemID [16]byte `mp4:"1,size=8,uuid"` + KIDCount uint32 `mp4:"2,size=32,nver=0"` + KIDs []PsshKID `mp4:"3,nver=0,len=dynamic,size=128"` + DataSize int32 `mp4:"4,size=32"` + Data []byte `mp4:"5,size=8,len=dynamic"` +} + +type PsshKID struct { + KID [16]byte `mp4:"0,size=8,uuid"` +} + +// GetFieldLength returns length of dynamic field +func (pssh *Pssh) GetFieldLength(name string, ctx Context) uint { + switch name { + case "KIDs": + return uint(pssh.KIDCount) + case "Data": + return uint(pssh.DataSize) + } + panic(fmt.Errorf("invalid name of dynamic-length field: boxType=pssh fieldName=%s", name)) +} + +// StringifyField returns field value as string +func (pssh *Pssh) StringifyField(name string, indent string, depth int, ctx Context) (string, bool) { + switch name { + case "KIDs": + buf := bytes.NewBuffer(nil) + buf.WriteString("[") + for i, e := range pssh.KIDs { + if i != 0 { + buf.WriteString(", ") + } + buf.WriteString(uuid.UUID(e.KID).String()) + } + buf.WriteString("]") + return buf.String(), true + + default: + return "", false + } +} + +// GetType returns the BoxType +func (*Pssh) GetType() BoxType { + return BoxTypePssh() +} + +/*************************** tenc ****************************/ + +func BoxTypeTenc() BoxType { return StrToBoxType("tenc") } + +func init() { + AddBoxDef(&Tenc{}, 0, 1) +} + +// Tenc is ISOBMFF tenc box type +type Tenc struct { + FullBox `mp4:"0,extend"` + Reserved uint8 `mp4:"1,size=8,dec"` + DefaultCryptByteBlock uint8 `mp4:"2,size=4,dec"` // always 0 on version 0 + DefaultSkipByteBlock uint8 `mp4:"3,size=4,dec"` // always 0 on version 0 + DefaultIsProtected uint8 `mp4:"4,size=8,dec"` + DefaultPerSampleIVSize uint8 `mp4:"5,size=8,dec"` + DefaultKID [16]byte `mp4:"6,size=8,uuid"` + DefaultConstantIVSize uint8 `mp4:"7,size=8,opt=dynamic,dec"` + DefaultConstantIV []byte `mp4:"8,size=8,opt=dynamic,len=dynamic"` +} + +func (tenc *Tenc) IsOptFieldEnabled(name string, ctx Context) bool { + switch name { + case "DefaultConstantIVSize", "DefaultConstantIV": + return tenc.DefaultIsProtected == 1 && tenc.DefaultPerSampleIVSize == 0 + } + return false +} + +func (tenc *Tenc) GetFieldLength(name string, ctx Context) uint { + switch name { + case "DefaultConstantIV": + return uint(tenc.DefaultConstantIVSize) + } + panic(fmt.Errorf("invalid name of dynamic-length field: boxType=tenc fieldName=%s", name)) +} + +// GetType returns the BoxType +func (*Tenc) GetType() BoxType { + return BoxTypeTenc() +} diff --git a/vendor/github.com/abema/go-mp4/box_types_metadata.go b/vendor/github.com/abema/go-mp4/box_types_metadata.go new file mode 100644 index 000000000..a56145e99 --- /dev/null +++ b/vendor/github.com/abema/go-mp4/box_types_metadata.go @@ -0,0 +1,172 @@ +package mp4 + +import ( + "fmt" + + "github.com/abema/go-mp4/util" +) + +/*************************** ilst ****************************/ + +func BoxTypeIlst() BoxType { return StrToBoxType("ilst") } +func BoxTypeData() BoxType { return StrToBoxType("data") } + +var ilstMetaBoxTypes = []BoxType{ + StrToBoxType("----"), + StrToBoxType("aART"), + StrToBoxType("akID"), + StrToBoxType("apID"), + StrToBoxType("atID"), + StrToBoxType("cmID"), + StrToBoxType("cnID"), + StrToBoxType("covr"), + StrToBoxType("cpil"), + StrToBoxType("cprt"), + StrToBoxType("desc"), + StrToBoxType("disk"), + StrToBoxType("egid"), + StrToBoxType("geID"), + StrToBoxType("gnre"), + StrToBoxType("pcst"), + StrToBoxType("pgap"), + StrToBoxType("plID"), + StrToBoxType("purd"), + StrToBoxType("purl"), + StrToBoxType("rtng"), + StrToBoxType("sfID"), + StrToBoxType("soaa"), + StrToBoxType("soal"), + StrToBoxType("soar"), + StrToBoxType("soco"), + StrToBoxType("sonm"), + StrToBoxType("sosn"), + StrToBoxType("stik"), + StrToBoxType("tmpo"), + StrToBoxType("trkn"), + StrToBoxType("tven"), + StrToBoxType("tves"), + StrToBoxType("tvnn"), + StrToBoxType("tvsh"), + StrToBoxType("tvsn"), + {0xA9, 'A', 'R', 'T'}, + {0xA9, 'a', 'l', 'b'}, + {0xA9, 'c', 'm', 't'}, + {0xA9, 'c', 'o', 'm'}, + {0xA9, 'd', 'a', 'y'}, + {0xA9, 'g', 'e', 'n'}, + {0xA9, 'g', 'r', 'p'}, + {0xA9, 'n', 'a', 'm'}, + {0xA9, 't', 'o', 'o'}, + {0xA9, 'w', 'r', 't'}, +} + +func IsIlstMetaBoxType(boxType BoxType) bool { + for _, bt := range ilstMetaBoxTypes { + if boxType == bt { + return true + } + } + return false +} + +func init() { + AddBoxDef(&Ilst{}) + AddBoxDefEx(&Data{}, isUnderIlstMeta) + for _, bt := range ilstMetaBoxTypes { + AddAnyTypeBoxDefEx(&IlstMetaContainer{}, bt, isIlstMetaContainer) + } + AddAnyTypeBoxDefEx(&StringData{}, StrToBoxType("mean"), isUnderIlstFreeFormat) + AddAnyTypeBoxDefEx(&StringData{}, StrToBoxType("name"), isUnderIlstFreeFormat) +} + +type Ilst struct { + Box +} + +// GetType returns the BoxType +func (*Ilst) GetType() BoxType { + return BoxTypeIlst() +} + +type IlstMetaContainer struct { + AnyTypeBox +} + +func isIlstMetaContainer(ctx Context) bool { + return ctx.UnderIlst && !ctx.UnderIlstMeta +} + +const ( + DataTypeBinary = 0 + DataTypeStringUTF8 = 1 + DataTypeStringUTF16 = 2 + DataTypeStringMac = 3 + DataTypeStringJPEG = 14 + DataTypeSignedIntBigEndian = 21 + DataTypeFloat32BigEndian = 22 + DataTypeFloat64BigEndian = 23 +) + +type Data struct { + Box + DataType uint32 `mp4:"0,size=32"` + DataLang uint32 `mp4:"1,size=32"` + Data []byte `mp4:"2,size=8"` +} + +// GetType returns the BoxType +func (*Data) GetType() BoxType { + return BoxTypeData() +} + +func isUnderIlstMeta(ctx Context) bool { + return ctx.UnderIlstMeta +} + +// StringifyField returns field value as string +func (data *Data) StringifyField(name string, indent string, depth int, ctx Context) (string, bool) { + switch name { + case "DataType": + switch data.DataType { + case DataTypeBinary: + return "BINARY", true + case DataTypeStringUTF8: + return "UTF8", true + case DataTypeStringUTF16: + return "UTF16", true + case DataTypeStringMac: + return "MAC_STR", true + case DataTypeStringJPEG: + return "JPEG", true + case DataTypeSignedIntBigEndian: + return "INT", true + case DataTypeFloat32BigEndian: + return "FLOAT32", true + case DataTypeFloat64BigEndian: + return "FLOAT64", true + } + case "Data": + switch data.DataType { + case DataTypeStringUTF8: + return fmt.Sprintf("\"%s\"", util.EscapeUnprintables(string(data.Data))), true + } + } + return "", false +} + +type StringData struct { + AnyTypeBox + Data []byte `mp4:"0,size=8"` +} + +// StringifyField returns field value as string +func (sd *StringData) StringifyField(name string, indent string, depth int, ctx Context) (string, bool) { + if name == "Data" { + return fmt.Sprintf("\"%s\"", util.EscapeUnprintables(string(sd.Data))), true + } + return "", false +} + +func isUnderIlstFreeFormat(ctx Context) bool { + return ctx.UnderIlstFreeMeta +} diff --git a/vendor/github.com/abema/go-mp4/box_types_opus.go b/vendor/github.com/abema/go-mp4/box_types_opus.go new file mode 100644 index 000000000..5d02d365d --- /dev/null +++ b/vendor/github.com/abema/go-mp4/box_types_opus.go @@ -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 +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 0f6884fb1..645c71666 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -77,7 +77,7 @@ github.com/DmitriyVTitov/size ## explicit; go 1.19 github.com/KimMachineGun/automemlimit github.com/KimMachineGun/automemlimit/memlimit -# github.com/abema/go-mp4 v0.11.0 +# github.com/abema/go-mp4 v0.12.0 ## explicit; go 1.14 github.com/abema/go-mp4 github.com/abema/go-mp4/bitio