From 82b17612dd676e21d204d6fe03a47ff13bcc70ea Mon Sep 17 00:00:00 2001 From: nareix Date: Mon, 18 Apr 2016 00:20:01 +0800 Subject: [PATCH] add frag atom support --- atom/genStruct.js | 66 +++++++++ atom/otherStruct.go | 318 ++++++++++++++++++++++++++++++++++++++++---- atom/struct.go | 223 +++++++++++++++++++++++++++++++ 3 files changed, 581 insertions(+), 26 deletions(-) diff --git a/atom/genStruct.js b/atom/genStruct.js index 4c1c2c7..6a2122f 100644 --- a/atom/genStruct.js +++ b/atom/genStruct.js @@ -340,6 +340,72 @@ var atoms = { ], }, + movieFrag: { + cc4: 'moof', + fields: [ + ['$atoms', [ + ['header', '*movieFragHeader'], + ['tracks', '[]*trackFrag'], + ]], + ], + }, + + trackFragDecodeTime: { + cc4: 'tfdt', + }, + + movieFragHeader: { + cc4: 'mfhd', + fields: [ + ['version', 'int8'], + ['flags', 'int24'], + ['seqNum', 'int32'], + ], + }, + + trackFrag: { + cc4: 'traf', + fields: [ + ['$atoms', [ + ['header', '*trackFragHeader'], + ['decodeTime', '*trackFragDecodeTime'], + ['run', '*trackFragRun'], + ]], + ], + }, + + trackFragRun: { + cc4: 'trun', + }, + + trackFragHeader: { + cc4: 'tfhd', + }, + + /* + // need hand write + trackFragRun: { + cc4: 'trun', + fields: [ + ['version', 'int8'], + ['flags', 'int24'], + ['sampleCount', 'int32'], + ['dataOffset', 'int32'], + ['entries', '[]int32'], + ], + }, + + trackFragHeader: { + cc4: 'tfhd', + fields: [ + ['version', 'int8'], + ['flags', 'int24'], + ['id', 'int32'], + ['sampleDescriptionIndex', 'int32'], + ['_', '[12]byte'], + ], + }, + */ }; var DeclReadFunc = (opts) => { diff --git a/atom/otherStruct.go b/atom/otherStruct.go index ec73293..c5b298e 100644 --- a/atom/otherStruct.go +++ b/atom/otherStruct.go @@ -1,15 +1,15 @@ - package atom import ( - "io" - "fmt" "bytes" + "fmt" + "io" + "github.com/nareix/bits" ) type GolombBitReader struct { - R io.Reader - buf [1]byte + R io.Reader + buf [1]byte left byte } @@ -21,7 +21,7 @@ func (self *GolombBitReader) ReadBit() (res uint, err error) { self.left = 8 } self.left-- - res = uint(self.buf[0]>>self.left)&1 + res = uint(self.buf[0]>>self.left) & 1 return } @@ -31,7 +31,7 @@ func (self *GolombBitReader) ReadBits(n int) (res uint, err error) { if bit, err = self.ReadBit(); err != nil { return } - res |= bit< 0 { + flags = self.Flags + } else { + flags = self.FirstSampleFlags + } + + entry := TrackFragRunEntry{} + if flags&TRUN_SAMPLE_DURATION != 0 { + if entry.Duration, err = ReadInt(r, 4); err != nil { + return + } + } + if flags&TRUN_SAMPLE_SIZE != 0 { + if entry.Size, err = ReadInt(r, 4); err != nil { + return + } + } + if flags&TRUN_SAMPLE_FLAGS != 0 { + if entry.Flags, err = ReadInt(r, 4); err != nil { + return + } + } + if flags&TRUN_SAMPLE_CTS != 0 { + if entry.Cts, err = ReadInt(r, 4); err != nil { + return + } + } + + self.Entries = append(self.Entries, entry) + } + + res = self + return +} + +type TrackFragDecodeTime struct { + Version int + Flags int + Time int64 +} + +func ReadTrackFragDecodeTime(r *io.LimitedReader) (res *TrackFragDecodeTime, err error) { + + self := &TrackFragDecodeTime{} + if self.Version, err = ReadInt(r, 1); err != nil { + return + } + if self.Flags, err = ReadInt(r, 3); err != nil { + return + } + if self.Version != 0 { + if self.Time, err = bits.ReadInt64BE(r, 64); err != nil { + return + } + } else { + if self.Time, err = bits.ReadInt64BE(r, 32); err != nil { + return + } + } + res = self + return +} + +func WriteTrackFragDecodeTime(w io.WriteSeeker, self *TrackFragDecodeTime) (err error) { + var aw *Writer + if aw, err = WriteAtomHeader(w, "tfdt"); err != nil { + return + } + w = aw + if err = WriteInt(w, self.Version, 1); err != nil { + return + } + if err = WriteInt(w, self.Flags, 3); err != nil { + return + } + if self.Version != 0 { + if err = bits.WriteInt64BE(w, self.Time, 64); err != nil { + return + } + } else { + if err = bits.WriteInt64BE(w, self.Time, 32); err != nil { + return + } + } + if err = aw.Close(); err != nil { + return + } + return +} + +func WalkTrackFragDecodeTime(w Walker, self *TrackFragDecodeTime) { + w.StartStruct("TrackFragDecodeTime") + w.Name("Version") + w.Int(self.Version) + w.Name("Flags") + w.Int(self.Flags) + w.Name("Time") + w.Int64(self.Time) + w.EndStruct() + return +} + diff --git a/atom/struct.go b/atom/struct.go index 17128b5..3e75a92 100644 --- a/atom/struct.go +++ b/atom/struct.go @@ -2475,3 +2475,226 @@ func WalkChunkOffset(w Walker, self *ChunkOffset) { w.EndStruct() return } + +type MovieFrag struct { + Header *MovieFragHeader + Tracks []*TrackFrag +} + +func ReadMovieFrag(r *io.LimitedReader) (res *MovieFrag, err error) { + + self := &MovieFrag{} + for r.N > 0 { + var cc4 string + var ar *io.LimitedReader + if ar, cc4, err = ReadAtomHeader(r, ""); err != nil { + return + } + switch cc4 { + case "mfhd": + { + if self.Header, err = ReadMovieFragHeader(ar); err != nil { + return + } + } + case "traf": + { + var item *TrackFrag + if item, err = ReadTrackFrag(ar); err != nil { + return + } + self.Tracks = append(self.Tracks, item) + } + + } + if _, err = ReadDummy(ar, int(ar.N)); err != nil { + return + } + } + res = self + return +} +func WriteMovieFrag(w io.WriteSeeker, self *MovieFrag) (err error) { + + var aw *Writer + if aw, err = WriteAtomHeader(w, "moof"); err != nil { + return + } + w = aw + if self.Header != nil { + if err = WriteMovieFragHeader(w, self.Header); err != nil { + return + } + } + if self.Tracks != nil { + for _, elem := range self.Tracks { + if err = WriteTrackFrag(w, elem); err != nil { + return + } + } + } + if err = aw.Close(); err != nil { + return + } + return +} +func WalkMovieFrag(w Walker, self *MovieFrag) { + + w.StartStruct("MovieFrag") + if self.Header != nil { + WalkMovieFragHeader(w, self.Header) + } + for i, item := range self.Tracks { + if w.FilterArrayItem("MovieFrag", "Tracks", i, len(self.Tracks)) { + if item != nil { + WalkTrackFrag(w, item) + } + } else { + w.ArrayLeft(i, len(self.Tracks)) + break + } + } + w.EndStruct() + return +} + +type MovieFragHeader struct { + Version int + Flags int + SeqNum int +} + +func ReadMovieFragHeader(r *io.LimitedReader) (res *MovieFragHeader, err error) { + + self := &MovieFragHeader{} + if self.Version, err = ReadInt(r, 1); err != nil { + return + } + if self.Flags, err = ReadInt(r, 3); err != nil { + return + } + if self.SeqNum, err = ReadInt(r, 4); err != nil { + return + } + res = self + return +} +func WriteMovieFragHeader(w io.WriteSeeker, self *MovieFragHeader) (err error) { + + var aw *Writer + if aw, err = WriteAtomHeader(w, "mfhd"); err != nil { + return + } + w = aw + if err = WriteInt(w, self.Version, 1); err != nil { + return + } + if err = WriteInt(w, self.Flags, 3); err != nil { + return + } + if err = WriteInt(w, self.SeqNum, 4); err != nil { + return + } + if err = aw.Close(); err != nil { + return + } + return +} +func WalkMovieFragHeader(w Walker, self *MovieFragHeader) { + + w.StartStruct("MovieFragHeader") + w.Name("Version") + w.Int(self.Version) + w.Name("Flags") + w.Int(self.Flags) + w.Name("SeqNum") + w.Int(self.SeqNum) + w.EndStruct() + return +} + +type TrackFrag struct { + Header *TrackFragHeader + DecodeTime *TrackFragDecodeTime + Run *TrackFragRun +} + +func ReadTrackFrag(r *io.LimitedReader) (res *TrackFrag, err error) { + + self := &TrackFrag{} + for r.N > 0 { + var cc4 string + var ar *io.LimitedReader + if ar, cc4, err = ReadAtomHeader(r, ""); err != nil { + return + } + switch cc4 { + case "tfhd": + { + if self.Header, err = ReadTrackFragHeader(ar); err != nil { + return + } + } + case "tfdt": + { + if self.DecodeTime, err = ReadTrackFragDecodeTime(ar); err != nil { + return + } + } + case "trun": + { + if self.Run, err = ReadTrackFragRun(ar); err != nil { + return + } + } + + } + if _, err = ReadDummy(ar, int(ar.N)); err != nil { + return + } + } + res = self + return +} +func WriteTrackFrag(w io.WriteSeeker, self *TrackFrag) (err error) { + + var aw *Writer + if aw, err = WriteAtomHeader(w, "traf"); err != nil { + return + } + w = aw + if self.Header != nil { + if err = WriteTrackFragHeader(w, self.Header); err != nil { + return + } + } + if self.DecodeTime != nil { + if err = WriteTrackFragDecodeTime(w, self.DecodeTime); err != nil { + return + } + } + if self.Run != nil { + if err = WriteTrackFragRun(w, self.Run); err != nil { + return + } + } + if err = aw.Close(); err != nil { + return + } + return +} +func WalkTrackFrag(w Walker, self *TrackFrag) { + + w.StartStruct("TrackFrag") + if self.Header != nil { + WalkTrackFragHeader(w, self.Header) + } + if self.DecodeTime != nil { + WalkTrackFragDecodeTime(w, self.DecodeTime) + } + if self.Run != nil { + WalkTrackFragRun(w, self.Run) + } + w.EndStruct() + return +}