extract.go (2088B)
1 package mp4 2 3 import ( 4 "errors" 5 "io" 6 ) 7 8 type BoxInfoWithPayload struct { 9 Info BoxInfo 10 Payload IBox 11 } 12 13 func ExtractBoxWithPayload(r io.ReadSeeker, parent *BoxInfo, path BoxPath) ([]*BoxInfoWithPayload, error) { 14 return ExtractBoxesWithPayload(r, parent, []BoxPath{path}) 15 } 16 17 func ExtractBoxesWithPayload(r io.ReadSeeker, parent *BoxInfo, paths []BoxPath) ([]*BoxInfoWithPayload, error) { 18 bis, err := ExtractBoxes(r, parent, paths) 19 if err != nil { 20 return nil, err 21 } 22 23 bs := make([]*BoxInfoWithPayload, 0, len(bis)) 24 for _, bi := range bis { 25 if _, err := bi.SeekToPayload(r); err != nil { 26 return nil, err 27 } 28 29 var ctx Context 30 if parent != nil { 31 ctx = parent.Context 32 } 33 box, _, err := UnmarshalAny(r, bi.Type, bi.Size-bi.HeaderSize, ctx) 34 if err != nil { 35 return nil, err 36 } 37 bs = append(bs, &BoxInfoWithPayload{ 38 Info: *bi, 39 Payload: box, 40 }) 41 } 42 return bs, nil 43 } 44 45 func ExtractBox(r io.ReadSeeker, parent *BoxInfo, path BoxPath) ([]*BoxInfo, error) { 46 return ExtractBoxes(r, parent, []BoxPath{path}) 47 } 48 49 func ExtractBoxes(r io.ReadSeeker, parent *BoxInfo, paths []BoxPath) ([]*BoxInfo, error) { 50 if len(paths) == 0 { 51 return nil, nil 52 } 53 54 for i := range paths { 55 if len(paths[i]) == 0 { 56 return nil, errors.New("box path must not be empty") 57 } 58 } 59 60 boxes := make([]*BoxInfo, 0, 8) 61 62 handler := func(handle *ReadHandle) (interface{}, error) { 63 path := handle.Path 64 if parent != nil { 65 path = path[1:] 66 } 67 if handle.BoxInfo.Type == BoxTypeAny() { 68 return nil, nil 69 } 70 fm, m := matchPath(paths, path) 71 if m { 72 boxes = append(boxes, &handle.BoxInfo) 73 } 74 75 if fm { 76 if _, err := handle.Expand(); err != nil { 77 return nil, err 78 } 79 } 80 return nil, nil 81 } 82 83 if parent != nil { 84 _, err := ReadBoxStructureFromInternal(r, parent, handler) 85 return boxes, err 86 } 87 _, err := ReadBoxStructure(r, handler) 88 return boxes, err 89 } 90 91 func matchPath(paths []BoxPath, path BoxPath) (forwardMatch bool, match bool) { 92 for i := range paths { 93 fm, m := path.compareWith(paths[i]) 94 forwardMatch = forwardMatch || fm 95 match = match || m 96 } 97 return 98 }