// 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" // TrackFragmentHeaderBox Track Fragment Header // // 8.8.7 Track Fragment Header Box // Box Type: ‘tfhd’ // Container: Track Fragment Box ('traf') // Mandatory: Yes // Quantity: Exactly one // // Each movie fragment can add zero or more fragments to each track; and a track fragment can add zero // or more contiguous runs of samples. The track fragment header sets up information and defaults used // for those runs of samples. // // The base‐data‐offset, if explicitly provided, is a data offset that is identical to a chunk offset in the Chunk // Offset Box, i.e. applying to the complete file (e.g. starting with a file‐type box and movie box). In // circumstances when the complete file does not exist or its size is unknown, it may be impossible to use // an explicit base‐data‐offset; then, offsets need to be established relative to the movie fragment. type TrackFragmentHeaderBox struct { *FullBox TrackID uint32 // the base offset to use when calculating data offsets BaseDataOffset uint64 SampleDescriptionIndex uint32 DefaultSampleDuration uint32 DefaultSampleSize uint32 DefaultSampleFlags uint32 } // BoxTypeTrackFragmentHeader Track Fragment Header const BoxTypeTrackFragmentHeader = "tfhd" func init() { BoxDefinitions = append(BoxDefinitions, BoxDefinition{ Type: BoxTypeTrackFragmentHeader, ParentTypes: []string{BoxTypeTrackFragment}, Parser: ParseTrackFragmentHeaderBox, }) } const ( // TrackFragmentHeaderBoxFlagBaseDataOffsetPresent Base Offset Present Flag // // indicates the presence of the base‐data‐offset field. This // provides an explicit anchor for the data offsets in each track run (see below). If not provided and // if the default‐base‐is‐moof flag is not set, the base‐data‐offset for the first track in the movie // fragment is the position of the first byte of the enclosing Movie Fragment Box, and for second // and subsequent track fragments, the default is the end of the data defined by the preceding // track fragment. Fragments 'inheriting' their offset in this way must all use the same data‐ // reference (i.e., the data for these tracks must be in the same file) TrackFragmentHeaderBoxFlagBaseDataOffsetPresent uint32 = 0x00000001 // TrackFragmentHeaderBoxFlagSampleDescriptionIndexPresent Sample Description Index Present Flag // // indicates the presence of this field, which over‐rides, // in this fragment, the default set up in the Track Extends Box. TrackFragmentHeaderBoxFlagSampleDescriptionIndexPresent uint32 = 0x00000002 // TrackFragmentHeaderBoxFlagDefaultSampleDurationPresent Default Sample Duration Present Flag TrackFragmentHeaderBoxFlagDefaultSampleDurationPresent uint32 = 0x00000008 // TrackFragmentHeaderBoxFlagDefaultSampleSize Default Sample Size Present Flag TrackFragmentHeaderBoxFlagDefaultSampleSize uint32 = 0x00000010 // TrackFragmentHeaderBoxFlagDefaultSampleFlags Default Sample Flags Present Flag TrackFragmentHeaderBoxFlagDefaultSampleFlags uint32 = 0x00000020 // TODO: define other flags ) // ParseTrackFragmentHeaderBox creates a new track fragment header box struct func ParseTrackFragmentHeaderBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) { box := &TrackFragmentHeaderBox{FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4])} position := 4 // parse track ID box.TrackID = binary.BigEndian.Uint32(content[position : position+4]) position += 4 // TODO: check other flags return box, nil }