summaryrefslogtreecommitdiff
path: root/vendor/github.com/abema/go-mp4/field.go
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2022-12-17 05:38:56 +0100
committerLibravatar GitHub <noreply@github.com>2022-12-17 04:38:56 +0000
commit2bbc64be4317166d3abb7aa177d4913f166a53e8 (patch)
tree88c3d613eb986b18894f311afa4291987a0e26c4 /vendor/github.com/abema/go-mp4/field.go
parent[chore] fix some little config whoopsies (#1272) (diff)
downloadgotosocial-2bbc64be4317166d3abb7aa177d4913f166a53e8.tar.xz
[feature] Enable basic video support (mp4 only) (#1274)
* [feature] basic video support * fix missing semicolon * replace text shadow with stacked icons Co-authored-by: f0x <f0x@cthu.lu>
Diffstat (limited to 'vendor/github.com/abema/go-mp4/field.go')
-rw-r--r--vendor/github.com/abema/go-mp4/field.go290
1 files changed, 290 insertions, 0 deletions
diff --git a/vendor/github.com/abema/go-mp4/field.go b/vendor/github.com/abema/go-mp4/field.go
new file mode 100644
index 000000000..585833e0d
--- /dev/null
+++ b/vendor/github.com/abema/go-mp4/field.go
@@ -0,0 +1,290 @@
+package mp4
+
+import (
+ "fmt"
+ "os"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+)
+
+type (
+ stringType uint8
+ fieldFlag uint16
+)
+
+const (
+ stringType_C stringType = iota
+ stringType_C_P
+
+ fieldString fieldFlag = 1 << iota // 0
+ fieldExtend // 1
+ fieldDec // 2
+ fieldHex // 3
+ fieldISO639_2 // 4
+ fieldUUID // 5
+ fieldHidden // 6
+ fieldOptDynamic // 7
+ fieldVarint // 8
+ fieldSizeDynamic // 9
+ fieldLengthDynamic // 10
+)
+
+type field struct {
+ children []*field
+ name string
+ cnst string
+ order int
+ optFlag uint32
+ nOptFlag uint32
+ size uint
+ length uint
+ flags fieldFlag
+ strType stringType
+ version uint8
+ nVersion uint8
+}
+
+func (f *field) set(flag fieldFlag) {
+ f.flags |= flag
+}
+
+func (f *field) is(flag fieldFlag) bool {
+ return f.flags&flag != 0
+}
+
+func buildFields(box IImmutableBox) []*field {
+ t := reflect.TypeOf(box).Elem()
+ return buildFieldsStruct(t)
+}
+
+func buildFieldsStruct(t reflect.Type) []*field {
+ fs := make([]*field, 0, 8)
+ for i := 0; i < t.NumField(); i++ {
+ ft := t.Field(i).Type
+ tag, ok := t.Field(i).Tag.Lookup("mp4")
+ if !ok {
+ continue
+ }
+ f := buildField(t.Field(i).Name, tag)
+ f.children = buildFieldsAny(ft)
+ fs = append(fs, f)
+ }
+ sort.SliceStable(fs, func(i, j int) bool {
+ return fs[i].order < fs[j].order
+ })
+ return fs
+}
+
+func buildFieldsAny(t reflect.Type) []*field {
+ switch t.Kind() {
+ case reflect.Struct:
+ return buildFieldsStruct(t)
+ case reflect.Ptr, reflect.Array, reflect.Slice:
+ return buildFieldsAny(t.Elem())
+ default:
+ return nil
+ }
+}
+
+func buildField(fieldName string, tag string) *field {
+ f := &field{
+ name: fieldName,
+ }
+ tagMap := parseFieldTag(tag)
+ for key, val := range tagMap {
+ if val != "" {
+ continue
+ }
+ if order, err := strconv.Atoi(key); err == nil {
+ f.order = order
+ break
+ }
+ }
+
+ if val, contained := tagMap["string"]; contained {
+ f.set(fieldString)
+ if val == "c_p" {
+ f.strType = stringType_C_P
+ fmt.Fprint(os.Stderr, "go-mp4: string=c_p tag is deprecated!! See https://github.com/abema/go-mp4/issues/76\n")
+ }
+ }
+
+ if _, contained := tagMap["varint"]; contained {
+ f.set(fieldVarint)
+ }
+
+ if val, contained := tagMap["opt"]; contained {
+ if val == "dynamic" {
+ f.set(fieldOptDynamic)
+ } else {
+ base := 10
+ if strings.HasPrefix(val, "0x") {
+ val = val[2:]
+ base = 16
+ }
+ opt, err := strconv.ParseUint(val, base, 32)
+ if err != nil {
+ panic(err)
+ }
+ f.optFlag = uint32(opt)
+ }
+ }
+
+ if val, contained := tagMap["nopt"]; contained {
+ base := 10
+ if strings.HasPrefix(val, "0x") {
+ val = val[2:]
+ base = 16
+ }
+ nopt, err := strconv.ParseUint(val, base, 32)
+ if err != nil {
+ panic(err)
+ }
+ f.nOptFlag = uint32(nopt)
+ }
+
+ if _, contained := tagMap["extend"]; contained {
+ f.set(fieldExtend)
+ }
+
+ if _, contained := tagMap["dec"]; contained {
+ f.set(fieldDec)
+ }
+
+ if _, contained := tagMap["hex"]; contained {
+ f.set(fieldHex)
+ }
+
+ if _, contained := tagMap["iso639-2"]; contained {
+ f.set(fieldISO639_2)
+ }
+
+ if _, contained := tagMap["uuid"]; contained {
+ f.set(fieldUUID)
+ }
+
+ if _, contained := tagMap["hidden"]; contained {
+ f.set(fieldHidden)
+ }
+
+ if val, contained := tagMap["const"]; contained {
+ f.cnst = val
+ }
+
+ f.version = anyVersion
+ if val, contained := tagMap["ver"]; contained {
+ ver, err := strconv.Atoi(val)
+ if err != nil {
+ panic(err)
+ }
+ f.version = uint8(ver)
+ }
+
+ f.nVersion = anyVersion
+ if val, contained := tagMap["nver"]; contained {
+ ver, err := strconv.Atoi(val)
+ if err != nil {
+ panic(err)
+ }
+ f.nVersion = uint8(ver)
+ }
+
+ if val, contained := tagMap["size"]; contained {
+ if val == "dynamic" {
+ f.set(fieldSizeDynamic)
+ } else {
+ size, err := strconv.ParseUint(val, 10, 32)
+ if err != nil {
+ panic(err)
+ }
+ f.size = uint(size)
+ }
+ }
+
+ f.length = LengthUnlimited
+ if val, contained := tagMap["len"]; contained {
+ if val == "dynamic" {
+ f.set(fieldLengthDynamic)
+ } else {
+ l, err := strconv.ParseUint(val, 10, 32)
+ if err != nil {
+ panic(err)
+ }
+ f.length = uint(l)
+ }
+ }
+
+ return f
+}
+
+func parseFieldTag(str string) map[string]string {
+ tag := make(map[string]string, 8)
+
+ list := strings.Split(str, ",")
+ for _, e := range list {
+ kv := strings.SplitN(e, "=", 2)
+ if len(kv) == 2 {
+ tag[strings.Trim(kv[0], " ")] = strings.Trim(kv[1], " ")
+ } else {
+ tag[strings.Trim(kv[0], " ")] = ""
+ }
+ }
+
+ return tag
+}
+
+type fieldInstance struct {
+ field
+ cfo ICustomFieldObject
+}
+
+func resolveFieldInstance(f *field, box IImmutableBox, parent reflect.Value, ctx Context) *fieldInstance {
+ fi := fieldInstance{
+ field: *f,
+ }
+
+ cfo, ok := parent.Addr().Interface().(ICustomFieldObject)
+ if ok {
+ fi.cfo = cfo
+ } else {
+ fi.cfo = box
+ }
+
+ if fi.is(fieldSizeDynamic) {
+ fi.size = fi.cfo.GetFieldSize(f.name, ctx)
+ }
+
+ if fi.is(fieldLengthDynamic) {
+ fi.length = fi.cfo.GetFieldLength(f.name, ctx)
+ }
+
+ return &fi
+}
+
+func isTargetField(box IImmutableBox, fi *fieldInstance, ctx Context) bool {
+ if box.GetVersion() != anyVersion {
+ if fi.version != anyVersion && box.GetVersion() != fi.version {
+ return false
+ }
+
+ if fi.nVersion != anyVersion && box.GetVersion() == fi.nVersion {
+ return false
+ }
+ }
+
+ if fi.optFlag != 0 && box.GetFlags()&fi.optFlag == 0 {
+ return false
+ }
+
+ if fi.nOptFlag != 0 && box.GetFlags()&fi.nOptFlag != 0 {
+ return false
+ }
+
+ if fi.is(fieldOptDynamic) && !fi.cfo.IsOptFieldEnabled(fi.name, ctx) {
+ return false
+ }
+
+ return true
+}