mp4/DataReferenceBox.go
2024-12-03 19:24:00 +01:00

169 lines
5.9 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2024 Martin Riedl
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package gomp4
import (
"encoding/binary"
"fmt"
)
// DataReferenceBox data reference box struct
//
// 8.7.2 Data Reference Box
//
// Box Types: dref
// Container: Data Information Box (dinf)
// Mandatory: Yes
// Quantity: Exactly one
//
// The data reference object contains a table of data references (normally URLs) that declare the
// location(s) of the media data used within the presentation. The data reference index in the sample
// description ties entries in this table to the samples in the track. A track may be split over several
// sources in this way.
//
// If the flag is set indicating that the data is in the same file as this box, then no string (not even an empty
// one) shall be supplied in the entry field.
//
// The entry_count in the DataReferenceBox shall be 1 or greater; each DataEntryBox within the
// DataReferenceBox shall be either a DataEntryUrnBox or a DataEntryUrlBox.
//
// When a file that has data entries with the flag set indicating that the media data is in the same file, is
// split into segments for transport, the value of this flag does not change, as the file is (logically)
// reassembled after the transport operation.
type DataReferenceBox struct {
*FullBox
// EntryCount is an integer that counts the actual entries
EntryCount uint32
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(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &DataReferenceBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
// parse entry counter
box.EntryCount = binary.BigEndian.Uint32(content[4:8])
// parse child boxes
var err error
box.ChildBoxes, err = box.parseChildBoxes(parser, BoxTypeDataReference, filePosition, content[8:])
if err != nil {
return box, err
}
// validate entries amount
if len(box.ChildBoxes) != int(box.EntryCount) {
return box, fmt.Errorf("invalid amount of boxes at %d", filePosition)
}
return box, err
}
// DataEntryUrlBox data entry URL box struct
//
// Box Types: url
// Container: Data Information Box (dref)
// Mandatory: Yes (at least one of url or urn shall be present)
// Quantity: One or more
type DataEntryUrlBox struct {
*FullBox
// Location is a URL, and is required in a URL entry and optional in a URN entry, where it gives a location to find
// the resource with the given name. If the
// selfcontained flag is set, the URL form is used and no string is present; the box terminates with
// the entryflags field. The URL type should be of a service that delivers a file (e.g. URLs of type file,
// http, ftp etc.), and which services ideally also permit random access. Relative URLs are
// permissible and are relative to the file containing the Movie Box that contains this data
// reference.
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(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, nil
}
// DataEntryUrnBox data entry URN box struct
//
// Box Types: urn
// Container: Data Information Box (dref)
// Mandatory: Yes (at least one of url or urn shall be present)
// Quantity: One or more
type DataEntryUrnBox struct {
*FullBox
// Name is a URN, and is required in a URN entry.
Name string
// Location is a URL, and is required in a URL entry and optional in a URN entry, where it gives a location to find
// the resource with the given name. If the
// selfcontained flag is set, the URL form is used and no string is present; the box terminates with
// the entryflags field. The URL type should be of a service that delivers a file (e.g. URLs of type file,
// http, ftp etc.), and which services ideally also permit random access. Relative URLs are
// permissible and are relative to the file containing the Movie Box that contains this data
// reference.
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(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &DataEntryUrnBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
name, endIndex := ParseStringNullTerminated(content[4:])
box.Name = name
box.Location, _ = ParseStringNullTerminated(content[4+endIndex:])
return box, nil
}