new box scoping

This commit is contained in:
Martin Riedl 2024-12-03 19:24:00 +01:00
parent b3dc1b253d
commit 5a13e6352d
Signed by: martinr92
GPG key ID: FB68DA65516A804C
23 changed files with 332 additions and 151 deletions

55
Box.go
View file

@ -20,50 +20,7 @@ const (
boxSizeLength uint32 = 4
boxTypeLength uint32 = 4
// BoxTypeFileType File Type Box
BoxTypeFileType = "ftyp"
// BoxTypeMediaData Media Data Box
BoxTypeMediaData = "mdat"
// BoxTypeMovie Movie Box
BoxTypeMovie = "moov"
// BoxTypeMovieHeader Movie Header Box
BoxTypeMovieHeader = "mvhd"
// BoxTypeTrack Track Box
BoxTypeTrack = "trak"
// BoxTypeTrackHeader Track Header Box
BoxTypeTrackHeader = "tkhd"
// BoxTypeMedia Media Box
BoxTypeMedia = "mdia"
// BoxTypeMediaHeader Media Header Box
BoxTypeMediaHeader = "mdhd"
// BoxTypeHandlerReference Handler Reference Box
BoxTypeHandlerReference = "hdlr"
// BoxTypeMediaInformation Media Information Box
BoxTypeMediaInformation = "minf"
// BoxTypeSampleTable Sample Table Box
BoxTypeSampleTable = "stbl"
// BoxTypeSampleDescription Sample Description Box
BoxTypeSampleDescription = "stsd"
// BoxTypeDataInformation Data Information Box
BoxTypeDataInformation = "dinf"
// BoxTypeDataReferenceBox Data Reference Box
BoxTypeDataReferenceBox = "dref"
// BoxTypeDataEntryUrlBox Data Entry URL Box
BoxTypeDataEntryUrlBox = "url "
// BoxTypeDataEntryUrnBox Data Entry URN Box
BoxTypeDataEntryUrnBox = "urn "
// BoxTypeMovieFragment Movie Fragment Box
BoxTypeMovieFragment = "moof"
// BoxTypeMovieFragmentHeader Movie Fragment Header Box
BoxTypeMovieFragmentHeader = "mfhd"
// BoxTypeTrackFragment Track Fragment Box
BoxTypeTrackFragment = "traf"
// BoxTypeTrackFragmentHeader Track Fragment Header
BoxTypeTrackFragmentHeader = "tfhd"
// BoxTypeTrackFragmentRun Track Fragment Run Box
BoxTypeTrackFragmentRun = "trun"
// BoxTypeVideoMediaHeader Video Media Header Box
BoxTypeVideoMediaHeader = "vmhd"
boxTypeParentFile = "__file"
)
// Box is an abstract box struct
@ -93,3 +50,13 @@ func newFullBox(box *Box, data []byte) *FullBox {
return fullBox
}
type BoxDefinition struct {
Type string
ParentTypes []string
Parser BoxDefinitionParser
}
type BoxDefinitionParser func(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error)
var BoxDefinitions []BoxDefinition

View file

@ -26,15 +26,26 @@ package gomp4
// The data information box contains objects that declare the location of the media information in a track.
type DataInformationBox struct {
*Box
ChildBoxes []interface{}
ChildBoxes []any
}
// BoxTypeDataInformation Data Information Box
const BoxTypeDataInformation = "dinf"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeDataInformation,
ParentTypes: []string{BoxTypeMediaInformation}, // TODO: add Meta Box `meta`
Parser: ParseDataInformationBox,
})
}
// ParseDataInformationBox creates a new data information box struct based on bytes
func ParseDataInformationBox(filePosition uint64, headerSize uint32, content []byte) (*DataInformationBox, error) {
func ParseDataInformationBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &DataInformationBox{Box: &Box{filePosition, headerSize}}
// parse child boxes
var err error
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeDataInformation, filePosition, content)
return box, err
}

View file

@ -46,11 +46,22 @@ type DataReferenceBox struct {
*FullBox
// EntryCount is an integer that counts the actual entries
EntryCount uint32
ChildBoxes []interface{}
ChildBoxes []any
}
// BoxTypeDataReference Data Reference Box
const BoxTypeDataReference = "dref"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeDataReference,
ParentTypes: []string{BoxTypeDataInformation},
Parser: ParseDataReferenceBox,
})
}
// ParseDataReferenceBox creates a new data reference box struct based on bytes
func ParseDataReferenceBox(filePosition uint64, headerSize uint32, content []byte) (*DataReferenceBox, error) {
func ParseDataReferenceBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &DataReferenceBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
@ -60,7 +71,7 @@ func ParseDataReferenceBox(filePosition uint64, headerSize uint32, content []byt
// parse child boxes
var err error
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content[8:])
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeDataReference, filePosition, content[8:])
if err != nil {
return box, err
}
@ -91,15 +102,26 @@ type DataEntryUrlBox struct {
Location string
}
// BoxTypeDataEntryUrl Data Entry URL Box
const BoxTypeDataEntryUrl = "url "
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeDataEntryUrl,
ParentTypes: []string{BoxTypeDataReference},
Parser: ParseDataEntryUrlBox,
})
}
// ParseDataEntryUrlBox creates a data entry URL box struct based on bytes
func ParseDataEntryUrlBox(filePosition uint64, headerSize uint32, content []byte) *DataEntryUrlBox {
func ParseDataEntryUrlBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &DataEntryUrlBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
box.Location, _ = ParseStringNullTerminated(content[4:])
return box
return box, nil
}
// DataEntryUrnBox data entry URN box struct
@ -122,8 +144,19 @@ type DataEntryUrnBox struct {
Location string
}
// BoxTypeDataEntryUrn Data Entry URN Box
const BoxTypeDataEntryUrn = "urn "
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeDataEntryUrn,
ParentTypes: []string{BoxTypeDataReference},
Parser: ParseDataEntryUrnBox,
})
}
// ParseDataEntryUrnBox creates a data entry URN box struct based on bytes
func ParseDataEntryUrnBox(filePosition uint64, headerSize uint32, content []byte) *DataEntryUrnBox {
func ParseDataEntryUrnBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &DataEntryUrnBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
@ -132,5 +165,5 @@ func ParseDataEntryUrnBox(filePosition uint64, headerSize uint32, content []byte
box.Name = name
box.Location, _ = ParseStringNullTerminated(content[4+endIndex:])
return box
return box, nil
}

View file

@ -62,8 +62,19 @@ type FileTypeBox struct {
CompatibleBrands []string
}
// BoxTypeFileType File Type Box
const BoxTypeFileType = "ftyp"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeFileType,
ParentTypes: []string{boxTypeParentFile},
Parser: ParseFileTypeBox,
})
}
// ParseFileTypeBox creates new file type box based on bytes
func ParseFileTypeBox(filePosition uint64, headerSize uint32, content []byte) *FileTypeBox {
func ParseFileTypeBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
// create new box
box := &FileTypeBox{
Box: &Box{filePosition, headerSize},
@ -83,5 +94,5 @@ func ParseFileTypeBox(filePosition uint64, headerSize uint32, content []byte) *F
box.CompatibleBrands = append(box.CompatibleBrands, brand)
}
return box
return box, nil
}

View file

@ -49,7 +49,18 @@ type HandlerReferenceBox struct {
Name string
}
func ParseHandlerReferenceBox(filePosition uint64, headerSize uint32, content []byte) *HandlerReferenceBox {
// BoxTypeHandlerReference Handler Reference Box
const BoxTypeHandlerReference = "hdlr"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeHandlerReference,
ParentTypes: []string{BoxTypeMedia}, // TODO: add box type `meta` (Meta Box)
Parser: ParseHandlerReferenceBox,
})
}
func ParseHandlerReferenceBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &HandlerReferenceBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
@ -67,5 +78,5 @@ func ParseHandlerReferenceBox(filePosition uint64, headerSize uint32, content []
// parse name
box.Name, _ = ParseStringNullTerminated(content[position:])
return box
return box, nil
}

View file

@ -27,15 +27,26 @@ package gomp4
// within a track.
type MediaBox struct {
*Box
ChildBoxes []interface{}
ChildBoxes []any
}
// BoxTypeMedia Media Box
const BoxTypeMedia = "mdia"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeMedia,
ParentTypes: []string{BoxTypeTrack},
Parser: ParseMediaBox,
})
}
// ParseMediaBox creates a new media box struct based on bytes
func ParseMediaBox(filePosition uint64, headerSize uint32, content []byte) (*MediaBox, error) {
func ParseMediaBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &MediaBox{Box: &Box{filePosition, headerSize}}
// parse child boxes
var err error
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeMedia, filePosition, content)
return box, err
}

View file

@ -40,13 +40,24 @@ type MediaDataBox struct {
ContentEndPosition uint64
}
// BoxTypeMediaData Media Data Box
const BoxTypeMediaData = "mdat"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeMediaData,
ParentTypes: []string{boxTypeParentFile},
Parser: ParseMediaDataBox,
})
}
// ParseMediaDataBox creates a new media data box struct
func ParseMediaDataBox(filePosition uint64, headerSize uint32, content []byte) *MediaDataBox {
func ParseMediaDataBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &MediaDataBox{Box: &Box{filePosition, headerSize}}
// parse positions of content
box.ContentStartPosition = filePosition + uint64(headerSize)
box.ContentEndPosition = box.ContentStartPosition + uint64(len(content))
return box
return box, nil
}

View file

@ -58,8 +58,19 @@ type MediaHeaderBox struct {
// TODO: parse language language
}
// BoxTypeMediaHeader Media Header Box
const BoxTypeMediaHeader = "mdhd"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeMediaHeader,
ParentTypes: []string{BoxTypeMedia},
Parser: ParseMediaHeaderBox,
})
}
// ParseMediaHeaderBox creates a new Media Header Box struct
func ParseMediaHeaderBox(filePosition uint64, headerSize uint32, content []byte) *MediaHeaderBox {
func ParseMediaHeaderBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &MediaHeaderBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
@ -81,5 +92,5 @@ func ParseMediaHeaderBox(filePosition uint64, headerSize uint32, content []byte)
// TODO: parse language language
return box
return box, nil
}

View file

@ -25,15 +25,26 @@ package gomp4
// This box contains all the objects that declare characteristic information of the media in the track.
type MediaInformationBox struct {
*Box
ChildBoxes []interface{}
ChildBoxes []any
}
// BoxTypeMediaInformation Media Information Box
const BoxTypeMediaInformation = "minf"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeMediaInformation,
ParentTypes: []string{BoxTypeMedia},
Parser: ParseMediaInformationBox,
})
}
// ParseMediaInformationBox creates a new media information box struct based on bytes
func ParseMediaInformationBox(filePosition uint64, headerSize uint32, content []byte) (*MediaBox, error) {
func ParseMediaInformationBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &MediaBox{Box: &Box{filePosition, headerSize}}
// parse child boxes
var err error
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeMediaInformation, filePosition, content)
return box, err
}

View file

@ -26,15 +26,26 @@ package gomp4
// Normally this box is close to the beginning or end of the file, though this is not required.
type MovieBox struct {
*Box
ChildBoxes []interface{}
ChildBoxes []any
}
// BoxTypeMovie Movie Box
const BoxTypeMovie = "moov"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeMovie,
ParentTypes: []string{boxTypeParentFile},
Parser: ParseMovieBox,
})
}
// ParseMovieBox creates a new movie box struct based on bytes
func ParseMovieBox(filePosition uint64, headerSize uint32, content []byte) (*MovieBox, error) {
func ParseMovieBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &MovieBox{Box: &Box{filePosition, headerSize}}
// parse content boxes
var err error
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeMovie, filePosition, content)
return box, err
}

View file

@ -35,17 +35,28 @@ package gomp4
// However, derived specifications may make such restrictions.
type MovieFragmentBox struct {
*Box
ChildBoxes []interface{}
ChildBoxes []any
}
// BoxTypeMovieFragment Movie Fragment Box
const BoxTypeMovieFragment = "moof"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeMovieFragment,
ParentTypes: []string{boxTypeParentFile},
Parser: ParseMovieFragmentBox,
})
}
// ParseMovieFragmentBox creates a new movie fragment box struct based on bytes
func ParseMovieFragmentBox(filePosition uint64, headerSize uint32, content []byte) (*MovieFragmentBox, error) {
func ParseMovieFragmentBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &MovieFragmentBox{
Box: &Box{filePosition, headerSize},
}
// parse child boxes
var err error
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeMovieFragment, filePosition, content)
return box, err
}

View file

@ -36,8 +36,19 @@ type MovieFragmentHeaderBox struct {
SequenceNumber uint32
}
// BoxTypeMovieFragmentHeader Movie Fragment Header Box
const BoxTypeMovieFragmentHeader = "mfhd"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeMovieFragmentHeader,
ParentTypes: []string{BoxTypeMovieFragment},
Parser: ParseMovieFragmentHeaderBox,
})
}
// ParseMovieFragmentHeaderBox creates a new Movie Fragment Header Box struct
func ParseMovieFragmentHeaderBox(filePosition uint64, headerSize uint32, content []byte) *MovieFragmentHeaderBox {
func ParseMovieFragmentHeaderBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &MovieFragmentHeaderBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
@ -45,5 +56,5 @@ func ParseMovieFragmentHeaderBox(filePosition uint64, headerSize uint32, content
// parse sequence number
box.SequenceNumber = binary.BigEndian.Uint32(content[4:8])
return box
return box, nil
}

View file

@ -74,8 +74,19 @@ type MovieHeaderBox struct {
NextTrackID uint32
}
// BoxTypeMovieHeader Movie Header Box
const BoxTypeMovieHeader = "mvhd"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeMovieHeader,
ParentTypes: []string{BoxTypeMovie},
Parser: ParseMovieHeaderBox,
})
}
// ParseMovieHeaderBox creates a new Movie Header Box struct
func ParseMovieHeaderBox(filePosition uint64, headerSize uint32, content []byte) *MovieHeaderBox {
func ParseMovieHeaderBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &MovieHeaderBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
@ -107,5 +118,5 @@ func ParseMovieHeaderBox(filePosition uint64, headerSize uint32, content []byte)
position += 6 * 4
box.NextTrackID = binary.BigEndian.Uint32(content[position : position+4])
return box
return box, nil
}

View file

@ -24,20 +24,32 @@ import (
// Parser struct for mp4 container parsing
type Parser struct {
reader io.Reader
Content []interface{}
reader io.Reader
childBoxDefinitions map[string]map[string]BoxDefinition
Content []any
}
// NewParser creates a new parser with byte data
func NewParser(reader io.Reader) *Parser {
return &Parser{reader: reader}
// prepare valid box type combinations
types := make(map[string]map[string]BoxDefinition, 0)
for _, definition := range BoxDefinitions {
for _, parent := range definition.ParentTypes {
if _, exists := types[parent]; !exists {
types[parent] = make(map[string]BoxDefinition, 0)
}
types[parent][definition.Type] = definition
}
}
return &Parser{reader: reader, childBoxDefinitions: types}
}
// Parse starts the file parsing
func (parser *Parser) Parse() error {
var filePosition uint64 = 0
for {
box, endPosition, endOfFile, err := parseNextBox(parser.reader, filePosition)
box, endPosition, endOfFile, err := parseNextBox(parser, parser.reader, boxTypeParentFile, filePosition)
if box != nil {
parser.Content = append(parser.Content, box)
}
@ -52,7 +64,7 @@ func (parser *Parser) Parse() error {
}
}
func parseNextBox(reader io.Reader, filePosition uint64) (box interface{}, endPosition uint64, endOfFile bool, err error) {
func parseNextBox(parser *Parser, reader io.Reader, currentBoxType string, filePosition uint64) (box any, endPosition uint64, endOfFile bool, err error) {
// first 4 bytes are the size of the box
sizeBytes := make([]byte, boxSizeLength)
sizeBytesCount, err := reader.Read(sizeBytes)
@ -103,54 +115,11 @@ func parseNextBox(reader io.Reader, filePosition uint64) (box interface{}, endPo
}
// parse struct of box type
switch boxType {
case BoxTypeFileType:
box = ParseFileTypeBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeMediaData:
box = ParseMediaDataBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeMovie:
box, err = ParseMovieBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeMovieHeader:
box = ParseMovieHeaderBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeTrack:
box, err = ParseTrackBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeTrackHeader:
box = ParseTrackHeaderBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeMedia:
box, err = ParseMediaBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeMediaHeader:
box = ParseMediaHeaderBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeHandlerReference:
box = ParseHandlerReferenceBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeMediaInformation:
box, err = ParseMediaInformationBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeSampleTable:
box, err = ParseSampleTableBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeSampleDescription:
box = ParseSampleDescriptionBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeDataInformation:
box, err = ParseDataInformationBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeDataReferenceBox:
box, err = ParseDataReferenceBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeDataEntryUrlBox:
box = ParseDataEntryUrlBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeDataEntryUrnBox:
box = ParseDataEntryUrnBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeMovieFragment:
box, err = ParseMovieFragmentBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeMovieFragmentHeader:
box = ParseMovieFragmentHeaderBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeTrackFragment:
box, err = ParseTrackFragmentBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeTrackFragmentHeader:
box = ParseTrackFragmentHeaderBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeTrackFragmentRun:
box, err = ParseTrackFragmentRunBox(filePosition, boxHeaderSize, boxContentBytes)
case BoxTypeVideoMediaHeader:
box = ParseVideoMediaHeaderBox(filePosition, boxHeaderSize, boxContentBytes)
default:
logger.Println("unknown box type", boxType, "at", filePosition)
return nil, filePosition, false, errors.New("unknown box type " + boxType)
if boxTypeDefinition, found := parser.childBoxDefinitions[currentBoxType][boxType]; found {
box, err = boxTypeDefinition.Parser(parser, filePosition, boxHeaderSize, boxContentBytes)
} else {
logger.Println("unknown box type", boxType, "at", filePosition, "in", currentBoxType)
return nil, filePosition, false, errors.New("unknown box type " + boxType + " in " + currentBoxType)
}
// check for box errors
@ -163,13 +132,13 @@ func parseNextBox(reader io.Reader, filePosition uint64) (box interface{}, endPo
return
}
func (box *Box) parseChildBoxes(filePosition uint64, content []byte) (subBoxes []interface{}, e error) {
func (box *Box) parseChildBoxes(parser *Parser, currentBoxType string, filePosition uint64, content []byte) (subBoxes []any, e error) {
byteReader := bytes.NewReader(content)
endPosition := filePosition + uint64(box.HeaderSize) + uint64(len(content))
var currentFilePosition = filePosition + uint64(box.HeaderSize)
for {
// parse next packet
currentBox, currentEndPosition, _, err := parseNextBox(byteReader, currentFilePosition)
currentBox, currentEndPosition, _, err := parseNextBox(parser, byteReader, currentBoxType, currentFilePosition)
if err != nil {
e = err
logger.Println("error at", currentEndPosition, err)

View file

@ -16,6 +16,8 @@ package gomp4
import (
"encoding/binary"
"fmt"
"log"
)
// SampleDescriptionBox sample description box struct
@ -64,10 +66,22 @@ type SampleDescriptionBox struct {
*FullBox
// is an integer that gives the number of entries in the following table
EntryCount uint32
ChildBoxes []any
}
// BoxTypeSampleDescription Sample Description Box
const BoxTypeSampleDescription = "stsd"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeSampleDescription,
ParentTypes: []string{BoxTypeSampleTable},
Parser: ParseSampleDescriptionBox,
})
}
// ParseSampleDescriptionBox creates a new sample description box struct based on bytes
func ParseSampleDescriptionBox(filePosition uint64, headerSize uint32, content []byte) *SampleDescriptionBox {
func ParseSampleDescriptionBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &SampleDescriptionBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}

View file

@ -39,15 +39,26 @@ package gomp4
// are sync samples.
type SampleTableBox struct {
*Box
ChildBoxes []interface{}
ChildBoxes []any
}
// BoxTypeSampleTable Sample Table Box
const BoxTypeSampleTable = "stbl"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeSampleTable,
ParentTypes: []string{BoxTypeMediaInformation},
Parser: ParseSampleTableBox,
})
}
// ParseSampleTableBox creates a new sample table box struct based on bytes
func ParseSampleTableBox(filePosition uint64, headerSize uint32, content []byte) (*SampleTableBox, error) {
func ParseSampleTableBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &SampleTableBox{Box: &Box{filePosition, headerSize}}
// parse child boxes
var err error
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeSampleTable, filePosition, content)
return box, err
}

View file

@ -34,15 +34,26 @@ package gomp4
// tracks; after deleting all hint tracks, the entire unhinted presentation shall remain.
type TrackBox struct {
*Box
ChildBoxes []interface{}
ChildBoxes []any
}
// BoxTypeTrack Track Box
const BoxTypeTrack = "trak"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeTrack,
ParentTypes: []string{BoxTypeMovie},
Parser: ParseTrackBox,
})
}
// ParseTrackBox creates a new track box struct based on bytes
func ParseTrackBox(filePosition uint64, headerSize uint32, content []byte) (*TrackBox, error) {
func ParseTrackBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &TrackBox{Box: &Box{filePosition, headerSize}}
// parse child boxes
var err error
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeTrack, filePosition, content)
return box, err
}

View file

@ -30,15 +30,26 @@ package gomp4
// inserts can be used in audio tracks doing silence suppression, for example.
type TrackFragmentBox struct {
*Box
ChildBoxes []interface{}
ChildBoxes []any
}
// BoxTypeTrackFragment Track Fragment Box
const BoxTypeTrackFragment = "traf"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeTrackFragment,
ParentTypes: []string{BoxTypeMovieFragment},
Parser: ParseTrackFragmentBox,
})
}
// ParseTrackFragmentBox creates a new Track Fragment Box struct
func ParseTrackFragmentBox(filePosition uint64, headerSize uint32, content []byte) (*TrackFragmentBox, error) {
func ParseTrackFragmentBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &TrackFragmentBox{Box: &Box{filePosition, headerSize}}
// parse child boxes
var err error
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeTrackFragment, filePosition, content)
return box, err
}

View file

@ -43,6 +43,17 @@ type TrackFragmentHeaderBox struct {
DefaultSampleFlags uint32
}
// BoxTypeTrackFragmentHeader Track Fragment Header
const BoxTypeTrackFragmentHeader = "tfhd"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeTrackFragmentHeader,
ParentTypes: []string{BoxTypeTrackFragment},
Parser: ParseTrackFragmentHeaderBox,
})
}
const (
// TrackFragmentHeaderBoxFlagBaseDataOffsetPresent Base Offset Present Flag
//
@ -74,7 +85,7 @@ const (
)
// ParseTrackFragmentHeaderBox creates a new track fragment header box struct
func ParseTrackFragmentHeaderBox(filePosition uint64, headerSize uint32, content []byte) *TrackFragmentHeaderBox {
func ParseTrackFragmentHeaderBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &TrackFragmentHeaderBox{FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4])}
position := 4
@ -84,5 +95,5 @@ func ParseTrackFragmentHeaderBox(filePosition uint64, headerSize uint32, content
// TODO: check other flags
return box
return box, nil
}

View file

@ -54,6 +54,17 @@ type TrackFragmentRunBox struct {
Samples []TrackFragmentRunBoxSample
}
// BoxTypeTrackFragmentRun Track Fragment Run Box
const BoxTypeTrackFragmentRun = "trun"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeTrackFragmentRun,
ParentTypes: []string{BoxTypeTrackFragment},
Parser: ParseTrackFragmentRunBox,
})
}
const (
// TrackFragmentRunBoxFlagDataOffsetPresent Data Offset Flag
TrackFragmentRunBoxFlagDataOffsetPresent uint32 = 0x00000001
@ -84,7 +95,7 @@ const (
)
// ParseTrackFragmentRunBox creates a new Track Fragment Run Box struct
func ParseTrackFragmentRunBox(filePosition uint64, headerSize uint32, content []byte) (*TrackFragmentRunBox, error) {
func ParseTrackFragmentRunBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
// build full box with additional 4 bytes header
fullBox := newFullBox(&Box{filePosition, headerSize}, content[0:4])
position := 4

View file

@ -148,8 +148,19 @@ const (
TrackHeaderBoxFlagTrackSizeIsAspectRatio uint32 = 0x00000008
)
// BoxTypeTrackHeader Track Header Box
const BoxTypeTrackHeader = "tkhd"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeTrackHeader,
ParentTypes: []string{BoxTypeTrack},
Parser: ParseTrackHeaderBox,
})
}
// ParseTrackHeaderBox creates a new Track Header Box struct
func ParseTrackHeaderBox(filePosition uint64, headerSize uint32, content []byte) *TrackHeaderBox {
func ParseTrackHeaderBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &TrackHeaderBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
@ -190,5 +201,5 @@ func ParseTrackHeaderBox(filePosition uint64, headerSize uint32, content []byte)
box.Width = NewFixed1616ByBytes(content[position : position+4])
box.Height = NewFixed1616ByBytes(content[position+4 : position+8])
return box
return box, nil
}

View file

@ -37,8 +37,19 @@ type VideoMediaHeaderBox struct {
CPColor []uint16
}
// BoxTypeVideoMediaHeader Video Media Header Box
const BoxTypeVideoMediaHeader = "vmhd"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeVideoMediaHeader,
ParentTypes: []string{BoxTypeMediaInformation},
Parser: ParseVideoMediaHeaderBox,
})
}
// ParseVideoMediaHeaderBox creates a new Video Media Header Box struct
func ParseVideoMediaHeaderBox(filePosition uint64, headerSize uint32, content []byte) *VideoMediaHeaderBox {
func ParseVideoMediaHeaderBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &VideoMediaHeaderBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
@ -49,5 +60,5 @@ func ParseVideoMediaHeaderBox(filePosition uint64, headerSize uint32, content []
box.CPColor = append(box.CPColor, binary.BigEndian.Uint16(content[position+4:position+6]))
box.CPColor = append(box.CPColor, binary.BigEndian.Uint16(content[position+6:position+8]))
return box
return box, nil
}

2
go.mod
View file

@ -1,3 +1,3 @@
module gitlab.com/martinr92/gomp4
go 1.15
go 1.18