new box scoping
This commit is contained in:
parent
b3dc1b253d
commit
5a13e6352d
23 changed files with 332 additions and 151 deletions
55
Box.go
55
Box.go
|
@ -20,50 +20,7 @@ const (
|
||||||
boxSizeLength uint32 = 4
|
boxSizeLength uint32 = 4
|
||||||
boxTypeLength uint32 = 4
|
boxTypeLength uint32 = 4
|
||||||
|
|
||||||
// BoxTypeFileType File Type Box
|
boxTypeParentFile = "__file"
|
||||||
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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Box is an abstract box struct
|
// Box is an abstract box struct
|
||||||
|
@ -93,3 +50,13 @@ func newFullBox(box *Box, data []byte) *FullBox {
|
||||||
|
|
||||||
return 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
|
||||||
|
|
|
@ -26,15 +26,26 @@ package gomp4
|
||||||
// The data information box contains objects that declare the location of the media information in a track.
|
// The data information box contains objects that declare the location of the media information in a track.
|
||||||
type DataInformationBox struct {
|
type DataInformationBox struct {
|
||||||
*Box
|
*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
|
// 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}}
|
box := &DataInformationBox{Box: &Box{filePosition, headerSize}}
|
||||||
|
|
||||||
// parse child boxes
|
// parse child boxes
|
||||||
var err error
|
var err error
|
||||||
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
|
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeDataInformation, filePosition, content)
|
||||||
return box, err
|
return box, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,11 +46,22 @@ type DataReferenceBox struct {
|
||||||
*FullBox
|
*FullBox
|
||||||
// EntryCount is an integer that counts the actual entries
|
// EntryCount is an integer that counts the actual entries
|
||||||
EntryCount uint32
|
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
|
// 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{
|
box := &DataReferenceBox{
|
||||||
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
||||||
}
|
}
|
||||||
|
@ -60,7 +71,7 @@ func ParseDataReferenceBox(filePosition uint64, headerSize uint32, content []byt
|
||||||
|
|
||||||
// parse child boxes
|
// parse child boxes
|
||||||
var err error
|
var err error
|
||||||
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content[8:])
|
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeDataReference, filePosition, content[8:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return box, err
|
return box, err
|
||||||
}
|
}
|
||||||
|
@ -91,15 +102,26 @@ type DataEntryUrlBox struct {
|
||||||
Location string
|
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
|
// 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{
|
box := &DataEntryUrlBox{
|
||||||
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
||||||
}
|
}
|
||||||
|
|
||||||
box.Location, _ = ParseStringNullTerminated(content[4:])
|
box.Location, _ = ParseStringNullTerminated(content[4:])
|
||||||
|
|
||||||
return box
|
return box, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataEntryUrnBox data entry URN box struct
|
// DataEntryUrnBox data entry URN box struct
|
||||||
|
@ -122,8 +144,19 @@ type DataEntryUrnBox struct {
|
||||||
Location string
|
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
|
// 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{
|
box := &DataEntryUrnBox{
|
||||||
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
||||||
}
|
}
|
||||||
|
@ -132,5 +165,5 @@ func ParseDataEntryUrnBox(filePosition uint64, headerSize uint32, content []byte
|
||||||
box.Name = name
|
box.Name = name
|
||||||
box.Location, _ = ParseStringNullTerminated(content[4+endIndex:])
|
box.Location, _ = ParseStringNullTerminated(content[4+endIndex:])
|
||||||
|
|
||||||
return box
|
return box, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,8 +62,19 @@ type FileTypeBox struct {
|
||||||
CompatibleBrands []string
|
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
|
// 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
|
// create new box
|
||||||
box := &FileTypeBox{
|
box := &FileTypeBox{
|
||||||
Box: &Box{filePosition, headerSize},
|
Box: &Box{filePosition, headerSize},
|
||||||
|
@ -83,5 +94,5 @@ func ParseFileTypeBox(filePosition uint64, headerSize uint32, content []byte) *F
|
||||||
box.CompatibleBrands = append(box.CompatibleBrands, brand)
|
box.CompatibleBrands = append(box.CompatibleBrands, brand)
|
||||||
}
|
}
|
||||||
|
|
||||||
return box
|
return box, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,18 @@ type HandlerReferenceBox struct {
|
||||||
Name string
|
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{
|
box := &HandlerReferenceBox{
|
||||||
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
||||||
}
|
}
|
||||||
|
@ -67,5 +78,5 @@ func ParseHandlerReferenceBox(filePosition uint64, headerSize uint32, content []
|
||||||
// parse name
|
// parse name
|
||||||
box.Name, _ = ParseStringNullTerminated(content[position:])
|
box.Name, _ = ParseStringNullTerminated(content[position:])
|
||||||
|
|
||||||
return box
|
return box, nil
|
||||||
}
|
}
|
||||||
|
|
17
MediaBox.go
17
MediaBox.go
|
@ -27,15 +27,26 @@ package gomp4
|
||||||
// within a track.
|
// within a track.
|
||||||
type MediaBox struct {
|
type MediaBox struct {
|
||||||
*Box
|
*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
|
// 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}}
|
box := &MediaBox{Box: &Box{filePosition, headerSize}}
|
||||||
|
|
||||||
// parse child boxes
|
// parse child boxes
|
||||||
var err error
|
var err error
|
||||||
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
|
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeMedia, filePosition, content)
|
||||||
return box, err
|
return box, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,13 +40,24 @@ type MediaDataBox struct {
|
||||||
ContentEndPosition uint64
|
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
|
// 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}}
|
box := &MediaDataBox{Box: &Box{filePosition, headerSize}}
|
||||||
|
|
||||||
// parse positions of content
|
// parse positions of content
|
||||||
box.ContentStartPosition = filePosition + uint64(headerSize)
|
box.ContentStartPosition = filePosition + uint64(headerSize)
|
||||||
box.ContentEndPosition = box.ContentStartPosition + uint64(len(content))
|
box.ContentEndPosition = box.ContentStartPosition + uint64(len(content))
|
||||||
|
|
||||||
return box
|
return box, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,8 +58,19 @@ type MediaHeaderBox struct {
|
||||||
// TODO: parse language language
|
// 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
|
// 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{
|
box := &MediaHeaderBox{
|
||||||
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
||||||
}
|
}
|
||||||
|
@ -81,5 +92,5 @@ func ParseMediaHeaderBox(filePosition uint64, headerSize uint32, content []byte)
|
||||||
|
|
||||||
// TODO: parse language language
|
// TODO: parse language language
|
||||||
|
|
||||||
return box
|
return box, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,15 +25,26 @@ package gomp4
|
||||||
// This box contains all the objects that declare characteristic information of the media in the track.
|
// This box contains all the objects that declare characteristic information of the media in the track.
|
||||||
type MediaInformationBox struct {
|
type MediaInformationBox struct {
|
||||||
*Box
|
*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
|
// 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}}
|
box := &MediaBox{Box: &Box{filePosition, headerSize}}
|
||||||
|
|
||||||
// parse child boxes
|
// parse child boxes
|
||||||
var err error
|
var err error
|
||||||
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
|
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeMediaInformation, filePosition, content)
|
||||||
return box, err
|
return box, err
|
||||||
}
|
}
|
||||||
|
|
17
MovieBox.go
17
MovieBox.go
|
@ -26,15 +26,26 @@ package gomp4
|
||||||
// Normally this box is close to the beginning or end of the file, though this is not required.
|
// Normally this box is close to the beginning or end of the file, though this is not required.
|
||||||
type MovieBox struct {
|
type MovieBox struct {
|
||||||
*Box
|
*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
|
// 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}}
|
box := &MovieBox{Box: &Box{filePosition, headerSize}}
|
||||||
|
|
||||||
// parse content boxes
|
// parse content boxes
|
||||||
var err error
|
var err error
|
||||||
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
|
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeMovie, filePosition, content)
|
||||||
return box, err
|
return box, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,17 +35,28 @@ package gomp4
|
||||||
// However, derived specifications may make such restrictions.
|
// However, derived specifications may make such restrictions.
|
||||||
type MovieFragmentBox struct {
|
type MovieFragmentBox struct {
|
||||||
*Box
|
*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
|
// 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 := &MovieFragmentBox{
|
||||||
Box: &Box{filePosition, headerSize},
|
Box: &Box{filePosition, headerSize},
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse child boxes
|
// parse child boxes
|
||||||
var err error
|
var err error
|
||||||
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
|
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeMovieFragment, filePosition, content)
|
||||||
return box, err
|
return box, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,19 @@ type MovieFragmentHeaderBox struct {
|
||||||
SequenceNumber uint32
|
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
|
// 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{
|
box := &MovieFragmentHeaderBox{
|
||||||
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
||||||
}
|
}
|
||||||
|
@ -45,5 +56,5 @@ func ParseMovieFragmentHeaderBox(filePosition uint64, headerSize uint32, content
|
||||||
// parse sequence number
|
// parse sequence number
|
||||||
box.SequenceNumber = binary.BigEndian.Uint32(content[4:8])
|
box.SequenceNumber = binary.BigEndian.Uint32(content[4:8])
|
||||||
|
|
||||||
return box
|
return box, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,8 +74,19 @@ type MovieHeaderBox struct {
|
||||||
NextTrackID uint32
|
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
|
// 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{
|
box := &MovieHeaderBox{
|
||||||
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
||||||
}
|
}
|
||||||
|
@ -107,5 +118,5 @@ func ParseMovieHeaderBox(filePosition uint64, headerSize uint32, content []byte)
|
||||||
position += 6 * 4
|
position += 6 * 4
|
||||||
box.NextTrackID = binary.BigEndian.Uint32(content[position : position+4])
|
box.NextTrackID = binary.BigEndian.Uint32(content[position : position+4])
|
||||||
|
|
||||||
return box
|
return box, nil
|
||||||
}
|
}
|
||||||
|
|
77
Parser.go
77
Parser.go
|
@ -25,19 +25,31 @@ import (
|
||||||
// Parser struct for mp4 container parsing
|
// Parser struct for mp4 container parsing
|
||||||
type Parser struct {
|
type Parser struct {
|
||||||
reader io.Reader
|
reader io.Reader
|
||||||
Content []interface{}
|
childBoxDefinitions map[string]map[string]BoxDefinition
|
||||||
|
Content []any
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewParser creates a new parser with byte data
|
// NewParser creates a new parser with byte data
|
||||||
func NewParser(reader io.Reader) *Parser {
|
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
|
// Parse starts the file parsing
|
||||||
func (parser *Parser) Parse() error {
|
func (parser *Parser) Parse() error {
|
||||||
var filePosition uint64 = 0
|
var filePosition uint64 = 0
|
||||||
for {
|
for {
|
||||||
box, endPosition, endOfFile, err := parseNextBox(parser.reader, filePosition)
|
box, endPosition, endOfFile, err := parseNextBox(parser, parser.reader, boxTypeParentFile, filePosition)
|
||||||
if box != nil {
|
if box != nil {
|
||||||
parser.Content = append(parser.Content, box)
|
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
|
// first 4 bytes are the size of the box
|
||||||
sizeBytes := make([]byte, boxSizeLength)
|
sizeBytes := make([]byte, boxSizeLength)
|
||||||
sizeBytesCount, err := reader.Read(sizeBytes)
|
sizeBytesCount, err := reader.Read(sizeBytes)
|
||||||
|
@ -103,54 +115,11 @@ func parseNextBox(reader io.Reader, filePosition uint64) (box interface{}, endPo
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse struct of box type
|
// parse struct of box type
|
||||||
switch boxType {
|
if boxTypeDefinition, found := parser.childBoxDefinitions[currentBoxType][boxType]; found {
|
||||||
case BoxTypeFileType:
|
box, err = boxTypeDefinition.Parser(parser, filePosition, boxHeaderSize, boxContentBytes)
|
||||||
box = ParseFileTypeBox(filePosition, boxHeaderSize, boxContentBytes)
|
} else {
|
||||||
case BoxTypeMediaData:
|
logger.Println("unknown box type", boxType, "at", filePosition, "in", currentBoxType)
|
||||||
box = ParseMediaDataBox(filePosition, boxHeaderSize, boxContentBytes)
|
return nil, filePosition, false, errors.New("unknown box type " + boxType + " in " + currentBoxType)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for box errors
|
// check for box errors
|
||||||
|
@ -163,13 +132,13 @@ func parseNextBox(reader io.Reader, filePosition uint64) (box interface{}, endPo
|
||||||
return
|
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)
|
byteReader := bytes.NewReader(content)
|
||||||
endPosition := filePosition + uint64(box.HeaderSize) + uint64(len(content))
|
endPosition := filePosition + uint64(box.HeaderSize) + uint64(len(content))
|
||||||
var currentFilePosition = filePosition + uint64(box.HeaderSize)
|
var currentFilePosition = filePosition + uint64(box.HeaderSize)
|
||||||
for {
|
for {
|
||||||
// parse next packet
|
// parse next packet
|
||||||
currentBox, currentEndPosition, _, err := parseNextBox(byteReader, currentFilePosition)
|
currentBox, currentEndPosition, _, err := parseNextBox(parser, byteReader, currentBoxType, currentFilePosition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e = err
|
e = err
|
||||||
logger.Println("error at", currentEndPosition, err)
|
logger.Println("error at", currentEndPosition, err)
|
||||||
|
|
|
@ -16,6 +16,8 @@ package gomp4
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SampleDescriptionBox sample description box struct
|
// SampleDescriptionBox sample description box struct
|
||||||
|
@ -64,10 +66,22 @@ type SampleDescriptionBox struct {
|
||||||
*FullBox
|
*FullBox
|
||||||
// is an integer that gives the number of entries in the following table
|
// is an integer that gives the number of entries in the following table
|
||||||
EntryCount uint32
|
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
|
// 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{
|
box := &SampleDescriptionBox{
|
||||||
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,15 +39,26 @@ package gomp4
|
||||||
// are sync samples.
|
// are sync samples.
|
||||||
type SampleTableBox struct {
|
type SampleTableBox struct {
|
||||||
*Box
|
*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
|
// 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}}
|
box := &SampleTableBox{Box: &Box{filePosition, headerSize}}
|
||||||
|
|
||||||
// parse child boxes
|
// parse child boxes
|
||||||
var err error
|
var err error
|
||||||
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
|
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeSampleTable, filePosition, content)
|
||||||
return box, err
|
return box, err
|
||||||
}
|
}
|
||||||
|
|
17
TrackBox.go
17
TrackBox.go
|
@ -34,15 +34,26 @@ package gomp4
|
||||||
// tracks; after deleting all hint tracks, the entire un‐hinted presentation shall remain.
|
// tracks; after deleting all hint tracks, the entire un‐hinted presentation shall remain.
|
||||||
type TrackBox struct {
|
type TrackBox struct {
|
||||||
*Box
|
*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
|
// 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}}
|
box := &TrackBox{Box: &Box{filePosition, headerSize}}
|
||||||
|
|
||||||
// parse child boxes
|
// parse child boxes
|
||||||
var err error
|
var err error
|
||||||
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
|
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeTrack, filePosition, content)
|
||||||
return box, err
|
return box, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,15 +30,26 @@ package gomp4
|
||||||
// inserts can be used in audio tracks doing silence suppression, for example.
|
// inserts can be used in audio tracks doing silence suppression, for example.
|
||||||
type TrackFragmentBox struct {
|
type TrackFragmentBox struct {
|
||||||
*Box
|
*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
|
// 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}}
|
box := &TrackFragmentBox{Box: &Box{filePosition, headerSize}}
|
||||||
|
|
||||||
// parse child boxes
|
// parse child boxes
|
||||||
var err error
|
var err error
|
||||||
box.ChildBoxes, err = box.parseChildBoxes(filePosition, content)
|
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeTrackFragment, filePosition, content)
|
||||||
return box, err
|
return box, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,17 @@ type TrackFragmentHeaderBox struct {
|
||||||
DefaultSampleFlags uint32
|
DefaultSampleFlags uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BoxTypeTrackFragmentHeader Track Fragment Header
|
||||||
|
const BoxTypeTrackFragmentHeader = "tfhd"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
|
||||||
|
Type: BoxTypeTrackFragmentHeader,
|
||||||
|
ParentTypes: []string{BoxTypeTrackFragment},
|
||||||
|
Parser: ParseTrackFragmentHeaderBox,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// TrackFragmentHeaderBoxFlagBaseDataOffsetPresent Base Offset Present Flag
|
// TrackFragmentHeaderBoxFlagBaseDataOffsetPresent Base Offset Present Flag
|
||||||
//
|
//
|
||||||
|
@ -74,7 +85,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseTrackFragmentHeaderBox creates a new track fragment header box struct
|
// 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])}
|
box := &TrackFragmentHeaderBox{FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4])}
|
||||||
position := 4
|
position := 4
|
||||||
|
|
||||||
|
@ -84,5 +95,5 @@ func ParseTrackFragmentHeaderBox(filePosition uint64, headerSize uint32, content
|
||||||
|
|
||||||
// TODO: check other flags
|
// TODO: check other flags
|
||||||
|
|
||||||
return box
|
return box, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,17 @@ type TrackFragmentRunBox struct {
|
||||||
Samples []TrackFragmentRunBoxSample
|
Samples []TrackFragmentRunBoxSample
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BoxTypeTrackFragmentRun Track Fragment Run Box
|
||||||
|
const BoxTypeTrackFragmentRun = "trun"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
|
||||||
|
Type: BoxTypeTrackFragmentRun,
|
||||||
|
ParentTypes: []string{BoxTypeTrackFragment},
|
||||||
|
Parser: ParseTrackFragmentRunBox,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// TrackFragmentRunBoxFlagDataOffsetPresent Data Offset Flag
|
// TrackFragmentRunBoxFlagDataOffsetPresent Data Offset Flag
|
||||||
TrackFragmentRunBoxFlagDataOffsetPresent uint32 = 0x00000001
|
TrackFragmentRunBoxFlagDataOffsetPresent uint32 = 0x00000001
|
||||||
|
@ -84,7 +95,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseTrackFragmentRunBox creates a new Track Fragment Run Box struct
|
// 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
|
// build full box with additional 4 bytes header
|
||||||
fullBox := newFullBox(&Box{filePosition, headerSize}, content[0:4])
|
fullBox := newFullBox(&Box{filePosition, headerSize}, content[0:4])
|
||||||
position := 4
|
position := 4
|
||||||
|
|
|
@ -148,8 +148,19 @@ const (
|
||||||
TrackHeaderBoxFlagTrackSizeIsAspectRatio uint32 = 0x00000008
|
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
|
// 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{
|
box := &TrackHeaderBox{
|
||||||
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
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.Width = NewFixed1616ByBytes(content[position : position+4])
|
||||||
box.Height = NewFixed1616ByBytes(content[position+4 : position+8])
|
box.Height = NewFixed1616ByBytes(content[position+4 : position+8])
|
||||||
|
|
||||||
return box
|
return box, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,19 @@ type VideoMediaHeaderBox struct {
|
||||||
CPColor []uint16
|
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
|
// 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{
|
box := &VideoMediaHeaderBox{
|
||||||
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
|
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+4:position+6]))
|
||||||
box.CPColor = append(box.CPColor, binary.BigEndian.Uint16(content[position+6:position+8]))
|
box.CPColor = append(box.CPColor, binary.BigEndian.Uint16(content[position+6:position+8]))
|
||||||
|
|
||||||
return box
|
return box, nil
|
||||||
}
|
}
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -1,3 +1,3 @@
|
||||||
module gitlab.com/martinr92/gomp4
|
module gitlab.com/martinr92/gomp4
|
||||||
|
|
||||||
go 1.15
|
go 1.18
|
||||||
|
|
Loading…
Add table
Reference in a new issue