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: {
|
||||
cc4: 'mdia',
|
||||
atoms: [
|
||||
['header', '*mediaHeader'],
|
||||
['info', '*mediaInfo'],
|
||||
['hdlr', '*handlerRefer'],
|
||||
],
|
||||
},
|
||||
|
||||
@ -182,7 +187,7 @@ var atoms = {
|
||||
fields: [
|
||||
['version', 'int8'],
|
||||
['flags', 'int24'],
|
||||
['entries', '[int32]int32'],
|
||||
['entries', '[int32]compositionOffsetEntry'],
|
||||
],
|
||||
},
|
||||
|
||||
@ -207,6 +212,7 @@ var atoms = {
|
||||
fields: [
|
||||
['version', 'int8'],
|
||||
['flags', 'int24'],
|
||||
['sampleSize', 'int32'],
|
||||
['entries', '[int32]int32'],
|
||||
],
|
||||
},
|
||||
@ -225,7 +231,7 @@ var atoms = {
|
||||
var DeclReadFunc = (opts) => {
|
||||
var stmts = [];
|
||||
|
||||
var DebugStmt = type => StrStmt(`// ${JSON.stringify(type)}`);
|
||||
var DebugStmt = type => `// ${JSON.stringify(type)}`;
|
||||
|
||||
var ReadArr = (name, type) => {
|
||||
return [
|
||||
@ -234,7 +240,7 @@ var DeclReadFunc = (opts) => {
|
||||
type.varcount && [
|
||||
DeclVar('count', 'int'),
|
||||
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), [
|
||||
ReadCommnType(name+'[i]', type),
|
||||
@ -244,8 +250,7 @@ var DeclReadFunc = (opts) => {
|
||||
|
||||
var elemTypeStr = type => typeStr(Object.assign({}, type, {arr: false}));
|
||||
var ReadAtoms = () => [
|
||||
StrStmt(`// ReadAtoms`),
|
||||
For(StrStmt(`r.N > 0`), [
|
||||
For(`r.N > 0`, [
|
||||
DeclVar('cc4', 'string'),
|
||||
DeclVar('ar', '*io.LimitedReader'),
|
||||
CallCheckAssign('ReadAtomHeader', ['r', '""'], ['ar', 'cc4']),
|
||||
@ -254,12 +259,12 @@ var DeclReadFunc = (opts) => {
|
||||
field.type.arr ? [
|
||||
DeclVar('item', elemTypeStr(field.type)),
|
||||
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}`]),
|
||||
],
|
||||
]
|
||||
]), showlog && [StrStmt(`log.Println("skip", cc4)`)]),
|
||||
]), showlog && [`log.Println("skip", cc4)`]),
|
||||
CallCheckAssign('ReadDummy', ['ar', 'int(ar.N)'], ['_']),
|
||||
])
|
||||
];
|
||||
@ -296,9 +301,70 @@ var DeclReadFunc = (opts) => {
|
||||
[['r', '*io.LimitedReader']],
|
||||
[[ptr?'res':'self', (ptr?'*':'')+opts.type], ['err', 'error']],
|
||||
[
|
||||
ptr && StrStmt(`self := &${opts.type}{}`),
|
||||
ptr && `self := &${opts.type}{}`,
|
||||
!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('Switch', 'cond', 'cases', 'default');
|
||||
|
||||
var showlog = false;
|
||||
var showlog = true;
|
||||
var S = s => s && s || '';
|
||||
|
||||
var dumpFn = f => {
|
||||
@ -334,7 +400,9 @@ var dumpFn = f => {
|
||||
|
||||
var dumpStmts = stmts => {
|
||||
var dumpStmt = stmt => {
|
||||
if (stmt instanceof Array) {
|
||||
if (typeof(stmt) == 'string') {
|
||||
return stmt;
|
||||
} else if (stmt instanceof Array) {
|
||||
return dumpStmts(stmt);
|
||||
} if (stmt.cls == 'CallCheckAssign') {
|
||||
return `if ${stmt.rets.concat(['err']).join(',')} = ${stmt.fn}(${stmt.args.join(',')}); err != nil {
|
||||
@ -433,9 +501,13 @@ var allStmts = () => {
|
||||
|
||||
for (var k in atoms) {
|
||||
var atom = atoms[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 {
|
||||
name: uc(field[0]),
|
||||
type: parseType(field[1]),
|
||||
@ -454,6 +526,13 @@ var allStmts = () => {
|
||||
cc4: atom.cc4,
|
||||
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 (
|
||||
"io"
|
||||
"log"
|
||||
)
|
||||
|
||||
type FileType struct {
|
||||
}
|
||||
|
||||
func ReadFileType(r *io.LimitedReader) (res *FileType, err error) {
|
||||
|
||||
log.Println("ReadFileType")
|
||||
self := &FileType{}
|
||||
|
||||
res = self
|
||||
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 {
|
||||
Header *MovieHeader
|
||||
@ -22,9 +36,8 @@ type Movie struct {
|
||||
}
|
||||
|
||||
func ReadMovie(r *io.LimitedReader) (res *Movie, err error) {
|
||||
|
||||
log.Println("ReadMovie")
|
||||
self := &Movie{}
|
||||
// ReadAtoms
|
||||
for r.N > 0 {
|
||||
var cc4 string
|
||||
var ar *io.LimitedReader
|
||||
@ -46,7 +59,10 @@ func ReadMovie(r *io.LimitedReader) (res *Movie, err error) {
|
||||
}
|
||||
self.Tracks = append(self.Tracks, item)
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
log.Println("skip", cc4)
|
||||
}
|
||||
}
|
||||
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||
return
|
||||
@ -55,6 +71,30 @@ func ReadMovie(r *io.LimitedReader) (res *Movie, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Version int
|
||||
@ -76,7 +116,7 @@ type MovieHeader struct {
|
||||
}
|
||||
|
||||
func ReadMovieHeader(r *io.LimitedReader) (res *MovieHeader, err error) {
|
||||
|
||||
log.Println("ReadMovieHeader")
|
||||
self := &MovieHeader{}
|
||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||
return
|
||||
@ -134,6 +174,71 @@ func ReadMovieHeader(r *io.LimitedReader) (res *MovieHeader, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Header *TrackHeader
|
||||
@ -141,9 +246,8 @@ type Track struct {
|
||||
}
|
||||
|
||||
func ReadTrack(r *io.LimitedReader) (res *Track, err error) {
|
||||
|
||||
log.Println("ReadTrack")
|
||||
self := &Track{}
|
||||
// ReadAtoms
|
||||
for r.N > 0 {
|
||||
var cc4 string
|
||||
var ar *io.LimitedReader
|
||||
@ -163,7 +267,10 @@ func ReadTrack(r *io.LimitedReader) (res *Track, err error) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
log.Println("skip", cc4)
|
||||
}
|
||||
}
|
||||
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||
return
|
||||
@ -172,6 +279,28 @@ func ReadTrack(r *io.LimitedReader) (res *Track, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Version int
|
||||
@ -189,7 +318,7 @@ type TrackHeader struct {
|
||||
}
|
||||
|
||||
func ReadTrackHeader(r *io.LimitedReader) (res *TrackHeader, err error) {
|
||||
|
||||
log.Println("ReadTrackHeader")
|
||||
self := &TrackHeader{}
|
||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||
return
|
||||
@ -241,16 +370,75 @@ func ReadTrackHeader(r *io.LimitedReader) (res *TrackHeader, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Header *MediaHeader
|
||||
Info *MediaInfo
|
||||
Hdlr *HandlerRefer
|
||||
}
|
||||
|
||||
func ReadMedia(r *io.LimitedReader) (res *Media, err error) {
|
||||
|
||||
log.Println("ReadMedia")
|
||||
self := &Media{}
|
||||
// ReadAtoms
|
||||
for r.N > 0 {
|
||||
var cc4 string
|
||||
var ar *io.LimitedReader
|
||||
@ -270,7 +458,16 @@ func ReadMedia(r *io.LimitedReader) (res *Media, err error) {
|
||||
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 {
|
||||
return
|
||||
@ -279,6 +476,33 @@ func ReadMedia(r *io.LimitedReader) (res *Media, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Version int
|
||||
@ -292,7 +516,7 @@ type MediaHeader struct {
|
||||
}
|
||||
|
||||
func ReadMediaHeader(r *io.LimitedReader) (res *MediaHeader, err error) {
|
||||
|
||||
log.Println("ReadMediaHeader")
|
||||
self := &MediaHeader{}
|
||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||
return
|
||||
@ -321,6 +545,42 @@ func ReadMediaHeader(r *io.LimitedReader) (res *MediaHeader, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Sound *SoundMediaInfo
|
||||
@ -329,9 +589,8 @@ type MediaInfo struct {
|
||||
}
|
||||
|
||||
func ReadMediaInfo(r *io.LimitedReader) (res *MediaInfo, err error) {
|
||||
|
||||
log.Println("ReadMediaInfo")
|
||||
self := &MediaInfo{}
|
||||
// ReadAtoms
|
||||
for r.N > 0 {
|
||||
var cc4 string
|
||||
var ar *io.LimitedReader
|
||||
@ -357,7 +616,10 @@ func ReadMediaInfo(r *io.LimitedReader) (res *MediaInfo, err error) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
log.Println("skip", cc4)
|
||||
}
|
||||
}
|
||||
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||
return
|
||||
@ -366,6 +628,33 @@ func ReadMediaInfo(r *io.LimitedReader) (res *MediaInfo, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Version int
|
||||
@ -374,7 +663,7 @@ type SoundMediaInfo struct {
|
||||
}
|
||||
|
||||
func ReadSoundMediaInfo(r *io.LimitedReader) (res *SoundMediaInfo, err error) {
|
||||
|
||||
log.Println("ReadSoundMediaInfo")
|
||||
self := &SoundMediaInfo{}
|
||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||
return
|
||||
@ -391,6 +680,30 @@ func ReadSoundMediaInfo(r *io.LimitedReader) (res *SoundMediaInfo, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Version int
|
||||
@ -400,7 +713,7 @@ type VideoMediaInfo struct {
|
||||
}
|
||||
|
||||
func ReadVideoMediaInfo(r *io.LimitedReader) (res *VideoMediaInfo, err error) {
|
||||
|
||||
log.Println("ReadVideoMediaInfo")
|
||||
self := &VideoMediaInfo{}
|
||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||
return
|
||||
@ -419,6 +732,32 @@ func ReadVideoMediaInfo(r *io.LimitedReader) (res *VideoMediaInfo, err error) {
|
||||
res = self
|
||||
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 {
|
||||
SampleDesc *SampleDesc
|
||||
@ -431,9 +770,8 @@ type SampleTable struct {
|
||||
}
|
||||
|
||||
func ReadSampleTable(r *io.LimitedReader) (res *SampleTable, err error) {
|
||||
|
||||
log.Println("ReadSampleTable")
|
||||
self := &SampleTable{}
|
||||
// ReadAtoms
|
||||
for r.N > 0 {
|
||||
var cc4 string
|
||||
var ar *io.LimitedReader
|
||||
@ -483,7 +821,10 @@ func ReadSampleTable(r *io.LimitedReader) (res *SampleTable, err error) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
log.Println("skip", cc4)
|
||||
}
|
||||
}
|
||||
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
|
||||
return
|
||||
@ -492,6 +833,53 @@ func ReadSampleTable(r *io.LimitedReader) (res *SampleTable, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Version int
|
||||
@ -500,7 +888,7 @@ type SampleDesc struct {
|
||||
}
|
||||
|
||||
func ReadSampleDesc(r *io.LimitedReader) (res *SampleDesc, err error) {
|
||||
|
||||
log.Println("ReadSampleDesc")
|
||||
self := &SampleDesc{}
|
||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||
return
|
||||
@ -521,6 +909,32 @@ func ReadSampleDesc(r *io.LimitedReader) (res *SampleDesc, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Version int
|
||||
@ -529,7 +943,7 @@ type TimeToSample struct {
|
||||
}
|
||||
|
||||
func ReadTimeToSample(r *io.LimitedReader) (res *TimeToSample, err error) {
|
||||
|
||||
log.Println("ReadTimeToSample")
|
||||
self := &TimeToSample{}
|
||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||
return
|
||||
@ -550,6 +964,32 @@ func ReadTimeToSample(r *io.LimitedReader) (res *TimeToSample, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Count int
|
||||
@ -557,7 +997,7 @@ type TimeToSampleEntry struct {
|
||||
}
|
||||
|
||||
func ReadTimeToSampleEntry(r *io.LimitedReader) (self TimeToSampleEntry, err error) {
|
||||
|
||||
log.Println("ReadTimeToSampleEntry")
|
||||
if self.Count, err = ReadInt(r, 4); err != nil {
|
||||
return
|
||||
}
|
||||
@ -566,6 +1006,16 @@ func ReadTimeToSampleEntry(r *io.LimitedReader) (self TimeToSampleEntry, err err
|
||||
}
|
||||
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 {
|
||||
Version int
|
||||
@ -574,7 +1024,7 @@ type SampleToChunk struct {
|
||||
}
|
||||
|
||||
func ReadSampleToChunk(r *io.LimitedReader) (res *SampleToChunk, err error) {
|
||||
|
||||
log.Println("ReadSampleToChunk")
|
||||
self := &SampleToChunk{}
|
||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||
return
|
||||
@ -595,6 +1045,32 @@ func ReadSampleToChunk(r *io.LimitedReader) (res *SampleToChunk, err error) {
|
||||
res = self
|
||||
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 {
|
||||
FirstChunk int
|
||||
@ -603,7 +1079,7 @@ type SampleToChunkEntry struct {
|
||||
}
|
||||
|
||||
func ReadSampleToChunkEntry(r *io.LimitedReader) (self SampleToChunkEntry, err error) {
|
||||
|
||||
log.Println("ReadSampleToChunkEntry")
|
||||
if self.FirstChunk, err = ReadInt(r, 4); err != nil {
|
||||
return
|
||||
}
|
||||
@ -615,15 +1091,28 @@ func ReadSampleToChunkEntry(r *io.LimitedReader) (self SampleToChunkEntry, err e
|
||||
}
|
||||
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 {
|
||||
Version int
|
||||
Flags int
|
||||
Entries []int
|
||||
Entries []CompositionOffsetEntry
|
||||
}
|
||||
|
||||
func ReadCompositionOffset(r *io.LimitedReader) (res *CompositionOffset, err error) {
|
||||
|
||||
log.Println("ReadCompositionOffset")
|
||||
self := &CompositionOffset{}
|
||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||
return
|
||||
@ -635,15 +1124,41 @@ func ReadCompositionOffset(r *io.LimitedReader) (res *CompositionOffset, err err
|
||||
if count, err = ReadInt(r, 4); err != nil {
|
||||
return
|
||||
}
|
||||
self.Entries = make([]int, count)
|
||||
self.Entries = make([]CompositionOffsetEntry, count)
|
||||
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
|
||||
}
|
||||
}
|
||||
res = self
|
||||
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 {
|
||||
Count int
|
||||
@ -651,7 +1166,7 @@ type CompositionOffsetEntry struct {
|
||||
}
|
||||
|
||||
func ReadCompositionOffsetEntry(r *io.LimitedReader) (self CompositionOffsetEntry, err error) {
|
||||
|
||||
log.Println("ReadCompositionOffsetEntry")
|
||||
if self.Count, err = ReadInt(r, 4); err != nil {
|
||||
return
|
||||
}
|
||||
@ -660,6 +1175,16 @@ func ReadCompositionOffsetEntry(r *io.LimitedReader) (self CompositionOffsetEntr
|
||||
}
|
||||
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 {
|
||||
Version int
|
||||
@ -668,7 +1193,7 @@ type SyncSample struct {
|
||||
}
|
||||
|
||||
func ReadSyncSample(r *io.LimitedReader) (res *SyncSample, err error) {
|
||||
|
||||
log.Println("ReadSyncSample")
|
||||
self := &SyncSample{}
|
||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||
return
|
||||
@ -689,15 +1214,42 @@ func ReadSyncSample(r *io.LimitedReader) (res *SyncSample, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Version int
|
||||
Flags int
|
||||
Entries []int
|
||||
Version int
|
||||
Flags int
|
||||
SampleSize int
|
||||
Entries []int
|
||||
}
|
||||
|
||||
func ReadSampleSize(r *io.LimitedReader) (res *SampleSize, err error) {
|
||||
|
||||
log.Println("ReadSampleSize")
|
||||
self := &SampleSize{}
|
||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||
return
|
||||
@ -705,6 +1257,9 @@ func ReadSampleSize(r *io.LimitedReader) (res *SampleSize, err error) {
|
||||
if self.Flags, err = ReadInt(r, 3); err != nil {
|
||||
return
|
||||
}
|
||||
if self.SampleSize, err = ReadInt(r, 4); err != nil {
|
||||
return
|
||||
}
|
||||
var count int
|
||||
if count, err = ReadInt(r, 4); err != nil {
|
||||
return
|
||||
@ -718,6 +1273,35 @@ func ReadSampleSize(r *io.LimitedReader) (res *SampleSize, err error) {
|
||||
res = self
|
||||
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 {
|
||||
Version int
|
||||
@ -726,7 +1310,7 @@ type ChunkOffset struct {
|
||||
}
|
||||
|
||||
func ReadChunkOffset(r *io.LimitedReader) (res *ChunkOffset, err error) {
|
||||
|
||||
log.Println("ReadChunkOffset")
|
||||
self := &ChunkOffset{}
|
||||
if self.Version, err = ReadInt(r, 1); err != nil {
|
||||
return
|
||||
@ -747,3 +1331,29 @@ func ReadChunkOffset(r *io.LimitedReader) (res *ChunkOffset, err error) {
|
||||
res = self
|
||||
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()}
|
||||
|
||||
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))
|
||||
var outfile *os.File
|
||||
if outfile, err = os.Create(filename+".out.mp4"); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user