feat: new data reference box
This commit is contained in:
parent
65eb9ae5c1
commit
00105f5142
6 changed files with 153 additions and 5 deletions
6
Box.go
6
Box.go
|
@ -42,6 +42,12 @@ const (
|
||||||
BoxTypeMediaInformation = "minf"
|
BoxTypeMediaInformation = "minf"
|
||||||
// BoxTypeDataInformation Data Information Box
|
// BoxTypeDataInformation Data Information Box
|
||||||
BoxTypeDataInformation = "dinf"
|
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 Movie Fragment Box
|
||||||
BoxTypeMovieFragment = "moof"
|
BoxTypeMovieFragment = "moof"
|
||||||
// BoxTypeMovieFragmentHeader Movie Fragment Header Box
|
// BoxTypeMovieFragmentHeader Movie Fragment Header Box
|
||||||
|
|
136
DataReferenceBox.go
Normal file
136
DataReferenceBox.go
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
// 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
|
||||||
|
}
|
|
@ -65,7 +65,7 @@ func ParseHandlerReferenceBox(filePosition uint64, headerSize uint32, content []
|
||||||
position += 3 * 4
|
position += 3 * 4
|
||||||
|
|
||||||
// parse name
|
// parse name
|
||||||
box.Name = ParseStringNullTerminated(content[position:])
|
box.Name, _ = ParseStringNullTerminated(content[position:])
|
||||||
|
|
||||||
return box
|
return box
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,12 @@ func parseNextBox(reader io.Reader, filePosition uint64) (box interface{}, endPo
|
||||||
box, err = ParseMediaInformationBox(filePosition, boxHeaderSize, boxContentBytes)
|
box, err = ParseMediaInformationBox(filePosition, boxHeaderSize, boxContentBytes)
|
||||||
case BoxTypeDataInformation:
|
case BoxTypeDataInformation:
|
||||||
box, err = ParseDataInformationBox(filePosition, boxHeaderSize, boxContentBytes)
|
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:
|
case BoxTypeMovieFragment:
|
||||||
box, err = ParseMovieFragmentBox(filePosition, boxHeaderSize, boxContentBytes)
|
box, err = ParseMovieFragmentBox(filePosition, boxHeaderSize, boxContentBytes)
|
||||||
case BoxTypeMovieFragmentHeader:
|
case BoxTypeMovieFragmentHeader:
|
||||||
|
|
|
@ -45,7 +45,7 @@ Implementation progress
|
||||||
| 8.6.5 Edit Box | edts | - |
|
| 8.6.5 Edit Box | edts | - |
|
||||||
| 8.6.6 Edit List Box | elst | - |
|
| 8.6.6 Edit List Box | elst | - |
|
||||||
| 8.7.1 Data Information Box | dinf | 100% |
|
| 8.7.1 Data Information Box | dinf | 100% |
|
||||||
| 8.7.2 Data Reference Box | dref, url, urn | - |
|
| 8.7.2 Data Reference Box | dref, url, urn | 100% |
|
||||||
| 8.7.3 Sample Size Boxes | stsz, stz2 | - |
|
| 8.7.3 Sample Size Boxes | stsz, stz2 | - |
|
||||||
| 8.7.4 Sample To Chunk Box | stsc | - |
|
| 8.7.4 Sample To Chunk Box | stsc | - |
|
||||||
| 8.7.5 Chunk Offset Box | stco, co64 | - |
|
| 8.7.5 Chunk Offset Box | stco, co64 | - |
|
||||||
|
|
|
@ -18,11 +18,11 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ParseStringNullTerminated(b []byte) string {
|
func ParseStringNullTerminated(b []byte) (string, int) {
|
||||||
endIndex := bytes.IndexByte(b, '\x00')
|
endIndex := bytes.IndexByte(b, '\x00')
|
||||||
if endIndex == -1 {
|
if endIndex == -1 {
|
||||||
return ""
|
return "", -1
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(b[:endIndex])
|
return string(b[:endIndex]), endIndex
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue