mp4/MovieHeaderBox.go

111 lines
4.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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"
)
// MovieHeaderBox Movie Header Box struct
//
// 8.2.2 Movie Header Box
// Box Type: mvhd
// Container: Movie Box (moov)
// Mandatory: Yes
// Quantity: Exactly one
//
// This box defines overall information which is mediaindependent, and relevant to the entire
// presentation considered as a whole.
type MovieHeaderBox struct {
*FullBox
// is an integer that declares the creation time of the presentation (in seconds
// since midnight, Jan. 1, 1904, in UTC time)
CreationTimeV0 time.Time
// is an integer that declares the creation time of the presentation (in seconds
// since midnight, Jan. 1, 1904, in UTC time)
CreationTimeV1 time.Time
// is an integer that declares the most recent time the presentation 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 presentation was
// modified (in seconds since midnight, Jan. 1, 1904, in UTC time)
ModificationTimeV1 time.Time
// is an integer that specifies the timescale for the entire presentation; 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 length of the presentation (in the indicated timescale). This
// property is derived from the presentations tracks: the value of this field corresponds to the
// duration of the longest track in the presentation. If the duration cannot be determined then
// duration is set to all 1s.
DurationV0 uint32
// is an integer that declares length of the presentation (in the indicated timescale). This
// property is derived from the presentations tracks: the value of this field corresponds to the
// duration of the longest track in the presentation. If the duration cannot be determined then
// duration is set to all 1s.
DurationV1 uint64
// is a fixed point 16.16 number that indicates the preferred rate to play the presentation; 1.0
// (0x00010000) is normal forward playback
Rate Fixed1616
// is a fixed point 8.8 number that indicates the preferred playback volume. 1.0 (0x0100) is
// full volume.
Volume Fixed88
// provides a transformation matrix for the video; (u,v,w) are restricted here to (0,0,1), hex
// values (0,0,0x40000000).
Matrix []int32
// is a nonzero integer that indicates a value to use for the track ID of the next track
// to be added to this presentation. Zero is not a valid track ID value. The value of
// next_track_ID shall be larger than the largest trackID in use. If this value is equal to all 1s
// (32bit maxint), and a new media track is to be added, then a search must be made in the file for
// an unused track identifier.
NextTrackID uint32
}
// ParseMovieHeaderBox creates a new Movie Header Box struct
func ParseMovieHeaderBox(filePosition uint64, headerSize uint32, content []byte) *MovieHeaderBox {
box := &MovieHeaderBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
position := 4
if box.Version == 1 {
box.CreationTimeV1 = since1904ToTime(int64(binary.BigEndian.Uint64(content[4:12])))
box.ModificationTimeV1 = since1904ToTime(int64(binary.BigEndian.Uint64(content[12:20])))
box.Timescale = binary.BigEndian.Uint32(content[20:24])
box.DurationV1 = binary.BigEndian.Uint64(content[24:32])
position += 28
} else { // version == 0
box.CreationTimeV0 = since1904ToTime(int64(binary.BigEndian.Uint32(content[4:8])))
box.ModificationTimeV0 = since1904ToTime(int64(binary.BigEndian.Uint32(content[8:12])))
box.Timescale = binary.BigEndian.Uint32(content[12:16])
box.DurationV0 = binary.BigEndian.Uint32(content[16:20])
position += 16
}
box.Rate = NewFixed1616ByBytes(content[position : position+4])
box.Volume = NewFixed88ByBytes(content[position+4 : position+6])
position += 4 + 2 + 2 + 8 // 4 bytes for rate, 2 bytes for volume, 2 bytes reserved and 8 bytes reserved
for i := 0; i < 9; i++ {
box.Matrix = append(box.Matrix, int32(binary.BigEndian.Uint32(content[position:position+4])))
position += 4
}
// skip 6*32 bit "pre-defined"
position += 6 * 4
box.NextTrackID = binary.BigEndian.Uint32(content[position : position+4])
return box
}