// 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 []interface{} } // ParseDataReferenceBox creates a new data reference box struct based on bytes func ParseDataReferenceBox(filePosition uint64, headerSize uint32, content []byte) (*DataReferenceBox, 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(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 } // ParseDataEntryUrlBox creates a data entry URL box struct based on bytes func ParseDataEntryUrlBox(filePosition uint64, headerSize uint32, content []byte) *DataEntryUrlBox { box := &DataEntryUrlBox{ FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]), } box.Location, _ = ParseStringNullTerminated(content[4:]) return box } // 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 } // ParseDataEntryUrnBox creates a data entry URN box struct based on bytes func ParseDataEntryUrnBox(filePosition uint64, headerSize uint32, content []byte) *DataEntryUrnBox { 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 }