97 lines
3.6 KiB
Go
97 lines
3.6 KiB
Go
// 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
|
||
// samples‐per‐chunk.
|
||
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 samples‐per‐chunk and sample‐description‐index; 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
|
||
}
|