Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions atom/box.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type Mp4Reader struct {
Reader io.ReaderAt
Ftyp *FtypBox
Moov *MoovBox
Moof *MoofBox
Mdat *MdatBox
Uuids []*UuidBox
Size int64
Expand Down Expand Up @@ -48,6 +49,9 @@ func (m *Mp4Reader) Parse() error {
m.Moov = &MoovBox{Box: box}
_ = m.Moov.parse()
m.IsFragmented = m.Moov.IsFragmented
case "moof":
m.Moof = &MoofBox{Box: box}
_ = m.Moof.parse()
case "uuid":
uuidBox := &UuidBox{Box: box}
_ = uuidBox.parse()
Expand Down
29 changes: 29 additions & 0 deletions atom/mfhd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package atom

import "encoding/binary"

// MfhdBox - Movie Fragment Header Box
// Box Type: mfhd
// Container: Movie Fragment Box (moof)
// Mandatory: Yes
// Quantity: Exactly one.
//
// The movie fragment header contains a sequence number, as a safety check. The sequence number
// usually starts at 1 and increases for each movie fragment in the file, in the order in which they occur.
// This allows readers to verify integrity of the sequence in environments where undesired re‐ordering
// might occur.
type MfhdBox struct {
*Box
Version byte
Flags uint32
SequenceNumber uint32
}

func (b *MfhdBox) parse() error {
data := b.ReadBoxData()
b.Version = data[0]
b.Flags = binary.BigEndian.Uint32(data[0:4])
b.SequenceNumber = binary.BigEndian.Uint32(data[4:8])

return nil
}
35 changes: 35 additions & 0 deletions atom/moof.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package atom

// MoofBox - Movie Fragment Box
// Box Type: moof
// Container: File
// Mandatory: No
// Quantity: Zero or more.
//
// The movie fragments extend the presentation in time. They provide the information that would
// previously have been in the Movie Box. The actual samples are in Media Data Boxes, as usual, if they are
// in the same file. The data reference index is in the sample description, so it is possible to build
// incremental presentations where the media data is in files other than the file containing the Movie Box.
type MoofBox struct {
*Box
Mfhd *MfhdBox
Traf []*TrafBox
}

func (b *MoofBox) parse() error {
boxes := readBoxes(b.Reader, b.Start+BoxHeaderSize, b.Size-BoxHeaderSize)

for _, box := range boxes {
switch box.Name {
case "mfhd":
b.Mfhd = &MfhdBox{Box: box}
b.Mfhd.parse()

case "traf":
traf := &TrafBox{Box: box}
traf.parse()
b.Traf = append(b.Traf, traf)
}
}
return nil
}
55 changes: 55 additions & 0 deletions atom/tfhd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package atom

import (
"encoding/binary"
)

// TfhdBox - Track Fragment Header Box
// Box Type: tfhd
// Container: Track Fragment Box (traf)
// Mandatory: Yes
// Quantity: Exactly one.
type TfhdBox struct {
*Box
Version byte
Flags uint32
TrackID uint32
//Optional fields
BaseDataOffset uint64
SampleDescriptionIndex uint32
DefaultSampleDuration uint32
DefaultSampleSize uint32
DefaultSampleFlags uint32
}

func (b *TfhdBox) parse() error {
data := b.ReadBoxData()

b.Version = data[0]
b.Flags = binary.BigEndian.Uint32(data[0:4])
b.TrackID = binary.BigEndian.Uint32(data[4:8])

oPos := 8
if b.Flags&1 != 0 {
b.BaseDataOffset = binary.BigEndian.Uint64(data[16:24])
oPos += 8
}
if b.Flags&2 != 0 {
b.SampleDescriptionIndex = binary.BigEndian.Uint32(data[oPos : oPos+4])
oPos += 4
}
if b.Flags&8 != 0 {
b.DefaultSampleDuration = binary.BigEndian.Uint32(data[oPos : oPos+4])
oPos += 4
}
if b.Flags&10 != 0 {
b.DefaultSampleSize = binary.BigEndian.Uint32(data[oPos : oPos+4])
oPos += 4
}
if b.Flags&20 != 0 {
b.DefaultSampleFlags = binary.BigEndian.Uint32(data[oPos : oPos+4])
oPos += 4
}

return nil
}
29 changes: 29 additions & 0 deletions atom/traf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package atom

// TrafBox - Track Fragment Box
// Box Type: traf
// Container: Track Fragment Box (traf)
// Mandatory: Yes
// Quantity: Zero or more.
type TrafBox struct {
*Box
Tfhd *TfhdBox
Trun *TrunBox
}

func (b *TrafBox) parse() error {
boxes := readBoxes(b.Reader, b.Start+BoxHeaderSize, b.Size-BoxHeaderSize)

for _, box := range boxes {
switch box.Name {
case "tfhd":
b.Tfhd = &TfhdBox{Box: box}
b.Tfhd.parse()

case "trun":
b.Trun = &TrunBox{Box: box}
b.Trun.parse()
}
}
return nil
}
27 changes: 27 additions & 0 deletions atom/trun.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package atom

import (
"encoding/binary"
)

// TrunBox - Track Fragment Run Box
// Box Type: trun
// Container: Track Fragment Box (traf)
// Mandatory: No
// Quantity: Zero or more.
type TrunBox struct {
*Box
Version byte
Flags uint32
SampleCount uint32
//TODO Optional fields not yet implemented
}

func (b *TrunBox) parse() error {
data := b.ReadBoxData()
b.Version = data[0]
// b.Flags = [3]byte{data[1], data[2], data[3]}
b.Flags = binary.BigEndian.Uint32(data[0:4])
b.SampleCount = binary.BigEndian.Uint32(data[4:8])
return nil
}
2 changes: 2 additions & 0 deletions cmd/mp4info/mp4info.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ Track: {{$trak.Tkhd.TrackID}}
width: {{to16 $trak.Tkhd.Width}}
height: {{to16 $trak.Tkhd.Height}}
media:
{{- if (ne $trak.Mdia.Minf.Stbl.Stts.EntryCount 0) }}
sample count: {{index $trak.Mdia.Minf.Stbl.Stts.SampleCounts 0}}
{{- end}}
timescale: {{$trak.Mdia.Mdhd.Timescale}}
duration: {{$trak.Mdia.Mdhd.Duration}} (media timescale units)
duration: {{getDurationMS $trak.Mdia.Mdhd.Duration $trak.Mdia.Mdhd.Timescale}} (ms)
Expand Down