mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2024-11-24 13:23:20 +00:00
99 lines
2 KiB
Go
99 lines
2 KiB
Go
|
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
|
||
|
}
|