test hls ll
This commit is contained in:
616
format/fmp4/fmp4io/media.go
Normal file
616
format/fmp4/fmp4io/media.go
Normal file
@@ -0,0 +1,616 @@
|
||||
package fmp4io
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/deepch/vdk/utils/bits/pio"
|
||||
)
|
||||
|
||||
const MDIA = Tag(0x6d646961)
|
||||
|
||||
type Media struct {
|
||||
Header *MediaHeader
|
||||
Handler *HandlerRefer
|
||||
Info *MediaInfo
|
||||
Unknowns []Atom
|
||||
AtomPos
|
||||
}
|
||||
|
||||
func (a Media) Marshal(b []byte) (n int) {
|
||||
pio.PutU32BE(b[4:], uint32(MDIA))
|
||||
n += a.marshal(b[8:]) + 8
|
||||
pio.PutU32BE(b[0:], uint32(n))
|
||||
return
|
||||
}
|
||||
|
||||
func (a Media) marshal(b []byte) (n int) {
|
||||
if a.Header != nil {
|
||||
n += a.Header.Marshal(b[n:])
|
||||
}
|
||||
if a.Handler != nil {
|
||||
n += a.Handler.Marshal(b[n:])
|
||||
}
|
||||
if a.Info != nil {
|
||||
n += a.Info.Marshal(b[n:])
|
||||
}
|
||||
for _, atom := range a.Unknowns {
|
||||
n += atom.Marshal(b[n:])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a Media) Len() (n int) {
|
||||
n += 8
|
||||
if a.Header != nil {
|
||||
n += a.Header.Len()
|
||||
}
|
||||
if a.Handler != nil {
|
||||
n += a.Handler.Len()
|
||||
}
|
||||
if a.Info != nil {
|
||||
n += a.Info.Len()
|
||||
}
|
||||
for _, atom := range a.Unknowns {
|
||||
n += atom.Len()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a *Media) Unmarshal(b []byte, offset int) (n int, err error) {
|
||||
(&a.AtomPos).setPos(offset, len(b))
|
||||
n += 8
|
||||
for n+8 < len(b) {
|
||||
tag := Tag(pio.U32BE(b[n+4:]))
|
||||
size := int(pio.U32BE(b[n:]))
|
||||
if len(b) < n+size {
|
||||
err = parseErr("TagSizeInvalid", n+offset, err)
|
||||
return
|
||||
}
|
||||
switch tag {
|
||||
case MDHD:
|
||||
{
|
||||
atom := &MediaHeader{}
|
||||
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
||||
err = parseErr("mdhd", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Header = atom
|
||||
}
|
||||
case HDLR:
|
||||
{
|
||||
atom := &HandlerRefer{}
|
||||
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
||||
err = parseErr("hdlr", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Handler = atom
|
||||
}
|
||||
case MINF:
|
||||
{
|
||||
atom := &MediaInfo{}
|
||||
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
||||
err = parseErr("minf", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Info = atom
|
||||
}
|
||||
default:
|
||||
{
|
||||
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
|
||||
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
||||
err = parseErr("", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Unknowns = append(a.Unknowns, atom)
|
||||
}
|
||||
}
|
||||
n += size
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a Media) Children() (r []Atom) {
|
||||
if a.Header != nil {
|
||||
r = append(r, a.Header)
|
||||
}
|
||||
if a.Handler != nil {
|
||||
r = append(r, a.Handler)
|
||||
}
|
||||
if a.Info != nil {
|
||||
r = append(r, a.Info)
|
||||
}
|
||||
r = append(r, a.Unknowns...)
|
||||
return
|
||||
}
|
||||
|
||||
func (a Media) Tag() Tag {
|
||||
return MDIA
|
||||
}
|
||||
|
||||
const MDHD = Tag(0x6d646864)
|
||||
|
||||
type MediaHeader struct {
|
||||
Version uint8
|
||||
Flags uint32
|
||||
CreateTime time.Time
|
||||
ModifyTime time.Time
|
||||
TimeScale uint32
|
||||
Duration uint32
|
||||
Language int16
|
||||
Quality int16
|
||||
AtomPos
|
||||
}
|
||||
|
||||
func (a MediaHeader) Marshal(b []byte) (n int) {
|
||||
pio.PutU32BE(b[4:], uint32(MDHD))
|
||||
n += a.marshal(b[8:]) + 8
|
||||
pio.PutU32BE(b[0:], uint32(n))
|
||||
return
|
||||
}
|
||||
|
||||
func (a MediaHeader) marshal(b []byte) (n int) {
|
||||
pio.PutU8(b[n:], a.Version)
|
||||
n += 1
|
||||
pio.PutU24BE(b[n:], a.Flags)
|
||||
n += 3
|
||||
PutTime32(b[n:], a.CreateTime)
|
||||
n += 4
|
||||
PutTime32(b[n:], a.ModifyTime)
|
||||
n += 4
|
||||
pio.PutU32BE(b[n:], a.TimeScale)
|
||||
n += 4
|
||||
pio.PutU32BE(b[n:], a.Duration)
|
||||
n += 4
|
||||
pio.PutI16BE(b[n:], a.Language)
|
||||
n += 2
|
||||
pio.PutI16BE(b[n:], a.Quality)
|
||||
n += 2
|
||||
return
|
||||
}
|
||||
|
||||
func (a MediaHeader) Len() (n int) {
|
||||
n += 8
|
||||
n += 1
|
||||
n += 3
|
||||
n += 4
|
||||
n += 4
|
||||
n += 4
|
||||
n += 4
|
||||
n += 2
|
||||
n += 2
|
||||
return
|
||||
}
|
||||
|
||||
func (a *MediaHeader) Unmarshal(b []byte, offset int) (n int, err error) {
|
||||
(&a.AtomPos).setPos(offset, len(b))
|
||||
n += 8
|
||||
if len(b) < n+1 {
|
||||
err = parseErr("Version", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Version = pio.U8(b[n:])
|
||||
n += 1
|
||||
if len(b) < n+3 {
|
||||
err = parseErr("Flags", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Flags = pio.U24BE(b[n:])
|
||||
n += 3
|
||||
if len(b) < n+4 {
|
||||
err = parseErr("CreateTime", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.CreateTime = GetTime32(b[n:])
|
||||
n += 4
|
||||
if len(b) < n+4 {
|
||||
err = parseErr("ModifyTime", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.ModifyTime = GetTime32(b[n:])
|
||||
n += 4
|
||||
if len(b) < n+4 {
|
||||
err = parseErr("TimeScale", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.TimeScale = pio.U32BE(b[n:])
|
||||
n += 4
|
||||
if len(b) < n+4 {
|
||||
err = parseErr("Duration", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Duration = pio.U32BE(b[n:])
|
||||
n += 4
|
||||
if len(b) < n+2 {
|
||||
err = parseErr("Language", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Language = pio.I16BE(b[n:])
|
||||
n += 2
|
||||
if len(b) < n+2 {
|
||||
err = parseErr("Quality", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Quality = pio.I16BE(b[n:])
|
||||
n += 2
|
||||
return
|
||||
}
|
||||
|
||||
func (a MediaHeader) Children() (r []Atom) {
|
||||
return
|
||||
}
|
||||
|
||||
func (a MediaHeader) Tag() Tag {
|
||||
return MDHD
|
||||
}
|
||||
|
||||
const MINF = Tag(0x6d696e66)
|
||||
|
||||
type MediaInfo struct {
|
||||
Sound *SoundMediaInfo
|
||||
Video *VideoMediaInfo
|
||||
Data *DataInfo
|
||||
Sample *SampleTable
|
||||
Unknowns []Atom
|
||||
AtomPos
|
||||
}
|
||||
|
||||
func (a MediaInfo) Marshal(b []byte) (n int) {
|
||||
pio.PutU32BE(b[4:], uint32(MINF))
|
||||
n += a.marshal(b[8:]) + 8
|
||||
pio.PutU32BE(b[0:], uint32(n))
|
||||
return
|
||||
}
|
||||
|
||||
func (a MediaInfo) marshal(b []byte) (n int) {
|
||||
if a.Sound != nil {
|
||||
n += a.Sound.Marshal(b[n:])
|
||||
}
|
||||
if a.Video != nil {
|
||||
n += a.Video.Marshal(b[n:])
|
||||
}
|
||||
if a.Data != nil {
|
||||
n += a.Data.Marshal(b[n:])
|
||||
}
|
||||
if a.Sample != nil {
|
||||
n += a.Sample.Marshal(b[n:])
|
||||
}
|
||||
for _, atom := range a.Unknowns {
|
||||
n += atom.Marshal(b[n:])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a MediaInfo) Len() (n int) {
|
||||
n += 8
|
||||
if a.Sound != nil {
|
||||
n += a.Sound.Len()
|
||||
}
|
||||
if a.Video != nil {
|
||||
n += a.Video.Len()
|
||||
}
|
||||
if a.Data != nil {
|
||||
n += a.Data.Len()
|
||||
}
|
||||
if a.Sample != nil {
|
||||
n += a.Sample.Len()
|
||||
}
|
||||
for _, atom := range a.Unknowns {
|
||||
n += atom.Len()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a *MediaInfo) Unmarshal(b []byte, offset int) (n int, err error) {
|
||||
(&a.AtomPos).setPos(offset, len(b))
|
||||
n += 8
|
||||
for n+8 < len(b) {
|
||||
tag := Tag(pio.U32BE(b[n+4:]))
|
||||
size := int(pio.U32BE(b[n:]))
|
||||
if len(b) < n+size {
|
||||
err = parseErr("TagSizeInvalid", n+offset, err)
|
||||
return
|
||||
}
|
||||
switch tag {
|
||||
case SMHD:
|
||||
{
|
||||
atom := &SoundMediaInfo{}
|
||||
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
||||
err = parseErr("smhd", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Sound = atom
|
||||
}
|
||||
case VMHD:
|
||||
{
|
||||
atom := &VideoMediaInfo{}
|
||||
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
||||
err = parseErr("vmhd", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Video = atom
|
||||
}
|
||||
case DINF:
|
||||
{
|
||||
atom := &DataInfo{}
|
||||
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
||||
err = parseErr("dinf", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Data = atom
|
||||
}
|
||||
case STBL:
|
||||
{
|
||||
atom := &SampleTable{}
|
||||
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
||||
err = parseErr("stbl", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Sample = atom
|
||||
}
|
||||
default:
|
||||
{
|
||||
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
|
||||
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
||||
err = parseErr("", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Unknowns = append(a.Unknowns, atom)
|
||||
}
|
||||
}
|
||||
n += size
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a MediaInfo) Children() (r []Atom) {
|
||||
if a.Sound != nil {
|
||||
r = append(r, a.Sound)
|
||||
}
|
||||
if a.Video != nil {
|
||||
r = append(r, a.Video)
|
||||
}
|
||||
if a.Data != nil {
|
||||
r = append(r, a.Data)
|
||||
}
|
||||
if a.Sample != nil {
|
||||
r = append(r, a.Sample)
|
||||
}
|
||||
r = append(r, a.Unknowns...)
|
||||
return
|
||||
}
|
||||
|
||||
func (a MediaInfo) Tag() Tag {
|
||||
return MINF
|
||||
}
|
||||
|
||||
const VMHD = Tag(0x766d6864)
|
||||
|
||||
type VideoMediaInfo struct {
|
||||
Version uint8
|
||||
Flags uint32
|
||||
GraphicsMode int16
|
||||
Opcolor [3]int16
|
||||
AtomPos
|
||||
}
|
||||
|
||||
func (a VideoMediaInfo) Marshal(b []byte) (n int) {
|
||||
pio.PutU32BE(b[4:], uint32(VMHD))
|
||||
n += a.marshal(b[8:]) + 8
|
||||
pio.PutU32BE(b[0:], uint32(n))
|
||||
return
|
||||
}
|
||||
|
||||
func (a VideoMediaInfo) marshal(b []byte) (n int) {
|
||||
pio.PutU8(b[n:], a.Version)
|
||||
n += 1
|
||||
pio.PutU24BE(b[n:], a.Flags)
|
||||
n += 3
|
||||
pio.PutI16BE(b[n:], a.GraphicsMode)
|
||||
n += 2
|
||||
for _, entry := range a.Opcolor {
|
||||
pio.PutI16BE(b[n:], entry)
|
||||
n += 2
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a VideoMediaInfo) Len() (n int) {
|
||||
n += 8
|
||||
n += 1
|
||||
n += 3
|
||||
n += 2
|
||||
n += 2 * len(a.Opcolor[:])
|
||||
return
|
||||
}
|
||||
|
||||
func (a *VideoMediaInfo) Unmarshal(b []byte, offset int) (n int, err error) {
|
||||
(&a.AtomPos).setPos(offset, len(b))
|
||||
n += 8
|
||||
if len(b) < n+1 {
|
||||
err = parseErr("Version", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Version = pio.U8(b[n:])
|
||||
n += 1
|
||||
if len(b) < n+3 {
|
||||
err = parseErr("Flags", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Flags = pio.U24BE(b[n:])
|
||||
n += 3
|
||||
if len(b) < n+2 {
|
||||
err = parseErr("GraphicsMode", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.GraphicsMode = pio.I16BE(b[n:])
|
||||
n += 2
|
||||
if len(b) < n+2*len(a.Opcolor) {
|
||||
err = parseErr("Opcolor", n+offset, err)
|
||||
return
|
||||
}
|
||||
for i := range a.Opcolor {
|
||||
a.Opcolor[i] = pio.I16BE(b[n:])
|
||||
n += 2
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a VideoMediaInfo) Children() (r []Atom) {
|
||||
return
|
||||
}
|
||||
|
||||
func (a VideoMediaInfo) Tag() Tag {
|
||||
return VMHD
|
||||
}
|
||||
|
||||
const SMHD = Tag(0x736d6864)
|
||||
|
||||
type SoundMediaInfo struct {
|
||||
Version uint8
|
||||
Flags uint32
|
||||
Balance int16
|
||||
AtomPos
|
||||
}
|
||||
|
||||
func (a SoundMediaInfo) Marshal(b []byte) (n int) {
|
||||
pio.PutU32BE(b[4:], uint32(SMHD))
|
||||
n += a.marshal(b[8:]) + 8
|
||||
pio.PutU32BE(b[0:], uint32(n))
|
||||
return
|
||||
}
|
||||
|
||||
func (a SoundMediaInfo) marshal(b []byte) (n int) {
|
||||
pio.PutU8(b[n:], a.Version)
|
||||
n += 1
|
||||
pio.PutU24BE(b[n:], a.Flags)
|
||||
n += 3
|
||||
pio.PutI16BE(b[n:], a.Balance)
|
||||
n += 2
|
||||
n += 2
|
||||
return
|
||||
}
|
||||
|
||||
func (a SoundMediaInfo) Len() (n int) {
|
||||
n += 8
|
||||
n += 1
|
||||
n += 3
|
||||
n += 2
|
||||
n += 2
|
||||
return
|
||||
}
|
||||
|
||||
func (a *SoundMediaInfo) Unmarshal(b []byte, offset int) (n int, err error) {
|
||||
(&a.AtomPos).setPos(offset, len(b))
|
||||
n += 8
|
||||
if len(b) < n+1 {
|
||||
err = parseErr("Version", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Version = pio.U8(b[n:])
|
||||
n += 1
|
||||
if len(b) < n+3 {
|
||||
err = parseErr("Flags", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Flags = pio.U24BE(b[n:])
|
||||
n += 3
|
||||
if len(b) < n+2 {
|
||||
err = parseErr("Balance", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Balance = pio.I16BE(b[n:])
|
||||
n += 2
|
||||
n += 2
|
||||
return
|
||||
}
|
||||
|
||||
func (a SoundMediaInfo) Children() (r []Atom) {
|
||||
return
|
||||
}
|
||||
|
||||
func (a SoundMediaInfo) Tag() Tag {
|
||||
return SMHD
|
||||
}
|
||||
|
||||
const DINF = Tag(0x64696e66)
|
||||
|
||||
func (a DataInfo) Tag() Tag {
|
||||
return DINF
|
||||
}
|
||||
|
||||
type DataInfo struct {
|
||||
Refer *DataRefer
|
||||
Unknowns []Atom
|
||||
AtomPos
|
||||
}
|
||||
|
||||
func (a DataInfo) Marshal(b []byte) (n int) {
|
||||
pio.PutU32BE(b[4:], uint32(DINF))
|
||||
n += a.marshal(b[8:]) + 8
|
||||
pio.PutU32BE(b[0:], uint32(n))
|
||||
return
|
||||
}
|
||||
|
||||
func (a DataInfo) marshal(b []byte) (n int) {
|
||||
if a.Refer != nil {
|
||||
n += a.Refer.Marshal(b[n:])
|
||||
}
|
||||
for _, atom := range a.Unknowns {
|
||||
n += atom.Marshal(b[n:])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a DataInfo) Len() (n int) {
|
||||
n += 8
|
||||
if a.Refer != nil {
|
||||
n += a.Refer.Len()
|
||||
}
|
||||
for _, atom := range a.Unknowns {
|
||||
n += atom.Len()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a *DataInfo) Unmarshal(b []byte, offset int) (n int, err error) {
|
||||
(&a.AtomPos).setPos(offset, len(b))
|
||||
n += 8
|
||||
for n+8 < len(b) {
|
||||
tag := Tag(pio.U32BE(b[n+4:]))
|
||||
size := int(pio.U32BE(b[n:]))
|
||||
if len(b) < n+size {
|
||||
err = parseErr("TagSizeInvalid", n+offset, err)
|
||||
return
|
||||
}
|
||||
switch tag {
|
||||
case DREF:
|
||||
{
|
||||
atom := &DataRefer{}
|
||||
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
||||
err = parseErr("dref", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Refer = atom
|
||||
}
|
||||
default:
|
||||
{
|
||||
atom := &Dummy{Tag_: tag, Data: b[n : n+size]}
|
||||
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
||||
err = parseErr("", n+offset, err)
|
||||
return
|
||||
}
|
||||
a.Unknowns = append(a.Unknowns, atom)
|
||||
}
|
||||
}
|
||||
n += size
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (a DataInfo) Children() (r []Atom) {
|
||||
if a.Refer != nil {
|
||||
r = append(r, a.Refer)
|
||||
}
|
||||
r = append(r, a.Unknowns...)
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user