test hls ll
This commit is contained in:
204
format/fmp4/fmp4io/atom.go
Normal file
204
format/fmp4/fmp4io/atom.go
Normal file
@@ -0,0 +1,204 @@
|
||||
package fmp4io
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/deepch/vdk/utils/bits/pio"
|
||||
)
|
||||
|
||||
type Tag uint32
|
||||
|
||||
func (a Tag) String() string {
|
||||
var b [4]byte
|
||||
pio.PutU32BE(b[:], uint32(a))
|
||||
for i := 0; i < 4; i++ {
|
||||
if b[i] == 0 {
|
||||
b[i] = ' '
|
||||
}
|
||||
}
|
||||
return string(b[:])
|
||||
}
|
||||
|
||||
type Atom interface {
|
||||
Pos() (int, int)
|
||||
Tag() Tag
|
||||
Marshal([]byte) int
|
||||
Unmarshal([]byte, int) (int, error)
|
||||
Len() int
|
||||
Children() []Atom
|
||||
}
|
||||
|
||||
type AtomPos struct {
|
||||
Offset int
|
||||
Size int
|
||||
}
|
||||
|
||||
func (a AtomPos) Pos() (int, int) {
|
||||
return a.Offset, a.Size
|
||||
}
|
||||
|
||||
func (a *AtomPos) setPos(offset int, size int) {
|
||||
a.Offset, a.Size = offset, size
|
||||
}
|
||||
|
||||
type Dummy struct {
|
||||
Data []byte
|
||||
Tag_ Tag
|
||||
AtomPos
|
||||
}
|
||||
|
||||
func (a Dummy) Children() []Atom {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a Dummy) Tag() Tag {
|
||||
return a.Tag_
|
||||
}
|
||||
|
||||
func (a Dummy) Len() int {
|
||||
return len(a.Data)
|
||||
}
|
||||
|
||||
func (a Dummy) Marshal(b []byte) int {
|
||||
copy(b, a.Data)
|
||||
return len(a.Data)
|
||||
}
|
||||
|
||||
func (a *Dummy) Unmarshal(b []byte, offset int) (n int, err error) {
|
||||
(&a.AtomPos).setPos(offset, len(b))
|
||||
a.Data = b
|
||||
n = len(b)
|
||||
return
|
||||
}
|
||||
|
||||
type FullAtom struct {
|
||||
Version uint8
|
||||
Flags uint32
|
||||
AtomPos
|
||||
}
|
||||
|
||||
func (f FullAtom) marshalAtom(b []byte, tag Tag) (n int) {
|
||||
pio.PutU32BE(b[4:], uint32(tag))
|
||||
pio.PutU8(b[8:], f.Version)
|
||||
pio.PutU24BE(b[9:], f.Flags)
|
||||
return 12
|
||||
}
|
||||
|
||||
func (f FullAtom) atomLen() int {
|
||||
return 12
|
||||
}
|
||||
|
||||
func (f *FullAtom) unmarshalAtom(b []byte, offset int) (n int, err error) {
|
||||
f.AtomPos.setPos(offset, len(b))
|
||||
n = 8
|
||||
if len(b) < n+4 {
|
||||
return 0, parseErr("fullAtom", offset, nil)
|
||||
}
|
||||
f.Version = pio.U8(b[n:])
|
||||
f.Flags = pio.U24BE(b[n+1:])
|
||||
n += 4
|
||||
return
|
||||
}
|
||||
|
||||
func StringToTag(tag string) Tag {
|
||||
var b [4]byte
|
||||
copy(b[:], []byte(tag))
|
||||
return Tag(pio.U32BE(b[:]))
|
||||
}
|
||||
|
||||
func FindChildrenByName(root Atom, tag string) Atom {
|
||||
return FindChildren(root, StringToTag(tag))
|
||||
}
|
||||
|
||||
func FindChildren(root Atom, tag Tag) Atom {
|
||||
if root.Tag() == tag {
|
||||
return root
|
||||
}
|
||||
for _, child := range root.Children() {
|
||||
if r := FindChildren(child, tag); r != nil {
|
||||
return r
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReadFileAtoms(r io.ReadSeeker) (atoms []Atom, err error) {
|
||||
for {
|
||||
offset, _ := r.Seek(0, 1)
|
||||
taghdr := make([]byte, 8)
|
||||
if _, err = io.ReadFull(r, taghdr); err != nil {
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
size := pio.U32BE(taghdr[0:])
|
||||
tag := Tag(pio.U32BE(taghdr[4:]))
|
||||
|
||||
var atom Atom
|
||||
switch tag {
|
||||
case FTYP:
|
||||
atom = &FileType{}
|
||||
case STYP:
|
||||
atom = &SegmentType{}
|
||||
case MOOV:
|
||||
atom = &Movie{}
|
||||
case MOOF:
|
||||
atom = &MovieFrag{}
|
||||
case SIDX:
|
||||
atom = &SegmentIndex{}
|
||||
}
|
||||
|
||||
if atom != nil {
|
||||
b := make([]byte, int(size))
|
||||
if _, err = io.ReadFull(r, b[8:]); err != nil {
|
||||
return
|
||||
}
|
||||
copy(b, taghdr)
|
||||
if _, err = atom.Unmarshal(b, int(offset)); err != nil {
|
||||
return
|
||||
}
|
||||
atoms = append(atoms, atom)
|
||||
} else {
|
||||
dummy := &Dummy{Tag_: tag}
|
||||
dummy.setPos(int(offset), int(size))
|
||||
if _, err = r.Seek(int64(size)-8, 1); err != nil {
|
||||
return
|
||||
}
|
||||
atoms = append(atoms, dummy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printatom(out io.Writer, root Atom, depth int) {
|
||||
offset, size := root.Pos()
|
||||
|
||||
type stringintf interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
fmt.Fprintf(out,
|
||||
"%s%s offset=%d size=%d",
|
||||
strings.Repeat(" ", depth*2), root.Tag(), offset, size,
|
||||
)
|
||||
if str, ok := root.(stringintf); ok {
|
||||
fmt.Fprint(out, " ", str.String())
|
||||
}
|
||||
fmt.Fprintln(out)
|
||||
|
||||
children := root.Children()
|
||||
for _, child := range children {
|
||||
printatom(out, child, depth+1)
|
||||
}
|
||||
}
|
||||
|
||||
func FprintAtom(out io.Writer, root Atom) {
|
||||
printatom(out, root, 0)
|
||||
}
|
||||
|
||||
func PrintAtom(root Atom) {
|
||||
FprintAtom(os.Stdout, root)
|
||||
}
|
||||
Reference in New Issue
Block a user