add hdlr and fix bugs make vlc can play
This commit is contained in:
parent
3bbc27f470
commit
637f47b250
@ -71,11 +71,16 @@ var atoms = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handlerRefer: {
|
||||||
|
cc4: 'hdlr',
|
||||||
|
},
|
||||||
|
|
||||||
media: {
|
media: {
|
||||||
cc4: 'mdia',
|
cc4: 'mdia',
|
||||||
atoms: [
|
atoms: [
|
||||||
['header', '*mediaHeader'],
|
['header', '*mediaHeader'],
|
||||||
['info', '*mediaInfo'],
|
['info', '*mediaInfo'],
|
||||||
|
['hdlr', '*handlerRefer'],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -182,7 +187,7 @@ var atoms = {
|
|||||||
fields: [
|
fields: [
|
||||||
['version', 'int8'],
|
['version', 'int8'],
|
||||||
['flags', 'int24'],
|
['flags', 'int24'],
|
||||||
['entries', '[int32]int32'],
|
['entries', '[int32]compositionOffsetEntry'],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -207,6 +212,7 @@ var atoms = {
|
|||||||
fields: [
|
fields: [
|
||||||
['version', 'int8'],
|
['version', 'int8'],
|
||||||
['flags', 'int24'],
|
['flags', 'int24'],
|
||||||
|
['sampleSize', 'int32'],
|
||||||
['entries', '[int32]int32'],
|
['entries', '[int32]int32'],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -225,7 +231,7 @@ var atoms = {
|
|||||||
var DeclReadFunc = (opts) => {
|
var DeclReadFunc = (opts) => {
|
||||||
var stmts = [];
|
var stmts = [];
|
||||||
|
|
||||||
var DebugStmt = type => StrStmt(`// ${JSON.stringify(type)}`);
|
var DebugStmt = type => `// ${JSON.stringify(type)}`;
|
||||||
|
|
||||||
var ReadArr = (name, type) => {
|
var ReadArr = (name, type) => {
|
||||||
return [
|
return [
|
||||||
@ -234,7 +240,7 @@ var DeclReadFunc = (opts) => {
|
|||||||
type.varcount && [
|
type.varcount && [
|
||||||
DeclVar('count', 'int'),
|
DeclVar('count', 'int'),
|
||||||
CallCheckAssign('ReadInt', ['r', type.varcount], ['count']),
|
CallCheckAssign('ReadInt', ['r', type.varcount], ['count']),
|
||||||
StrStmt(`${name} = make(${typeStr(type)}, count)`),
|
`${name} = make(${typeStr(type)}, count)`,
|
||||||
],
|
],
|
||||||
For(RangeN('i', type.varcount ? 'count' : type.count), [
|
For(RangeN('i', type.varcount ? 'count' : type.count), [
|
||||||
ReadCommnType(name+'[i]', type),
|
ReadCommnType(name+'[i]', type),
|
||||||
@ -244,8 +250,7 @@ var DeclReadFunc = (opts) => {
|
|||||||
|
|
||||||
var elemTypeStr = type => typeStr(Object.assign({}, type, {arr: false}));
|
var elemTypeStr = type => typeStr(Object.assign({}, type, {arr: false}));
|
||||||
var ReadAtoms = () => [
|
var ReadAtoms = () => [
|
||||||
StrStmt(`// ReadAtoms`),
|
For(`r.N > 0`, [
|
||||||
For(StrStmt(`r.N > 0`), [
|
|
||||||
DeclVar('cc4', 'string'),
|
DeclVar('cc4', 'string'),
|
||||||
DeclVar('ar', '*io.LimitedReader'),
|
DeclVar('ar', '*io.LimitedReader'),
|
||||||
CallCheckAssign('ReadAtomHeader', ['r', '""'], ['ar', 'cc4']),
|
CallCheckAssign('ReadAtomHeader', ['r', '""'], ['ar', 'cc4']),
|
||||||
@ -254,12 +259,12 @@ var DeclReadFunc = (opts) => {
|
|||||||
field.type.arr ? [
|
field.type.arr ? [
|
||||||
DeclVar('item', elemTypeStr(field.type)),
|
DeclVar('item', elemTypeStr(field.type)),
|
||||||
CallCheckAssign('Read'+field.type.Struct, ['ar'], ['item']),
|
CallCheckAssign('Read'+field.type.Struct, ['ar'], ['item']),
|
||||||
StrStmt(`self.${field.name} = append(self.${field.name}, item)`),
|
`self.${field.name} = append(self.${field.name}, item)`,
|
||||||
] : [
|
] : [
|
||||||
CallCheckAssign('Read'+field.type.Struct, ['ar'], [`self.${field.name}`]),
|
CallCheckAssign('Read'+field.type.Struct, ['ar'], [`self.${field.name}`]),
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
]), showlog && [StrStmt(`log.Println("skip", cc4)`)]),
|
]), showlog && [`log.Println("skip", cc4)`]),
|
||||||
CallCheckAssign('ReadDummy', ['ar', 'int(ar.N)'], ['_']),
|
CallCheckAssign('ReadDummy', ['ar', 'int(ar.N)'], ['_']),
|
||||||
])
|
])
|
||||||
];
|
];
|
||||||
@ -296,9 +301,70 @@ var DeclReadFunc = (opts) => {
|
|||||||
[['r', '*io.LimitedReader']],
|
[['r', '*io.LimitedReader']],
|
||||||
[[ptr?'res':'self', (ptr?'*':'')+opts.type], ['err', 'error']],
|
[[ptr?'res':'self', (ptr?'*':'')+opts.type], ['err', 'error']],
|
||||||
[
|
[
|
||||||
ptr && StrStmt(`self := &${opts.type}{}`),
|
ptr && `self := &${opts.type}{}`,
|
||||||
!opts.atoms ? ReadFields() : ReadAtoms(),
|
!opts.atoms ? ReadFields() : ReadAtoms(),
|
||||||
ptr && StrStmt(`res = self`),
|
ptr && `res = self`,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
var DeclWriteFunc = (opts) => {
|
||||||
|
var SavePos = [
|
||||||
|
DeclVar('aw', '*Writer'),
|
||||||
|
CallCheckAssign('WriteAtomHeader', ['w', `"${opts.cc4}"`], ['aw']),
|
||||||
|
`w = aw`,
|
||||||
|
];
|
||||||
|
|
||||||
|
var RestorePosSetSize = [
|
||||||
|
CallCheckAssign('aw.Close', [], []),
|
||||||
|
];
|
||||||
|
|
||||||
|
var WriteAtoms = () => opts.fields.map(field => {
|
||||||
|
var name = 'self.'+field.name;
|
||||||
|
return [
|
||||||
|
`if ${name} != nil {`,
|
||||||
|
field.type.arr ? WriteArr(name, field.type) : WriteCommnType(name, field.type),
|
||||||
|
`}`,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
var WriteArr = (name, type) => {
|
||||||
|
return [
|
||||||
|
type.varcount && CallCheckAssign('WriteInt', ['w', `len(${name})`, type.varcount], []),
|
||||||
|
For(`_, elem := range ${name}`, [
|
||||||
|
WriteCommnType('elem', type),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
var WriteCommnType = (name, type) => {
|
||||||
|
if (type.struct)
|
||||||
|
return CallCheckAssign(
|
||||||
|
'Write'+type.Struct, ['w', name], []);
|
||||||
|
return [
|
||||||
|
CallCheckAssign(
|
||||||
|
'Write'+type.fn, ['w', name, type.len].nonull(), []),
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
var WriteField = (name, type) => {
|
||||||
|
if (name == '_')
|
||||||
|
return CallCheckAssign('WriteDummy', ['w', type.len], []);
|
||||||
|
if (type.arr && type.fn != 'Bytes')
|
||||||
|
return WriteArr('self.'+name, type);
|
||||||
|
return WriteCommnType('self.'+name, type);
|
||||||
|
};
|
||||||
|
|
||||||
|
var WriteFields = () => opts.fields.map(field => WriteField(field.name, field.type));
|
||||||
|
|
||||||
|
return Func(
|
||||||
|
'Write'+opts.type,
|
||||||
|
[['w', 'io.WriteSeeker'], ['self', (opts.cc4?'*':'')+opts.type]],
|
||||||
|
[['err', 'error']],
|
||||||
|
[
|
||||||
|
opts.cc4 && SavePos,
|
||||||
|
opts.atoms ? WriteAtoms() : WriteFields(),
|
||||||
|
opts.cc4 && RestorePosSetSize,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -320,7 +386,7 @@ D('DeclStruct', 'name', 'body');
|
|||||||
D('StrStmt', 'content');
|
D('StrStmt', 'content');
|
||||||
D('Switch', 'cond', 'cases', 'default');
|
D('Switch', 'cond', 'cases', 'default');
|
||||||
|
|
||||||
var showlog = false;
|
var showlog = true;
|
||||||
var S = s => s && s || '';
|
var S = s => s && s || '';
|
||||||
|
|
||||||
var dumpFn = f => {
|
var dumpFn = f => {
|
||||||
@ -334,7 +400,9 @@ var dumpFn = f => {
|
|||||||
|
|
||||||
var dumpStmts = stmts => {
|
var dumpStmts = stmts => {
|
||||||
var dumpStmt = stmt => {
|
var dumpStmt = stmt => {
|
||||||
if (stmt instanceof Array) {
|
if (typeof(stmt) == 'string') {
|
||||||
|
return stmt;
|
||||||
|
} else if (stmt instanceof Array) {
|
||||||
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 {
|
||||||
@ -433,9 +501,13 @@ var allStmts = () => {
|
|||||||
|
|
||||||
for (var k in atoms) {
|
for (var k in atoms) {
|
||||||
var atom = atoms[k];
|
var atom = atoms[k];
|
||||||
|
|
||||||
var name = uc(k);
|
var name = uc(k);
|
||||||
var fields = (atom.fields || atom.atoms).map(field => {
|
|
||||||
|
var fields = (atom.fields || atom.atoms);
|
||||||
|
if (fields == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fields = fields.map(field => {
|
||||||
return {
|
return {
|
||||||
name: uc(field[0]),
|
name: uc(field[0]),
|
||||||
type: parseType(field[1]),
|
type: parseType(field[1]),
|
||||||
@ -454,6 +526,13 @@ var allStmts = () => {
|
|||||||
cc4: atom.cc4,
|
cc4: atom.cc4,
|
||||||
atoms: atom.atoms != null,
|
atoms: atom.atoms != null,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
DeclWriteFunc({
|
||||||
|
type: name,
|
||||||
|
fields: fields,
|
||||||
|
cc4: atom.cc4,
|
||||||
|
atoms: atom.atoms != null,
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
114
atom/otherStruct.go
Normal file
114
atom/otherStruct.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
|
||||||
|
package atom
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SampleDescEntry struct {
|
||||||
|
Format string
|
||||||
|
DataRefIndex int
|
||||||
|
Data []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadSampleDescEntry(r *io.LimitedReader) (res *SampleDescEntry, err error) {
|
||||||
|
self := &SampleDescEntry{}
|
||||||
|
if r, self.Format, err = ReadAtomHeader(r, ""); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = ReadDummy(r, 6); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.DataRefIndex, err = ReadInt(r, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.Data, err = ReadBytes(r, int(r.N)); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res = self
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteSampleDescEntry(w io.WriteSeeker, self *SampleDescEntry) (err error) {
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, self.Format); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w = aw
|
||||||
|
if err = WriteDummy(w, 6); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.DataRefIndex, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteBytes(w, self.Data); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type HandlerRefer struct {
|
||||||
|
Version int
|
||||||
|
Flags int
|
||||||
|
Type string
|
||||||
|
SubType string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadHandlerRefer(r *io.LimitedReader) (res *HandlerRefer, err error) {
|
||||||
|
self := &HandlerRefer{}
|
||||||
|
if self.Version, err = ReadInt(r, 3); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.Flags, err = ReadInt(r, 1); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.Type, err = ReadString(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.SubType, err = ReadString(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = ReadDummy(r, 12); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if self.Name, err = ReadString(r, int(r.N)); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res = self
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteHandlerRefer(w io.WriteSeeker, self *HandlerRefer) (err error) {
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "hdlr"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w = aw
|
||||||
|
if err = WriteInt(w, self.Version, 3); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.Flags, 1); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteString(w, self.Type); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteString(w, self.SubType); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteDummy(w, 12); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteString(w, self.Name); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
684
atom/struct.go
684
atom/struct.go
@ -3,18 +3,32 @@ package atom
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FileType struct {
|
type FileType struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadFileType(r *io.LimitedReader) (res *FileType, err error) {
|
func ReadFileType(r *io.LimitedReader) (res *FileType, err error) {
|
||||||
|
log.Println("ReadFileType")
|
||||||
self := &FileType{}
|
self := &FileType{}
|
||||||
|
|
||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteFileType(w io.WriteSeeker, self *FileType) (err error) {
|
||||||
|
log.Println("WriteFileType")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "ftyp"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w = aw
|
||||||
|
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type Movie struct {
|
type Movie struct {
|
||||||
Header *MovieHeader
|
Header *MovieHeader
|
||||||
@ -22,9 +36,8 @@ type Movie struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadMovie(r *io.LimitedReader) (res *Movie, err error) {
|
func ReadMovie(r *io.LimitedReader) (res *Movie, err error) {
|
||||||
|
log.Println("ReadMovie")
|
||||||
self := &Movie{}
|
self := &Movie{}
|
||||||
// ReadAtoms
|
|
||||||
for r.N > 0 {
|
for r.N > 0 {
|
||||||
var cc4 string
|
var cc4 string
|
||||||
var ar *io.LimitedReader
|
var ar *io.LimitedReader
|
||||||
@ -46,7 +59,10 @@ func ReadMovie(r *io.LimitedReader) (res *Movie, err error) {
|
|||||||
}
|
}
|
||||||
self.Tracks = append(self.Tracks, item)
|
self.Tracks = append(self.Tracks, item)
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
log.Println("skip", cc4)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||||
return
|
return
|
||||||
@ -55,6 +71,30 @@ func ReadMovie(r *io.LimitedReader) (res *Movie, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteMovie(w io.WriteSeeker, self *Movie) (err error) {
|
||||||
|
log.Println("WriteMovie")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "moov"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w = aw
|
||||||
|
if self.Header != nil {
|
||||||
|
if err = WriteMovieHeader(w, self.Header); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.Tracks != nil {
|
||||||
|
for _, elem := range self.Tracks {
|
||||||
|
if err = WriteTrack(w, elem); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type MovieHeader struct {
|
type MovieHeader struct {
|
||||||
Version int
|
Version int
|
||||||
@ -76,7 +116,7 @@ type MovieHeader struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadMovieHeader(r *io.LimitedReader) (res *MovieHeader, err error) {
|
func ReadMovieHeader(r *io.LimitedReader) (res *MovieHeader, err error) {
|
||||||
|
log.Println("ReadMovieHeader")
|
||||||
self := &MovieHeader{}
|
self := &MovieHeader{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -134,6 +174,71 @@ func ReadMovieHeader(r *io.LimitedReader) (res *MovieHeader, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteMovieHeader(w io.WriteSeeker, self *MovieHeader) (err error) {
|
||||||
|
log.Println("WriteMovieHeader")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "mvhd"); 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 = WriteTimeStamp(w, self.CTime, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteTimeStamp(w, self.MTime, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteTimeStamp(w, self.TimeScale, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteTimeStamp(w, self.Duration, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.PreferredRate, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.PreferredVolume, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteDummy(w, 10); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, elem := range self.Matrix {
|
||||||
|
if err = WriteInt(w, elem, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = WriteTimeStamp(w, self.PreviewTime, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteTimeStamp(w, self.PreviewDuration, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteTimeStamp(w, self.PosterTime, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteTimeStamp(w, self.SelectionTime, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteTimeStamp(w, self.SelectionDuration, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteTimeStamp(w, self.CurrentTime, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.NextTrackId, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type Track struct {
|
type Track struct {
|
||||||
Header *TrackHeader
|
Header *TrackHeader
|
||||||
@ -141,9 +246,8 @@ type Track struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadTrack(r *io.LimitedReader) (res *Track, err error) {
|
func ReadTrack(r *io.LimitedReader) (res *Track, err error) {
|
||||||
|
log.Println("ReadTrack")
|
||||||
self := &Track{}
|
self := &Track{}
|
||||||
// ReadAtoms
|
|
||||||
for r.N > 0 {
|
for r.N > 0 {
|
||||||
var cc4 string
|
var cc4 string
|
||||||
var ar *io.LimitedReader
|
var ar *io.LimitedReader
|
||||||
@ -163,7 +267,10 @@ func ReadTrack(r *io.LimitedReader) (res *Track, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
log.Println("skip", cc4)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||||
return
|
return
|
||||||
@ -172,6 +279,28 @@ func ReadTrack(r *io.LimitedReader) (res *Track, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteTrack(w io.WriteSeeker, self *Track) (err error) {
|
||||||
|
log.Println("WriteTrack")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "trak"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w = aw
|
||||||
|
if self.Header != nil {
|
||||||
|
if err = WriteTrackHeader(w, self.Header); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.Media != nil {
|
||||||
|
if err = WriteMedia(w, self.Media); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type TrackHeader struct {
|
type TrackHeader struct {
|
||||||
Version int
|
Version int
|
||||||
@ -189,7 +318,7 @@ type TrackHeader struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadTrackHeader(r *io.LimitedReader) (res *TrackHeader, err error) {
|
func ReadTrackHeader(r *io.LimitedReader) (res *TrackHeader, err error) {
|
||||||
|
log.Println("ReadTrackHeader")
|
||||||
self := &TrackHeader{}
|
self := &TrackHeader{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -241,16 +370,75 @@ func ReadTrackHeader(r *io.LimitedReader) (res *TrackHeader, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteTrackHeader(w io.WriteSeeker, self *TrackHeader) (err error) {
|
||||||
|
log.Println("WriteTrackHeader")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "tkhd"); 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 = WriteTimeStamp(w, self.CTime, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteTimeStamp(w, self.MTime, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteTimeStamp(w, self.TrackId, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteDummy(w, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteTimeStamp(w, self.Duration, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteDummy(w, 8); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.Layer, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.AlternateGroup, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.Volume, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteDummy(w, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, elem := range self.Matrix {
|
||||||
|
if err = WriteInt(w, elem, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.TrackWidth, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.TrackHeader, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type Media struct {
|
type Media struct {
|
||||||
Header *MediaHeader
|
Header *MediaHeader
|
||||||
Info *MediaInfo
|
Info *MediaInfo
|
||||||
|
Hdlr *HandlerRefer
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadMedia(r *io.LimitedReader) (res *Media, err error) {
|
func ReadMedia(r *io.LimitedReader) (res *Media, err error) {
|
||||||
|
log.Println("ReadMedia")
|
||||||
self := &Media{}
|
self := &Media{}
|
||||||
// ReadAtoms
|
|
||||||
for r.N > 0 {
|
for r.N > 0 {
|
||||||
var cc4 string
|
var cc4 string
|
||||||
var ar *io.LimitedReader
|
var ar *io.LimitedReader
|
||||||
@ -270,7 +458,16 @@ func ReadMedia(r *io.LimitedReader) (res *Media, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case "hdlr":
|
||||||
|
{
|
||||||
|
if self.Hdlr, err = ReadHandlerRefer(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
log.Println("skip", cc4)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||||
return
|
return
|
||||||
@ -279,6 +476,33 @@ func ReadMedia(r *io.LimitedReader) (res *Media, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteMedia(w io.WriteSeeker, self *Media) (err error) {
|
||||||
|
log.Println("WriteMedia")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "mdia"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w = aw
|
||||||
|
if self.Header != nil {
|
||||||
|
if err = WriteMediaHeader(w, self.Header); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.Info != nil {
|
||||||
|
if err = WriteMediaInfo(w, self.Info); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.Hdlr != nil {
|
||||||
|
if err = WriteHandlerRefer(w, self.Hdlr); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type MediaHeader struct {
|
type MediaHeader struct {
|
||||||
Version int
|
Version int
|
||||||
@ -292,7 +516,7 @@ type MediaHeader struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadMediaHeader(r *io.LimitedReader) (res *MediaHeader, err error) {
|
func ReadMediaHeader(r *io.LimitedReader) (res *MediaHeader, err error) {
|
||||||
|
log.Println("ReadMediaHeader")
|
||||||
self := &MediaHeader{}
|
self := &MediaHeader{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -321,6 +545,42 @@ func ReadMediaHeader(r *io.LimitedReader) (res *MediaHeader, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteMediaHeader(w io.WriteSeeker, self *MediaHeader) (err error) {
|
||||||
|
log.Println("WriteMediaHeader")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "mdhd"); 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.CTime, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.MTime, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.TimeScale, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.Duration, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.Language, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.Quality, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type MediaInfo struct {
|
type MediaInfo struct {
|
||||||
Sound *SoundMediaInfo
|
Sound *SoundMediaInfo
|
||||||
@ -329,9 +589,8 @@ type MediaInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadMediaInfo(r *io.LimitedReader) (res *MediaInfo, err error) {
|
func ReadMediaInfo(r *io.LimitedReader) (res *MediaInfo, err error) {
|
||||||
|
log.Println("ReadMediaInfo")
|
||||||
self := &MediaInfo{}
|
self := &MediaInfo{}
|
||||||
// ReadAtoms
|
|
||||||
for r.N > 0 {
|
for r.N > 0 {
|
||||||
var cc4 string
|
var cc4 string
|
||||||
var ar *io.LimitedReader
|
var ar *io.LimitedReader
|
||||||
@ -357,7 +616,10 @@ func ReadMediaInfo(r *io.LimitedReader) (res *MediaInfo, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
log.Println("skip", cc4)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||||
return
|
return
|
||||||
@ -366,6 +628,33 @@ func ReadMediaInfo(r *io.LimitedReader) (res *MediaInfo, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteMediaInfo(w io.WriteSeeker, self *MediaInfo) (err error) {
|
||||||
|
log.Println("WriteMediaInfo")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "minf"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w = aw
|
||||||
|
if self.Sound != nil {
|
||||||
|
if err = WriteSoundMediaInfo(w, self.Sound); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.Video != nil {
|
||||||
|
if err = WriteVideoMediaInfo(w, self.Video); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.Sample != nil {
|
||||||
|
if err = WriteSampleTable(w, self.Sample); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type SoundMediaInfo struct {
|
type SoundMediaInfo struct {
|
||||||
Version int
|
Version int
|
||||||
@ -374,7 +663,7 @@ type SoundMediaInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadSoundMediaInfo(r *io.LimitedReader) (res *SoundMediaInfo, err error) {
|
func ReadSoundMediaInfo(r *io.LimitedReader) (res *SoundMediaInfo, err error) {
|
||||||
|
log.Println("ReadSoundMediaInfo")
|
||||||
self := &SoundMediaInfo{}
|
self := &SoundMediaInfo{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -391,6 +680,30 @@ func ReadSoundMediaInfo(r *io.LimitedReader) (res *SoundMediaInfo, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteSoundMediaInfo(w io.WriteSeeker, self *SoundMediaInfo) (err error) {
|
||||||
|
log.Println("WriteSoundMediaInfo")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "smhd"); 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.Balance, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteDummy(w, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type VideoMediaInfo struct {
|
type VideoMediaInfo struct {
|
||||||
Version int
|
Version int
|
||||||
@ -400,7 +713,7 @@ type VideoMediaInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadVideoMediaInfo(r *io.LimitedReader) (res *VideoMediaInfo, err error) {
|
func ReadVideoMediaInfo(r *io.LimitedReader) (res *VideoMediaInfo, err error) {
|
||||||
|
log.Println("ReadVideoMediaInfo")
|
||||||
self := &VideoMediaInfo{}
|
self := &VideoMediaInfo{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -419,6 +732,32 @@ func ReadVideoMediaInfo(r *io.LimitedReader) (res *VideoMediaInfo, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteVideoMediaInfo(w io.WriteSeeker, self *VideoMediaInfo) (err error) {
|
||||||
|
log.Println("WriteVideoMediaInfo")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "vmhd"); 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.GraphicsMode, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, elem := range self.Opcolor {
|
||||||
|
if err = WriteInt(w, elem, 2); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type SampleTable struct {
|
type SampleTable struct {
|
||||||
SampleDesc *SampleDesc
|
SampleDesc *SampleDesc
|
||||||
@ -431,9 +770,8 @@ type SampleTable struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadSampleTable(r *io.LimitedReader) (res *SampleTable, err error) {
|
func ReadSampleTable(r *io.LimitedReader) (res *SampleTable, err error) {
|
||||||
|
log.Println("ReadSampleTable")
|
||||||
self := &SampleTable{}
|
self := &SampleTable{}
|
||||||
// ReadAtoms
|
|
||||||
for r.N > 0 {
|
for r.N > 0 {
|
||||||
var cc4 string
|
var cc4 string
|
||||||
var ar *io.LimitedReader
|
var ar *io.LimitedReader
|
||||||
@ -483,7 +821,10 @@ func ReadSampleTable(r *io.LimitedReader) (res *SampleTable, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
log.Println("skip", cc4)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||||
return
|
return
|
||||||
@ -492,6 +833,53 @@ func ReadSampleTable(r *io.LimitedReader) (res *SampleTable, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteSampleTable(w io.WriteSeeker, self *SampleTable) (err error) {
|
||||||
|
log.Println("WriteSampleTable")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "stbl"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w = aw
|
||||||
|
if self.SampleDesc != nil {
|
||||||
|
if err = WriteSampleDesc(w, self.SampleDesc); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.TimeToSample != nil {
|
||||||
|
if err = WriteTimeToSample(w, self.TimeToSample); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.CompositionOffset != nil {
|
||||||
|
if err = WriteCompositionOffset(w, self.CompositionOffset); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.SampleToChunk != nil {
|
||||||
|
if err = WriteSampleToChunk(w, self.SampleToChunk); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.SyncSample != nil {
|
||||||
|
if err = WriteSyncSample(w, self.SyncSample); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.ChunkOffset != nil {
|
||||||
|
if err = WriteChunkOffset(w, self.ChunkOffset); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.SampleSize != nil {
|
||||||
|
if err = WriteSampleSize(w, self.SampleSize); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type SampleDesc struct {
|
type SampleDesc struct {
|
||||||
Version int
|
Version int
|
||||||
@ -500,7 +888,7 @@ type SampleDesc struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadSampleDesc(r *io.LimitedReader) (res *SampleDesc, err error) {
|
func ReadSampleDesc(r *io.LimitedReader) (res *SampleDesc, err error) {
|
||||||
|
log.Println("ReadSampleDesc")
|
||||||
self := &SampleDesc{}
|
self := &SampleDesc{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -521,6 +909,32 @@ func ReadSampleDesc(r *io.LimitedReader) (res *SampleDesc, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteSampleDesc(w io.WriteSeeker, self *SampleDesc) (err error) {
|
||||||
|
log.Println("WriteSampleDesc")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "stsd"); 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, len(self.Entries), 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, elem := range self.Entries {
|
||||||
|
if err = WriteSampleDescEntry(w, elem); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type TimeToSample struct {
|
type TimeToSample struct {
|
||||||
Version int
|
Version int
|
||||||
@ -529,7 +943,7 @@ type TimeToSample struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadTimeToSample(r *io.LimitedReader) (res *TimeToSample, err error) {
|
func ReadTimeToSample(r *io.LimitedReader) (res *TimeToSample, err error) {
|
||||||
|
log.Println("ReadTimeToSample")
|
||||||
self := &TimeToSample{}
|
self := &TimeToSample{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -550,6 +964,32 @@ func ReadTimeToSample(r *io.LimitedReader) (res *TimeToSample, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteTimeToSample(w io.WriteSeeker, self *TimeToSample) (err error) {
|
||||||
|
log.Println("WriteTimeToSample")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "stts"); 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, len(self.Entries), 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, elem := range self.Entries {
|
||||||
|
if err = WriteTimeToSampleEntry(w, elem); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type TimeToSampleEntry struct {
|
type TimeToSampleEntry struct {
|
||||||
Count int
|
Count int
|
||||||
@ -557,7 +997,7 @@ type TimeToSampleEntry struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadTimeToSampleEntry(r *io.LimitedReader) (self TimeToSampleEntry, err error) {
|
func ReadTimeToSampleEntry(r *io.LimitedReader) (self TimeToSampleEntry, err error) {
|
||||||
|
log.Println("ReadTimeToSampleEntry")
|
||||||
if self.Count, err = ReadInt(r, 4); err != nil {
|
if self.Count, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -566,6 +1006,16 @@ func ReadTimeToSampleEntry(r *io.LimitedReader) (self TimeToSampleEntry, err err
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteTimeToSampleEntry(w io.WriteSeeker, self TimeToSampleEntry) (err error) {
|
||||||
|
log.Println("WriteTimeToSampleEntry")
|
||||||
|
if err = WriteInt(w, self.Count, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.Duration, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type SampleToChunk struct {
|
type SampleToChunk struct {
|
||||||
Version int
|
Version int
|
||||||
@ -574,7 +1024,7 @@ type SampleToChunk struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadSampleToChunk(r *io.LimitedReader) (res *SampleToChunk, err error) {
|
func ReadSampleToChunk(r *io.LimitedReader) (res *SampleToChunk, err error) {
|
||||||
|
log.Println("ReadSampleToChunk")
|
||||||
self := &SampleToChunk{}
|
self := &SampleToChunk{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -595,6 +1045,32 @@ func ReadSampleToChunk(r *io.LimitedReader) (res *SampleToChunk, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteSampleToChunk(w io.WriteSeeker, self *SampleToChunk) (err error) {
|
||||||
|
log.Println("WriteSampleToChunk")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "stsc"); 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, len(self.Entries), 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, elem := range self.Entries {
|
||||||
|
if err = WriteSampleToChunkEntry(w, elem); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type SampleToChunkEntry struct {
|
type SampleToChunkEntry struct {
|
||||||
FirstChunk int
|
FirstChunk int
|
||||||
@ -603,7 +1079,7 @@ type SampleToChunkEntry struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadSampleToChunkEntry(r *io.LimitedReader) (self SampleToChunkEntry, err error) {
|
func ReadSampleToChunkEntry(r *io.LimitedReader) (self SampleToChunkEntry, err error) {
|
||||||
|
log.Println("ReadSampleToChunkEntry")
|
||||||
if self.FirstChunk, err = ReadInt(r, 4); err != nil {
|
if self.FirstChunk, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -615,15 +1091,28 @@ func ReadSampleToChunkEntry(r *io.LimitedReader) (self SampleToChunkEntry, err e
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteSampleToChunkEntry(w io.WriteSeeker, self SampleToChunkEntry) (err error) {
|
||||||
|
log.Println("WriteSampleToChunkEntry")
|
||||||
|
if err = WriteInt(w, self.FirstChunk, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.SamplesPerChunk, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.SampleDescId, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type CompositionOffset struct {
|
type CompositionOffset struct {
|
||||||
Version int
|
Version int
|
||||||
Flags int
|
Flags int
|
||||||
Entries []int
|
Entries []CompositionOffsetEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadCompositionOffset(r *io.LimitedReader) (res *CompositionOffset, err error) {
|
func ReadCompositionOffset(r *io.LimitedReader) (res *CompositionOffset, err error) {
|
||||||
|
log.Println("ReadCompositionOffset")
|
||||||
self := &CompositionOffset{}
|
self := &CompositionOffset{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -635,15 +1124,41 @@ func ReadCompositionOffset(r *io.LimitedReader) (res *CompositionOffset, err err
|
|||||||
if count, err = ReadInt(r, 4); err != nil {
|
if count, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.Entries = make([]int, count)
|
self.Entries = make([]CompositionOffsetEntry, count)
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
if self.Entries[i], err = ReadInt(r, 4); err != nil {
|
if self.Entries[i], err = ReadCompositionOffsetEntry(r); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteCompositionOffset(w io.WriteSeeker, self *CompositionOffset) (err error) {
|
||||||
|
log.Println("WriteCompositionOffset")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "ctts"); 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, len(self.Entries), 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, elem := range self.Entries {
|
||||||
|
if err = WriteCompositionOffsetEntry(w, elem); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type CompositionOffsetEntry struct {
|
type CompositionOffsetEntry struct {
|
||||||
Count int
|
Count int
|
||||||
@ -651,7 +1166,7 @@ type CompositionOffsetEntry struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadCompositionOffsetEntry(r *io.LimitedReader) (self CompositionOffsetEntry, err error) {
|
func ReadCompositionOffsetEntry(r *io.LimitedReader) (self CompositionOffsetEntry, err error) {
|
||||||
|
log.Println("ReadCompositionOffsetEntry")
|
||||||
if self.Count, err = ReadInt(r, 4); err != nil {
|
if self.Count, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -660,6 +1175,16 @@ func ReadCompositionOffsetEntry(r *io.LimitedReader) (self CompositionOffsetEntr
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteCompositionOffsetEntry(w io.WriteSeeker, self CompositionOffsetEntry) (err error) {
|
||||||
|
log.Println("WriteCompositionOffsetEntry")
|
||||||
|
if err = WriteInt(w, self.Count, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, self.Offset, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type SyncSample struct {
|
type SyncSample struct {
|
||||||
Version int
|
Version int
|
||||||
@ -668,7 +1193,7 @@ type SyncSample struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadSyncSample(r *io.LimitedReader) (res *SyncSample, err error) {
|
func ReadSyncSample(r *io.LimitedReader) (res *SyncSample, err error) {
|
||||||
|
log.Println("ReadSyncSample")
|
||||||
self := &SyncSample{}
|
self := &SyncSample{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -689,15 +1214,42 @@ func ReadSyncSample(r *io.LimitedReader) (res *SyncSample, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteSyncSample(w io.WriteSeeker, self *SyncSample) (err error) {
|
||||||
|
log.Println("WriteSyncSample")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "stss"); 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, len(self.Entries), 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, elem := range self.Entries {
|
||||||
|
if err = WriteInt(w, elem, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type SampleSize struct {
|
type SampleSize struct {
|
||||||
Version int
|
Version int
|
||||||
Flags int
|
Flags int
|
||||||
Entries []int
|
SampleSize int
|
||||||
|
Entries []int
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadSampleSize(r *io.LimitedReader) (res *SampleSize, err error) {
|
func ReadSampleSize(r *io.LimitedReader) (res *SampleSize, err error) {
|
||||||
|
log.Println("ReadSampleSize")
|
||||||
self := &SampleSize{}
|
self := &SampleSize{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -705,6 +1257,9 @@ func ReadSampleSize(r *io.LimitedReader) (res *SampleSize, err error) {
|
|||||||
if self.Flags, err = ReadInt(r, 3); err != nil {
|
if self.Flags, err = ReadInt(r, 3); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if self.SampleSize, err = ReadInt(r, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
var count int
|
var count int
|
||||||
if count, err = ReadInt(r, 4); err != nil {
|
if count, err = ReadInt(r, 4); err != nil {
|
||||||
return
|
return
|
||||||
@ -718,6 +1273,35 @@ func ReadSampleSize(r *io.LimitedReader) (res *SampleSize, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteSampleSize(w io.WriteSeeker, self *SampleSize) (err error) {
|
||||||
|
log.Println("WriteSampleSize")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "stsz"); 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.SampleSize, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(w, len(self.Entries), 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, elem := range self.Entries {
|
||||||
|
if err = WriteInt(w, elem, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type ChunkOffset struct {
|
type ChunkOffset struct {
|
||||||
Version int
|
Version int
|
||||||
@ -726,7 +1310,7 @@ type ChunkOffset struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadChunkOffset(r *io.LimitedReader) (res *ChunkOffset, err error) {
|
func ReadChunkOffset(r *io.LimitedReader) (res *ChunkOffset, err error) {
|
||||||
|
log.Println("ReadChunkOffset")
|
||||||
self := &ChunkOffset{}
|
self := &ChunkOffset{}
|
||||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||||
return
|
return
|
||||||
@ -747,3 +1331,29 @@ func ReadChunkOffset(r *io.LimitedReader) (res *ChunkOffset, err error) {
|
|||||||
res = self
|
res = self
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
func WriteChunkOffset(w io.WriteSeeker, self *ChunkOffset) (err error) {
|
||||||
|
log.Println("WriteChunkOffset")
|
||||||
|
var aw *Writer
|
||||||
|
if aw, err = WriteAtomHeader(w, "stco"); 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, len(self.Entries), 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, elem := range self.Entries {
|
||||||
|
if err = WriteInt(w, elem, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
80
atom/writer.go
Normal file
80
atom/writer.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
package atom
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func WriteBytes(w io.Writer, b []byte) (err error) {
|
||||||
|
_, err = w.Write(b)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteUInt(w io.Writer, val uint, n int) (err error) {
|
||||||
|
var b [8]byte
|
||||||
|
for i := n-1; i >= 0; i-- {
|
||||||
|
b[i] = byte(val)
|
||||||
|
val >>= 8
|
||||||
|
}
|
||||||
|
return WriteBytes(w, b[0:n])
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteInt(w io.Writer, val int, n int) (err error) {
|
||||||
|
return WriteUInt(w, uint(val), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteTimeStamp(w io.Writer, ts TimeStamp, n int) (err error) {
|
||||||
|
return WriteUInt(w, uint(ts), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteString(w io.Writer, val string) (err error) {
|
||||||
|
return WriteBytes(w, []byte(val))
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteDummy(w io.Writer, n int) (err error) {
|
||||||
|
return WriteBytes(w, make([]byte, n))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Writer struct {
|
||||||
|
io.WriteSeeker
|
||||||
|
sizePos int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *Writer) Close() (err error) {
|
||||||
|
var curPos int64
|
||||||
|
if curPos, err = self.Seek(0, 1); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = self.Seek(self.sizePos, 0); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteInt(self, int(curPos - self.sizePos), 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = self.Seek(curPos, 0); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if false {
|
||||||
|
log.Println("writeback", self.sizePos, curPos, curPos-self.sizePos)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteAtomHeader(w io.WriteSeeker, cc4 string) (res *Writer, err error) {
|
||||||
|
self := &Writer{WriteSeeker: w}
|
||||||
|
|
||||||
|
if self.sizePos, err = w.Seek(0, 1); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteDummy(self, 4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = WriteString(self, cc4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res = self
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
55
mp4.go
55
mp4.go
@ -45,24 +45,47 @@ func Open(filename string) (file *File, err error) {
|
|||||||
|
|
||||||
lr := &io.LimitedReader{R: osfile, N: finfo.Size()}
|
lr := &io.LimitedReader{R: osfile, N: finfo.Size()}
|
||||||
|
|
||||||
for lr.N > 0 {
|
var outfile *os.File
|
||||||
var r *io.LimitedReader
|
if outfile, err = os.Create(filename+".out.mp4"); err != nil {
|
||||||
var cc4 string
|
return
|
||||||
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 {
|
for lr.N > 0 {
|
||||||
|
var ar *io.LimitedReader
|
||||||
|
|
||||||
|
var cc4 string
|
||||||
|
if ar, cc4, err = atom.ReadAtomHeader(lr, ""); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if cc4 == "moov" {
|
||||||
|
var moov *atom.Movie
|
||||||
|
if moov, err = atom.ReadMovie(ar); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("regen moov", "tracks nr", len(moov.Tracks))
|
||||||
|
if err = atom.WriteMovie(outfile, moov); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var aw *atom.Writer
|
||||||
|
if aw, err = atom.WriteAtomHeader(outfile, cc4); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("copy", cc4)
|
||||||
|
if _, err = io.CopyN(aw, ar, ar.N); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = aw.Close(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//log.Println("atom", cc4, "left", lr.N)
|
||||||
|
//atom.ReadDummy(ar, int(ar.N))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = outfile.Close(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user