rewrite genStruct.js
This commit is contained in:
parent
dff1b98e9d
commit
3bbc27f470
@ -4,227 +4,302 @@ Array.prototype.nonull = function () {
|
|||||||
return this.filter(x => x);
|
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 = {
|
var atoms = {
|
||||||
fileType: [
|
fileType: {
|
||||||
'ftyp',
|
cc4: 'ftyp',
|
||||||
AtomPtr('movie', 'movie'),
|
fields: [
|
||||||
],
|
],
|
||||||
|
},
|
||||||
|
|
||||||
movie: [
|
movie: {
|
||||||
'moov',
|
cc4: 'moov',
|
||||||
AtomPtr('movieHeader', 'header'),
|
atoms: [
|
||||||
Arr('tracks', AtomPtr('track')),
|
['header', '*movieHeader'],
|
||||||
],
|
['tracks', '[]*track'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
movieHeader: [
|
movieHeader: {
|
||||||
'mvhd',
|
cc4: 'mvhd',
|
||||||
Int('version', 1),
|
fields: [
|
||||||
Int('flags', 3),
|
['version', 'int8'],
|
||||||
TimeStamp('cTime', 4),
|
['flags', 'int24'],
|
||||||
TimeStamp('mTime', 4),
|
['cTime', 'TimeStamp32'],
|
||||||
Int('timeScale', 4),
|
['mTime', 'TimeStamp32'],
|
||||||
Int('duration', 4),
|
['timeScale', 'TimeStamp32'],
|
||||||
Int('preferredRate', 4),
|
['duration', 'TimeStamp32'],
|
||||||
Int('preferredVolume', 2),
|
['preferredRate', 'int32'],
|
||||||
_(10),
|
['preferredVolume', 'int16'],
|
||||||
Bytes('matrix', 36),
|
['_', '[10]byte'],
|
||||||
TimeStamp('previewTime', 4),
|
['matrix', '[9]int32'],
|
||||||
TimeStamp('previewDuration', 4),
|
['previewTime', 'TimeStamp32'],
|
||||||
TimeStamp('posterTime', 4),
|
['previewDuration', 'TimeStamp32'],
|
||||||
TimeStamp('selectionTime', 4),
|
['posterTime', 'TimeStamp32'],
|
||||||
TimeStamp('selectionDuration', 4),
|
['selectionTime', 'TimeStamp32'],
|
||||||
TimeStamp('currentTime', 4),
|
['selectionDuration', 'TimeStamp32'],
|
||||||
Int('nextTrackId', 4),
|
['currentTime', 'TimeStamp32'],
|
||||||
],
|
['nextTrackId', 'int32'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
track: [
|
track: {
|
||||||
'trak',
|
cc4: 'trak',
|
||||||
AtomPtr('trackHeader', 'header'),
|
atoms: [
|
||||||
AtomPtr('media', 'media'),
|
['header', '*trackHeader'],
|
||||||
],
|
['media', '*media'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
trackHeader: [
|
trackHeader: {
|
||||||
'tkhd',
|
cc4: 'tkhd',
|
||||||
Int('version', 1),
|
fields: [
|
||||||
Int('flags', 3),
|
['version', 'int8'],
|
||||||
TimeStamp('cTime', 4),
|
['flags', 'int24'],
|
||||||
TimeStamp('mTime', 4),
|
['cTime', 'TimeStamp32'],
|
||||||
Int('trackId', 4),
|
['mTime', 'TimeStamp32'],
|
||||||
_(4),
|
['trackId', 'TimeStamp32'],
|
||||||
Int('duration', 4),
|
['_', '[4]byte'],
|
||||||
_(8),
|
['duration', 'TimeStamp32'],
|
||||||
Int('layer', 2),
|
['_', '[8]byte'],
|
||||||
Int('alternateGroup', 2),
|
['layer', 'int16'],
|
||||||
Int('volume', 2),
|
['alternateGroup', 'int16'],
|
||||||
_(2),
|
['volume', 'int16'],
|
||||||
Bytes('matrix', 36),
|
['_', '[2]byte'],
|
||||||
Fixed32('trackWidth', 4),
|
['matrix', '[9]int32'],
|
||||||
Fixed32('trackHeight', 4),
|
['trackWidth', 'int32'],
|
||||||
],
|
['trackHeader', 'int32'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
media: [
|
media: {
|
||||||
'mdia',
|
cc4: 'mdia',
|
||||||
AtomPtr('mediaHeader', 'header'),
|
atoms: [
|
||||||
AtomPtr('mediaInfo', 'info'),
|
['header', '*mediaHeader'],
|
||||||
],
|
['info', '*mediaInfo'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
mediaHeader: [
|
mediaHeader: {
|
||||||
'mdhd',
|
cc4: 'mdhd',
|
||||||
Int('version', 1),
|
fields: [
|
||||||
Int('flags', 3),
|
['version', 'int8'],
|
||||||
TimeStamp('cTime', 4),
|
['flags', 'int24'],
|
||||||
TimeStamp('mTime', 4),
|
['cTime', 'int32'],
|
||||||
Int('timeScale', 4),
|
['mTime', 'int32'],
|
||||||
Int('duration', 4),
|
['timeScale', 'int32'],
|
||||||
Int('language', 2),
|
['duration', 'int32'],
|
||||||
Int('quality', 2),
|
['language', 'int16'],
|
||||||
],
|
['quality', 'int16'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
mediaInfo: [
|
mediaInfo: {
|
||||||
'minf',
|
cc4: 'minf',
|
||||||
AtomPtr('videoMediaInfo', 'video'),
|
atoms: [
|
||||||
AtomPtr('sampleTable', 'sample'),
|
['sound', '*soundMediaInfo'],
|
||||||
],
|
['video', '*videoMediaInfo'],
|
||||||
|
['sample', '*sampleTable'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
videoMediaInfo: [
|
soundMediaInfo: {
|
||||||
'vmhd',
|
cc4: 'smhd',
|
||||||
Int('version', 1),
|
fields: [
|
||||||
Int('flags', 3),
|
['version', 'int8'],
|
||||||
Int('graphicsMode', 2),
|
['flags', 'int24'],
|
||||||
Arr('opcolor', Int('', 2), 3),
|
['balance', 'int16'],
|
||||||
],
|
['_', 'int16'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
sampleTable: [
|
videoMediaInfo: {
|
||||||
'stbl',
|
cc4: 'vmhd',
|
||||||
AtomPtr('sampleDesc', 'sampleDesc'),
|
fields: [
|
||||||
AtomPtr('timeToSample', 'timeToSample'),
|
['version', 'int8'],
|
||||||
AtomPtr('compositionOffset', 'compositionOffset'),
|
['flags', 'int24'],
|
||||||
AtomPtr('syncSample', 'syncSample'),
|
['graphicsMode', 'int16'],
|
||||||
AtomPtr('sampleSize', 'sampleSize'),
|
['opcolor', '[3]int16'],
|
||||||
AtomPtr('chunkOffset', 'chunkOffset'),
|
],
|
||||||
],
|
},
|
||||||
|
|
||||||
sampleDesc: [
|
sampleTable: {
|
||||||
'stsd',
|
cc4: 'stbl',
|
||||||
Int('version', 1),
|
atoms: [
|
||||||
Int('flags', 3),
|
['sampleDesc', '*sampleDesc'],
|
||||||
LenArr(4, 'entries', Struct('sampleDescEntry')),
|
['timeToSample', '*timeToSample'],
|
||||||
],
|
['compositionOffset', '*compositionOffset'],
|
||||||
|
['sampleToChunk', '*sampleToChunk'],
|
||||||
|
['syncSample', '*syncSample'],
|
||||||
|
['chunkOffset', '*chunkOffset'],
|
||||||
|
['sampleSize', '*sampleSize'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
timeToSample: [
|
sampleDesc: {
|
||||||
'stts',
|
cc4: 'stsd',
|
||||||
Int('version', 1),
|
fields: [
|
||||||
Int('flags', 3),
|
['version', 'int8'],
|
||||||
LenArr(4, 'entries', Struct('timeToSampleEntry')),
|
['flags', 'int24'],
|
||||||
],
|
['entries', '[int32]*sampleDescEntry'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
compositionOffset: [
|
timeToSample: {
|
||||||
'ctts',
|
cc4: 'stts',
|
||||||
Int('version', 1),
|
fields: [
|
||||||
Int('flags', 3),
|
['version', 'int8'],
|
||||||
LenArr(4, 'entries', Struct('compositionOffsetEntry')),
|
['flags', 'int24'],
|
||||||
],
|
['entries', '[int32]timeToSampleEntry'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
syncSample: [
|
timeToSampleEntry: {
|
||||||
'stss',
|
fields: [
|
||||||
Int('version', 1),
|
['count', 'int32'],
|
||||||
Int('flags', 3),
|
['duration', 'int32'],
|
||||||
LenArr(4, 'entries', Int('', 4)),
|
],
|
||||||
],
|
},
|
||||||
|
|
||||||
sampleSize: [
|
sampleToChunk: {
|
||||||
'stsz',
|
cc4: 'stsc',
|
||||||
Int('version', 1),
|
fields: [
|
||||||
Int('flags', 3),
|
['version', 'int8'],
|
||||||
LenArr(4, 'entries', Int('', 4)),
|
['flags', 'int24'],
|
||||||
],
|
['entries', '[int32]sampleToChunkEntry'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
sampleToChunkEntry: {
|
||||||
|
fields: [
|
||||||
|
['firstChunk', 'int32'],
|
||||||
|
['samplesPerChunk', 'int32'],
|
||||||
|
['sampleDescId', 'int32'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
compositionOffset: {
|
||||||
|
cc4: 'ctts',
|
||||||
|
fields: [
|
||||||
|
['version', 'int8'],
|
||||||
|
['flags', 'int24'],
|
||||||
|
['entries', '[int32]int32'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
compositionOffsetEntry: {
|
||||||
|
fields: [
|
||||||
|
['count', 'int32'],
|
||||||
|
['offset', 'int32'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
syncSample: {
|
||||||
|
cc4: 'stss',
|
||||||
|
fields: [
|
||||||
|
['version', 'int8'],
|
||||||
|
['flags', 'int24'],
|
||||||
|
['entries', '[int32]int32'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
sampleSize: {
|
||||||
|
cc4: 'stsz',
|
||||||
|
fields: [
|
||||||
|
['version', 'int8'],
|
||||||
|
['flags', 'int24'],
|
||||||
|
['entries', '[int32]int32'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
chunkOffset: {
|
||||||
|
cc4: 'stco',
|
||||||
|
fields: [
|
||||||
|
['version', 'int8'],
|
||||||
|
['flags', 'int24'],
|
||||||
|
['entries', '[int32]int32'],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
chunkOffset: [
|
|
||||||
'stco',
|
|
||||||
Int('version', 1),
|
|
||||||
Int('flags', 3),
|
|
||||||
LenArr(4, 'entries', Int('', 4)),
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var structs = {
|
var DeclReadFunc = (opts) => {
|
||||||
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 = [];
|
var stmts = [];
|
||||||
|
|
||||||
if (opts.resIsPtr)
|
var DebugStmt = type => StrStmt(`// ${JSON.stringify(type)}`);
|
||||||
stmts = stmts.concat([StrStmt(`self := &${opts.atomType}{}`)]);
|
|
||||||
|
|
||||||
var readElemStmts = field => {
|
var ReadArr = (name, type) => {
|
||||||
var arr = 'self.'+field.name;
|
|
||||||
return [
|
return [
|
||||||
DeclVar('item', field.elem.type),
|
//StrStmt('// ReadArr'),
|
||||||
CallCheckAssign('Read'+field.elem.fn, ['r', field.elem.len].nonull(), ['item']),
|
//DebugStmt(type),
|
||||||
StrStmt(`${arr} = append(${arr}, item)`),
|
type.varcount && [
|
||||||
|
DeclVar('count', 'int'),
|
||||||
|
CallCheckAssign('ReadInt', ['r', type.varcount], ['count']),
|
||||||
|
StrStmt(`${name} = make(${typeStr(type)}, count)`),
|
||||||
|
],
|
||||||
|
For(RangeN('i', type.varcount ? 'count' : type.count), [
|
||||||
|
ReadCommnType(name+'[i]', type),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
var elemTypeStr = type => typeStr(Object.assign({}, type, {arr: false}));
|
||||||
|
var ReadAtoms = () => [
|
||||||
|
StrStmt(`// ReadAtoms`),
|
||||||
|
For(StrStmt(`r.N > 0`), [
|
||||||
|
DeclVar('cc4', 'string'),
|
||||||
|
DeclVar('ar', '*io.LimitedReader'),
|
||||||
|
CallCheckAssign('ReadAtomHeader', ['r', '""'], ['ar', 'cc4']),
|
||||||
|
Switch('cc4', opts.fields.map(field => [
|
||||||
|
`"${atoms[field.type.struct].cc4}"`, [
|
||||||
|
field.type.arr ? [
|
||||||
|
DeclVar('item', elemTypeStr(field.type)),
|
||||||
|
CallCheckAssign('Read'+field.type.Struct, ['ar'], ['item']),
|
||||||
|
StrStmt(`self.${field.name} = append(self.${field.name}, item)`),
|
||||||
|
] : [
|
||||||
|
CallCheckAssign('Read'+field.type.Struct, ['ar'], [`self.${field.name}`]),
|
||||||
|
],
|
||||||
|
]
|
||||||
|
]), showlog && [StrStmt(`log.Println("skip", cc4)`)]),
|
||||||
|
CallCheckAssign('ReadDummy', ['ar', 'int(ar.N)'], ['_']),
|
||||||
|
])
|
||||||
|
];
|
||||||
|
|
||||||
|
var ReadCommnType = (name, type) => {
|
||||||
|
if (type.struct)
|
||||||
|
return CallCheckAssign(
|
||||||
|
'Read'+type.Struct, ['r'], [name]);
|
||||||
|
return [
|
||||||
|
//DebugStmt(type),
|
||||||
|
CallCheckAssign(
|
||||||
|
'Read'+type.fn, ['r', type.len].nonull(), [name]),
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
stmts = stmts.concat(opts.fields.map(field => {
|
var ReadField = (name, type) => {
|
||||||
if (field.sizelen) {
|
if (name == '_')
|
||||||
var arr = 'self.'+field.name;
|
return CallCheckAssign('ReadDummy', ['r', type.len], ['_']);
|
||||||
return [
|
if (type.arr && type.fn != 'Bytes')
|
||||||
DeclVar('count', 'int'),
|
return ReadArr('self.'+name, type);
|
||||||
CallCheckAssign('ReadInt', ['r', field.sizelen], ['count']),
|
return ReadCommnType('self.'+name, type);
|
||||||
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)
|
var ReadFields = () => opts.fields.map(field => {
|
||||||
stmts = stmts.concat([StrStmt(`res = self`)]);
|
var name = field.name;
|
||||||
|
var type = field.type;
|
||||||
|
return ReadField(name, type);
|
||||||
|
}).nonull();
|
||||||
|
|
||||||
|
var ptr = opts.cc4;
|
||||||
|
|
||||||
return Func(
|
return Func(
|
||||||
'Read'+opts.fnName,
|
'Read'+opts.type,
|
||||||
[['r', '*io.LimitedReader']],
|
[['r', '*io.LimitedReader']],
|
||||||
[[opts.resIsPtr?'res':'self', (opts.resIsPtr?'*':'')+opts.atomType], ['err', 'error']],
|
[[ptr?'res':'self', (ptr?'*':'')+opts.type], ['err', 'error']],
|
||||||
stmts
|
[
|
||||||
|
ptr && StrStmt(`self := &${opts.type}{}`),
|
||||||
|
!opts.atoms ? ReadFields() : ReadAtoms(),
|
||||||
|
ptr && StrStmt(`res = self`),
|
||||||
|
]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -237,16 +312,21 @@ var D = (cls, ...fields) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
D('Func', 'name', 'args', 'rets', 'body');
|
D('Func', 'name', 'args', 'rets', 'body');
|
||||||
D('CallCheckAssign', 'fn', 'args', 'rets');
|
D('CallCheckAssign', 'fn', 'args', 'rets', 'action');
|
||||||
D('DeclVar', 'name', 'type');
|
D('DeclVar', 'name', 'type');
|
||||||
D('For', 'cond', 'body');
|
D('For', 'cond', 'body');
|
||||||
D('RangeN', 'i', 'n');
|
D('RangeN', 'i', 'n');
|
||||||
D('DeclStruct', 'name', 'body');
|
D('DeclStruct', 'name', 'body');
|
||||||
D('StrStmt', 'content');
|
D('StrStmt', 'content');
|
||||||
|
D('Switch', 'cond', 'cases', 'default');
|
||||||
|
|
||||||
|
var showlog = false;
|
||||||
|
var S = s => s && s || '';
|
||||||
|
|
||||||
var dumpFn = f => {
|
var dumpFn = f => {
|
||||||
var dumpArgs = x => x.map(x => x.join(' ')).join(',');
|
var dumpArgs = x => x.map(x => x.join(' ')).join(',');
|
||||||
return `func ${f.name}(${dumpArgs(f.args)}) (${dumpArgs(f.rets)}) {
|
return `func ${f.name}(${dumpArgs(f.args)}) (${dumpArgs(f.rets)}) {
|
||||||
|
${S(showlog && 'log.Println("'+f.name+'")')}
|
||||||
${dumpStmts(f.body)}
|
${dumpStmts(f.body)}
|
||||||
return
|
return
|
||||||
}`;
|
}`;
|
||||||
@ -258,7 +338,7 @@ var dumpStmts = stmts => {
|
|||||||
return dumpStmts(stmt);
|
return dumpStmts(stmt);
|
||||||
} if (stmt.cls == 'CallCheckAssign') {
|
} if (stmt.cls == 'CallCheckAssign') {
|
||||||
return `if ${stmt.rets.concat(['err']).join(',')} = ${stmt.fn}(${stmt.args.join(',')}); err != nil {
|
return `if ${stmt.rets.concat(['err']).join(',')} = ${stmt.fn}(${stmt.args.join(',')}); err != nil {
|
||||||
return
|
${stmt.action ? stmt.action : 'return'}
|
||||||
}`;
|
}`;
|
||||||
} else if (stmt.cls == 'DeclVar') {
|
} else if (stmt.cls == 'DeclVar') {
|
||||||
return `var ${stmt.name} ${stmt.type}`;
|
return `var ${stmt.name} ${stmt.type}`;
|
||||||
@ -276,68 +356,103 @@ var dumpStmts = stmts => {
|
|||||||
return dumpFn(stmt);
|
return dumpFn(stmt);
|
||||||
} else if (stmt.cls == 'StrStmt') {
|
} else if (stmt.cls == 'StrStmt') {
|
||||||
return stmt.content;
|
return stmt.content;
|
||||||
|
} else if (stmt.cls == 'Switch') {
|
||||||
|
var dumpCase = c => `case ${c[0]}: { ${dumpStmts(c[1])} }`;
|
||||||
|
var dumpDefault = c => `default: { ${dumpStmts(c)} }`;
|
||||||
|
return `switch ${stmt.cond} {
|
||||||
|
${stmt.cases.map(dumpCase).join('\n')}
|
||||||
|
${stmt.default && dumpDefault(stmt.default) || ''}
|
||||||
|
}`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return stmts.map(dumpStmt).join('\n')
|
return stmts.nonull().map(dumpStmt).join('\n')
|
||||||
};
|
};
|
||||||
|
|
||||||
(() => {
|
var parseType = s => {
|
||||||
var len = 3;
|
var r = {};
|
||||||
var f = Func('Readxx', [['f', '*io.LimitedReader']], [['res', '*xx'], ['err', 'error']], [
|
var bracket = /^\[(.*)\]/;
|
||||||
CallCheckAssign('ReadInt', ['f', len], ['self.xx']),
|
if (s.match(bracket)) {
|
||||||
CallCheckAssign('WriteInt', ['f', len], ['self.xx']),
|
var count = s.match(bracket)[1];
|
||||||
DeclVar('n', 'int'),
|
if (count.substr(0,3) == 'int') {
|
||||||
For(RangeN('i', 'n'), [
|
r.varcount = +count.substr(3)/8;
|
||||||
CallCheckAssign('WriteInt', ['f', len], ['self.xx']),
|
} else {
|
||||||
DeclStruct('hi', [['a', 'b'], ['c', 'd'], ['e', 'f']]),
|
r.count = +count;
|
||||||
]),
|
}
|
||||||
]);
|
r.arr = true;
|
||||||
console.log(dumpFn(f));
|
s = s.replace(bracket, '');
|
||||||
});
|
}
|
||||||
|
if (s.substr(0,1) == '*') {
|
||||||
|
r.ptr = true;
|
||||||
|
s = s.slice(1);
|
||||||
|
}
|
||||||
|
var types = /^(int|TimeStamp|byte|cc)/;
|
||||||
|
if (s.match(types)) {
|
||||||
|
r.type = s.match(types)[0];
|
||||||
|
r.fn = uc(r.type);
|
||||||
|
s = s.replace(types, '');
|
||||||
|
}
|
||||||
|
if (r.type == 'byte' && r.arr) {
|
||||||
|
r.len = r.count;
|
||||||
|
r.fn = 'Bytes';
|
||||||
|
}
|
||||||
|
var lenDiv = 8;
|
||||||
|
if (r.type == 'cc') {
|
||||||
|
r.fn = 'String';
|
||||||
|
r.type = 'string';
|
||||||
|
lenDiv = 1;
|
||||||
|
}
|
||||||
|
var number = /[0-9]+/;
|
||||||
|
if (s.match(number)) {
|
||||||
|
r.len = +s.match(number)[0]/lenDiv;
|
||||||
|
s = s.replace(number, '');
|
||||||
|
}
|
||||||
|
if (s != '') {
|
||||||
|
r.struct = s;
|
||||||
|
r.Struct = uc(s);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
|
||||||
|
var typeStr = (t) => {
|
||||||
|
var s = '';
|
||||||
|
if (t.arr)
|
||||||
|
s += '['+(t.count||'')+']';
|
||||||
|
if (t.ptr)
|
||||||
|
s += '*';
|
||||||
|
if (t.struct)
|
||||||
|
s += t.Struct;
|
||||||
|
if (t.type)
|
||||||
|
s += t.type;
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
|
||||||
|
var nameShouldHide = (name) => name == '_'
|
||||||
|
|
||||||
var allStmts = () => {
|
var allStmts = () => {
|
||||||
var stmts = [];
|
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) {
|
for (var k in atoms) {
|
||||||
var list = atoms[k];
|
var atom = 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);
|
var name = uc(k);
|
||||||
|
var fields = (atom.fields || atom.atoms).map(field => {
|
||||||
|
return {
|
||||||
|
name: uc(field[0]),
|
||||||
|
type: parseType(field[1]),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
stmts = stmts.concat([
|
stmts = stmts.concat([
|
||||||
DeclStruct(name, convStructFields(fields)),
|
DeclStruct(name, fields.map(field => !nameShouldHide(field.name) && [
|
||||||
genReadStmts({
|
uc(field.name),
|
||||||
|
typeStr(field.type),
|
||||||
|
]).nonull()),
|
||||||
|
|
||||||
|
DeclReadFunc({
|
||||||
|
type: name,
|
||||||
fields: fields,
|
fields: fields,
|
||||||
fnName: name,
|
cc4: atom.cc4,
|
||||||
atomType: name,
|
atoms: atom.atoms != null,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -345,10 +460,12 @@ var allStmts = () => {
|
|||||||
return stmts;
|
return stmts;
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log(`// THIS FILE IS AUTO GENERATED
|
console.log(`
|
||||||
|
// THIS FILE IS AUTO GENERATED
|
||||||
package atom
|
package atom
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
${showlog && '"log"' || ''}
|
||||||
)
|
)
|
||||||
`, dumpStmts(allStmts()));
|
`, dumpStmts(allStmts()));
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ package atom
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Fixed32 uint32
|
type Fixed32 uint32
|
||||||
@ -17,10 +18,6 @@ func ReadBytes(r io.Reader, n int) (res []byte, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadBytesLeft(r *io.LimitedReader) (res []byte, err error) {
|
|
||||||
return ReadBytes(r, int(r.N))
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadUInt(r io.Reader, n int) (res uint, err error) {
|
func ReadUInt(r io.Reader, n int) (res uint, err error) {
|
||||||
var b []byte
|
var b []byte
|
||||||
if b, err = ReadBytes(r, n); err != nil {
|
if b, err = ReadBytes(r, n); err != nil {
|
||||||
@ -74,42 +71,38 @@ func ReadDummy(r io.Reader, n int) (res int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func ReadAtomHeader(r io.Reader, targetCC4 string) (res *io.LimitedReader, cc4 string, err error) {
|
||||||
func (self Reader) ReadAtom(atom Atom) (res Atom, err error) {
|
|
||||||
for {
|
for {
|
||||||
var size int
|
var size int
|
||||||
if size, err = self.ReadInt(4); err != nil {
|
if size, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var cc4 string
|
if cc4, err = ReadString(r, 4); err != nil {
|
||||||
if cc4, err = self.ReadString(4); err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if atom.CC4() != cc4 {
|
size = size - 8
|
||||||
if err = self.Skip(size); err != nil {
|
|
||||||
|
if false {
|
||||||
|
log.Println(cc4, targetCC4, size, cc4 == targetCC4)
|
||||||
|
}
|
||||||
|
|
||||||
|
if targetCC4 != "" && cc4 != targetCC4 {
|
||||||
|
log.Println("ReadAtomHeader skip:", cc4)
|
||||||
|
if _, err = ReadDummy(r, size); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
reader := &io.LimitedReader{
|
res = &io.LimitedReader{
|
||||||
R: self.Reader,
|
R: r,
|
||||||
N: int64(size - 8),
|
N: int64(size),
|
||||||
}
|
}
|
||||||
if err = atom.Read(Reader{reader}); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err = self.Skip(int(reader.N)); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
res = atom
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
712
atom/struct.go
712
atom/struct.go
@ -5,50 +5,67 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileTypeAtom struct {
|
type FileType struct {
|
||||||
Movie *MovieAtom
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadFileTypeAtom(r *io.LimitedReader) (res *FileTypeAtom, err error) {
|
func ReadFileType(r *io.LimitedReader) (res *FileType, err error) {
|
||||||
self := &FileTypeAtom{}
|
|
||||||
if self.Movie, err = ReadMovieAtom(r); err != nil {
|
self := &FileType{}
|
||||||
return
|
|
||||||
}
|
|
||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type MovieAtom struct {
|
type Movie struct {
|
||||||
Header *MovieHeaderAtom
|
Header *MovieHeader
|
||||||
Tracks []*TrackAtom
|
Tracks []*Track
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadMovieAtom(r *io.LimitedReader) (res *MovieAtom, err error) {
|
func ReadMovie(r *io.LimitedReader) (res *Movie, err error) {
|
||||||
self := &MovieAtom{}
|
|
||||||
if self.Header, err = ReadMovieHeaderAtom(r); err != nil {
|
self := &Movie{}
|
||||||
return
|
// ReadAtoms
|
||||||
}
|
|
||||||
for r.N > 0 {
|
for r.N > 0 {
|
||||||
var item *TrackAtom
|
var cc4 string
|
||||||
if item, err = ReadTrackAtom(r); err != nil {
|
var ar *io.LimitedReader
|
||||||
|
if ar, cc4, err = ReadAtomHeader(r, ""); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch cc4 {
|
||||||
|
case "mvhd":
|
||||||
|
{
|
||||||
|
if self.Header, err = ReadMovieHeader(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "trak":
|
||||||
|
{
|
||||||
|
var item *Track
|
||||||
|
if item, err = ReadTrack(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.Tracks = append(self.Tracks, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.Tracks = append(self.Tracks, item)
|
|
||||||
}
|
}
|
||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type MovieHeaderAtom struct {
|
type MovieHeader struct {
|
||||||
Version int
|
Version int
|
||||||
Flags int
|
Flags int
|
||||||
CTime TimeStamp
|
CTime TimeStamp
|
||||||
MTime TimeStamp
|
MTime TimeStamp
|
||||||
TimeScale int
|
TimeScale TimeStamp
|
||||||
Duration int
|
Duration TimeStamp
|
||||||
PreferredRate int
|
PreferredRate int
|
||||||
PreferredVolume int
|
PreferredVolume int
|
||||||
Matrix []byte
|
Matrix [9]int
|
||||||
PreviewTime TimeStamp
|
PreviewTime TimeStamp
|
||||||
PreviewDuration TimeStamp
|
PreviewDuration TimeStamp
|
||||||
PosterTime TimeStamp
|
PosterTime TimeStamp
|
||||||
@ -58,8 +75,9 @@ type MovieHeaderAtom struct {
|
|||||||
NextTrackId int
|
NextTrackId int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadMovieHeaderAtom(r *io.LimitedReader) (res *MovieHeaderAtom, err error) {
|
func ReadMovieHeader(r *io.LimitedReader) (res *MovieHeader, err error) {
|
||||||
self := &MovieHeaderAtom{}
|
|
||||||
|
self := &MovieHeader{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -72,10 +90,10 @@ func ReadMovieHeaderAtom(r *io.LimitedReader) (res *MovieHeaderAtom, err error)
|
|||||||
if self.MTime, err = ReadTimeStamp(r, 4); err != nil {
|
if self.MTime, err = ReadTimeStamp(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.TimeScale, err = ReadInt(r, 4); err != nil {
|
if self.TimeScale, err = ReadTimeStamp(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.Duration, err = ReadInt(r, 4); err != nil {
|
if self.Duration, err = ReadTimeStamp(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.PreferredRate, err = ReadInt(r, 4); err != nil {
|
if self.PreferredRate, err = ReadInt(r, 4); err != nil {
|
||||||
@ -84,9 +102,14 @@ func ReadMovieHeaderAtom(r *io.LimitedReader) (res *MovieHeaderAtom, err error)
|
|||||||
if self.PreferredVolume, err = ReadInt(r, 2); err != nil {
|
if self.PreferredVolume, err = ReadInt(r, 2); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.Matrix, err = ReadBytes(r, 36); err != nil {
|
if _, err = ReadDummy(r, 10); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
for i := 0; i < 9; i++ {
|
||||||
|
if self.Matrix[i], err = ReadInt(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
if self.PreviewTime, err = ReadTimeStamp(r, 4); err != nil {
|
if self.PreviewTime, err = ReadTimeStamp(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -112,40 +135,62 @@ func ReadMovieHeaderAtom(r *io.LimitedReader) (res *MovieHeaderAtom, err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type TrackAtom struct {
|
type Track struct {
|
||||||
Header *TrackHeaderAtom
|
Header *TrackHeader
|
||||||
Media *MediaAtom
|
Media *Media
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadTrackAtom(r *io.LimitedReader) (res *TrackAtom, err error) {
|
func ReadTrack(r *io.LimitedReader) (res *Track, err error) {
|
||||||
self := &TrackAtom{}
|
|
||||||
if self.Header, err = ReadTrackHeaderAtom(r); err != nil {
|
self := &Track{}
|
||||||
return
|
// ReadAtoms
|
||||||
}
|
for r.N > 0 {
|
||||||
if self.Media, err = ReadMediaAtom(r); err != nil {
|
var cc4 string
|
||||||
return
|
var ar *io.LimitedReader
|
||||||
|
if ar, cc4, err = ReadAtomHeader(r, ""); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch cc4 {
|
||||||
|
case "tkhd":
|
||||||
|
{
|
||||||
|
if self.Header, err = ReadTrackHeader(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "mdia":
|
||||||
|
{
|
||||||
|
if self.Media, err = ReadMedia(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type TrackHeaderAtom struct {
|
type TrackHeader struct {
|
||||||
Version int
|
Version int
|
||||||
Flags int
|
Flags int
|
||||||
CTime TimeStamp
|
CTime TimeStamp
|
||||||
MTime TimeStamp
|
MTime TimeStamp
|
||||||
TrackId int
|
TrackId TimeStamp
|
||||||
Duration int
|
Duration TimeStamp
|
||||||
Layer int
|
Layer int
|
||||||
AlternateGroup int
|
AlternateGroup int
|
||||||
Volume int
|
Volume int
|
||||||
Matrix []byte
|
Matrix [9]int
|
||||||
TrackWidth Fixed32
|
TrackWidth int
|
||||||
TrackHeight Fixed32
|
TrackHeader int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadTrackHeaderAtom(r *io.LimitedReader) (res *TrackHeaderAtom, err error) {
|
func ReadTrackHeader(r *io.LimitedReader) (res *TrackHeader, err error) {
|
||||||
self := &TrackHeaderAtom{}
|
|
||||||
|
self := &TrackHeader{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -158,10 +203,16 @@ func ReadTrackHeaderAtom(r *io.LimitedReader) (res *TrackHeaderAtom, err error)
|
|||||||
if self.MTime, err = ReadTimeStamp(r, 4); err != nil {
|
if self.MTime, err = ReadTimeStamp(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.TrackId, err = ReadInt(r, 4); err != nil {
|
if self.TrackId, err = ReadTimeStamp(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.Duration, err = ReadInt(r, 4); err != nil {
|
if _, err = ReadDummy(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.Duration, err = ReadTimeStamp(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = ReadDummy(r, 8); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.Layer, err = ReadInt(r, 2); err != nil {
|
if self.Layer, err = ReadInt(r, 2); err != nil {
|
||||||
@ -173,59 +224,86 @@ func ReadTrackHeaderAtom(r *io.LimitedReader) (res *TrackHeaderAtom, err error)
|
|||||||
if self.Volume, err = ReadInt(r, 2); err != nil {
|
if self.Volume, err = ReadInt(r, 2); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.Matrix, err = ReadBytes(r, 36); err != nil {
|
if _, err = ReadDummy(r, 2); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.TrackWidth, err = ReadFixed32(r, 4); err != nil {
|
for i := 0; i < 9; i++ {
|
||||||
|
if self.Matrix[i], err = ReadInt(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.TrackWidth, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.TrackHeight, err = ReadFixed32(r, 4); err != nil {
|
if self.TrackHeader, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type MediaAtom struct {
|
type Media struct {
|
||||||
Header *MediaHeaderAtom
|
Header *MediaHeader
|
||||||
Info *MediaInfoAtom
|
Info *MediaInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadMediaAtom(r *io.LimitedReader) (res *MediaAtom, err error) {
|
func ReadMedia(r *io.LimitedReader) (res *Media, err error) {
|
||||||
self := &MediaAtom{}
|
|
||||||
if self.Header, err = ReadMediaHeaderAtom(r); err != nil {
|
self := &Media{}
|
||||||
return
|
// ReadAtoms
|
||||||
}
|
for r.N > 0 {
|
||||||
if self.Info, err = ReadMediaInfoAtom(r); err != nil {
|
var cc4 string
|
||||||
return
|
var ar *io.LimitedReader
|
||||||
|
if ar, cc4, err = ReadAtomHeader(r, ""); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch cc4 {
|
||||||
|
case "mdhd":
|
||||||
|
{
|
||||||
|
if self.Header, err = ReadMediaHeader(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "minf":
|
||||||
|
{
|
||||||
|
if self.Info, err = ReadMediaInfo(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type MediaHeaderAtom struct {
|
type MediaHeader struct {
|
||||||
Version int
|
Version int
|
||||||
Flags int
|
Flags int
|
||||||
CTime TimeStamp
|
CTime int
|
||||||
MTime TimeStamp
|
MTime int
|
||||||
TimeScale int
|
TimeScale int
|
||||||
Duration int
|
Duration int
|
||||||
Language int
|
Language int
|
||||||
Quality int
|
Quality int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadMediaHeaderAtom(r *io.LimitedReader) (res *MediaHeaderAtom, err error) {
|
func ReadMediaHeader(r *io.LimitedReader) (res *MediaHeader, err error) {
|
||||||
self := &MediaHeaderAtom{}
|
|
||||||
|
self := &MediaHeader{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.Flags, err = ReadInt(r, 3); err != nil {
|
if self.Flags, err = ReadInt(r, 3); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.CTime, err = ReadTimeStamp(r, 4); err != nil {
|
if self.CTime, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.MTime, err = ReadTimeStamp(r, 4); err != nil {
|
if self.MTime, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.TimeScale, err = ReadInt(r, 4); err != nil {
|
if self.TimeScale, err = ReadInt(r, 4); err != nil {
|
||||||
@ -244,32 +322,86 @@ func ReadMediaHeaderAtom(r *io.LimitedReader) (res *MediaHeaderAtom, err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type MediaInfoAtom struct {
|
type MediaInfo struct {
|
||||||
Video *VideoMediaInfoAtom
|
Sound *SoundMediaInfo
|
||||||
Sample *SampleTableAtom
|
Video *VideoMediaInfo
|
||||||
|
Sample *SampleTable
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadMediaInfoAtom(r *io.LimitedReader) (res *MediaInfoAtom, err error) {
|
func ReadMediaInfo(r *io.LimitedReader) (res *MediaInfo, err error) {
|
||||||
self := &MediaInfoAtom{}
|
|
||||||
if self.Video, err = ReadVideoMediaInfoAtom(r); err != nil {
|
self := &MediaInfo{}
|
||||||
|
// ReadAtoms
|
||||||
|
for r.N > 0 {
|
||||||
|
var cc4 string
|
||||||
|
var ar *io.LimitedReader
|
||||||
|
if ar, cc4, err = ReadAtomHeader(r, ""); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch cc4 {
|
||||||
|
case "smhd":
|
||||||
|
{
|
||||||
|
if self.Sound, err = ReadSoundMediaInfo(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "vmhd":
|
||||||
|
{
|
||||||
|
if self.Video, err = ReadVideoMediaInfo(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "stbl":
|
||||||
|
{
|
||||||
|
if self.Sample, err = ReadSampleTable(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = self
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type SoundMediaInfo struct {
|
||||||
|
Version int
|
||||||
|
Flags int
|
||||||
|
Balance int
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadSoundMediaInfo(r *io.LimitedReader) (res *SoundMediaInfo, err error) {
|
||||||
|
|
||||||
|
self := &SoundMediaInfo{}
|
||||||
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.Sample, err = ReadSampleTableAtom(r); err != nil {
|
if self.Flags, err = ReadInt(r, 3); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.Balance, err = ReadInt(r, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = ReadDummy(r, 2); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type VideoMediaInfoAtom struct {
|
type VideoMediaInfo struct {
|
||||||
Version int
|
Version int
|
||||||
Flags int
|
Flags int
|
||||||
GraphicsMode int
|
GraphicsMode int
|
||||||
Opcolor []int
|
Opcolor [3]int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadVideoMediaInfoAtom(r *io.LimitedReader) (res *VideoMediaInfoAtom, err error) {
|
func ReadVideoMediaInfo(r *io.LimitedReader) (res *VideoMediaInfo, err error) {
|
||||||
self := &VideoMediaInfoAtom{}
|
|
||||||
|
self := &VideoMediaInfo{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -280,57 +412,96 @@ func ReadVideoMediaInfoAtom(r *io.LimitedReader) (res *VideoMediaInfoAtom, err e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
var item int
|
if self.Opcolor[i], err = ReadInt(r, 2); err != nil {
|
||||||
if item, err = ReadInt(r, 2); err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.Opcolor = append(self.Opcolor, item)
|
|
||||||
}
|
}
|
||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type SampleTableAtom struct {
|
type SampleTable struct {
|
||||||
SampleDesc *SampleDescAtom
|
SampleDesc *SampleDesc
|
||||||
TimeToSample *TimeToSampleAtom
|
TimeToSample *TimeToSample
|
||||||
CompositionOffset *CompositionOffsetAtom
|
CompositionOffset *CompositionOffset
|
||||||
SyncSample *SyncSampleAtom
|
SampleToChunk *SampleToChunk
|
||||||
SampleSize *SampleSizeAtom
|
SyncSample *SyncSample
|
||||||
ChunkOffset *ChunkOffsetAtom
|
ChunkOffset *ChunkOffset
|
||||||
|
SampleSize *SampleSize
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadSampleTableAtom(r *io.LimitedReader) (res *SampleTableAtom, err error) {
|
func ReadSampleTable(r *io.LimitedReader) (res *SampleTable, err error) {
|
||||||
self := &SampleTableAtom{}
|
|
||||||
if self.SampleDesc, err = ReadSampleDescAtom(r); err != nil {
|
self := &SampleTable{}
|
||||||
return
|
// ReadAtoms
|
||||||
}
|
for r.N > 0 {
|
||||||
if self.TimeToSample, err = ReadTimeToSampleAtom(r); err != nil {
|
var cc4 string
|
||||||
return
|
var ar *io.LimitedReader
|
||||||
}
|
if ar, cc4, err = ReadAtomHeader(r, ""); err != nil {
|
||||||
if self.CompositionOffset, err = ReadCompositionOffsetAtom(r); err != nil {
|
return
|
||||||
return
|
}
|
||||||
}
|
switch cc4 {
|
||||||
if self.SyncSample, err = ReadSyncSampleAtom(r); err != nil {
|
case "stsd":
|
||||||
return
|
{
|
||||||
}
|
if self.SampleDesc, err = ReadSampleDesc(ar); err != nil {
|
||||||
if self.SampleSize, err = ReadSampleSizeAtom(r); err != nil {
|
return
|
||||||
return
|
}
|
||||||
}
|
}
|
||||||
if self.ChunkOffset, err = ReadChunkOffsetAtom(r); err != nil {
|
case "stts":
|
||||||
return
|
{
|
||||||
|
if self.TimeToSample, err = ReadTimeToSample(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "ctts":
|
||||||
|
{
|
||||||
|
if self.CompositionOffset, err = ReadCompositionOffset(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "stsc":
|
||||||
|
{
|
||||||
|
if self.SampleToChunk, err = ReadSampleToChunk(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "stss":
|
||||||
|
{
|
||||||
|
if self.SyncSample, err = ReadSyncSample(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "stco":
|
||||||
|
{
|
||||||
|
if self.ChunkOffset, err = ReadChunkOffset(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "stsz":
|
||||||
|
{
|
||||||
|
if self.SampleSize, err = ReadSampleSize(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type SampleDescAtom struct {
|
type SampleDesc struct {
|
||||||
Version int
|
Version int
|
||||||
Flags int
|
Flags int
|
||||||
Entries []SampleDescEntry
|
Entries []*SampleDescEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadSampleDescAtom(r *io.LimitedReader) (res *SampleDescAtom, err error) {
|
func ReadSampleDesc(r *io.LimitedReader) (res *SampleDesc, err error) {
|
||||||
self := &SampleDescAtom{}
|
|
||||||
|
self := &SampleDesc{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -341,25 +512,25 @@ func ReadSampleDescAtom(r *io.LimitedReader) (res *SampleDescAtom, err error) {
|
|||||||
if count, err = ReadInt(r, 4); err != nil {
|
if count, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
self.Entries = make([]*SampleDescEntry, count)
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
var item SampleDescEntry
|
if self.Entries[i], err = ReadSampleDescEntry(r); err != nil {
|
||||||
if item, err = ReadSampleDescEntry(r); err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.Entries = append(self.Entries, item)
|
|
||||||
}
|
}
|
||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type TimeToSampleAtom struct {
|
type TimeToSample struct {
|
||||||
Version int
|
Version int
|
||||||
Flags int
|
Flags int
|
||||||
Entries []TimeToSampleEntry
|
Entries []TimeToSampleEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadTimeToSampleAtom(r *io.LimitedReader) (res *TimeToSampleAtom, err error) {
|
func ReadTimeToSample(r *io.LimitedReader) (res *TimeToSample, err error) {
|
||||||
self := &TimeToSampleAtom{}
|
|
||||||
|
self := &TimeToSample{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -370,158 +541,23 @@ func ReadTimeToSampleAtom(r *io.LimitedReader) (res *TimeToSampleAtom, err error
|
|||||||
if count, err = ReadInt(r, 4); err != nil {
|
if count, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
self.Entries = make([]TimeToSampleEntry, count)
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
var item TimeToSampleEntry
|
if self.Entries[i], err = ReadTimeToSampleEntry(r); err != nil {
|
||||||
if item, err = ReadTimeToSampleEntry(r); err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.Entries = append(self.Entries, item)
|
|
||||||
}
|
}
|
||||||
res = self
|
res = self
|
||||||
return
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
type TimeToSampleEntry struct {
|
||||||
Count int
|
Count int
|
||||||
Duration int
|
Duration int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadTimeToSampleEntry(r *io.LimitedReader) (self TimeToSampleEntry, err error) {
|
func ReadTimeToSampleEntry(r *io.LimitedReader) (self TimeToSampleEntry, err error) {
|
||||||
|
|
||||||
if self.Count, err = ReadInt(r, 4); err != nil {
|
if self.Count, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -531,12 +567,91 @@ func ReadTimeToSampleEntry(r *io.LimitedReader) (self TimeToSampleEntry, err err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SampleToChunk struct {
|
||||||
|
Version int
|
||||||
|
Flags int
|
||||||
|
Entries []SampleToChunkEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadSampleToChunk(r *io.LimitedReader) (res *SampleToChunk, err error) {
|
||||||
|
|
||||||
|
self := &SampleToChunk{}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
self.Entries = make([]SampleToChunkEntry, count)
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
if self.Entries[i], err = ReadSampleToChunkEntry(r); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = self
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type SampleToChunkEntry struct {
|
||||||
|
FirstChunk int
|
||||||
|
SamplesPerChunk int
|
||||||
|
SampleDescId int
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadSampleToChunkEntry(r *io.LimitedReader) (self SampleToChunkEntry, err error) {
|
||||||
|
|
||||||
|
if self.FirstChunk, err = ReadInt(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.SamplesPerChunk, err = ReadInt(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.SampleDescId, err = ReadInt(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type CompositionOffset struct {
|
||||||
|
Version int
|
||||||
|
Flags int
|
||||||
|
Entries []int
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadCompositionOffset(r *io.LimitedReader) (res *CompositionOffset, err error) {
|
||||||
|
|
||||||
|
self := &CompositionOffset{}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
self.Entries = make([]int, count)
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
if self.Entries[i], err = ReadInt(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = self
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type CompositionOffsetEntry struct {
|
type CompositionOffsetEntry struct {
|
||||||
Count int
|
Count int
|
||||||
Offset int
|
Offset int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadCompositionOffsetEntry(r *io.LimitedReader) (self CompositionOffsetEntry, err error) {
|
func ReadCompositionOffsetEntry(r *io.LimitedReader) (self CompositionOffsetEntry, err error) {
|
||||||
|
|
||||||
if self.Count, err = ReadInt(r, 4); err != nil {
|
if self.Count, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -545,3 +660,90 @@ func ReadCompositionOffsetEntry(r *io.LimitedReader) (self CompositionOffsetEntr
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SyncSample struct {
|
||||||
|
Version int
|
||||||
|
Flags int
|
||||||
|
Entries []int
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadSyncSample(r *io.LimitedReader) (res *SyncSample, err error) {
|
||||||
|
|
||||||
|
self := &SyncSample{}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
self.Entries = make([]int, count)
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
if self.Entries[i], err = ReadInt(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = self
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type SampleSize struct {
|
||||||
|
Version int
|
||||||
|
Flags int
|
||||||
|
Entries []int
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadSampleSize(r *io.LimitedReader) (res *SampleSize, err error) {
|
||||||
|
|
||||||
|
self := &SampleSize{}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
self.Entries = make([]int, count)
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
if self.Entries[i], err = ReadInt(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = self
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChunkOffset struct {
|
||||||
|
Version int
|
||||||
|
Flags int
|
||||||
|
Entries []int
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadChunkOffset(r *io.LimitedReader) (res *ChunkOffset, err error) {
|
||||||
|
|
||||||
|
self := &ChunkOffset{}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
self.Entries = make([]int, count)
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
if self.Entries[i], err = ReadInt(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = self
|
||||||
|
return
|
||||||
|
}
|
||||||
|
15
example/read.go
Normal file
15
example/read.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
mp4 "./.."
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if _, err := mp4.Open("tiny2-avconv.mp4"); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
35
mp4.go
35
mp4.go
@ -4,11 +4,11 @@ package mp4
|
|||||||
import (
|
import (
|
||||||
"./atom"
|
"./atom"
|
||||||
"os"
|
"os"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type File struct {
|
type File struct {
|
||||||
moov *atom.Moov
|
|
||||||
ftyp *atom.Ftyp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *File) AddAvcc(avcc *Avcc) {
|
func (self *File) AddAvcc(avcc *Avcc) {
|
||||||
@ -37,19 +37,34 @@ func Open(filename string) (file *File, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var entry atom.Atom
|
var finfo os.FileInfo
|
||||||
file = &File{}
|
if finfo, err = osfile.Stat(); err != nil {
|
||||||
r := atom.Reader{osfile}
|
|
||||||
|
|
||||||
if entry, err = r.ReadAtom(&atom.Ftyp{}); err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
file.ftyp = entry.(*atom.Ftyp)
|
log.Println("filesize", finfo.Size())
|
||||||
|
|
||||||
if entry, err = r.ReadAtom(&atom.Moov{}); err != nil {
|
lr := &io.LimitedReader{R: osfile, N: finfo.Size()}
|
||||||
|
|
||||||
|
for lr.N > 0 {
|
||||||
|
var r *io.LimitedReader
|
||||||
|
var cc4 string
|
||||||
|
if r, cc4, err = atom.ReadAtomHeader(lr, ""); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cc4 == "moov" {
|
||||||
|
var moov *atom.Movie
|
||||||
|
if moov, err = atom.ReadMovie(r); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("tracks nr", len(moov.Tracks))
|
||||||
|
}
|
||||||
|
log.Println("atom", cc4, "left", lr.N)
|
||||||
|
atom.ReadDummy(r, int(r.N))
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = os.Create(filename+".out.mp4"); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
file.moov = entry.(*atom.Moov)
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user