diff --git a/atom/atom.go b/atom/atom.go index 8cf5f58..b97bac0 100644 --- a/atom/atom.go +++ b/atom/atom.go @@ -1,116 +1,3 @@ package atom -import ( - "log" -) - -type Atom interface { - CC4() string - Read(Reader) error -} - -type Ftyp struct { -} - -func (self Ftyp) CC4() string { - return "ftyp" -} - -func (self Ftyp) Read(r Reader) (err error) { - log.Println("read ftyp") - return -} - -type Moov struct { - *Mvhd - Trak []*Trak -} - -func (self Moov) CC4() string { - return "moov" -} - -func (self *Moov) Read(r Reader) (err error) { - var atom Atom - if atom, err = r.ReadAtom(&Mvhd{}); err != nil { - return - } - self.Mvhd = atom.(*Mvhd) - - for { - if atom, err := r.ReadAtom(&Trak{}); err != nil { - break - } else { - self.Trak = append(self.Trak, atom.(*Trak)) - } - } - return -} - -type Mvhd struct { -} - -func (self Mvhd) CC4() string { - return "mvhd" -} - -func (self Mvhd) Read(r Reader) (err error) { - return -} - -type Tkhd struct { -} - -func (self Tkhd) CC4() string { - return "tkhd" -} - -func (self *Tkhd) Read(r Reader) (err error) { - return -} - -type Minf struct { -} - -type Mdia struct { - *Minf -} - -type Trak struct { - Tkhd []*Tkhd - *Mdia -} - -func (self Trak) CC4() string { - return "tkhd" -} - -func (self *Trak) Read(r Reader) (err error) { - return -} - -// Time-to-Sample Atoms -type Stts struct { -} - -// Composition Offset Atom -type Ctts struct { -} - -// Sync Sample Atoms (Keyframe) -type Stss struct { -} - -// Sample-to-Chunk Atoms -type Stsc struct { -} - -// Sample Size Atoms -type Stsz struct { -} - -// Chunk Offset Atoms -type Stco struct { -} - diff --git a/atom/genAtomStruct.js b/atom/genAtomStruct.js deleted file mode 100644 index 4431b5b..0000000 --- a/atom/genAtomStruct.js +++ /dev/null @@ -1,294 +0,0 @@ - -var ucfirst = x => x.substr(0,1).toUpperCase() + x.slice(1); - -var D = (cls, prop, ...fields) => { - var ctor = function (args) { - this.cls = cls; - Object.assign(this, prop); - fields.forEach((f, i) => this[f] = typeof(args[i]) == 'string' ? ucfirst(args[i]) : args[i]); - if (cls == 'Atom' || cls == 'AtomPtr') - this.type = this.type + 'Atom'; - }; - global[cls] = (...args) => new ctor(args); -} - -D('Int', {basic: true, type: 'int'}, 'name', 'len'); -D('Str', {basic: true, type: 'string'}, 'name', 'len'); -D('TimeStamp', {basic: true, type: 'TimeStamp'}, 'name', 'len'); -D('Bytes', {basic: true, type: '[]byte'}, 'name', 'len'); -D('Fixed32', {basic: true, type: 'Fixed32'}, 'name', 'len'); - -D('Atom', {}, 'type', 'name'); -D('AtomPtr', {}, 'type', 'name'); -D('Struct', {}, 'type', 'name'); -D('StructPtr', {}, 'type', 'name'); - -D('Arr', {}, 'name', 'elem', 'count'); -D('LenArr', {}, 'len', 'name', 'elem', 'isptr'); - -D('Size', {hide: true}, 'len'); -D('_', {type: 'Dummy', hide: true}, 'len'); - -var atoms = { - fileType: [ - 'ftyp', - AtomPtr('movie', 'movie'), - ], - - movie: [ - 'moov', - AtomPtr('movieHeader', 'header'), - Arr('tracks', AtomPtr('track')), - ], - - movieHeader: [ - 'mvhd', - Int('version', 1), - Int('flags', 3), - TimeStamp('cTime', 4), - TimeStamp('mTime', 4), - Int('timeScale', 4), - Int('duration', 4), - Int('preferredRate', 4), - Int('preferredVolume', 2), - _(10), - Bytes('matrix', 36), - TimeStamp('previewTime', 4), - TimeStamp('previewDuration', 4), - TimeStamp('posterTime', 4), - TimeStamp('selectionTime', 4), - TimeStamp('selectionDuration', 4), - TimeStamp('currentTime', 4), - Int('nextTrackId', 4), - ], - - track: [ - 'trak', - AtomPtr('trackHeader', 'header'), - AtomPtr('media', 'media'), - ], - - trackHeader: [ - 'tkhd', - Int('version', 1), - Int('flags', 3), - TimeStamp('cTime', 4), - TimeStamp('mTime', 4), - Int('trackId', 4), - _(4), - Int('duration', 4), - _(8), - Int('layer', 2), - Int('alternateGroup', 2), - Int('volume', 2), - _(2), - Bytes('matrix', 36), - Fixed32('trackWidth', 4), - Fixed32('trackHeight', 4), - ], - - media: [ - 'mdia', - AtomPtr('mediaHeader', 'header'), - AtomPtr('mediaInfo', 'info'), - ], - - mediaHeader: [ - 'mdhd', - Int('version', 1), - Int('flags', 3), - TimeStamp('cTime', 4), - TimeStamp('mTime', 4), - Int('timeScale', 4), - Int('duration', 4), - Int('language', 2), - Int('quality', 2), - ], - - mediaInfo: [ - 'minf', - AtomPtr('videoMediaInfo', 'video'), - AtomPtr('sampleTable', 'sample'), - ], - - videoMediaInfo: [ - 'vmhd', - Int('version', 1), - Int('flags', 3), - Int('graphicsMode', 2), - Arr('opcolor', Int('', 2), 3), - ], - - sampleTable: [ - 'stbl', - AtomPtr('sampleDesc', 'sampleDesc'), - AtomPtr('timeToSample', 'timeToSample'), - AtomPtr('compositionOffset', 'compositionOffset'), - AtomPtr('syncSample', 'syncSample'), - AtomPtr('sampleSize', 'sampleSize'), - AtomPtr('chunkOffset', 'chunkOffset'), - ], - - sampleDesc: [ - 'stsd', - Int('version', 1), - Int('flags', 3), - LenArr(4, 'entries', Struct('sampleDescEntry')), - ], - - timeToSample: [ - 'stts', - Int('version', 1), - Int('flags', 3), - LenArr(4, 'entries', Struct('timeToSampleEntry')), - ], - - compositionOffset: [ - 'ctts', - Int('version', 1), - Int('flags', 3), - LenArr(4, 'entries', Struct('compositionOffsetEntry')), - ], - - syncSample: [ - 'stss', - Int('version', 1), - Int('flags', 3), - LenArr(4, 'entries', Int('', 4)), - ], - - sampleSize: [ - 'stsz', - Int('version', 1), - Int('flags', 3), - LenArr(4, 'entries', Int('', 4)), - ], - - chunkOffset: [ - 'stco', - Int('version', 1), - Int('flags', 3), - LenArr(4, 'entries', Int('', 4)), - ], -}; - -var structs = { - sampleDescEntry: [ - Size(4), - Str('format', 4), - _(6), - Int('dataRefIdx', 2), - Bytes('data'), - ], - - timeToSampleEntry: [ - Int('count', 4), - Int('duration', 4), - ], - - compositionOffsetEntry: [ - Int('count', 4), - Int('offset', 4), - ], -}; - -var typeStr = field => ( - field.cls == 'AtomPtr' || field.cls == 'StructPtr') ? '*'+field.type : field.type; - -var dumpStruct = (name, list) => { - console.log(`type ${name} struct { - %s - }`, list - .filter(field => !field.hide) - .map(field => { - if (field.cls == 'Arr' || field.cls == 'LenArr') - return field.name +' []'+typeStr(field.elem); - return field.name+' '+typeStr(field) - }).join('\n') - ); - - dumpReadFn(name, null, false, list); -}; - -var dumpReadFn = (type, cc4, retptr, list) => { - var useSize; - - if (retptr) { - console.log(`func Read${type}(r io.LimitedReader) (res *${type}, err error) {`); - console.log(`self := &${type}{}`); - } else { - console.log(`func Read${type}(r io.LimitedReader) (self ${type}, err error) {`); - } - - list.forEach(field => { - if (field.cls == 'Size') { - useSize = true; - console.log(`size := ReadInt(r, ${field.len})`); - } else if (field.cls == 'Arr') { - var cond = field.count ? `i := 0; i < ${field.count}; i++` : `r.N > 0`; - console.log(`for ${cond} {`); - console.log(`var item ${typeStr(field.elem)}`); - console.log(`if item, err = Read${field.elem.type}(r); err != nil { - return - } else { - self.${field.name} = append(self.${field.name}, item) - }`); - console.log(`}`); - } else if (field.cls == 'LenArr') { - console.log(`if n, err := ReadInt(r, ${field.len}); err != nil { - return nil, err - } else { - for i := 0; i < n; i++ { - self.${field.name} = append(self.${field.name}, item) - } - }`); - } else { - var fn = field.basic ? field.cls : field.type; - var args = field.basic ? 'r, ' + field.len : 'r'; - console.log(`if self.${field.name}, err = Read${fn}(${args}); err != nil { - return - }`); - } - }); - - if (retptr) { - console.log(`res = self`); - } - console.log(`return`); - console.log(`}`); -}; - -var dumpWriteFn = (name, list) => { - var useSize; - - console.log(`func Write${name}(w Writer, atom ${name}) (err error) {`); - - list.map(x => { - if (x.type == 'size') { - useSize = true; - return `ReadInt(r, ${x.len})`; - } - }); - - console.log(`}`); -}; - -console.log('// THIS FILE IS AUTO GENERATED'); -console.log(''); -console.log('package atom'); - -for (var k in atoms) { - var list = atoms[k]; - var name = ucfirst(k)+'Atom'; - - var cc4 = list[0]; - list = list.slice(1); - dumpStruct(name, list); - dumpReadFn(name, cc4, true, list); -} - -for (var k in structs) { - var list = structs[k]; - dumpStruct(ucfirst(k), list) -} - diff --git a/atom/genStruct.js b/atom/genStruct.js new file mode 100644 index 0000000..94b2fa2 --- /dev/null +++ b/atom/genStruct.js @@ -0,0 +1,354 @@ + +var uc = x => x && x.substr(0,1).toUpperCase()+x.slice(1); +Array.prototype.nonull = function () { + return this.filter(x => x); +}; + +var Int = (name,len) => {return {name:uc(name),len,type:'int',fn:'Int'}}; +var Str = (name,len) => {return {name:uc(name),len,type:'string',fn:'String'}}; +var TimeStamp = (name,len) => {return {name:uc(name),len,type:'TimeStamp',fn:'TimeStamp'}}; +var Bytes = (name,len) => {return {name:uc(name),len,type:'[]byte',fn:'Bytes'}}; +var BytesLeft = (name) => {return {name:uc(name),type:'[]byte',fn:'BytesLeft'}}; +var Fixed32 = (name,len) => {return {name:uc(name),len,type:'Fixed32',fn:'Fixed32'}}; + +var Atom = (type,name) => {return {name:uc(name),type:uc(type)+'Atom',fn:uc(type)+'Atom'}}; +var AtomPtr = (type,name) => {return {name:uc(name),type:'*'+uc(type)+'Atom',fn:uc(type)+'Atom'}}; + +var Struct = (type,name) => {return {name:uc(name),type:uc(type),fn:uc(type)}}; +var StructPtr = (type,name) => {return {name:uc(name),type:'*'+uc(type),fn:uc(type)}}; + +var Arr = (name,elem,count) => {return {name:uc(name),elem,count,type:'[]'+elem.type}}; +var LenArr = (sizelen,name,elem) => {return {sizelen,name:uc(name),elem,type:'[]'+elem.type}}; + +var Size = (len) => {return {len,hide:true,fn:'Int'}}; +var _ = (len) => {return {len,hide:true,fn:'Dummy'}}; + +var atoms = { + fileType: [ + 'ftyp', + AtomPtr('movie', 'movie'), + ], + + movie: [ + 'moov', + AtomPtr('movieHeader', 'header'), + Arr('tracks', AtomPtr('track')), + ], + + movieHeader: [ + 'mvhd', + Int('version', 1), + Int('flags', 3), + TimeStamp('cTime', 4), + TimeStamp('mTime', 4), + Int('timeScale', 4), + Int('duration', 4), + Int('preferredRate', 4), + Int('preferredVolume', 2), + _(10), + Bytes('matrix', 36), + TimeStamp('previewTime', 4), + TimeStamp('previewDuration', 4), + TimeStamp('posterTime', 4), + TimeStamp('selectionTime', 4), + TimeStamp('selectionDuration', 4), + TimeStamp('currentTime', 4), + Int('nextTrackId', 4), + ], + + track: [ + 'trak', + AtomPtr('trackHeader', 'header'), + AtomPtr('media', 'media'), + ], + + trackHeader: [ + 'tkhd', + Int('version', 1), + Int('flags', 3), + TimeStamp('cTime', 4), + TimeStamp('mTime', 4), + Int('trackId', 4), + _(4), + Int('duration', 4), + _(8), + Int('layer', 2), + Int('alternateGroup', 2), + Int('volume', 2), + _(2), + Bytes('matrix', 36), + Fixed32('trackWidth', 4), + Fixed32('trackHeight', 4), + ], + + media: [ + 'mdia', + AtomPtr('mediaHeader', 'header'), + AtomPtr('mediaInfo', 'info'), + ], + + mediaHeader: [ + 'mdhd', + Int('version', 1), + Int('flags', 3), + TimeStamp('cTime', 4), + TimeStamp('mTime', 4), + Int('timeScale', 4), + Int('duration', 4), + Int('language', 2), + Int('quality', 2), + ], + + mediaInfo: [ + 'minf', + AtomPtr('videoMediaInfo', 'video'), + AtomPtr('sampleTable', 'sample'), + ], + + videoMediaInfo: [ + 'vmhd', + Int('version', 1), + Int('flags', 3), + Int('graphicsMode', 2), + Arr('opcolor', Int('', 2), 3), + ], + + sampleTable: [ + 'stbl', + AtomPtr('sampleDesc', 'sampleDesc'), + AtomPtr('timeToSample', 'timeToSample'), + AtomPtr('compositionOffset', 'compositionOffset'), + AtomPtr('syncSample', 'syncSample'), + AtomPtr('sampleSize', 'sampleSize'), + AtomPtr('chunkOffset', 'chunkOffset'), + ], + + sampleDesc: [ + 'stsd', + Int('version', 1), + Int('flags', 3), + LenArr(4, 'entries', Struct('sampleDescEntry')), + ], + + timeToSample: [ + 'stts', + Int('version', 1), + Int('flags', 3), + LenArr(4, 'entries', Struct('timeToSampleEntry')), + ], + + compositionOffset: [ + 'ctts', + Int('version', 1), + Int('flags', 3), + LenArr(4, 'entries', Struct('compositionOffsetEntry')), + ], + + syncSample: [ + 'stss', + Int('version', 1), + Int('flags', 3), + LenArr(4, 'entries', Int('', 4)), + ], + + sampleSize: [ + 'stsz', + Int('version', 1), + Int('flags', 3), + LenArr(4, 'entries', Int('', 4)), + ], + + chunkOffset: [ + 'stco', + Int('version', 1), + Int('flags', 3), + LenArr(4, 'entries', Int('', 4)), + ], +}; + +var structs = { + sampleDescEntry: [ + Size(4), + Str('format', 4), + _(6), + Int('dataRefIdx', 2), + BytesLeft('data'), + ], + + timeToSampleEntry: [ + Int('count', 4), + Int('duration', 4), + ], + + compositionOffsetEntry: [ + Int('count', 4), + Int('offset', 4), + ], +}; + +var genReadStmts = (opts) => { + var stmts = []; + + if (opts.resIsPtr) + stmts = stmts.concat([StrStmt(`self := &${opts.atomType}{}`)]); + + var readElemStmts = field => { + var arr = 'self.'+field.name; + return [ + DeclVar('item', field.elem.type), + CallCheckAssign('Read'+field.elem.fn, ['r', field.elem.len].nonull(), ['item']), + StrStmt(`${arr} = append(${arr}, item)`), + ] + }; + + stmts = stmts.concat(opts.fields.map(field => { + if (field.sizelen) { + var arr = 'self.'+field.name; + return [ + DeclVar('count', 'int'), + CallCheckAssign('ReadInt', ['r', field.sizelen], ['count']), + For(RangeN('i', 'count'), readElemStmts(field)), + ]; + } else if (field.elem) { + var cond = field.count ? RangeN('i', field.count) : StrStmt('r.N > 0'); + return For(cond, readElemStmts(field)); + } else if (!field.hide) { + return CallCheckAssign('Read'+field.fn, ['r', field.len].nonull(), ['self.'+field.name]); + } + }).nonull()); + + if (opts.resIsPtr) + stmts = stmts.concat([StrStmt(`res = self`)]); + + return Func( + 'Read'+opts.fnName, + [['r', '*io.LimitedReader']], + [[opts.resIsPtr?'res':'self', (opts.resIsPtr?'*':'')+opts.atomType], ['err', 'error']], + stmts + ); +}; + +var D = (cls, ...fields) => { + global[cls] = (...args) => { + var obj = {cls: cls}; + fields.forEach((k, i) => obj[k] = args[i]); + return obj; + }; +}; + +D('Func', 'name', 'args', 'rets', 'body'); +D('CallCheckAssign', 'fn', 'args', 'rets'); +D('DeclVar', 'name', 'type'); +D('For', 'cond', 'body'); +D('RangeN', 'i', 'n'); +D('DeclStruct', 'name', 'body'); +D('StrStmt', 'content'); + +var dumpFn = f => { + var dumpArgs = x => x.map(x => x.join(' ')).join(','); + return `func ${f.name}(${dumpArgs(f.args)}) (${dumpArgs(f.rets)}) { + ${dumpStmts(f.body)} + return + }`; +}; + +var dumpStmts = stmts => { + var dumpStmt = stmt => { + if (stmt instanceof Array) { + return dumpStmts(stmt); + } if (stmt.cls == 'CallCheckAssign') { + return `if ${stmt.rets.concat(['err']).join(',')} = ${stmt.fn}(${stmt.args.join(',')}); err != nil { + return + }`; + } else if (stmt.cls == 'DeclVar') { + return `var ${stmt.name} ${stmt.type}`; + } else if (stmt.cls == 'For') { + return `for ${dumpStmt(stmt.cond)} { + ${dumpStmts(stmt.body)} + }`; + } else if (stmt.cls == 'RangeN') { + return `${stmt.i} := 0; ${stmt.i} < ${stmt.n}; ${stmt.i}++`; + } else if (stmt.cls == 'DeclStruct') { + return `type ${stmt.name} struct { + ${stmt.body.map(line => line.join(' ')).join('\n')} + }`; + } else if (stmt.cls == 'Func') { + return dumpFn(stmt); + } else if (stmt.cls == 'StrStmt') { + return stmt.content; + } + }; + return stmts.map(dumpStmt).join('\n') +}; + +(() => { + var len = 3; + var f = Func('Readxx', [['f', '*io.LimitedReader']], [['res', '*xx'], ['err', 'error']], [ + CallCheckAssign('ReadInt', ['f', len], ['self.xx']), + CallCheckAssign('WriteInt', ['f', len], ['self.xx']), + DeclVar('n', 'int'), + For(RangeN('i', 'n'), [ + CallCheckAssign('WriteInt', ['f', len], ['self.xx']), + DeclStruct('hi', [['a', 'b'], ['c', 'd'], ['e', 'f']]), + ]), + ]); + console.log(dumpFn(f)); +}); + +var allStmts = () => { + var stmts = []; + + var convStructFields = fields => { + var typeStr = field => ( + field.cls == 'AtomPtr' || field.cls == 'StructPtr') ? '*'+field.type : field.type; + + return fields.filter(field => !field.hide) + .map(field => { + if (field.cls == 'Arr' || field.cls == 'LenArr') + return [field.name, '[]'+typeStr(field.elem)]; + return [field.name, typeStr(field)]; + }); + }; + + for (var k in atoms) { + var list = atoms[k]; + var name = uc(k)+'Atom'; + var cc4 = list[0]; + var fields = list.slice(1); + + stmts = stmts.concat([ + DeclStruct(name, convStructFields(fields)), + genReadStmts({ + cc4: cc4, + fields: fields, + fnName: name, + atomType: name, + resIsPtr: true, + }), + ]); + } + + for (var k in structs) { + var fields = structs[k]; + var name = uc(k); + + stmts = stmts.concat([ + DeclStruct(name, convStructFields(fields)), + genReadStmts({ + fields: fields, + fnName: name, + atomType: name, + }), + ]); + } + + return stmts; +}; + +console.log(`// THIS FILE IS AUTO GENERATED +package atom +import ( + "io" +) +`, dumpStmts(allStmts())); + diff --git a/atom/reader.go b/atom/reader.go index 188fd9f..4af4a3a 100644 --- a/atom/reader.go +++ b/atom/reader.go @@ -6,15 +6,24 @@ import ( "io/ioutil" ) -type Reader struct { - io.LimitedReader +type Fixed32 uint32 +type TimeStamp uint32 + +func ReadBytes(r io.Reader, n int) (res []byte, err error) { + res = make([]byte, n) + if n, err = r.Read(res); err != nil { + return + } + return } -type Fixed32 uint32 +func ReadBytesLeft(r *io.LimitedReader) (res []byte, err error) { + return ReadBytes(r, int(r.N)) +} -func (self Reader) ReadUInt(n int) (res uint, err error) { - b := make([]byte, n) - if n, err = self.Read(b); err != nil { +func ReadUInt(r io.Reader, n int) (res uint, err error) { + var b []byte + if b, err = ReadBytes(r, n); err != nil { return } for i := 0; i < n; i++ { @@ -24,29 +33,48 @@ func (self Reader) ReadUInt(n int) (res uint, err error) { return } -func (self Reader) ReadInt(n int) (res int, err error) { - var resu uint - if resu, err = self.ReadUInt(n); err != nil { +func ReadInt(r io.Reader, n int) (res int, err error) { + var ui uint + if ui, err = ReadUInt(r, n); err != nil { return } - res = int(resu) + res = int(ui) return } -func (self Reader) ReadString(n int) (res string, err error) { - b := make([]byte, n) - if n, err = self.Read(b); err != nil { +func ReadFixed32(r io.Reader, n int) (res Fixed32, err error) { + var ui uint + if ui, err = ReadUInt(r, n); err != nil { + return + } + res = Fixed32(ui) + return +} + +func ReadTimeStamp(r io.Reader, n int) (res TimeStamp, err error) { + var ui uint + if ui, err = ReadUInt(r, n); err != nil { + return + } + res = TimeStamp(ui) + return +} + +func ReadString(r io.Reader, n int) (res string, err error) { + var b []byte + if b, err = ReadBytes(r, n); err != nil { return } res = string(b) return } -func (self Reader) Skip(n int) (err error) { - _, err = io.CopyN(ioutil.Discard, self.Reader, int64(n)) +func ReadDummy(r io.Reader, n int) (res int, err error) { + _, err = io.CopyN(ioutil.Discard, r, int64(n)) return } +/* func (self Reader) ReadAtom(atom Atom) (res Atom, err error) { for { var size int @@ -83,4 +111,5 @@ func (self Reader) ReadAtom(atom Atom) (res Atom, err error) { return } } +*/ diff --git a/atom/struct.go b/atom/struct.go index 9a3fac8..f0a240f 100644 --- a/atom/struct.go +++ b/atom/struct.go @@ -1,134 +1,547 @@ +// THIS FILE IS AUTO GENERATED package atom +import ( + "io" +) + type FileTypeAtom struct { - Movie *Movie + Movie *MovieAtom +} + +func ReadFileTypeAtom(r *io.LimitedReader) (res *FileTypeAtom, err error) { + self := &FileTypeAtom{} + if self.Movie, err = ReadMovieAtom(r); err != nil { + return + } + res = self + return } type MovieAtom struct { - MovieHeader *MovieHeader + Header *MovieHeaderAtom + Tracks []*TrackAtom +} + +func ReadMovieAtom(r *io.LimitedReader) (res *MovieAtom, err error) { + self := &MovieAtom{} + if self.Header, err = ReadMovieHeaderAtom(r); err != nil { + return + } + for r.N > 0 { + var item *TrackAtom + if item, err = ReadTrackAtom(r); err != nil { + return + } + self.Tracks = append(self.Tracks, item) + } + res = self + return } type MovieHeaderAtom struct { - Version int - Flags int - CTime Ts - MTime Ts - TimeScale int - Duration int - PreferredRate int - PreferredVolume int - + Version int + Flags int + CTime TimeStamp + MTime TimeStamp + TimeScale int + Duration int + PreferredRate int + PreferredVolume int Matrix []byte - PreviewTime Ts - PreviewDuration Ts - PosterTime Ts - SelectionTime Ts - SelectionDuration Ts - CurrentTime Ts + PreviewTime TimeStamp + PreviewDuration TimeStamp + PosterTime TimeStamp + SelectionTime TimeStamp + SelectionDuration TimeStamp + CurrentTime TimeStamp NextTrackId int } +func ReadMovieHeaderAtom(r *io.LimitedReader) (res *MovieHeaderAtom, err error) { + self := &MovieHeaderAtom{} + if self.Version, err = ReadInt(r, 1); err != nil { + return + } + if self.Flags, err = ReadInt(r, 3); err != nil { + return + } + if self.CTime, err = ReadTimeStamp(r, 4); err != nil { + return + } + if self.MTime, err = ReadTimeStamp(r, 4); err != nil { + return + } + if self.TimeScale, err = ReadInt(r, 4); err != nil { + return + } + if self.Duration, err = ReadInt(r, 4); err != nil { + return + } + if self.PreferredRate, err = ReadInt(r, 4); err != nil { + return + } + if self.PreferredVolume, err = ReadInt(r, 2); err != nil { + return + } + if self.Matrix, err = ReadBytes(r, 36); err != nil { + return + } + if self.PreviewTime, err = ReadTimeStamp(r, 4); err != nil { + return + } + if self.PreviewDuration, err = ReadTimeStamp(r, 4); err != nil { + return + } + if self.PosterTime, err = ReadTimeStamp(r, 4); err != nil { + return + } + if self.SelectionTime, err = ReadTimeStamp(r, 4); err != nil { + return + } + if self.SelectionDuration, err = ReadTimeStamp(r, 4); err != nil { + return + } + if self.CurrentTime, err = ReadTimeStamp(r, 4); err != nil { + return + } + if self.NextTrackId, err = ReadInt(r, 4); err != nil { + return + } + res = self + return +} + type TrackAtom struct { - TrackHeader *TrackHeader - Media *Media + Header *TrackHeaderAtom + Media *MediaAtom +} + +func ReadTrackAtom(r *io.LimitedReader) (res *TrackAtom, err error) { + self := &TrackAtom{} + if self.Header, err = ReadTrackHeaderAtom(r); err != nil { + return + } + if self.Media, err = ReadMediaAtom(r); err != nil { + return + } + res = self + return } type TrackHeaderAtom struct { - Version int - Flags int - CTime Ts - MTime Ts - TrackId int - - Duration int - + Version int + Flags int + CTime TimeStamp + MTime TimeStamp + TrackId int + Duration int Layer int AlternateGroup int Volume int + Matrix []byte + TrackWidth Fixed32 + TrackHeight Fixed32 +} - Matrix []byte - TrackWidth fixed32 - TrackHeight fixed32 +func ReadTrackHeaderAtom(r *io.LimitedReader) (res *TrackHeaderAtom, err error) { + self := &TrackHeaderAtom{} + if self.Version, err = ReadInt(r, 1); err != nil { + return + } + if self.Flags, err = ReadInt(r, 3); err != nil { + return + } + if self.CTime, err = ReadTimeStamp(r, 4); err != nil { + return + } + if self.MTime, err = ReadTimeStamp(r, 4); err != nil { + return + } + if self.TrackId, err = ReadInt(r, 4); err != nil { + return + } + if self.Duration, err = ReadInt(r, 4); err != nil { + return + } + if self.Layer, err = ReadInt(r, 2); err != nil { + return + } + if self.AlternateGroup, err = ReadInt(r, 2); err != nil { + return + } + if self.Volume, err = ReadInt(r, 2); err != nil { + return + } + if self.Matrix, err = ReadBytes(r, 36); err != nil { + return + } + if self.TrackWidth, err = ReadFixed32(r, 4); err != nil { + return + } + if self.TrackHeight, err = ReadFixed32(r, 4); err != nil { + return + } + res = self + return } type MediaAtom struct { - MediaHeader *MediaHeader - MediaInfo *MediaInfo + Header *MediaHeaderAtom + Info *MediaInfoAtom +} + +func ReadMediaAtom(r *io.LimitedReader) (res *MediaAtom, err error) { + self := &MediaAtom{} + if self.Header, err = ReadMediaHeaderAtom(r); err != nil { + return + } + if self.Info, err = ReadMediaInfoAtom(r); err != nil { + return + } + res = self + return } type MediaHeaderAtom struct { Version int Flags int - CTime Ts - MTime Ts + CTime TimeStamp + MTime TimeStamp TimeScale int Duration int Language int Quality int } +func ReadMediaHeaderAtom(r *io.LimitedReader) (res *MediaHeaderAtom, err error) { + self := &MediaHeaderAtom{} + if self.Version, err = ReadInt(r, 1); err != nil { + return + } + if self.Flags, err = ReadInt(r, 3); err != nil { + return + } + if self.CTime, err = ReadTimeStamp(r, 4); err != nil { + return + } + if self.MTime, err = ReadTimeStamp(r, 4); err != nil { + return + } + if self.TimeScale, err = ReadInt(r, 4); err != nil { + return + } + if self.Duration, err = ReadInt(r, 4); err != nil { + return + } + if self.Language, err = ReadInt(r, 2); err != nil { + return + } + if self.Quality, err = ReadInt(r, 2); err != nil { + return + } + res = self + return +} + type MediaInfoAtom struct { - VideoMediaInfo *VideoMediaInfo + Video *VideoMediaInfoAtom + Sample *SampleTableAtom +} + +func ReadMediaInfoAtom(r *io.LimitedReader) (res *MediaInfoAtom, err error) { + self := &MediaInfoAtom{} + if self.Video, err = ReadVideoMediaInfoAtom(r); err != nil { + return + } + if self.Sample, err = ReadSampleTableAtom(r); err != nil { + return + } + res = self + return } type VideoMediaInfoAtom struct { Version int Flags int GraphicsMode int + Opcolor []int +} + +func ReadVideoMediaInfoAtom(r *io.LimitedReader) (res *VideoMediaInfoAtom, err error) { + self := &VideoMediaInfoAtom{} + if self.Version, err = ReadInt(r, 1); err != nil { + return + } + if self.Flags, err = ReadInt(r, 3); err != nil { + return + } + if self.GraphicsMode, err = ReadInt(r, 2); err != nil { + return + } + for i := 0; i < 3; i++ { + var item int + if item, err = ReadInt(r, 2); err != nil { + return + } + self.Opcolor = append(self.Opcolor, item) + } + res = self + return } type SampleTableAtom struct { - SampleDesc *SampleDesc - TimeToSample *TimeToSample - CompositionOffset *CompositionOffset - SyncSample *SyncSample - SampleSize *SampleSize - ChunkOffset *ChunkOffset + SampleDesc *SampleDescAtom + TimeToSample *TimeToSampleAtom + CompositionOffset *CompositionOffsetAtom + SyncSample *SyncSampleAtom + SampleSize *SampleSizeAtom + ChunkOffset *ChunkOffsetAtom +} + +func ReadSampleTableAtom(r *io.LimitedReader) (res *SampleTableAtom, err error) { + self := &SampleTableAtom{} + if self.SampleDesc, err = ReadSampleDescAtom(r); err != nil { + return + } + if self.TimeToSample, err = ReadTimeToSampleAtom(r); err != nil { + return + } + if self.CompositionOffset, err = ReadCompositionOffsetAtom(r); err != nil { + return + } + if self.SyncSample, err = ReadSyncSampleAtom(r); err != nil { + return + } + if self.SampleSize, err = ReadSampleSizeAtom(r); err != nil { + return + } + if self.ChunkOffset, err = ReadChunkOffsetAtom(r); err != nil { + return + } + res = self + return } type SampleDescAtom struct { Version int Flags int + Entries []SampleDescEntry +} + +func ReadSampleDescAtom(r *io.LimitedReader) (res *SampleDescAtom, err error) { + self := &SampleDescAtom{} + if self.Version, err = ReadInt(r, 1); err != nil { + return + } + if self.Flags, err = ReadInt(r, 3); err != nil { + return + } + var count int + if count, err = ReadInt(r, 4); err != nil { + return + } + for i := 0; i < count; i++ { + var item SampleDescEntry + if item, err = ReadSampleDescEntry(r); err != nil { + return + } + self.Entries = append(self.Entries, item) + } + res = self + return } type TimeToSampleAtom struct { Version int Flags int + Entries []TimeToSampleEntry +} + +func ReadTimeToSampleAtom(r *io.LimitedReader) (res *TimeToSampleAtom, err error) { + self := &TimeToSampleAtom{} + if self.Version, err = ReadInt(r, 1); err != nil { + return + } + if self.Flags, err = ReadInt(r, 3); err != nil { + return + } + var count int + if count, err = ReadInt(r, 4); err != nil { + return + } + for i := 0; i < count; i++ { + var item TimeToSampleEntry + if item, err = ReadTimeToSampleEntry(r); err != nil { + return + } + self.Entries = append(self.Entries, item) + } + res = self + return } type CompositionOffsetAtom struct { Version int Flags int + Entries []CompositionOffsetEntry +} + +func ReadCompositionOffsetAtom(r *io.LimitedReader) (res *CompositionOffsetAtom, err error) { + self := &CompositionOffsetAtom{} + if self.Version, err = ReadInt(r, 1); err != nil { + return + } + if self.Flags, err = ReadInt(r, 3); err != nil { + return + } + var count int + if count, err = ReadInt(r, 4); err != nil { + return + } + for i := 0; i < count; i++ { + var item CompositionOffsetEntry + if item, err = ReadCompositionOffsetEntry(r); err != nil { + return + } + self.Entries = append(self.Entries, item) + } + res = self + return } type SyncSampleAtom struct { Version int Flags int + Entries []int +} + +func ReadSyncSampleAtom(r *io.LimitedReader) (res *SyncSampleAtom, err error) { + self := &SyncSampleAtom{} + if self.Version, err = ReadInt(r, 1); err != nil { + return + } + if self.Flags, err = ReadInt(r, 3); err != nil { + return + } + var count int + if count, err = ReadInt(r, 4); err != nil { + return + } + for i := 0; i < count; i++ { + var item int + if item, err = ReadInt(r, 4); err != nil { + return + } + self.Entries = append(self.Entries, item) + } + res = self + return } type SampleSizeAtom struct { Version int Flags int + Entries []int +} + +func ReadSampleSizeAtom(r *io.LimitedReader) (res *SampleSizeAtom, err error) { + self := &SampleSizeAtom{} + if self.Version, err = ReadInt(r, 1); err != nil { + return + } + if self.Flags, err = ReadInt(r, 3); err != nil { + return + } + var count int + if count, err = ReadInt(r, 4); err != nil { + return + } + for i := 0; i < count; i++ { + var item int + if item, err = ReadInt(r, 4); err != nil { + return + } + self.Entries = append(self.Entries, item) + } + res = self + return } type ChunkOffsetAtom struct { Version int Flags int + Entries []int } -type sampleDescEntry struct { - Format string +func ReadChunkOffsetAtom(r *io.LimitedReader) (res *ChunkOffsetAtom, err error) { + self := &ChunkOffsetAtom{} + if self.Version, err = ReadInt(r, 1); err != nil { + return + } + if self.Flags, err = ReadInt(r, 3); err != nil { + return + } + var count int + if count, err = ReadInt(r, 4); err != nil { + return + } + for i := 0; i < count; i++ { + var item int + if item, err = ReadInt(r, 4); err != nil { + return + } + self.Entries = append(self.Entries, item) + } + res = self + return +} +type SampleDescEntry struct { + Format string DataRefIdx int Data []byte } -type timeToSampleEntry struct { +func ReadSampleDescEntry(r *io.LimitedReader) (self SampleDescEntry, err error) { + if self.Format, err = ReadString(r, 4); err != nil { + return + } + if self.DataRefIdx, err = ReadInt(r, 2); err != nil { + return + } + if self.Data, err = ReadBytesLeft(r); err != nil { + return + } + return +} + +type TimeToSampleEntry struct { Count int Duration int } -type compositionOffsetEntry struct { +func ReadTimeToSampleEntry(r *io.LimitedReader) (self TimeToSampleEntry, err error) { + if self.Count, err = ReadInt(r, 4); err != nil { + return + } + if self.Duration, err = ReadInt(r, 4); err != nil { + return + } + return +} + +type CompositionOffsetEntry struct { Count int Offset int } + +func ReadCompositionOffsetEntry(r *io.LimitedReader) (self CompositionOffsetEntry, err error) { + if self.Count, err = ReadInt(r, 4); err != nil { + return + } + if self.Offset, err = ReadInt(r, 4); err != nil { + return + } + return +}