898 lines
17 KiB
Go
898 lines
17 KiB
Go
package fmp4io
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"git.r-2.top/kunmeng/vdk/utils/bits/pio"
|
|
)
|
|
|
|
const STBL = Tag(0x7374626c)
|
|
|
|
type SampleTable struct {
|
|
SampleDesc *SampleDesc
|
|
TimeToSample *TimeToSample
|
|
CompositionOffset *CompositionOffset
|
|
SampleToChunk *SampleToChunk
|
|
SyncSample *SyncSample
|
|
ChunkOffset *ChunkOffset
|
|
SampleSize *SampleSize
|
|
AtomPos
|
|
}
|
|
|
|
func (a SampleTable) Marshal(b []byte) (n int) {
|
|
pio.PutU32BE(b[4:], uint32(STBL))
|
|
n += a.marshal(b[8:]) + 8
|
|
pio.PutU32BE(b[0:], uint32(n))
|
|
return
|
|
}
|
|
|
|
func (a SampleTable) marshal(b []byte) (n int) {
|
|
if a.SampleDesc != nil {
|
|
n += a.SampleDesc.Marshal(b[n:])
|
|
}
|
|
if a.TimeToSample != nil {
|
|
n += a.TimeToSample.Marshal(b[n:])
|
|
}
|
|
if a.CompositionOffset != nil {
|
|
n += a.CompositionOffset.Marshal(b[n:])
|
|
}
|
|
if a.SampleToChunk != nil {
|
|
n += a.SampleToChunk.Marshal(b[n:])
|
|
}
|
|
if a.SyncSample != nil {
|
|
n += a.SyncSample.Marshal(b[n:])
|
|
}
|
|
if a.SampleSize != nil {
|
|
n += a.SampleSize.Marshal(b[n:])
|
|
}
|
|
if a.ChunkOffset != nil {
|
|
n += a.ChunkOffset.Marshal(b[n:])
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a SampleTable) Len() (n int) {
|
|
n += 8
|
|
if a.SampleDesc != nil {
|
|
n += a.SampleDesc.Len()
|
|
}
|
|
if a.TimeToSample != nil {
|
|
n += a.TimeToSample.Len()
|
|
}
|
|
if a.CompositionOffset != nil {
|
|
n += a.CompositionOffset.Len()
|
|
}
|
|
if a.SampleToChunk != nil {
|
|
n += a.SampleToChunk.Len()
|
|
}
|
|
if a.SyncSample != nil {
|
|
n += a.SyncSample.Len()
|
|
}
|
|
if a.ChunkOffset != nil {
|
|
n += a.ChunkOffset.Len()
|
|
}
|
|
if a.SampleSize != nil {
|
|
n += a.SampleSize.Len()
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a *SampleTable) 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 STSD:
|
|
{
|
|
atom := &SampleDesc{}
|
|
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
|
err = parseErr("stsd", n+offset, err)
|
|
return
|
|
}
|
|
a.SampleDesc = atom
|
|
}
|
|
case STTS:
|
|
{
|
|
atom := &TimeToSample{}
|
|
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
|
err = parseErr("stts", n+offset, err)
|
|
return
|
|
}
|
|
a.TimeToSample = atom
|
|
}
|
|
case CTTS:
|
|
{
|
|
atom := &CompositionOffset{}
|
|
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
|
err = parseErr("ctts", n+offset, err)
|
|
return
|
|
}
|
|
a.CompositionOffset = atom
|
|
}
|
|
case STSC:
|
|
{
|
|
atom := &SampleToChunk{}
|
|
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
|
err = parseErr("stsc", n+offset, err)
|
|
return
|
|
}
|
|
a.SampleToChunk = atom
|
|
}
|
|
case STSS:
|
|
{
|
|
atom := &SyncSample{}
|
|
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
|
err = parseErr("stss", n+offset, err)
|
|
return
|
|
}
|
|
a.SyncSample = atom
|
|
}
|
|
case STCO:
|
|
{
|
|
atom := &ChunkOffset{}
|
|
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
|
err = parseErr("stco", n+offset, err)
|
|
return
|
|
}
|
|
a.ChunkOffset = atom
|
|
}
|
|
case STSZ:
|
|
{
|
|
atom := &SampleSize{}
|
|
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
|
err = parseErr("stsz", n+offset, err)
|
|
return
|
|
}
|
|
a.SampleSize = atom
|
|
}
|
|
}
|
|
n += size
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a SampleTable) Children() (r []Atom) {
|
|
if a.SampleDesc != nil {
|
|
r = append(r, a.SampleDesc)
|
|
}
|
|
if a.TimeToSample != nil {
|
|
r = append(r, a.TimeToSample)
|
|
}
|
|
if a.CompositionOffset != nil {
|
|
r = append(r, a.CompositionOffset)
|
|
}
|
|
if a.SampleToChunk != nil {
|
|
r = append(r, a.SampleToChunk)
|
|
}
|
|
if a.SyncSample != nil {
|
|
r = append(r, a.SyncSample)
|
|
}
|
|
if a.ChunkOffset != nil {
|
|
r = append(r, a.ChunkOffset)
|
|
}
|
|
if a.SampleSize != nil {
|
|
r = append(r, a.SampleSize)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a SampleTable) Tag() Tag {
|
|
return STBL
|
|
}
|
|
|
|
const STSD = Tag(0x73747364)
|
|
|
|
type SampleDesc struct {
|
|
Version uint8
|
|
AVC1Desc *AVC1Desc
|
|
MP4ADesc *MP4ADesc
|
|
OpusDesc *OpusSampleEntry
|
|
Unknowns []Atom
|
|
AtomPos
|
|
}
|
|
|
|
func (a SampleDesc) Marshal(b []byte) (n int) {
|
|
pio.PutU32BE(b[4:], uint32(STSD))
|
|
n += a.marshal(b[8:]) + 8
|
|
pio.PutU32BE(b[0:], uint32(n))
|
|
return
|
|
}
|
|
|
|
func (a SampleDesc) marshal(b []byte) (n int) {
|
|
pio.PutU8(b[n:], a.Version)
|
|
n += 1
|
|
n += 3
|
|
_childrenNR := 0
|
|
if a.AVC1Desc != nil {
|
|
_childrenNR++
|
|
}
|
|
if a.MP4ADesc != nil {
|
|
_childrenNR++
|
|
}
|
|
if a.OpusDesc != nil {
|
|
_childrenNR++
|
|
}
|
|
_childrenNR += len(a.Unknowns)
|
|
pio.PutI32BE(b[n:], int32(_childrenNR))
|
|
n += 4
|
|
if a.AVC1Desc != nil {
|
|
n += a.AVC1Desc.Marshal(b[n:])
|
|
}
|
|
if a.MP4ADesc != nil {
|
|
n += a.MP4ADesc.Marshal(b[n:])
|
|
}
|
|
if a.OpusDesc != nil {
|
|
n += a.OpusDesc.Marshal(b[n:])
|
|
}
|
|
for _, atom := range a.Unknowns {
|
|
n += atom.Marshal(b[n:])
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a SampleDesc) Len() (n int) {
|
|
n += 8
|
|
n += 1
|
|
n += 3
|
|
n += 4
|
|
if a.AVC1Desc != nil {
|
|
n += a.AVC1Desc.Len()
|
|
}
|
|
if a.MP4ADesc != nil {
|
|
n += a.MP4ADesc.Len()
|
|
}
|
|
if a.OpusDesc != nil {
|
|
n += a.OpusDesc.Len()
|
|
}
|
|
for _, atom := range a.Unknowns {
|
|
n += atom.Len()
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a *SampleDesc) 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
|
|
n += 3
|
|
n += 4
|
|
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 AVC1:
|
|
{
|
|
atom := &AVC1Desc{}
|
|
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
|
err = parseErr("avc1", n+offset, err)
|
|
return
|
|
}
|
|
a.AVC1Desc = atom
|
|
}
|
|
case MP4A:
|
|
{
|
|
atom := &MP4ADesc{}
|
|
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
|
err = parseErr("mp4a", n+offset, err)
|
|
return
|
|
}
|
|
a.MP4ADesc = atom
|
|
}
|
|
case OPUS:
|
|
{
|
|
atom := &OpusSampleEntry{}
|
|
if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil {
|
|
err = parseErr("OPUS", n+offset, err)
|
|
return
|
|
}
|
|
}
|
|
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 SampleDesc) Children() (r []Atom) {
|
|
if a.AVC1Desc != nil {
|
|
r = append(r, a.AVC1Desc)
|
|
}
|
|
if a.MP4ADesc != nil {
|
|
r = append(r, a.MP4ADesc)
|
|
}
|
|
if a.OpusDesc != nil {
|
|
r = append(r, a.OpusDesc)
|
|
}
|
|
r = append(r, a.Unknowns...)
|
|
return
|
|
}
|
|
|
|
func (a SampleDesc) Tag() Tag {
|
|
return STSD
|
|
}
|
|
|
|
const STTS = Tag(0x73747473)
|
|
|
|
type TimeToSample struct {
|
|
Version uint8
|
|
Flags uint32
|
|
Entries []TimeToSampleEntry
|
|
AtomPos
|
|
}
|
|
|
|
func (a TimeToSample) Marshal(b []byte) (n int) {
|
|
pio.PutU32BE(b[4:], uint32(STTS))
|
|
n += a.marshal(b[8:]) + 8
|
|
pio.PutU32BE(b[0:], uint32(n))
|
|
return
|
|
}
|
|
|
|
func (a TimeToSample) marshal(b []byte) (n int) {
|
|
pio.PutU8(b[n:], a.Version)
|
|
n += 1
|
|
pio.PutU24BE(b[n:], a.Flags)
|
|
n += 3
|
|
pio.PutU32BE(b[n:], uint32(len(a.Entries)))
|
|
n += 4
|
|
for _, entry := range a.Entries {
|
|
putTimeToSampleEntry(b[n:], entry)
|
|
n += lenTimeToSampleEntry
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a TimeToSample) Len() (n int) {
|
|
n += 8
|
|
n += 1
|
|
n += 3
|
|
n += 4
|
|
n += lenTimeToSampleEntry * len(a.Entries)
|
|
return
|
|
}
|
|
|
|
func (a *TimeToSample) 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
|
|
var _len_Entries uint32
|
|
_len_Entries = pio.U32BE(b[n:])
|
|
n += 4
|
|
a.Entries = make([]TimeToSampleEntry, _len_Entries)
|
|
if len(b) < n+lenTimeToSampleEntry*len(a.Entries) {
|
|
err = parseErr("TimeToSampleEntry", n+offset, err)
|
|
return
|
|
}
|
|
for i := range a.Entries {
|
|
a.Entries[i] = getTimeToSampleEntry(b[n:])
|
|
n += lenTimeToSampleEntry
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a TimeToSample) Children() (r []Atom) {
|
|
return
|
|
}
|
|
|
|
func (a TimeToSample) String() string {
|
|
return fmt.Sprintf("entries=%d", len(a.Entries))
|
|
}
|
|
|
|
type TimeToSampleEntry struct {
|
|
Count uint32
|
|
Duration uint32
|
|
}
|
|
|
|
func getTimeToSampleEntry(b []byte) (a TimeToSampleEntry) {
|
|
a.Count = pio.U32BE(b[0:])
|
|
a.Duration = pio.U32BE(b[4:])
|
|
return
|
|
}
|
|
|
|
func putTimeToSampleEntry(b []byte, a TimeToSampleEntry) {
|
|
pio.PutU32BE(b[0:], a.Count)
|
|
pio.PutU32BE(b[4:], a.Duration)
|
|
}
|
|
|
|
const lenTimeToSampleEntry = 8
|
|
|
|
func (a TimeToSample) Tag() Tag {
|
|
return STTS
|
|
}
|
|
|
|
const STSC = Tag(0x73747363)
|
|
|
|
type SampleToChunk struct {
|
|
Version uint8
|
|
Flags uint32
|
|
Entries []SampleToChunkEntry
|
|
AtomPos
|
|
}
|
|
|
|
func (a SampleToChunk) Marshal(b []byte) (n int) {
|
|
pio.PutU32BE(b[4:], uint32(STSC))
|
|
n += a.marshal(b[8:]) + 8
|
|
pio.PutU32BE(b[0:], uint32(n))
|
|
return
|
|
}
|
|
|
|
func (a SampleToChunk) marshal(b []byte) (n int) {
|
|
pio.PutU8(b[n:], a.Version)
|
|
n += 1
|
|
pio.PutU24BE(b[n:], a.Flags)
|
|
n += 3
|
|
pio.PutU32BE(b[n:], uint32(len(a.Entries)))
|
|
n += 4
|
|
for _, entry := range a.Entries {
|
|
putSampleToChunkEntry(b[n:], entry)
|
|
n += lenSampleToChunkEntry
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a SampleToChunk) Len() (n int) {
|
|
n += 8
|
|
n += 1
|
|
n += 3
|
|
n += 4
|
|
n += lenSampleToChunkEntry * len(a.Entries)
|
|
return
|
|
}
|
|
|
|
func (a *SampleToChunk) 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
|
|
var _len_Entries uint32
|
|
_len_Entries = pio.U32BE(b[n:])
|
|
n += 4
|
|
a.Entries = make([]SampleToChunkEntry, _len_Entries)
|
|
if len(b) < n+lenSampleToChunkEntry*len(a.Entries) {
|
|
err = parseErr("SampleToChunkEntry", n+offset, err)
|
|
return
|
|
}
|
|
for i := range a.Entries {
|
|
a.Entries[i] = getSampleToChunkEntry(b[n:])
|
|
n += lenSampleToChunkEntry
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a SampleToChunk) Children() (r []Atom) {
|
|
return
|
|
}
|
|
|
|
func (a SampleToChunk) String() string {
|
|
return fmt.Sprintf("entries=%d", len(a.Entries))
|
|
}
|
|
|
|
type SampleToChunkEntry struct {
|
|
FirstChunk uint32
|
|
SamplesPerChunk uint32
|
|
SampleDescId uint32
|
|
}
|
|
|
|
func getSampleToChunkEntry(b []byte) (a SampleToChunkEntry) {
|
|
a.FirstChunk = pio.U32BE(b[0:])
|
|
a.SamplesPerChunk = pio.U32BE(b[4:])
|
|
a.SampleDescId = pio.U32BE(b[8:])
|
|
return
|
|
}
|
|
|
|
func putSampleToChunkEntry(b []byte, a SampleToChunkEntry) {
|
|
pio.PutU32BE(b[0:], a.FirstChunk)
|
|
pio.PutU32BE(b[4:], a.SamplesPerChunk)
|
|
pio.PutU32BE(b[8:], a.SampleDescId)
|
|
}
|
|
|
|
const lenSampleToChunkEntry = 12
|
|
|
|
func (a SampleToChunk) Tag() Tag {
|
|
return STSC
|
|
}
|
|
|
|
const CTTS = Tag(0x63747473)
|
|
|
|
type CompositionOffset struct {
|
|
Version uint8
|
|
Flags uint32
|
|
Entries []CompositionOffsetEntry
|
|
AtomPos
|
|
}
|
|
|
|
func (a CompositionOffset) Marshal(b []byte) (n int) {
|
|
pio.PutU32BE(b[4:], uint32(CTTS))
|
|
n += a.marshal(b[8:]) + 8
|
|
pio.PutU32BE(b[0:], uint32(n))
|
|
return
|
|
}
|
|
|
|
func (a CompositionOffset) marshal(b []byte) (n int) {
|
|
pio.PutU8(b[n:], a.Version)
|
|
n += 1
|
|
pio.PutU24BE(b[n:], a.Flags)
|
|
n += 3
|
|
pio.PutU32BE(b[n:], uint32(len(a.Entries)))
|
|
n += 4
|
|
for _, entry := range a.Entries {
|
|
putCompositionOffsetEntry(b[n:], entry)
|
|
n += lenCompositionOffsetEntry
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a CompositionOffset) Len() (n int) {
|
|
n += 8
|
|
n += 1
|
|
n += 3
|
|
n += 4
|
|
n += lenCompositionOffsetEntry * len(a.Entries)
|
|
return
|
|
}
|
|
|
|
func (a *CompositionOffset) 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
|
|
var _len_Entries uint32
|
|
_len_Entries = pio.U32BE(b[n:])
|
|
n += 4
|
|
a.Entries = make([]CompositionOffsetEntry, _len_Entries)
|
|
if len(b) < n+lenCompositionOffsetEntry*len(a.Entries) {
|
|
err = parseErr("CompositionOffsetEntry", n+offset, err)
|
|
return
|
|
}
|
|
for i := range a.Entries {
|
|
a.Entries[i] = getCompositionOffsetEntry(b[n:])
|
|
n += lenCompositionOffsetEntry
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a CompositionOffset) Children() (r []Atom) {
|
|
return
|
|
}
|
|
|
|
func (a CompositionOffset) String() string {
|
|
return fmt.Sprintf("entries=%d", len(a.Entries))
|
|
}
|
|
|
|
type CompositionOffsetEntry struct {
|
|
Count uint32
|
|
Offset uint32
|
|
}
|
|
|
|
func getCompositionOffsetEntry(b []byte) (a CompositionOffsetEntry) {
|
|
a.Count = pio.U32BE(b[0:])
|
|
a.Offset = pio.U32BE(b[4:])
|
|
return
|
|
}
|
|
|
|
func putCompositionOffsetEntry(b []byte, a CompositionOffsetEntry) {
|
|
pio.PutU32BE(b[0:], a.Count)
|
|
pio.PutU32BE(b[4:], a.Offset)
|
|
}
|
|
|
|
const lenCompositionOffsetEntry = 8
|
|
|
|
func (a CompositionOffset) Tag() Tag {
|
|
return CTTS
|
|
}
|
|
|
|
const STSS = Tag(0x73747373)
|
|
|
|
type SyncSample struct {
|
|
Version uint8
|
|
Flags uint32
|
|
Entries []uint32
|
|
AtomPos
|
|
}
|
|
|
|
func (a SyncSample) Marshal(b []byte) (n int) {
|
|
pio.PutU32BE(b[4:], uint32(STSS))
|
|
n += a.marshal(b[8:]) + 8
|
|
pio.PutU32BE(b[0:], uint32(n))
|
|
return
|
|
}
|
|
|
|
func (a SyncSample) marshal(b []byte) (n int) {
|
|
pio.PutU8(b[n:], a.Version)
|
|
n += 1
|
|
pio.PutU24BE(b[n:], a.Flags)
|
|
n += 3
|
|
pio.PutU32BE(b[n:], uint32(len(a.Entries)))
|
|
n += 4
|
|
for _, entry := range a.Entries {
|
|
pio.PutU32BE(b[n:], entry)
|
|
n += 4
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a SyncSample) Len() (n int) {
|
|
n += 8
|
|
n += 1
|
|
n += 3
|
|
n += 4
|
|
n += 4 * len(a.Entries)
|
|
return
|
|
}
|
|
|
|
func (a *SyncSample) 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
|
|
var _len_Entries uint32
|
|
_len_Entries = pio.U32BE(b[n:])
|
|
n += 4
|
|
a.Entries = make([]uint32, _len_Entries)
|
|
if len(b) < n+4*len(a.Entries) {
|
|
err = parseErr("uint32", n+offset, err)
|
|
return
|
|
}
|
|
for i := range a.Entries {
|
|
a.Entries[i] = pio.U32BE(b[n:])
|
|
n += 4
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a SyncSample) Children() (r []Atom) {
|
|
return
|
|
}
|
|
|
|
func (a SyncSample) Tag() Tag {
|
|
return STSS
|
|
}
|
|
|
|
func (a SyncSample) String() string {
|
|
return fmt.Sprintf("entries=%d", len(a.Entries))
|
|
}
|
|
|
|
const STCO = Tag(0x7374636f)
|
|
|
|
type ChunkOffset struct {
|
|
Version uint8
|
|
Flags uint32
|
|
Entries []uint32
|
|
AtomPos
|
|
}
|
|
|
|
func (a ChunkOffset) Marshal(b []byte) (n int) {
|
|
pio.PutU32BE(b[4:], uint32(STCO))
|
|
n += a.marshal(b[8:]) + 8
|
|
pio.PutU32BE(b[0:], uint32(n))
|
|
return
|
|
}
|
|
|
|
func (a ChunkOffset) marshal(b []byte) (n int) {
|
|
pio.PutU8(b[n:], a.Version)
|
|
n += 1
|
|
pio.PutU24BE(b[n:], a.Flags)
|
|
n += 3
|
|
pio.PutU32BE(b[n:], uint32(len(a.Entries)))
|
|
n += 4
|
|
for _, entry := range a.Entries {
|
|
pio.PutU32BE(b[n:], entry)
|
|
n += 4
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a ChunkOffset) Len() (n int) {
|
|
n += 8
|
|
n += 1
|
|
n += 3
|
|
n += 4
|
|
n += 4 * len(a.Entries)
|
|
return
|
|
}
|
|
|
|
func (a *ChunkOffset) 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
|
|
var _len_Entries uint32
|
|
_len_Entries = pio.U32BE(b[n:])
|
|
n += 4
|
|
a.Entries = make([]uint32, _len_Entries)
|
|
if len(b) < n+4*len(a.Entries) {
|
|
err = parseErr("uint32", n+offset, err)
|
|
return
|
|
}
|
|
for i := range a.Entries {
|
|
a.Entries[i] = pio.U32BE(b[n:])
|
|
n += 4
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a ChunkOffset) Children() (r []Atom) {
|
|
return
|
|
}
|
|
|
|
func (a ChunkOffset) Tag() Tag {
|
|
return STCO
|
|
}
|
|
|
|
func (a ChunkOffset) String() string {
|
|
return fmt.Sprintf("entries=%d", len(a.Entries))
|
|
}
|
|
|
|
const STSZ = Tag(0x7374737a)
|
|
|
|
type SampleSize struct {
|
|
Version uint8
|
|
Flags uint32
|
|
SampleSize uint32
|
|
Entries []uint32
|
|
AtomPos
|
|
}
|
|
|
|
func (a SampleSize) Marshal(b []byte) (n int) {
|
|
pio.PutU32BE(b[4:], uint32(STSZ))
|
|
n += a.marshal(b[8:]) + 8
|
|
pio.PutU32BE(b[0:], uint32(n))
|
|
return
|
|
}
|
|
|
|
func (a SampleSize) marshal(b []byte) (n int) {
|
|
pio.PutU8(b[n:], a.Version)
|
|
n += 1
|
|
pio.PutU24BE(b[n:], a.Flags)
|
|
n += 3
|
|
pio.PutU32BE(b[n:], a.SampleSize)
|
|
n += 4
|
|
if a.SampleSize != 0 {
|
|
return
|
|
}
|
|
pio.PutU32BE(b[n:], uint32(len(a.Entries)))
|
|
n += 4
|
|
for _, entry := range a.Entries {
|
|
pio.PutU32BE(b[n:], entry)
|
|
n += 4
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a SampleSize) Len() (n int) {
|
|
n += 8
|
|
n += 1
|
|
n += 3
|
|
n += 4
|
|
if a.SampleSize != 0 {
|
|
return
|
|
}
|
|
n += 4
|
|
n += 4 * len(a.Entries)
|
|
return
|
|
}
|
|
|
|
func (a *SampleSize) 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("SampleSize", n+offset, err)
|
|
return
|
|
}
|
|
a.SampleSize = pio.U32BE(b[n:])
|
|
n += 4
|
|
if a.SampleSize != 0 {
|
|
return
|
|
}
|
|
var _len_Entries uint32
|
|
_len_Entries = pio.U32BE(b[n:])
|
|
n += 4
|
|
a.Entries = make([]uint32, _len_Entries)
|
|
if len(b) < n+4*len(a.Entries) {
|
|
err = parseErr("uint32", n+offset, err)
|
|
return
|
|
}
|
|
for i := range a.Entries {
|
|
a.Entries[i] = pio.U32BE(b[n:])
|
|
n += 4
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a SampleSize) Children() (r []Atom) {
|
|
return
|
|
}
|
|
|
|
func (a SampleSize) Tag() Tag {
|
|
return STSZ
|
|
}
|
|
|
|
func (a SampleSize) String() string {
|
|
return fmt.Sprintf("entries=%d", len(a.Entries))
|
|
}
|