mp4/SampleToChunkBox.go

97 lines
3.6 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"
)
// SampleToChunkBox sample to chunk box struct
//
// 8.7.4 Sample To Chunk Box
//
// Box Type: stsc
// Container: Sample Table Box (stbl)
// Mandatory: Yes
// Quantity: Exactly one
//
// Samples within the media data are grouped into chunks. Chunks can be of different sizes, and the
// samples within a chunk can have different sizes. This table can be used to find the chunk that contains a
// sample, its position, and the associated sample description.
//
// The table is compactly coded. Each entry gives the index of the first chunk of a run of chunks with the
// same characteristics. By subtracting one entry here from the previous one, you can compute how many
// chunks are in this run. You can convert this to a sample count by multiplying by the appropriate
// samplesperchunk.
type SampleToChunkBox struct {
*FullBox
// is an integer that gives the number of entries in the following table
EntryCount uint32
Entries []SampleToChunkBoxEntry
}
type SampleToChunkBoxEntry struct {
// is an integer that gives the index of the first chunk in this run of chunks that share
// the same samplesperchunk and sampledescriptionindex; the index of the first chunk in a
// track has the value 1 (the first_chunk field in the first record of this box has the value 1,
// identifying that the first sample maps to the first chunk).
FirstChunk uint32
// is an integer that gives the number of samples in each of these chunks
SamplesPerChunk uint32
// is an integer that gives the index of the sample entry that
// describes the samples in this chunk. The index ranges from 1 to the number of sample entries in
// the Sample Description Box
SampleDescriptionIndex uint32
}
// BoxTypeSampleToChunk Sample To Chunk Box
const BoxTypeSampleToChunk = "stsc"
func init() {
BoxDefinitions = append(BoxDefinitions, BoxDefinition{
Type: BoxTypeSampleToChunk,
ParentTypes: []string{BoxTypeSampleTable},
Parser: ParseSampleToChunkBox,
})
}
// ParseSampleToChunkBox creates a new sample to chunk box struct based on bytes
func ParseSampleToChunkBox(parser *Parser, filePosition uint64, headerSize uint32, content []byte) (any, error) {
box := &SampleToChunkBox{
FullBox: newFullBox(&Box{filePosition, headerSize}, content[0:4]),
}
// parse entry counter
box.EntryCount = binary.BigEndian.Uint32(content[4:8])
// parse entries
position := 8
for i := 0; i < int(box.EntryCount); i++ {
newSampleEntry := SampleToChunkBoxEntry{
FirstChunk: binary.BigEndian.Uint32(content[position+(i*12) : position+4+(i*12)]),
SamplesPerChunk: binary.BigEndian.Uint32(content[position+4+(i*12) : position+8+(i*12)]),
SampleDescriptionIndex: binary.BigEndian.Uint32(content[position+8+(i*12) : position+12+(i*12)]),
}
box.Entries = append(box.Entries, newSampleEntry)
}
// validate entries amount
if len(box.Entries) != int(box.EntryCount) {
return box, fmt.Errorf("invalid amount of entries at %d; got %d but expected %d", filePosition, len(box.Entries), box.EntryCount)
}
return box, nil
}