package mp4 import ( "errors" "io" ) type BoxInfoWithPayload struct { Info BoxInfo Payload IBox } func ExtractBoxWithPayload(r io.ReadSeeker, parent *BoxInfo, path BoxPath) ([]*BoxInfoWithPayload, error) { return ExtractBoxesWithPayload(r, parent, []BoxPath{path}) } func ExtractBoxesWithPayload(r io.ReadSeeker, parent *BoxInfo, paths []BoxPath) ([]*BoxInfoWithPayload, error) { bis, err := ExtractBoxes(r, parent, paths) if err != nil { return nil, err } bs := make([]*BoxInfoWithPayload, 0, len(bis)) for _, bi := range bis { if _, err := bi.SeekToPayload(r); err != nil { return nil, err } var ctx Context if parent != nil { ctx = parent.Context } box, _, err := UnmarshalAny(r, bi.Type, bi.Size-bi.HeaderSize, ctx) if err != nil { return nil, err } bs = append(bs, &BoxInfoWithPayload{ Info: *bi, Payload: box, }) } return bs, nil } func ExtractBox(r io.ReadSeeker, parent *BoxInfo, path BoxPath) ([]*BoxInfo, error) { return ExtractBoxes(r, parent, []BoxPath{path}) } func ExtractBoxes(r io.ReadSeeker, parent *BoxInfo, paths []BoxPath) ([]*BoxInfo, error) { if len(paths) == 0 { return nil, nil } for i := range paths { if len(paths[i]) == 0 { return nil, errors.New("box path must not be empty") } } boxes := make([]*BoxInfo, 0, 8) handler := func(handle *ReadHandle) (interface{}, error) { path := handle.Path if parent != nil { path = path[1:] } if handle.BoxInfo.Type == BoxTypeAny() { return nil, nil } fm, m := matchPath(paths, path) if m { boxes = append(boxes, &handle.BoxInfo) } if fm { if _, err := handle.Expand(); err != nil { return nil, err } } return nil, nil } if parent != nil { _, err := ReadBoxStructureFromInternal(r, parent, handler) return boxes, err } _, err := ReadBoxStructure(r, handler) return boxes, err } func matchPath(paths []BoxPath, path BoxPath) (forwardMatch bool, match bool) { for i := range paths { fm, m := path.compareWith(paths[i]) forwardMatch = forwardMatch || fm match = match || m } return }