From 0400eb8009953437a9ae03d2177f558771f8d08c Mon Sep 17 00:00:00 2001 From: nareix Date: Sat, 30 Jul 2016 00:06:38 +0800 Subject: [PATCH] add mp4io/atoms.go --- format/mp4/mp4io/atoms.go | 3528 +++++++++++++++++++++++++++++++++++++ 1 file changed, 3528 insertions(+) create mode 100644 format/mp4/mp4io/atoms.go diff --git a/format/mp4/mp4io/atoms.go b/format/mp4/mp4io/atoms.go new file mode 100644 index 0000000..8818212 --- /dev/null +++ b/format/mp4/mp4io/atoms.go @@ -0,0 +1,3528 @@ +package mp4io + +import "github.com/nareix/bits/pio" +import "time" + +const MOOF = Tag(0x6d6f6f66) + +func (self MovieFrag) Tag() Tag { + return MOOF +} + +const HDLR = Tag(0x68646c72) + +func (self HandlerRefer) Tag() Tag { + return HDLR +} + +const AVC1 = Tag(0x61766331) + +func (self AVC1Desc) Tag() Tag { + return AVC1 +} + +const URL = Tag(0x75726c20) + +func (self DataReferUrl) Tag() Tag { + return URL +} + +const TREX = Tag(0x74726578) + +func (self TrackExtend) Tag() Tag { + return TREX +} + +const ESDS = Tag(0x65736473) + +func (self ElemStreamDesc) Tag() Tag { + return ESDS +} + +const MDHD = Tag(0x6d646864) + +func (self MediaHeader) Tag() Tag { + return MDHD +} + +const STTS = Tag(0x73747473) + +func (self TimeToSample) Tag() Tag { + return STTS +} + +const STSS = Tag(0x73747373) + +func (self SyncSample) Tag() Tag { + return STSS +} + +const MFHD = Tag(0x6d666864) + +func (self MovieFragHeader) Tag() Tag { + return MFHD +} + +const MVHD = Tag(0x6d766864) + +func (self MovieHeader) Tag() Tag { + return MVHD +} + +const MINF = Tag(0x6d696e66) + +func (self MediaInfo) Tag() Tag { + return MINF +} + +const MOOV = Tag(0x6d6f6f76) + +func (self Movie) Tag() Tag { + return MOOV +} + +const MVEX = Tag(0x6d766578) + +func (self MovieExtend) Tag() Tag { + return MVEX +} + +const STSD = Tag(0x73747364) + +func (self SampleDesc) Tag() Tag { + return STSD +} + +const MP4A = Tag(0x6d703461) + +func (self MP4ADesc) Tag() Tag { + return MP4A +} + +const CTTS = Tag(0x63747473) + +func (self CompositionOffset) Tag() Tag { + return CTTS +} + +const STCO = Tag(0x7374636f) + +func (self ChunkOffset) Tag() Tag { + return STCO +} + +const TRUN = Tag(0x7472756e) + +func (self TrackFragRun) Tag() Tag { + return TRUN +} + +const TRAK = Tag(0x7472616b) + +func (self Track) Tag() Tag { + return TRAK +} + +const MDIA = Tag(0x6d646961) + +func (self Media) Tag() Tag { + return MDIA +} + +const STSC = Tag(0x73747363) + +func (self SampleToChunk) Tag() Tag { + return STSC +} + +const VMHD = Tag(0x766d6864) + +func (self VideoMediaInfo) Tag() Tag { + return VMHD +} + +const STBL = Tag(0x7374626c) + +func (self SampleTable) Tag() Tag { + return STBL +} + +const AVCC = Tag(0x61766343) + +func (self AVC1Conf) Tag() Tag { + return AVCC +} + +const TFDT = Tag(0x74666474) + +func (self TrackFragDecodeTime) Tag() Tag { + return TFDT +} + +const DINF = Tag(0x64696e66) + +func (self DataInfo) Tag() Tag { + return DINF +} + +const DREF = Tag(0x64726566) + +func (self DataRefer) Tag() Tag { + return DREF +} + +const TRAF = Tag(0x74726166) + +func (self TrackFrag) Tag() Tag { + return TRAF +} + +const STSZ = Tag(0x7374737a) + +func (self SampleSize) Tag() Tag { + return STSZ +} + +const TFHD = Tag(0x74666864) + +func (self TrackFragHeader) Tag() Tag { + return TFHD +} + +const TKHD = Tag(0x746b6864) + +func (self TrackHeader) Tag() Tag { + return TKHD +} + +const SMHD = Tag(0x736d6864) + +func (self SoundMediaInfo) Tag() Tag { + return SMHD +} + +const MDAT = Tag(0x6d646174) + +type Movie struct { + Header *MovieHeader + MovieExtend *MovieExtend + Tracks []*Track + Unknowns []Atom + AtomPos +} + +func (self Movie) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(MOOV)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self Movie) marshal(b []byte) (n int) { + if self.Header != nil { + n += self.Header.Marshal(b[n:]) + } + if self.MovieExtend != nil { + n += self.MovieExtend.Marshal(b[n:]) + } + for _, atom := range self.Tracks { + n += atom.Marshal(b[n:]) + } + for _, atom := range self.Unknowns { + n += atom.Marshal(b[n:]) + } + return +} +func (self Movie) Len() (n int) { + n += 8 + if self.Header != nil { + n += self.Header.Len() + } + if self.MovieExtend != nil { + n += self.MovieExtend.Len() + } + for _, atom := range self.Tracks { + n += atom.Len() + } + for _, atom := range self.Unknowns { + n += atom.Len() + } + return +} +func (self *Movie) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.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 MVHD: + { + atom := &MovieHeader{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("mvhd", n+offset, err) + return + } + self.Header = atom + } + case MVEX: + { + atom := &MovieExtend{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("mvex", n+offset, err) + return + } + self.MovieExtend = atom + } + case TRAK: + { + atom := &Track{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("trak", n+offset, err) + return + } + self.Tracks = append(self.Tracks, 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 + } + self.Unknowns = append(self.Unknowns, atom) + } + } + n += size + } + return +} +func (self Movie) Children() (r []Atom) { + if self.Header != nil { + r = append(r, self.Header) + } + if self.MovieExtend != nil { + r = append(r, self.MovieExtend) + } + for _, atom := range self.Tracks { + r = append(r, atom) + } + r = append(r, self.Unknowns...) + return +} + +type MovieHeader struct { + Version uint8 + Flags uint32 + CreateTime time.Time + ModifyTime time.Time + TimeScale int32 + Duration int32 + PreferredRate float64 + PreferredVolume float64 + Matrix [9]int32 + PreviewTime time.Time + PreviewDuration time.Time + PosterTime time.Time + SelectionTime time.Time + SelectionDuration time.Time + CurrentTime time.Time + NextTrackId int32 + AtomPos +} + +func (self MovieHeader) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(MVHD)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self MovieHeader) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + PutTime32(b[n:], self.CreateTime) + n += 4 + PutTime32(b[n:], self.ModifyTime) + n += 4 + pio.PutI32BE(b[n:], self.TimeScale) + n += 4 + pio.PutI32BE(b[n:], self.Duration) + n += 4 + PutFixed32(b[n:], self.PreferredRate) + n += 4 + PutFixed16(b[n:], self.PreferredVolume) + n += 2 + n += 10 + for _, entry := range self.Matrix { + pio.PutI32BE(b[n:], entry) + n += 4 + } + PutTime32(b[n:], self.PreviewTime) + n += 4 + PutTime32(b[n:], self.PreviewDuration) + n += 4 + PutTime32(b[n:], self.PosterTime) + n += 4 + PutTime32(b[n:], self.SelectionTime) + n += 4 + PutTime32(b[n:], self.SelectionDuration) + n += 4 + PutTime32(b[n:], self.CurrentTime) + n += 4 + pio.PutI32BE(b[n:], self.NextTrackId) + n += 4 + return +} +func (self MovieHeader) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + n += 4 + n += 4 + n += 4 + n += 4 + n += 2 + n += 10 + n += 4*len(self.Matrix[:]) + n += 4 + n += 4 + n += 4 + n += 4 + n += 4 + n += 4 + n += 4 + return +} +func (self *MovieHeader) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + if len(b) < n+4 { + err = parseErr("CreateTime", n+offset, err) + return + } + self.CreateTime = GetTime32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("ModifyTime", n+offset, err) + return + } + self.ModifyTime = GetTime32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("TimeScale", n+offset, err) + return + } + self.TimeScale = pio.I32BE(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("Duration", n+offset, err) + return + } + self.Duration = pio.I32BE(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("PreferredRate", n+offset, err) + return + } + self.PreferredRate = GetFixed32(b[n:]) + n += 4 + if len(b) < n+2 { + err = parseErr("PreferredVolume", n+offset, err) + return + } + self.PreferredVolume = GetFixed16(b[n:]) + n += 2 + n += 10 + if len(b) < n+4*len(self.Matrix) { + err = parseErr("Matrix", n+offset, err) + return + } + for i := range self.Matrix { + self.Matrix[i] = pio.I32BE(b[n:]) + n += 4 + } + if len(b) < n+4 { + err = parseErr("PreviewTime", n+offset, err) + return + } + self.PreviewTime = GetTime32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("PreviewDuration", n+offset, err) + return + } + self.PreviewDuration = GetTime32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("PosterTime", n+offset, err) + return + } + self.PosterTime = GetTime32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("SelectionTime", n+offset, err) + return + } + self.SelectionTime = GetTime32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("SelectionDuration", n+offset, err) + return + } + self.SelectionDuration = GetTime32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("CurrentTime", n+offset, err) + return + } + self.CurrentTime = GetTime32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("NextTrackId", n+offset, err) + return + } + self.NextTrackId = pio.I32BE(b[n:]) + n += 4 + return +} +func (self MovieHeader) Children() (r []Atom) { + return +} + +type Track struct { + Header *TrackHeader + Media *Media + Unknowns []Atom + AtomPos +} + +func (self Track) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(TRAK)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self Track) marshal(b []byte) (n int) { + if self.Header != nil { + n += self.Header.Marshal(b[n:]) + } + if self.Media != nil { + n += self.Media.Marshal(b[n:]) + } + for _, atom := range self.Unknowns { + n += atom.Marshal(b[n:]) + } + return +} +func (self Track) Len() (n int) { + n += 8 + if self.Header != nil { + n += self.Header.Len() + } + if self.Media != nil { + n += self.Media.Len() + } + for _, atom := range self.Unknowns { + n += atom.Len() + } + return +} +func (self *Track) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.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 TKHD: + { + atom := &TrackHeader{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("tkhd", n+offset, err) + return + } + self.Header = atom + } + case MDIA: + { + atom := &Media{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("mdia", n+offset, err) + return + } + self.Media = 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 + } + self.Unknowns = append(self.Unknowns, atom) + } + } + n += size + } + return +} +func (self Track) Children() (r []Atom) { + if self.Header != nil { + r = append(r, self.Header) + } + if self.Media != nil { + r = append(r, self.Media) + } + r = append(r, self.Unknowns...) + return +} + +type TrackHeader struct { + Version uint8 + Flags uint32 + CreateTime time.Time + ModifyTime time.Time + TrackId int32 + Duration int32 + Layer int16 + AlternateGroup int16 + Volume float64 + Matrix [9]int32 + TrackWidth float64 + TrackHeight float64 + AtomPos +} + +func (self TrackHeader) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(TKHD)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self TrackHeader) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + PutTime32(b[n:], self.CreateTime) + n += 4 + PutTime32(b[n:], self.ModifyTime) + n += 4 + pio.PutI32BE(b[n:], self.TrackId) + n += 4 + n += 4 + pio.PutI32BE(b[n:], self.Duration) + n += 4 + n += 8 + pio.PutI16BE(b[n:], self.Layer) + n += 2 + pio.PutI16BE(b[n:], self.AlternateGroup) + n += 2 + PutFixed16(b[n:], self.Volume) + n += 2 + n += 2 + for _, entry := range self.Matrix { + pio.PutI32BE(b[n:], entry) + n += 4 + } + PutFixed32(b[n:], self.TrackWidth) + n += 4 + PutFixed32(b[n:], self.TrackHeight) + n += 4 + return +} +func (self TrackHeader) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + n += 4 + n += 4 + n += 4 + n += 4 + n += 8 + n += 2 + n += 2 + n += 2 + n += 2 + n += 4*len(self.Matrix[:]) + n += 4 + n += 4 + return +} +func (self *TrackHeader) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + if len(b) < n+4 { + err = parseErr("CreateTime", n+offset, err) + return + } + self.CreateTime = GetTime32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("ModifyTime", n+offset, err) + return + } + self.ModifyTime = GetTime32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("TrackId", n+offset, err) + return + } + self.TrackId = pio.I32BE(b[n:]) + n += 4 + n += 4 + if len(b) < n+4 { + err = parseErr("Duration", n+offset, err) + return + } + self.Duration = pio.I32BE(b[n:]) + n += 4 + n += 8 + if len(b) < n+2 { + err = parseErr("Layer", n+offset, err) + return + } + self.Layer = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+2 { + err = parseErr("AlternateGroup", n+offset, err) + return + } + self.AlternateGroup = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+2 { + err = parseErr("Volume", n+offset, err) + return + } + self.Volume = GetFixed16(b[n:]) + n += 2 + n += 2 + if len(b) < n+4*len(self.Matrix) { + err = parseErr("Matrix", n+offset, err) + return + } + for i := range self.Matrix { + self.Matrix[i] = pio.I32BE(b[n:]) + n += 4 + } + if len(b) < n+4 { + err = parseErr("TrackWidth", n+offset, err) + return + } + self.TrackWidth = GetFixed32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("TrackHeight", n+offset, err) + return + } + self.TrackHeight = GetFixed32(b[n:]) + n += 4 + return +} +func (self TrackHeader) Children() (r []Atom) { + return +} + +type HandlerRefer struct { + Version uint8 + Flags uint32 + Type [4]byte + SubType [4]byte + Name []byte + AtomPos +} + +func (self HandlerRefer) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(HDLR)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self HandlerRefer) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + copy(b[n:], self.Type[:]) + n += len(self.Type[:]) + copy(b[n:], self.SubType[:]) + n += len(self.SubType[:]) + copy(b[n:], self.Name[:]) + n += len(self.Name[:]) + return +} +func (self HandlerRefer) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += len(self.Type[:]) + n += len(self.SubType[:]) + n += len(self.Name[:]) + return +} +func (self *HandlerRefer) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + if len(b) < n+len(self.Type) { + err = parseErr("Type", n+offset, err) + return + } + copy(self.Type[:], b[n:]) + n += len(self.Type) + if len(b) < n+len(self.SubType) { + err = parseErr("SubType", n+offset, err) + return + } + copy(self.SubType[:], b[n:]) + n += len(self.SubType) + self.Name = b[n:] + n += len(b[n:]) + return +} +func (self HandlerRefer) Children() (r []Atom) { + return +} + +type Media struct { + Header *MediaHeader + Handler *HandlerRefer + Info *MediaInfo + Unknowns []Atom + AtomPos +} + +func (self Media) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(MDIA)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self Media) marshal(b []byte) (n int) { + if self.Header != nil { + n += self.Header.Marshal(b[n:]) + } + if self.Handler != nil { + n += self.Handler.Marshal(b[n:]) + } + if self.Info != nil { + n += self.Info.Marshal(b[n:]) + } + for _, atom := range self.Unknowns { + n += atom.Marshal(b[n:]) + } + return +} +func (self Media) Len() (n int) { + n += 8 + if self.Header != nil { + n += self.Header.Len() + } + if self.Handler != nil { + n += self.Handler.Len() + } + if self.Info != nil { + n += self.Info.Len() + } + for _, atom := range self.Unknowns { + n += atom.Len() + } + return +} +func (self *Media) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.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 + } + self.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 + } + self.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 + } + self.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 + } + self.Unknowns = append(self.Unknowns, atom) + } + } + n += size + } + return +} +func (self Media) Children() (r []Atom) { + if self.Header != nil { + r = append(r, self.Header) + } + if self.Handler != nil { + r = append(r, self.Handler) + } + if self.Info != nil { + r = append(r, self.Info) + } + r = append(r, self.Unknowns...) + return +} + +type MediaHeader struct { + Version uint8 + Flags uint32 + CreateTime time.Time + ModifyTime time.Time + TimeScale int32 + Duration int32 + Language int16 + Quality int16 + AtomPos +} + +func (self MediaHeader) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(MDHD)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self MediaHeader) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + PutTime32(b[n:], self.CreateTime) + n += 4 + PutTime32(b[n:], self.ModifyTime) + n += 4 + pio.PutI32BE(b[n:], self.TimeScale) + n += 4 + pio.PutI32BE(b[n:], self.Duration) + n += 4 + pio.PutI16BE(b[n:], self.Language) + n += 2 + pio.PutI16BE(b[n:], self.Quality) + n += 2 + return +} +func (self MediaHeader) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + n += 4 + n += 4 + n += 4 + n += 2 + n += 2 + return +} +func (self *MediaHeader) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + if len(b) < n+4 { + err = parseErr("CreateTime", n+offset, err) + return + } + self.CreateTime = GetTime32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("ModifyTime", n+offset, err) + return + } + self.ModifyTime = GetTime32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("TimeScale", n+offset, err) + return + } + self.TimeScale = pio.I32BE(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("Duration", n+offset, err) + return + } + self.Duration = pio.I32BE(b[n:]) + n += 4 + if len(b) < n+2 { + err = parseErr("Language", n+offset, err) + return + } + self.Language = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+2 { + err = parseErr("Quality", n+offset, err) + return + } + self.Quality = pio.I16BE(b[n:]) + n += 2 + return +} +func (self MediaHeader) Children() (r []Atom) { + return +} + +type MediaInfo struct { + Sound *SoundMediaInfo + Video *VideoMediaInfo + Data *DataInfo + Sample *SampleTable + Unknowns []Atom + AtomPos +} + +func (self MediaInfo) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(MINF)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self MediaInfo) marshal(b []byte) (n int) { + if self.Sound != nil { + n += self.Sound.Marshal(b[n:]) + } + if self.Video != nil { + n += self.Video.Marshal(b[n:]) + } + if self.Data != nil { + n += self.Data.Marshal(b[n:]) + } + if self.Sample != nil { + n += self.Sample.Marshal(b[n:]) + } + for _, atom := range self.Unknowns { + n += atom.Marshal(b[n:]) + } + return +} +func (self MediaInfo) Len() (n int) { + n += 8 + if self.Sound != nil { + n += self.Sound.Len() + } + if self.Video != nil { + n += self.Video.Len() + } + if self.Data != nil { + n += self.Data.Len() + } + if self.Sample != nil { + n += self.Sample.Len() + } + for _, atom := range self.Unknowns { + n += atom.Len() + } + return +} +func (self *MediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.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 + } + self.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 + } + self.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 + } + self.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 + } + self.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 + } + self.Unknowns = append(self.Unknowns, atom) + } + } + n += size + } + return +} +func (self MediaInfo) Children() (r []Atom) { + if self.Sound != nil { + r = append(r, self.Sound) + } + if self.Video != nil { + r = append(r, self.Video) + } + if self.Data != nil { + r = append(r, self.Data) + } + if self.Sample != nil { + r = append(r, self.Sample) + } + r = append(r, self.Unknowns...) + return +} + +type DataInfo struct { + Refer *DataRefer + Unknowns []Atom + AtomPos +} + +func (self DataInfo) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(DINF)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self DataInfo) marshal(b []byte) (n int) { + if self.Refer != nil { + n += self.Refer.Marshal(b[n:]) + } + for _, atom := range self.Unknowns { + n += atom.Marshal(b[n:]) + } + return +} +func (self DataInfo) Len() (n int) { + n += 8 + if self.Refer != nil { + n += self.Refer.Len() + } + for _, atom := range self.Unknowns { + n += atom.Len() + } + return +} +func (self *DataInfo) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.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 + } + self.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 + } + self.Unknowns = append(self.Unknowns, atom) + } + } + n += size + } + return +} +func (self DataInfo) Children() (r []Atom) { + if self.Refer != nil { + r = append(r, self.Refer) + } + r = append(r, self.Unknowns...) + return +} + +type DataRefer struct { + Version uint8 + Flags uint32 + Url *DataReferUrl + AtomPos +} + +func (self DataRefer) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(DREF)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self DataRefer) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + _childrenNR := 0 + if self.Url != nil { + _childrenNR++ + } + pio.PutI32BE(b[n:], int32(_childrenNR)) + n += 4 + if self.Url != nil { + n += self.Url.Marshal(b[n:]) + } + return +} +func (self DataRefer) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + if self.Url != nil { + n += self.Url.Len() + } + return +} +func (self *DataRefer) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + 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 URL : + { + atom := &DataReferUrl{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("url ", n+offset, err) + return + } + self.Url = atom + } + } + n += size + } + return +} +func (self DataRefer) Children() (r []Atom) { + if self.Url != nil { + r = append(r, self.Url) + } + return +} + +type DataReferUrl struct { + Version uint8 + Flags uint32 + AtomPos +} + +func (self DataReferUrl) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(URL )) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self DataReferUrl) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + return +} +func (self DataReferUrl) Len() (n int) { + n += 8 + n += 1 + n += 3 + return +} +func (self *DataReferUrl) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + return +} +func (self DataReferUrl) Children() (r []Atom) { + return +} + +type SoundMediaInfo struct { + Version uint8 + Flags uint32 + Balance int16 + AtomPos +} + +func (self SoundMediaInfo) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(SMHD)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self SoundMediaInfo) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + pio.PutI16BE(b[n:], self.Balance) + n += 2 + n += 2 + return +} +func (self SoundMediaInfo) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 2 + n += 2 + return +} +func (self *SoundMediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + if len(b) < n+2 { + err = parseErr("Balance", n+offset, err) + return + } + self.Balance = pio.I16BE(b[n:]) + n += 2 + n += 2 + return +} +func (self SoundMediaInfo) Children() (r []Atom) { + return +} + +type VideoMediaInfo struct { + Version uint8 + Flags uint32 + GraphicsMode int16 + Opcolor [3]int16 + AtomPos +} + +func (self VideoMediaInfo) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(VMHD)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self VideoMediaInfo) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + pio.PutI16BE(b[n:], self.GraphicsMode) + n += 2 + for _, entry := range self.Opcolor { + pio.PutI16BE(b[n:], entry) + n += 2 + } + return +} +func (self VideoMediaInfo) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 2 + n += 2*len(self.Opcolor[:]) + return +} +func (self *VideoMediaInfo) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + if len(b) < n+2 { + err = parseErr("GraphicsMode", n+offset, err) + return + } + self.GraphicsMode = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+2*len(self.Opcolor) { + err = parseErr("Opcolor", n+offset, err) + return + } + for i := range self.Opcolor { + self.Opcolor[i] = pio.I16BE(b[n:]) + n += 2 + } + return +} +func (self VideoMediaInfo) Children() (r []Atom) { + return +} + +type SampleTable struct { + SampleDesc *SampleDesc + TimeToSample *TimeToSample + CompositionOffset *CompositionOffset + SampleToChunk *SampleToChunk + SyncSample *SyncSample + ChunkOffset *ChunkOffset + SampleSize *SampleSize + AtomPos +} + +func (self SampleTable) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(STBL)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self SampleTable) marshal(b []byte) (n int) { + if self.SampleDesc != nil { + n += self.SampleDesc.Marshal(b[n:]) + } + if self.TimeToSample != nil { + n += self.TimeToSample.Marshal(b[n:]) + } + if self.CompositionOffset != nil { + n += self.CompositionOffset.Marshal(b[n:]) + } + if self.SampleToChunk != nil { + n += self.SampleToChunk.Marshal(b[n:]) + } + if self.SyncSample != nil { + n += self.SyncSample.Marshal(b[n:]) + } + if self.ChunkOffset != nil { + n += self.ChunkOffset.Marshal(b[n:]) + } + if self.SampleSize != nil { + n += self.SampleSize.Marshal(b[n:]) + } + return +} +func (self SampleTable) Len() (n int) { + n += 8 + if self.SampleDesc != nil { + n += self.SampleDesc.Len() + } + if self.TimeToSample != nil { + n += self.TimeToSample.Len() + } + if self.CompositionOffset != nil { + n += self.CompositionOffset.Len() + } + if self.SampleToChunk != nil { + n += self.SampleToChunk.Len() + } + if self.SyncSample != nil { + n += self.SyncSample.Len() + } + if self.ChunkOffset != nil { + n += self.ChunkOffset.Len() + } + if self.SampleSize != nil { + n += self.SampleSize.Len() + } + return +} +func (self *SampleTable) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.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 + } + self.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 + } + self.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 + } + self.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 + } + self.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 + } + self.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 + } + self.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 + } + self.SampleSize = atom + } + } + n += size + } + return +} +func (self SampleTable) Children() (r []Atom) { + if self.SampleDesc != nil { + r = append(r, self.SampleDesc) + } + if self.TimeToSample != nil { + r = append(r, self.TimeToSample) + } + if self.CompositionOffset != nil { + r = append(r, self.CompositionOffset) + } + if self.SampleToChunk != nil { + r = append(r, self.SampleToChunk) + } + if self.SyncSample != nil { + r = append(r, self.SyncSample) + } + if self.ChunkOffset != nil { + r = append(r, self.ChunkOffset) + } + if self.SampleSize != nil { + r = append(r, self.SampleSize) + } + return +} + +type SampleDesc struct { + Version uint8 + AVC1Desc *AVC1Desc + MP4ADesc *MP4ADesc + Unknowns []Atom + AtomPos +} + +func (self SampleDesc) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(STSD)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self SampleDesc) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + n += 3 + _childrenNR := 0 + if self.AVC1Desc != nil { + _childrenNR++ + } + if self.MP4ADesc != nil { + _childrenNR++ + } + _childrenNR += len(self.Unknowns) + pio.PutI32BE(b[n:], int32(_childrenNR)) + n += 4 + if self.AVC1Desc != nil { + n += self.AVC1Desc.Marshal(b[n:]) + } + if self.MP4ADesc != nil { + n += self.MP4ADesc.Marshal(b[n:]) + } + for _, atom := range self.Unknowns { + n += atom.Marshal(b[n:]) + } + return +} +func (self SampleDesc) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + if self.AVC1Desc != nil { + n += self.AVC1Desc.Len() + } + if self.MP4ADesc != nil { + n += self.MP4ADesc.Len() + } + for _, atom := range self.Unknowns { + n += atom.Len() + } + return +} +func (self *SampleDesc) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.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 + } + self.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 + } + self.MP4ADesc = 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 + } + self.Unknowns = append(self.Unknowns, atom) + } + } + n += size + } + return +} +func (self SampleDesc) Children() (r []Atom) { + if self.AVC1Desc != nil { + r = append(r, self.AVC1Desc) + } + if self.MP4ADesc != nil { + r = append(r, self.MP4ADesc) + } + r = append(r, self.Unknowns...) + return +} + +type MP4ADesc struct { + DataRefIdx int16 + Version int16 + RevisionLevel int16 + Vendor int32 + NumberOfChannels int16 + SampleSize int16 + CompressionId int16 + SampleRate float64 + Conf *ElemStreamDesc + Unknowns []Atom + AtomPos +} + +func (self MP4ADesc) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(MP4A)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self MP4ADesc) marshal(b []byte) (n int) { + n += 6 + pio.PutI16BE(b[n:], self.DataRefIdx) + n += 2 + pio.PutI16BE(b[n:], self.Version) + n += 2 + pio.PutI16BE(b[n:], self.RevisionLevel) + n += 2 + pio.PutI32BE(b[n:], self.Vendor) + n += 4 + pio.PutI16BE(b[n:], self.NumberOfChannels) + n += 2 + pio.PutI16BE(b[n:], self.SampleSize) + n += 2 + pio.PutI16BE(b[n:], self.CompressionId) + n += 2 + n += 2 + PutFixed32(b[n:], self.SampleRate) + n += 4 + if self.Conf != nil { + n += self.Conf.Marshal(b[n:]) + } + for _, atom := range self.Unknowns { + n += atom.Marshal(b[n:]) + } + return +} +func (self MP4ADesc) Len() (n int) { + n += 8 + n += 6 + n += 2 + n += 2 + n += 2 + n += 4 + n += 2 + n += 2 + n += 2 + n += 2 + n += 4 + if self.Conf != nil { + n += self.Conf.Len() + } + for _, atom := range self.Unknowns { + n += atom.Len() + } + return +} +func (self *MP4ADesc) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + n += 6 + if len(b) < n+2 { + err = parseErr("DataRefIdx", n+offset, err) + return + } + self.DataRefIdx = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+2 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+2 { + err = parseErr("RevisionLevel", n+offset, err) + return + } + self.RevisionLevel = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+4 { + err = parseErr("Vendor", n+offset, err) + return + } + self.Vendor = pio.I32BE(b[n:]) + n += 4 + if len(b) < n+2 { + err = parseErr("NumberOfChannels", n+offset, err) + return + } + self.NumberOfChannels = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+2 { + err = parseErr("SampleSize", n+offset, err) + return + } + self.SampleSize = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+2 { + err = parseErr("CompressionId", n+offset, err) + return + } + self.CompressionId = pio.I16BE(b[n:]) + n += 2 + n += 2 + if len(b) < n+4 { + err = parseErr("SampleRate", n+offset, err) + return + } + self.SampleRate = GetFixed32(b[n:]) + 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 ESDS: + { + atom := &ElemStreamDesc{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("esds", n+offset, err) + return + } + self.Conf = 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 + } + self.Unknowns = append(self.Unknowns, atom) + } + } + n += size + } + return +} +func (self MP4ADesc) Children() (r []Atom) { + if self.Conf != nil { + r = append(r, self.Conf) + } + r = append(r, self.Unknowns...) + return +} + +type AVC1Desc struct { + DataRefIdx int16 + Version int16 + Revision int16 + Vendor int32 + TemporalQuality int32 + SpatialQuality int32 + Width int16 + Height int16 + HorizontalResolution float64 + VorizontalResolution float64 + FrameCount int16 + CompressorName [32]byte + Depth int16 + ColorTableId int16 + Conf *AVC1Conf + Unknowns []Atom + AtomPos +} + +func (self AVC1Desc) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(AVC1)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self AVC1Desc) marshal(b []byte) (n int) { + n += 6 + pio.PutI16BE(b[n:], self.DataRefIdx) + n += 2 + pio.PutI16BE(b[n:], self.Version) + n += 2 + pio.PutI16BE(b[n:], self.Revision) + n += 2 + pio.PutI32BE(b[n:], self.Vendor) + n += 4 + pio.PutI32BE(b[n:], self.TemporalQuality) + n += 4 + pio.PutI32BE(b[n:], self.SpatialQuality) + n += 4 + pio.PutI16BE(b[n:], self.Width) + n += 2 + pio.PutI16BE(b[n:], self.Height) + n += 2 + PutFixed32(b[n:], self.HorizontalResolution) + n += 4 + PutFixed32(b[n:], self.VorizontalResolution) + n += 4 + n += 4 + pio.PutI16BE(b[n:], self.FrameCount) + n += 2 + copy(b[n:], self.CompressorName[:]) + n += len(self.CompressorName[:]) + pio.PutI16BE(b[n:], self.Depth) + n += 2 + pio.PutI16BE(b[n:], self.ColorTableId) + n += 2 + if self.Conf != nil { + n += self.Conf.Marshal(b[n:]) + } + for _, atom := range self.Unknowns { + n += atom.Marshal(b[n:]) + } + return +} +func (self AVC1Desc) Len() (n int) { + n += 8 + n += 6 + n += 2 + n += 2 + n += 2 + n += 4 + n += 4 + n += 4 + n += 2 + n += 2 + n += 4 + n += 4 + n += 4 + n += 2 + n += len(self.CompressorName[:]) + n += 2 + n += 2 + if self.Conf != nil { + n += self.Conf.Len() + } + for _, atom := range self.Unknowns { + n += atom.Len() + } + return +} +func (self *AVC1Desc) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + n += 6 + if len(b) < n+2 { + err = parseErr("DataRefIdx", n+offset, err) + return + } + self.DataRefIdx = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+2 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+2 { + err = parseErr("Revision", n+offset, err) + return + } + self.Revision = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+4 { + err = parseErr("Vendor", n+offset, err) + return + } + self.Vendor = pio.I32BE(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("TemporalQuality", n+offset, err) + return + } + self.TemporalQuality = pio.I32BE(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("SpatialQuality", n+offset, err) + return + } + self.SpatialQuality = pio.I32BE(b[n:]) + n += 4 + if len(b) < n+2 { + err = parseErr("Width", n+offset, err) + return + } + self.Width = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+2 { + err = parseErr("Height", n+offset, err) + return + } + self.Height = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+4 { + err = parseErr("HorizontalResolution", n+offset, err) + return + } + self.HorizontalResolution = GetFixed32(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("VorizontalResolution", n+offset, err) + return + } + self.VorizontalResolution = GetFixed32(b[n:]) + n += 4 + n += 4 + if len(b) < n+2 { + err = parseErr("FrameCount", n+offset, err) + return + } + self.FrameCount = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+len(self.CompressorName) { + err = parseErr("CompressorName", n+offset, err) + return + } + copy(self.CompressorName[:], b[n:]) + n += len(self.CompressorName) + if len(b) < n+2 { + err = parseErr("Depth", n+offset, err) + return + } + self.Depth = pio.I16BE(b[n:]) + n += 2 + if len(b) < n+2 { + err = parseErr("ColorTableId", n+offset, err) + return + } + self.ColorTableId = pio.I16BE(b[n:]) + n += 2 + 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 AVCC: + { + atom := &AVC1Conf{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("avcC", n+offset, err) + return + } + self.Conf = 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 + } + self.Unknowns = append(self.Unknowns, atom) + } + } + n += size + } + return +} +func (self AVC1Desc) Children() (r []Atom) { + if self.Conf != nil { + r = append(r, self.Conf) + } + r = append(r, self.Unknowns...) + return +} + +type AVC1Conf struct { + Data []byte + AtomPos +} + +func (self AVC1Conf) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(AVCC)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self AVC1Conf) marshal(b []byte) (n int) { + copy(b[n:], self.Data[:]) + n += len(self.Data[:]) + return +} +func (self AVC1Conf) Len() (n int) { + n += 8 + n += len(self.Data[:]) + return +} +func (self *AVC1Conf) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + self.Data = b[n:] + n += len(b[n:]) + return +} +func (self AVC1Conf) Children() (r []Atom) { + return +} + +type TimeToSample struct { + Version uint8 + Flags uint32 + Entries []TimeToSampleEntry + AtomPos +} + +func (self TimeToSample) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(STTS)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self TimeToSample) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + pio.PutU32BE(b[n:], uint32(len(self.Entries))) + n += 4 + for _, entry := range self.Entries { + PutTimeToSampleEntry(b[n:], entry) + n += LenTimeToSampleEntry + } + return +} +func (self TimeToSample) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + n += LenTimeToSampleEntry*len(self.Entries) + return +} +func (self *TimeToSample) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + var _len_Entries uint32 + _len_Entries = pio.U32BE(b[n:]) + n += 4 + self.Entries = make([]TimeToSampleEntry, _len_Entries) + if len(b) < n+LenTimeToSampleEntry*len(self.Entries) { + err = parseErr("TimeToSampleEntry", n+offset, err) + return + } + for i := range self.Entries { + self.Entries[i] = GetTimeToSampleEntry(b[n:]) + n += LenTimeToSampleEntry + } + return +} +func (self TimeToSample) Children() (r []Atom) { + return +} + +type TimeToSampleEntry struct { + Count uint32 + Duration uint32 +} + +func GetTimeToSampleEntry(b []byte) (self TimeToSampleEntry) { + self.Count = pio.U32BE(b[0:]) + self.Duration = pio.U32BE(b[4:]) + return +} +func PutTimeToSampleEntry(b []byte, self TimeToSampleEntry) { + pio.PutU32BE(b[0:], self.Count) + pio.PutU32BE(b[4:], self.Duration) +} + +const LenTimeToSampleEntry = 8 + +type SampleToChunk struct { + Version uint8 + Flags uint32 + Entries []SampleToChunkEntry + AtomPos +} + +func (self SampleToChunk) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(STSC)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self SampleToChunk) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + pio.PutU32BE(b[n:], uint32(len(self.Entries))) + n += 4 + for _, entry := range self.Entries { + PutSampleToChunkEntry(b[n:], entry) + n += LenSampleToChunkEntry + } + return +} +func (self SampleToChunk) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + n += LenSampleToChunkEntry*len(self.Entries) + return +} +func (self *SampleToChunk) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + var _len_Entries uint32 + _len_Entries = pio.U32BE(b[n:]) + n += 4 + self.Entries = make([]SampleToChunkEntry, _len_Entries) + if len(b) < n+LenSampleToChunkEntry*len(self.Entries) { + err = parseErr("SampleToChunkEntry", n+offset, err) + return + } + for i := range self.Entries { + self.Entries[i] = GetSampleToChunkEntry(b[n:]) + n += LenSampleToChunkEntry + } + return +} +func (self SampleToChunk) Children() (r []Atom) { + return +} + +type SampleToChunkEntry struct { + FirstChunk uint32 + SamplesPerChunk uint32 + SampleDescId uint32 +} + +func GetSampleToChunkEntry(b []byte) (self SampleToChunkEntry) { + self.FirstChunk = pio.U32BE(b[0:]) + self.SamplesPerChunk = pio.U32BE(b[4:]) + self.SampleDescId = pio.U32BE(b[8:]) + return +} +func PutSampleToChunkEntry(b []byte, self SampleToChunkEntry) { + pio.PutU32BE(b[0:], self.FirstChunk) + pio.PutU32BE(b[4:], self.SamplesPerChunk) + pio.PutU32BE(b[8:], self.SampleDescId) +} + +const LenSampleToChunkEntry = 12 + +type CompositionOffset struct { + Version uint8 + Flags uint32 + Entries []CompositionOffsetEntry + AtomPos +} + +func (self CompositionOffset) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(CTTS)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self CompositionOffset) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + pio.PutU32BE(b[n:], uint32(len(self.Entries))) + n += 4 + for _, entry := range self.Entries { + PutCompositionOffsetEntry(b[n:], entry) + n += LenCompositionOffsetEntry + } + return +} +func (self CompositionOffset) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + n += LenCompositionOffsetEntry*len(self.Entries) + return +} +func (self *CompositionOffset) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + var _len_Entries uint32 + _len_Entries = pio.U32BE(b[n:]) + n += 4 + self.Entries = make([]CompositionOffsetEntry, _len_Entries) + if len(b) < n+LenCompositionOffsetEntry*len(self.Entries) { + err = parseErr("CompositionOffsetEntry", n+offset, err) + return + } + for i := range self.Entries { + self.Entries[i] = GetCompositionOffsetEntry(b[n:]) + n += LenCompositionOffsetEntry + } + return +} +func (self CompositionOffset) Children() (r []Atom) { + return +} + +type CompositionOffsetEntry struct { + Count uint32 + Offset uint32 +} + +func GetCompositionOffsetEntry(b []byte) (self CompositionOffsetEntry) { + self.Count = pio.U32BE(b[0:]) + self.Offset = pio.U32BE(b[4:]) + return +} +func PutCompositionOffsetEntry(b []byte, self CompositionOffsetEntry) { + pio.PutU32BE(b[0:], self.Count) + pio.PutU32BE(b[4:], self.Offset) +} + +const LenCompositionOffsetEntry = 8 + +type SyncSample struct { + Version uint8 + Flags uint32 + Entries []uint32 + AtomPos +} + +func (self SyncSample) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(STSS)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self SyncSample) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + pio.PutU32BE(b[n:], uint32(len(self.Entries))) + n += 4 + for _, entry := range self.Entries { + pio.PutU32BE(b[n:], entry) + n += 4 + } + return +} +func (self SyncSample) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + n += 4*len(self.Entries) + return +} +func (self *SyncSample) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + var _len_Entries uint32 + _len_Entries = pio.U32BE(b[n:]) + n += 4 + self.Entries = make([]uint32, _len_Entries) + if len(b) < n+4*len(self.Entries) { + err = parseErr("uint32", n+offset, err) + return + } + for i := range self.Entries { + self.Entries[i] = pio.U32BE(b[n:]) + n += 4 + } + return +} +func (self SyncSample) Children() (r []Atom) { + return +} + +type ChunkOffset struct { + Version uint8 + Flags uint32 + Entries []uint32 + AtomPos +} + +func (self ChunkOffset) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(STCO)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self ChunkOffset) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + pio.PutU32BE(b[n:], uint32(len(self.Entries))) + n += 4 + for _, entry := range self.Entries { + pio.PutU32BE(b[n:], entry) + n += 4 + } + return +} +func (self ChunkOffset) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + n += 4*len(self.Entries) + return +} +func (self *ChunkOffset) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + var _len_Entries uint32 + _len_Entries = pio.U32BE(b[n:]) + n += 4 + self.Entries = make([]uint32, _len_Entries) + if len(b) < n+4*len(self.Entries) { + err = parseErr("uint32", n+offset, err) + return + } + for i := range self.Entries { + self.Entries[i] = pio.U32BE(b[n:]) + n += 4 + } + return +} +func (self ChunkOffset) Children() (r []Atom) { + return +} + +type MovieFrag struct { + Header *MovieFragHeader + Tracks []*TrackFrag + Unknowns []Atom + AtomPos +} + +func (self MovieFrag) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(MOOF)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self MovieFrag) marshal(b []byte) (n int) { + if self.Header != nil { + n += self.Header.Marshal(b[n:]) + } + for _, atom := range self.Tracks { + n += atom.Marshal(b[n:]) + } + for _, atom := range self.Unknowns { + n += atom.Marshal(b[n:]) + } + return +} +func (self MovieFrag) Len() (n int) { + n += 8 + if self.Header != nil { + n += self.Header.Len() + } + for _, atom := range self.Tracks { + n += atom.Len() + } + for _, atom := range self.Unknowns { + n += atom.Len() + } + return +} +func (self *MovieFrag) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.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 MFHD: + { + atom := &MovieFragHeader{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("mfhd", n+offset, err) + return + } + self.Header = atom + } + case TRAF: + { + atom := &TrackFrag{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("traf", n+offset, err) + return + } + self.Tracks = append(self.Tracks, 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 + } + self.Unknowns = append(self.Unknowns, atom) + } + } + n += size + } + return +} +func (self MovieFrag) Children() (r []Atom) { + if self.Header != nil { + r = append(r, self.Header) + } + for _, atom := range self.Tracks { + r = append(r, atom) + } + r = append(r, self.Unknowns...) + return +} + +type MovieFragHeader struct { + Version uint8 + Flags uint32 + Seqnum uint32 + AtomPos +} + +func (self MovieFragHeader) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(MFHD)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self MovieFragHeader) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + pio.PutU32BE(b[n:], self.Seqnum) + n += 4 + return +} +func (self MovieFragHeader) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + return +} +func (self *MovieFragHeader) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + if len(b) < n+4 { + err = parseErr("Seqnum", n+offset, err) + return + } + self.Seqnum = pio.U32BE(b[n:]) + n += 4 + return +} +func (self MovieFragHeader) Children() (r []Atom) { + return +} + +type TrackFrag struct { + Header *TrackFragHeader + DecodeTime *TrackFragDecodeTime + Run *TrackFragRun + Unknowns []Atom + AtomPos +} + +func (self TrackFrag) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(TRAF)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self TrackFrag) marshal(b []byte) (n int) { + if self.Header != nil { + n += self.Header.Marshal(b[n:]) + } + if self.DecodeTime != nil { + n += self.DecodeTime.Marshal(b[n:]) + } + if self.Run != nil { + n += self.Run.Marshal(b[n:]) + } + for _, atom := range self.Unknowns { + n += atom.Marshal(b[n:]) + } + return +} +func (self TrackFrag) Len() (n int) { + n += 8 + if self.Header != nil { + n += self.Header.Len() + } + if self.DecodeTime != nil { + n += self.DecodeTime.Len() + } + if self.Run != nil { + n += self.Run.Len() + } + for _, atom := range self.Unknowns { + n += atom.Len() + } + return +} +func (self *TrackFrag) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.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 TFHD: + { + atom := &TrackFragHeader{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("tfhd", n+offset, err) + return + } + self.Header = atom + } + case TFDT: + { + atom := &TrackFragDecodeTime{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("tfdt", n+offset, err) + return + } + self.DecodeTime = atom + } + case TRUN: + { + atom := &TrackFragRun{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("trun", n+offset, err) + return + } + self.Run = 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 + } + self.Unknowns = append(self.Unknowns, atom) + } + } + n += size + } + return +} +func (self TrackFrag) Children() (r []Atom) { + if self.Header != nil { + r = append(r, self.Header) + } + if self.DecodeTime != nil { + r = append(r, self.DecodeTime) + } + if self.Run != nil { + r = append(r, self.Run) + } + r = append(r, self.Unknowns...) + return +} + +type MovieExtend struct { + Tracks []*TrackExtend + Unknowns []Atom + AtomPos +} + +func (self MovieExtend) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(MVEX)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self MovieExtend) marshal(b []byte) (n int) { + for _, atom := range self.Tracks { + n += atom.Marshal(b[n:]) + } + for _, atom := range self.Unknowns { + n += atom.Marshal(b[n:]) + } + return +} +func (self MovieExtend) Len() (n int) { + n += 8 + for _, atom := range self.Tracks { + n += atom.Len() + } + for _, atom := range self.Unknowns { + n += atom.Len() + } + return +} +func (self *MovieExtend) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.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 TREX: + { + atom := &TrackExtend{} + if _, err = atom.Unmarshal(b[n:n+size], offset+n); err != nil { + err = parseErr("trex", n+offset, err) + return + } + self.Tracks = append(self.Tracks, 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 + } + self.Unknowns = append(self.Unknowns, atom) + } + } + n += size + } + return +} +func (self MovieExtend) Children() (r []Atom) { + for _, atom := range self.Tracks { + r = append(r, atom) + } + r = append(r, self.Unknowns...) + return +} + +type TrackExtend struct { + Version uint8 + Flags uint32 + TrackId uint32 + DefaultSampleDescIdx uint32 + DefaultSampleDuration uint32 + DefaultSampleSize uint32 + DefaultSampleFlags uint32 + AtomPos +} + +func (self TrackExtend) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(TREX)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self TrackExtend) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + pio.PutU32BE(b[n:], self.TrackId) + n += 4 + pio.PutU32BE(b[n:], self.DefaultSampleDescIdx) + n += 4 + pio.PutU32BE(b[n:], self.DefaultSampleDuration) + n += 4 + pio.PutU32BE(b[n:], self.DefaultSampleSize) + n += 4 + pio.PutU32BE(b[n:], self.DefaultSampleFlags) + n += 4 + return +} +func (self TrackExtend) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + n += 4 + n += 4 + n += 4 + n += 4 + return +} +func (self *TrackExtend) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + if len(b) < n+4 { + err = parseErr("TrackId", n+offset, err) + return + } + self.TrackId = pio.U32BE(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("DefaultSampleDescIdx", n+offset, err) + return + } + self.DefaultSampleDescIdx = pio.U32BE(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("DefaultSampleDuration", n+offset, err) + return + } + self.DefaultSampleDuration = pio.U32BE(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("DefaultSampleSize", n+offset, err) + return + } + self.DefaultSampleSize = pio.U32BE(b[n:]) + n += 4 + if len(b) < n+4 { + err = parseErr("DefaultSampleFlags", n+offset, err) + return + } + self.DefaultSampleFlags = pio.U32BE(b[n:]) + n += 4 + return +} +func (self TrackExtend) Children() (r []Atom) { + return +} + +type SampleSize struct { + Version uint8 + Flags uint32 + SampleSize uint32 + Entries []uint32 + AtomPos +} + +func (self SampleSize) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(STSZ)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self SampleSize) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + pio.PutU32BE(b[n:], self.SampleSize) + n += 4 + if self.SampleSize != 0 { + return + } + pio.PutU32BE(b[n:], uint32(len(self.Entries))) + n += 4 + for _, entry := range self.Entries { + pio.PutU32BE(b[n:], entry) + n += 4 + } + return +} +func (self SampleSize) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + if self.SampleSize != 0 { + return + } + n += 4 + n += 4*len(self.Entries) + return +} +func (self *SampleSize) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + if len(b) < n+4 { + err = parseErr("SampleSize", n+offset, err) + return + } + self.SampleSize = pio.U32BE(b[n:]) + n += 4 + if self.SampleSize != 0 { + return + } + var _len_Entries uint32 + _len_Entries = pio.U32BE(b[n:]) + n += 4 + self.Entries = make([]uint32, _len_Entries) + if len(b) < n+4*len(self.Entries) { + err = parseErr("uint32", n+offset, err) + return + } + for i := range self.Entries { + self.Entries[i] = pio.U32BE(b[n:]) + n += 4 + } + return +} +func (self SampleSize) Children() (r []Atom) { + return +} + +type TrackFragRun struct { + Version uint8 + Flags uint32 + DataOffset uint32 + FirstSampleFlags uint32 + Entries []TrackFragRunEntry + AtomPos +} + +func (self TrackFragRun) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(TRUN)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self TrackFragRun) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + pio.PutU32BE(b[n:], uint32(len(self.Entries))) + n += 4 + if self.Flags&TRUN_DATA_OFFSET != 0 { + { + pio.PutU32BE(b[n:], self.DataOffset) + n += 4 + } + } + if self.Flags&TRUN_FIRST_SAMPLE_FLAGS != 0 { + { + pio.PutU32BE(b[n:], self.FirstSampleFlags) + n += 4 + } + } + + for i, entry := range self.Entries { + var flags uint32 + if i > 0 { + flags = self.Flags + } else { + flags = self.FirstSampleFlags + } + if flags&TRUN_SAMPLE_DURATION != 0 { + pio.PutU32BE(b[n:], entry.Duration) + n += 4 + } + if flags&TRUN_SAMPLE_SIZE != 0 { + pio.PutU32BE(b[n:], entry.Size) + n += 4 + } + if flags&TRUN_SAMPLE_FLAGS != 0 { + pio.PutU32BE(b[n:], entry.Flags) + n += 4 + } + if flags&TRUN_SAMPLE_CTS != 0 { + pio.PutU32BE(b[n:], entry.Cts) + n += 4 + } + } + return +} +func (self TrackFragRun) Len() (n int) { + n += 8 + n += 1 + n += 3 + n += 4 + if self.Flags&TRUN_DATA_OFFSET != 0 { + { + n += 4 + } + } + if self.Flags&TRUN_FIRST_SAMPLE_FLAGS != 0 { + { + n += 4 + } + } + + for i := range self.Entries { + var flags uint32 + if i > 0 { + flags = self.Flags + } else { + flags = self.FirstSampleFlags + } + if flags&TRUN_SAMPLE_DURATION != 0 { + n += 4 + } + if flags&TRUN_SAMPLE_SIZE != 0 { + n += 4 + } + if flags&TRUN_SAMPLE_FLAGS != 0 { + n += 4 + } + if flags&TRUN_SAMPLE_CTS != 0 { + n += 4 + } + } + return +} +func (self *TrackFragRun) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + var _len_Entries uint32 + _len_Entries = pio.U32BE(b[n:]) + n += 4 + self.Entries = make([]TrackFragRunEntry, _len_Entries) + if self.Flags&TRUN_DATA_OFFSET != 0 { + { + if len(b) < n+4 { + err = parseErr("DataOffset", n+offset, err) + return + } + self.DataOffset = pio.U32BE(b[n:]) + n += 4 + } + } + if self.Flags&TRUN_FIRST_SAMPLE_FLAGS != 0 { + { + if len(b) < n+4 { + err = parseErr("FirstSampleFlags", n+offset, err) + return + } + self.FirstSampleFlags = pio.U32BE(b[n:]) + n += 4 + } + } + + for i := 0; i < int(_len_Entries); i++ { + var flags uint32 + if i > 0 { + flags = self.Flags + } else { + flags = self.FirstSampleFlags + } + entry := &self.Entries[i] + if flags&TRUN_SAMPLE_DURATION != 0 { + entry.Duration = pio.U32BE(b[n:]) + n += 4 + } + if flags&TRUN_SAMPLE_SIZE != 0 { + entry.Size = pio.U32BE(b[n:]) + n += 4 + } + if flags&TRUN_SAMPLE_FLAGS != 0 { + entry.Flags = pio.U32BE(b[n:]) + n += 4 + } + if flags&TRUN_SAMPLE_CTS != 0 { + entry.Cts = pio.U32BE(b[n:]) + n += 4 + } + } + return +} +func (self TrackFragRun) Children() (r []Atom) { + return +} + +type TrackFragRunEntry struct { + Duration uint32 + Size uint32 + Flags uint32 + Cts uint32 +} + +func GetTrackFragRunEntry(b []byte) (self TrackFragRunEntry) { + self.Duration = pio.U32BE(b[0:]) + self.Size = pio.U32BE(b[4:]) + self.Flags = pio.U32BE(b[8:]) + self.Cts = pio.U32BE(b[12:]) + return +} +func PutTrackFragRunEntry(b []byte, self TrackFragRunEntry) { + pio.PutU32BE(b[0:], self.Duration) + pio.PutU32BE(b[4:], self.Size) + pio.PutU32BE(b[8:], self.Flags) + pio.PutU32BE(b[12:], self.Cts) +} + +const LenTrackFragRunEntry = 16 + +type TrackFragHeader struct { + Version uint8 + Flags uint32 + BaseDataOffset uint64 + StsdId uint32 + DefaultDuration uint32 + DefaultSize uint32 + DefaultFlags uint32 + AtomPos +} + +func (self TrackFragHeader) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(TFHD)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self TrackFragHeader) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + if self.Flags&TFHD_BASE_DATA_OFFSET != 0 { + { + pio.PutU64BE(b[n:], self.BaseDataOffset) + n += 8 + } + } + if self.Flags&TFHD_STSD_ID != 0 { + { + pio.PutU32BE(b[n:], self.StsdId) + n += 4 + } + } + if self.Flags&TFHD_DEFAULT_DURATION != 0 { + { + pio.PutU32BE(b[n:], self.DefaultDuration) + n += 4 + } + } + if self.Flags&TFHD_DEFAULT_SIZE != 0 { + { + pio.PutU32BE(b[n:], self.DefaultSize) + n += 4 + } + } + if self.Flags&TFHD_DEFAULT_FLAGS != 0 { + { + pio.PutU32BE(b[n:], self.DefaultFlags) + n += 4 + } + } + return +} +func (self TrackFragHeader) Len() (n int) { + n += 8 + n += 1 + n += 3 + if self.Flags&TFHD_BASE_DATA_OFFSET != 0 { + { + n += 8 + } + } + if self.Flags&TFHD_STSD_ID != 0 { + { + n += 4 + } + } + if self.Flags&TFHD_DEFAULT_DURATION != 0 { + { + n += 4 + } + } + if self.Flags&TFHD_DEFAULT_SIZE != 0 { + { + n += 4 + } + } + if self.Flags&TFHD_DEFAULT_FLAGS != 0 { + { + n += 4 + } + } + return +} +func (self *TrackFragHeader) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + if self.Flags&TFHD_BASE_DATA_OFFSET != 0 { + { + if len(b) < n+8 { + err = parseErr("BaseDataOffset", n+offset, err) + return + } + self.BaseDataOffset = pio.U64BE(b[n:]) + n += 8 + } + } + if self.Flags&TFHD_STSD_ID != 0 { + { + if len(b) < n+4 { + err = parseErr("StsdId", n+offset, err) + return + } + self.StsdId = pio.U32BE(b[n:]) + n += 4 + } + } + if self.Flags&TFHD_DEFAULT_DURATION != 0 { + { + if len(b) < n+4 { + err = parseErr("DefaultDuration", n+offset, err) + return + } + self.DefaultDuration = pio.U32BE(b[n:]) + n += 4 + } + } + if self.Flags&TFHD_DEFAULT_SIZE != 0 { + { + if len(b) < n+4 { + err = parseErr("DefaultSize", n+offset, err) + return + } + self.DefaultSize = pio.U32BE(b[n:]) + n += 4 + } + } + if self.Flags&TFHD_DEFAULT_FLAGS != 0 { + { + if len(b) < n+4 { + err = parseErr("DefaultFlags", n+offset, err) + return + } + self.DefaultFlags = pio.U32BE(b[n:]) + n += 4 + } + } + return +} +func (self TrackFragHeader) Children() (r []Atom) { + return +} + +type TrackFragDecodeTime struct { + Version uint8 + Flags uint32 + Time time.Time + AtomPos +} + +func (self TrackFragDecodeTime) Marshal(b []byte) (n int) { + pio.PutU32BE(b[4:], uint32(TFDT)) + n += self.marshal(b[8:])+8 + pio.PutU32BE(b[0:], uint32(n)) + return +} +func (self TrackFragDecodeTime) marshal(b []byte) (n int) { + pio.PutU8(b[n:], self.Version) + n += 1 + pio.PutU24BE(b[n:], self.Flags) + n += 3 + if self.Version != 0 { + PutTime64(b[n:], self.Time) + n += 8 + } else { + + PutTime32(b[n:], self.Time) + n += 4 + } + return +} +func (self TrackFragDecodeTime) Len() (n int) { + n += 8 + n += 1 + n += 3 + if self.Version != 0 { + n += 8 + } else { + + n += 4 + } + return +} +func (self *TrackFragDecodeTime) Unmarshal(b []byte, offset int) (n int, err error) { + (&self.AtomPos).setPos(offset, len(b)) + n += 8 + if len(b) < n+1 { + err = parseErr("Version", n+offset, err) + return + } + self.Version = pio.U8(b[n:]) + n += 1 + if len(b) < n+3 { + err = parseErr("Flags", n+offset, err) + return + } + self.Flags = pio.U24BE(b[n:]) + n += 3 + if self.Version != 0 { + self.Time = GetTime64(b[n:]) + n += 8 + } else { + + self.Time = GetTime32(b[n:]) + n += 4 + } + return +} +func (self TrackFragDecodeTime) Children() (r []Atom) { + return +}