Skip to content

Commit

Permalink
fix: implement expectedSize for many boxes
Browse files Browse the repository at this point in the history
  • Loading branch information
eric committed Jan 15, 2025
1 parent 45c6631 commit 611dbb4
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 61 deletions.
23 changes: 16 additions & 7 deletions mp4/ctts.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,19 @@ func DecodeCttsSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, err
Flags: versionAndFlags & flagsMask,
}

if hdr.Size != b.expectedSize(entryCount) {
return nil, fmt.Errorf("ctts: expected size %d, got %d", b.expectedSize(entryCount), hdr.Size)
}

b.EndSampleNr = make([]uint32, entryCount+1)
b.SampleOffset = make([]int32, entryCount)

var endSampleNr uint32 = 0
b.EndSampleNr = append(b.EndSampleNr, endSampleNr)
b.EndSampleNr[0] = endSampleNr
for i := 0; i < int(entryCount); i++ {
endSampleNr += sr.ReadUint32() // Adding sampleCount
b.EndSampleNr = append(b.EndSampleNr, endSampleNr)
b.SampleOffset = append(b.SampleOffset, sr.ReadInt32())
if sr.AccError() != nil {
return nil, sr.AccError()
}
b.EndSampleNr[i+1] = endSampleNr
b.SampleOffset[i] = sr.ReadInt32()
}
return b, sr.AccError()
}
Expand All @@ -59,7 +63,12 @@ func (b *CttsBox) Type() string {

// Size - calculated size of box
func (b *CttsBox) Size() uint64 {
return uint64(boxHeaderSize + 8 + len(b.SampleOffset)*8)
return b.expectedSize(uint32(len(b.SampleOffset)))
}

// expectedSize - calculate size for a given entry count
func (b *CttsBox) expectedSize(entryCount uint32) uint64 {
return uint64(boxHeaderSize + 8 + int(entryCount)*8) // 8 = version + flags + entryCount, 8 = sampleCount(4) + sampleOffset(4)
}

// Encode - write box to w
Expand Down
41 changes: 21 additions & 20 deletions mp4/elst.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,29 +43,25 @@ func DecodeElstSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, err
Flags: versionAndFlags & flagsMask,
}

if hdr.Size != b.expectedSize(entryCount) {
return nil, fmt.Errorf("elst: expected size %d, got %d", b.expectedSize(entryCount), hdr.Size)
}

b.Entries = make([]ElstEntry, entryCount)

if version == 1 {
for i := 0; i < int(entryCount); i++ {
b.Entries = append(b.Entries, ElstEntry{
SegmentDuration: sr.ReadUint64(),
MediaTime: sr.ReadInt64(),
MediaRateInteger: sr.ReadInt16(),
MediaRateFraction: sr.ReadInt16(),
})
if sr.AccError() != nil {
return nil, sr.AccError()
}
b.Entries[i].SegmentDuration = sr.ReadUint64()
b.Entries[i].MediaTime = sr.ReadInt64()
b.Entries[i].MediaRateInteger = sr.ReadInt16()
b.Entries[i].MediaRateFraction = sr.ReadInt16()
}
} else if version == 0 {
for i := 0; i < int(entryCount); i++ {
b.Entries = append(b.Entries, ElstEntry{
SegmentDuration: uint64(sr.ReadUint32()),
MediaTime: int64(sr.ReadInt32()),
MediaRateInteger: sr.ReadInt16(),
MediaRateFraction: sr.ReadInt16(),
})
if sr.AccError() != nil {
return nil, sr.AccError()
}
b.Entries[i].SegmentDuration = uint64(sr.ReadUint32())
b.Entries[i].MediaTime = int64(sr.ReadInt32())
b.Entries[i].MediaRateInteger = sr.ReadInt16()
b.Entries[i].MediaRateFraction = sr.ReadInt16()
}
} else {
return nil, fmt.Errorf("unknown version for elst")
Expand All @@ -80,10 +76,15 @@ func (b *ElstBox) Type() string {

// Size - calculated size of box
func (b *ElstBox) Size() uint64 {
return b.expectedSize(uint32(len(b.Entries)))
}

// expectedSize - calculate size for a given entry count
func (b *ElstBox) expectedSize(entryCount uint32) uint64 {
if b.Version == 1 {
return uint64(boxHeaderSize + 8 + len(b.Entries)*20)
return uint64(boxHeaderSize + 8 + int(entryCount)*20) // 8 = version + flags + entryCount, 20 = uint64 + int64 + 2*int16
}
return uint64(boxHeaderSize + 8 + len(b.Entries)*12) // m.Version == 0
return uint64(boxHeaderSize + 8 + int(entryCount)*12) // 8 = version + flags + entryCount, 12 = uint32 + int32 + 2*int16
}

// Encode - write box to w
Expand Down
19 changes: 15 additions & 4 deletions mp4/saio.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package mp4

import (
"fmt"
"io"

"github.com/Eyevinn/mp4ff/bits"
Expand Down Expand Up @@ -50,6 +51,11 @@ func DecodeSaioSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, err
b.AuxInfoTypeParameter = sr.ReadUint32()
}
entryCount := sr.ReadUint32()

if hdr.Size != b.expectedSize(entryCount) {
return nil, fmt.Errorf("saio: expected size %d, got %d", b.expectedSize(entryCount), hdr.Size)
}

if version == 0 {
for i := uint32(0); i < entryCount; i++ {
b.Offset = append(b.Offset, int64(sr.ReadInt32()))
Expand All @@ -75,14 +81,19 @@ func (b *SaioBox) Type() string {

// Size - return calculated size
func (b *SaioBox) Size() uint64 {
size := uint64(boxHeaderSize) + 8
return b.expectedSize(uint32(len(b.Offset)))
}

// expectedSize - calculate size for a given entry count
func (b *SaioBox) expectedSize(entryCount uint32) uint64 {
size := uint64(boxHeaderSize + 8) // 8 = version + flags + entryCount
if b.Flags&0x01 != 0 {
size += 8
size += 8 // 4 for AuxInfoType + 4 for AuxInfoTypeParameter
}
if b.Version == 0 {
size += 4 * uint64(len(b.Offset))
size += 4 * uint64(entryCount) // 4 bytes per offset for version 0
} else {
size += 8 * uint64(len(b.Offset))
size += 8 * uint64(entryCount) // 8 bytes per offset for version 1
}
return size
}
Expand Down
22 changes: 16 additions & 6 deletions mp4/sbgp.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ func DecodeSbgpSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, err
b.GroupingTypeParameter = sr.ReadUint32()
}
entryCount := int(sr.ReadUint32())

if hdr.Size != b.expectedSize(uint32(entryCount)) {
return nil, fmt.Errorf("sbgp: expected size %d, got %d", b.expectedSize(uint32(entryCount)), hdr.Size)
}

for i := 0; i < entryCount; i++ {
b.SampleCounts = append(b.SampleCounts, sr.ReadUint32())
b.GroupDescriptionIndices = append(b.GroupDescriptionIndices, sr.ReadUint32())
Expand All @@ -62,12 +67,17 @@ func (b *SbgpBox) Type() string {

// Size - return calculated size
func (b *SbgpBox) Size() uint64 {
// Version + Flags:4
// GroupingType: 4
// (v1) GroupingTypeParameter: 4
// EntryCount: 4
// SampleCount + GroupDescriptionIndex : 8
return uint64(boxHeaderSize + 12 + 4*int(b.Version) + 8*len(b.GroupDescriptionIndices))
return b.expectedSize(uint32(len(b.GroupDescriptionIndices)))
}

// expectedSize - calculate size for a given entry count
func (b *SbgpBox) expectedSize(entryCount uint32) uint64 {
size := uint64(boxHeaderSize + 12) // 12 = version + flags(4) + groupingType(4) + entryCount(4)
if b.Version == 1 {
size += 4 // GroupingTypeParameter
}
size += 8 * uint64(entryCount) // 8 = SampleCount(4) + GroupDescriptionIndex(4)
return size
}

// Encode - write box to w
Expand Down
17 changes: 12 additions & 5 deletions mp4/stco.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ func DecodeStcoSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, err
Flags: versionAndFlags & flagsMask,
}

if hdr.Size != b.expectedSize(entryCount) {
return nil, fmt.Errorf("stco: expected size %d, got %d", b.expectedSize(entryCount), hdr.Size)
}

b.ChunkOffset = make([]uint32, entryCount)
for i := 0; i < int(entryCount); i++ {
b.ChunkOffset = append(b.ChunkOffset, sr.ReadUint32())
if sr.AccError() != nil {
return nil, sr.AccError()
}
b.ChunkOffset[i] = sr.ReadUint32()
}
return b, sr.AccError()
}
Expand All @@ -55,7 +57,12 @@ func (b *StcoBox) Type() string {

// Size - box-specific size
func (b *StcoBox) Size() uint64 {
return uint64(boxHeaderSize + 8 + len(b.ChunkOffset)*4)
return b.expectedSize(uint32(len(b.ChunkOffset)))
}

// expectedSize - calculate size for a given entry count
func (b *StcoBox) expectedSize(entryCount uint32) uint64 {
return uint64(boxHeaderSize + 8 + int(entryCount)*4) // 8 = version + flags(4) + entryCount(4), 4 bytes per offset
}

// Encode - write box to w
Expand Down
2 changes: 1 addition & 1 deletion mp4/stsc.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ func DecodeStscSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, err
b := StscBox{
Version: byte(versionAndFlags >> 24),
Flags: versionAndFlags & flagsMask,
Entries: make([]StscEntry, entryCount),
}

var accSampleNr uint32 = 1

for i := 0; i < int(entryCount); i++ {
b.Entries = append(b.Entries, StscEntry{})
b.Entries[i].FirstChunk = sr.ReadUint32()
b.Entries[i].SamplesPerChunk = sr.ReadUint32()
if i > 0 {
Expand Down
20 changes: 14 additions & 6 deletions mp4/stsz.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,15 @@ func DecodeStszSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, err
SampleUniformSize: sr.ReadUint32(),
SampleNumber: sr.ReadUint32(),
}

if hdr.Size != b.expectedSize() {
return nil, fmt.Errorf("stsz: expected size %d, got %d", b.expectedSize(), hdr.Size)
}

if b.SampleUniformSize == 0 {
b.SampleSize = make([]uint32, b.SampleNumber)
for i := 0; i < int(b.SampleNumber); i++ {
b.SampleSize = append(b.SampleSize, sr.ReadUint32())
if sr.AccError() != nil {
return nil, sr.AccError()
}
b.SampleSize[i] = sr.ReadUint32()
}
}
return &b, sr.AccError()
Expand All @@ -61,10 +64,15 @@ func (b *StszBox) Type() string {

// Size - box-specific size
func (b *StszBox) Size() uint64 {
return b.expectedSize()
}

// expectedSize - calculate size based on SampleUniformSize and SampleNumber
func (b *StszBox) expectedSize() uint64 {
if b.SampleUniformSize > 0 {
return uint64(boxHeaderSize + 12)
return uint64(boxHeaderSize + 12) // 12 = version + flags(4) + uniformSize(4) + sampleNumber(4)
}
return uint64(boxHeaderSize + 12 + b.SampleNumber*4)
return uint64(boxHeaderSize + 12 + b.SampleNumber*4) // 4 bytes per sample size
}

// Encode - write box to w
Expand Down
22 changes: 16 additions & 6 deletions mp4/stts.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,21 @@ func DecodeStts(hdr BoxHeader, startPos uint64, r io.Reader) (Box, error) {
func DecodeSttsSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, error) {
versionAndFlags := sr.ReadUint32()
entryCount := sr.ReadUint32()

b := SttsBox{
Version: byte(versionAndFlags >> 24),
Flags: versionAndFlags & flagsMask,
}

if hdr.Size != b.expectedSize(entryCount) {
return nil, fmt.Errorf("stts: expected size %d, got %d", b.expectedSize(entryCount), hdr.Size)
}

b.SampleCount = make([]uint32, entryCount)
b.SampleTimeDelta = make([]uint32, entryCount)
for i := 0; i < int(entryCount); i++ {
b.SampleCount = append(b.SampleCount, sr.ReadUint32())
b.SampleTimeDelta = append(b.SampleTimeDelta, sr.ReadUint32())
if sr.AccError() != nil {
return nil, sr.AccError()
}
b.SampleCount[i] = sr.ReadUint32()
b.SampleTimeDelta[i] = sr.ReadUint32()
}
return &b, nil
}
Expand All @@ -56,7 +61,12 @@ func (b *SttsBox) Type() string {

// Size - return calculated size
func (b *SttsBox) Size() uint64 {
return uint64(boxHeaderSize + 8 + len(b.SampleCount)*8)
return b.expectedSize(uint32(len(b.SampleCount)))
}

// expectedSize - calculate size for a given entry count
func (b *SttsBox) expectedSize(entryCount uint32) uint64 {
return uint64(boxHeaderSize + 8 + int(entryCount)*8) // 8 = version + flags(4) + entryCount(4), 8 = sampleCount(4) + sampleTimeDelta(4)
}

// GetTimeCode - return the timecode (duration since the beginning of the media)
Expand Down
14 changes: 8 additions & 6 deletions mp4/trun.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ func DecodeTrun(hdr BoxHeader, startPos uint64, r io.Reader) (Box, error) {
return nil, fmt.Errorf("trun: expected size %d, got %d", t.expectedSize(sampleCount), hdr.Size)
}

t.Samples = make([]Sample, 0, sampleCount)

if t.HasDataOffset() {
t.DataOffset = s.ReadInt32()
}
Expand Down Expand Up @@ -72,9 +74,6 @@ func DecodeTrun(hdr BoxHeader, startPos uint64, r io.Reader) (Box, error) {
cto = s.ReadInt32()
}
t.Samples = append(t.Samples, Sample{flags, dur, size, cto})
if s.AccError() != nil {
return nil, s.AccError()
}
}

return t, nil
Expand All @@ -89,6 +88,12 @@ func DecodeTrunSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, err
Flags: versionAndFlags & flagsMask,
}

if hdr.Size != t.expectedSize(sampleCount) {
return nil, fmt.Errorf("trun: expected size %d, got %d", t.expectedSize(sampleCount), hdr.Size)
}

t.Samples = make([]Sample, 0, sampleCount)

if t.HasDataOffset() {
t.DataOffset = sr.ReadInt32()
}
Expand Down Expand Up @@ -116,9 +121,6 @@ func DecodeTrunSR(hdr BoxHeader, startPos uint64, sr bits.SliceReader) (Box, err
cto = sr.ReadInt32()
}
t.Samples = append(t.Samples, Sample{flags, dur, size, cto})
if sr.AccError() != nil {
return nil, sr.AccError()
}
}

return t, sr.AccError()
Expand Down

0 comments on commit 611dbb4

Please sign in to comment.