// 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" "time" ) // MediaHeaderBox media header box struct // // 8.4.2 Media Header Box // // Box Type: ‘mdhd’ // Container: Media Box (‘mdia’) // Mandatory: Yes // Quantity: Exactly one // // The media header declares overall information that is media‐independent, and relevant to // characteristics of the media in a track. type MediaHeaderBox struct { *FullBox // is an integer that declares the creation time of the media in this track (in // seconds since midnight, Jan. 1, 1904, in UTC time). CreationTimeV0 time.Time // is an integer that declares the creation time of the media in this track (in // seconds since midnight, Jan. 1, 1904, in UTC time). CreationTimeV1 time.Time // is an integer that declares the most recent time the media in this track was // modified (in seconds since midnight, Jan. 1, 1904, in UTC time). ModificationTimeV0 time.Time // is an integer that declares the most recent time the media in this track was // modified (in seconds since midnight, Jan. 1, 1904, in UTC time). ModificationTimeV1 time.Time // is an integer that specifies the time‐scale for this media; this is the number of time // units that pass in one second. For example, a time coordinate system that measures time in // sixtieths of a second has a time scale of 60. Timescale uint32 // is an integer that declares the duration of this media (in the scale of the timescale). If the // duration cannot be determined then duration is set to all 1s. DurationV0 uint32 // is an integer that declares the duration of this media (in the scale of the timescale). If the // duration cannot be determined then duration is set to all 1s. DurationV1 uint64 // TODO: parse language language } // ParseMediaHeaderBox creates a new Media Header Box struct func ParseMediaHeaderBox(filePosition uint64, headerSize uint32, content []byte) *MediaHeaderBox { box := &MediaHeaderBox{ FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]), } position := 4 if box.Version == 1 { box.CreationTimeV1 = since1904ToTime(int64(binary.BigEndian.Uint64(content[position : position+8]))) box.ModificationTimeV1 = since1904ToTime(int64(binary.BigEndian.Uint64(content[position+8 : position+16]))) box.Timescale = binary.BigEndian.Uint32(content[position+16 : position+20]) box.DurationV1 = binary.BigEndian.Uint64(content[position+20 : position+28]) position += 28 } else { // version == 0 box.CreationTimeV0 = since1904ToTime(int64(binary.BigEndian.Uint32(content[position : position+4]))) box.ModificationTimeV0 = since1904ToTime(int64(binary.BigEndian.Uint32(content[position+4 : position+8]))) box.Timescale = binary.BigEndian.Uint32(content[position+8 : position+12]) box.DurationV0 = binary.BigEndian.Uint32(content[position+12 : position+16]) position += 16 } // TODO: parse language language return box }