mp4/DecodingTimeToSampleBox.go

95 lines
3.5 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"
"fmt"
)
// TimeToSampleBox time to sample box struct
//
// 8.6.1.2 Decoding Time to Sample Box
//
// Box Type: stts
// Container: Sample Table Box (stbl)
// Mandatory: Yes
// Quantity: Exactly one
//
// This box contains a compact version of a table that allows indexing from decoding time to sample
// number. Other tables give sample sizes and pointers, from the sample number. Each entry in the table
// gives the number of consecutive samples with the same time delta, and the delta of those samples. By
// adding the deltas a complete timetosample map may be built.
//
// The Decoding Time to Sample Box contains decode time delta's: DT(n+1) = DT(n) + STTS(n) where
// STTS(n) is the (uncompressed) table entry for sample n.
//
// The sample entries are ordered by decoding time stamps; therefore the deltas are all nonnegative.
//
// The DT axis has a zero origin; DT(i) = SUM(for j=0 to i1 of delta(j)), and the sum of all deltas gives the
// length of the media in the track (not mapped to the overall timescale, and not considering any edit list).
//
// The Edit List Box provides the initial CT value if it is nonempty (nonzero).
type TimeToSampleBox struct {
*FullBox
// is an integer that gives the number of entries in the following table.
EntryCount uint32
Entries []TimeToSampleBoxEntry
}
type TimeToSampleBoxEntry struct {
// s an integer that counts the number of consecutive samples that have the given duration.
SampleCount uint32
// is an integer that gives the delta of these samples in the timescale of the media.
SampleDelta uint32
}
// BoxTypeDecodingTimeToSample Decoding Time To Sample Box
const BoxTypeDecodingTimeToSample = "stts"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeDecodingTimeToSample,
ParentTypes: []string{BoxTypeSampleTable},
Parser: ParseDecodingTimeToSampleBox,
})
}
// ParseDecodingTimeToSampleBox creates a new decoding time to sample box struct based on bytes
func ParseDecodingTimeToSampleBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &TimeToSampleBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
// parse entry counter
box.EntryCount = binary.BigEndian.Uint32(content[4:8])
// parse sample entries
position := 8
for i := 0; i < int(box.EntryCount); i++ {
newSampleEntry := TimeToSampleBoxEntry{
SampleCount: binary.BigEndian.Uint32(content[position+(i*8) : position+4+(i*8)]),
SampleDelta: binary.BigEndian.Uint32(content[position+4+(i*8) : position+8+(i*8)]),
}
box.Entries = append(box.Entries, newSampleEntry)
}
// validate entries amount
if len(box.Entries) != int(box.EntryCount) {
return box, fmt.Errorf("invalid amount of sample entries at %d; got %d but expected %d", filePosition, len(box.Entries), box.EntryCount)
}
return box, nil
}