add hdlr and fix bugs make vlc can play

This commit is contained in:
nareix 2015-11-21 19:49:03 +08:00
parent 3bbc27f470
commit 637f47b250
5 changed files with 972 additions and 66 deletions

View File

@ -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
View 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
}

View File

@ -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
View 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
View File

@ -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
}