169 lines
5.9 KiB
Go
169 lines
5.9 KiB
Go
// 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
|
||
// self‐contained flag is set, the URL form is used and no string is present; the box terminates with
|
||
// the entry‐flags 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
|
||
// self‐contained flag is set, the URL form is used and no string is present; the box terminates with
|
||
// the entry‐flags 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
|
||
}
|