add frag atom support

This commit is contained in:
nareix 2016-04-18 00:20:01 +08:00
parent bac553e58e
commit 82b17612dd
3 changed files with 581 additions and 26 deletions

View File

@ -340,6 +340,72 @@ var atoms = {
],
},
movieFrag: {
cc4: 'moof',
fields: [
['$atoms', [
['header', '*movieFragHeader'],
['tracks', '[]*trackFrag'],
]],
],
},
trackFragDecodeTime: {
cc4: 'tfdt',
},
movieFragHeader: {
cc4: 'mfhd',
fields: [
['version', 'int8'],
['flags', 'int24'],
['seqNum', 'int32'],
],
},
trackFrag: {
cc4: 'traf',
fields: [
['$atoms', [
['header', '*trackFragHeader'],
['decodeTime', '*trackFragDecodeTime'],
['run', '*trackFragRun'],
]],
],
},
trackFragRun: {
cc4: 'trun',
},
trackFragHeader: {
cc4: 'tfhd',
},
/*
// need hand write
trackFragRun: {
cc4: 'trun',
fields: [
['version', 'int8'],
['flags', 'int24'],
['sampleCount', 'int32'],
['dataOffset', 'int32'],
['entries', '[]int32'],
],
},
trackFragHeader: {
cc4: 'tfhd',
fields: [
['version', 'int8'],
['flags', 'int24'],
['id', 'int32'],
['sampleDescriptionIndex', 'int32'],
['_', '[12]byte'],
],
},
*/
};
var DeclReadFunc = (opts) => {

View File

@ -1,10 +1,10 @@
package atom
import (
"io"
"fmt"
"bytes"
"fmt"
"io"
"github.com/nareix/bits"
)
type GolombBitReader struct {
@ -412,3 +412,269 @@ func ReadAVCDecoderConfRecord(r *io.LimitedReader) (self AVCDecoderConfRecord, e
return
}
const (
TFHD_BASE_DATA_OFFSET = 0x01
TFHD_STSD_ID = 0x02
TFHD_DEFAULT_DURATION = 0x08
TFHD_DEFAULT_SIZE = 0x10
TFHD_DEFAULT_FLAGS = 0x20
TFHD_DURATION_IS_EMPTY = 0x010000
TFHD_DEFAULT_BASE_IS_MOOF = 0x020000
)
type TrackFragHeader struct {
Version int
Flags int
Id int
DefaultSize int
DefaultDuration int
DefaultFlags int
BaseDataOffset int64
StsdId int
}
func WalkTrackFragHeader(w Walker, self *TrackFragHeader) {
w.StartStruct("TrackFragHeader")
w.Name("Flags")
w.HexInt(self.Flags)
w.Name("Id")
w.Int(self.Id)
w.Name("DefaultDuration")
w.Int(self.DefaultDuration)
w.Name("DefaultSize")
w.Int(self.DefaultSize)
w.Name("DefaultFlags")
w.HexInt(self.DefaultFlags)
w.EndStruct()
}
func WriteTrackFragHeader(w io.WriteSeeker, self *TrackFragHeader) (err error) {
panic("unimplmented")
return
}
func ReadTrackFragHeader(r *io.LimitedReader) (res *TrackFragHeader, err error) {
self := &TrackFragHeader{}
if self.Version, err = ReadInt(r, 1); err != nil {
return
}
if self.Flags, err = ReadInt(r, 3); err != nil {
return
}
if self.Id, err = ReadInt(r, 4); err != nil {
return
}
if self.Flags&TFHD_BASE_DATA_OFFSET != 0 {
if self.BaseDataOffset, err = bits.ReadInt64BE(r, 64); err != nil {
return
}
}
if self.Flags&TFHD_STSD_ID != 0 {
if self.StsdId, err = ReadInt(r, 4); err != nil {
return
}
}
if self.Flags&TFHD_DEFAULT_DURATION != 0 {
if self.DefaultDuration, err = ReadInt(r, 4); err != nil {
return
}
}
if self.Flags&TFHD_DEFAULT_SIZE != 0 {
if self.DefaultSize, err = ReadInt(r, 4); err != nil {
return
}
}
if self.Flags&TFHD_DEFAULT_FLAGS != 0 {
if self.DefaultFlags,err = ReadInt(r, 4); err != nil {
return
}
}
res = self
return
}
const (
TRUN_DATA_OFFSET = 0x01
TRUN_FIRST_SAMPLE_FLAGS = 0x04
TRUN_SAMPLE_DURATION = 0x100
TRUN_SAMPLE_SIZE = 0x200
TRUN_SAMPLE_FLAGS = 0x400
TRUN_SAMPLE_CTS = 0x800
)
type TrackFragRunEntry struct {
Duration int
Size int
Flags int
Cts int
}
type TrackFragRun struct {
Version int
Flags int
FirstSampleFlags int
DataOffset int
Entries []TrackFragRunEntry
}
func WalkTrackFragRun(w Walker, self *TrackFragRun) {
w.StartStruct("TrackFragRun")
w.Name("Flags")
w.HexInt(self.Flags)
w.Name("FirstSampleFlags")
w.HexInt(self.FirstSampleFlags)
w.Name("DataOffset")
w.Int(self.DataOffset)
w.Name("EntriesCount")
w.Int(len(self.Entries))
for i := 0; i < 10 && i < len(self.Entries); i++ {
entry := self.Entries[i]
w.Println(fmt.Sprintf("Entry[%d] Flags=%x Duration=%d Size=%d Cts=%d",
i, entry.Flags, entry.Duration, entry.Size, entry.Cts))
}
w.EndStruct()
}
func WriteTrackFragRun(w io.WriteSeeker, self *TrackFragRun) (err error) {
panic("unimplmented")
return
}
func ReadTrackFragRun(r *io.LimitedReader) (res *TrackFragRun, err error) {
self := &TrackFragRun{}
if self.Version, err = ReadInt(r, 1); err != nil {
return
}
if self.Flags, err = ReadInt(r, 3); err != nil {
return
}
var count int
if count, err = ReadInt(r, 4); err != nil {
return
}
if self.Flags&TRUN_DATA_OFFSET != 0 {
if self.DataOffset, err = ReadInt(r, 4); err != nil {
return
}
}
if self.Flags&TRUN_FIRST_SAMPLE_FLAGS != 0 {
if self.FirstSampleFlags, err = ReadInt(r, 4); err != nil {
return
}
}
for i := 0; i < count; i++ {
var flags int
if i > 0 {
flags = self.Flags
} else {
flags = self.FirstSampleFlags
}
entry := TrackFragRunEntry{}
if flags&TRUN_SAMPLE_DURATION != 0 {
if entry.Duration, err = ReadInt(r, 4); err != nil {
return
}
}
if flags&TRUN_SAMPLE_SIZE != 0 {
if entry.Size, err = ReadInt(r, 4); err != nil {
return
}
}
if flags&TRUN_SAMPLE_FLAGS != 0 {
if entry.Flags, err = ReadInt(r, 4); err != nil {
return
}
}
if flags&TRUN_SAMPLE_CTS != 0 {
if entry.Cts, err = ReadInt(r, 4); err != nil {
return
}
}
self.Entries = append(self.Entries, entry)
}
res = self
return
}
type TrackFragDecodeTime struct {
Version int
Flags int
Time int64
}
func ReadTrackFragDecodeTime(r *io.LimitedReader) (res *TrackFragDecodeTime, err error) {
self := &TrackFragDecodeTime{}
if self.Version, err = ReadInt(r, 1); err != nil {
return
}
if self.Flags, err = ReadInt(r, 3); err != nil {
return
}
if self.Version != 0 {
if self.Time, err = bits.ReadInt64BE(r, 64); err != nil {
return
}
} else {
if self.Time, err = bits.ReadInt64BE(r, 32); err != nil {
return
}
}
res = self
return
}
func WriteTrackFragDecodeTime(w io.WriteSeeker, self *TrackFragDecodeTime) (err error) {
var aw *Writer
if aw, err = WriteAtomHeader(w, "tfdt"); 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 self.Version != 0 {
if err = bits.WriteInt64BE(w, self.Time, 64); err != nil {
return
}
} else {
if err = bits.WriteInt64BE(w, self.Time, 32); err != nil {
return
}
}
if err = aw.Close(); err != nil {
return
}
return
}
func WalkTrackFragDecodeTime(w Walker, self *TrackFragDecodeTime) {
w.StartStruct("TrackFragDecodeTime")
w.Name("Version")
w.Int(self.Version)
w.Name("Flags")
w.Int(self.Flags)
w.Name("Time")
w.Int64(self.Time)
w.EndStruct()
return
}

View File

@ -2475,3 +2475,226 @@ func WalkChunkOffset(w Walker, self *ChunkOffset) {
w.EndStruct()
return
}
type MovieFrag struct {
Header *MovieFragHeader
Tracks []*TrackFrag
}
func ReadMovieFrag(r *io.LimitedReader) (res *MovieFrag, err error) {
self := &MovieFrag{}
for r.N > 0 {
var cc4 string
var ar *io.LimitedReader
if ar, cc4, err = ReadAtomHeader(r, ""); err != nil {
return
}
switch cc4 {
case "mfhd":
{
if self.Header, err = ReadMovieFragHeader(ar); err != nil {
return
}
}
case "traf":
{
var item *TrackFrag
if item, err = ReadTrackFrag(ar); err != nil {
return
}
self.Tracks = append(self.Tracks, item)
}
}
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
return
}
}
res = self
return
}
func WriteMovieFrag(w io.WriteSeeker, self *MovieFrag) (err error) {
var aw *Writer
if aw, err = WriteAtomHeader(w, "moof"); err != nil {
return
}
w = aw
if self.Header != nil {
if err = WriteMovieFragHeader(w, self.Header); err != nil {
return
}
}
if self.Tracks != nil {
for _, elem := range self.Tracks {
if err = WriteTrackFrag(w, elem); err != nil {
return
}
}
}
if err = aw.Close(); err != nil {
return
}
return
}
func WalkMovieFrag(w Walker, self *MovieFrag) {
w.StartStruct("MovieFrag")
if self.Header != nil {
WalkMovieFragHeader(w, self.Header)
}
for i, item := range self.Tracks {
if w.FilterArrayItem("MovieFrag", "Tracks", i, len(self.Tracks)) {
if item != nil {
WalkTrackFrag(w, item)
}
} else {
w.ArrayLeft(i, len(self.Tracks))
break
}
}
w.EndStruct()
return
}
type MovieFragHeader struct {
Version int
Flags int
SeqNum int
}
func ReadMovieFragHeader(r *io.LimitedReader) (res *MovieFragHeader, err error) {
self := &MovieFragHeader{}
if self.Version, err = ReadInt(r, 1); err != nil {
return
}
if self.Flags, err = ReadInt(r, 3); err != nil {
return
}
if self.SeqNum, err = ReadInt(r, 4); err != nil {
return
}
res = self
return
}
func WriteMovieFragHeader(w io.WriteSeeker, self *MovieFragHeader) (err error) {
var aw *Writer
if aw, err = WriteAtomHeader(w, "mfhd"); 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.SeqNum, 4); err != nil {
return
}
if err = aw.Close(); err != nil {
return
}
return
}
func WalkMovieFragHeader(w Walker, self *MovieFragHeader) {
w.StartStruct("MovieFragHeader")
w.Name("Version")
w.Int(self.Version)
w.Name("Flags")
w.Int(self.Flags)
w.Name("SeqNum")
w.Int(self.SeqNum)
w.EndStruct()
return
}
type TrackFrag struct {
Header *TrackFragHeader
DecodeTime *TrackFragDecodeTime
Run *TrackFragRun
}
func ReadTrackFrag(r *io.LimitedReader) (res *TrackFrag, err error) {
self := &TrackFrag{}
for r.N > 0 {
var cc4 string
var ar *io.LimitedReader
if ar, cc4, err = ReadAtomHeader(r, ""); err != nil {
return
}
switch cc4 {
case "tfhd":
{
if self.Header, err = ReadTrackFragHeader(ar); err != nil {
return
}
}
case "tfdt":
{
if self.DecodeTime, err = ReadTrackFragDecodeTime(ar); err != nil {
return
}
}
case "trun":
{
if self.Run, err = ReadTrackFragRun(ar); err != nil {
return
}
}
}
if _, err = ReadDummy(ar, int(ar.N)); err != nil {
return
}
}
res = self
return
}
func WriteTrackFrag(w io.WriteSeeker, self *TrackFrag) (err error) {
var aw *Writer
if aw, err = WriteAtomHeader(w, "traf"); err != nil {
return
}
w = aw
if self.Header != nil {
if err = WriteTrackFragHeader(w, self.Header); err != nil {
return
}
}
if self.DecodeTime != nil {
if err = WriteTrackFragDecodeTime(w, self.DecodeTime); err != nil {
return
}
}
if self.Run != nil {
if err = WriteTrackFragRun(w, self.Run); err != nil {
return
}
}
if err = aw.Close(); err != nil {
return
}
return
}
func WalkTrackFrag(w Walker, self *TrackFrag) {
w.StartStruct("TrackFrag")
if self.Header != nil {
WalkTrackFragHeader(w, self.Header)
}
if self.DecodeTime != nil {
WalkTrackFragDecodeTime(w, self.DecodeTime)
}
if self.Run != nil {
WalkTrackFragRun(w, self.Run)
}
w.EndStruct()
return
}