-
Notifications
You must be signed in to change notification settings - Fork 79
/
stblcrop.go
124 lines (113 loc) · 3.29 KB
/
stblcrop.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package main
import (
"fmt"
"sort"
"github.com/edgeware/mp4ff/mp4"
)
func cropStblChildren(traks []*mp4.TrakBox, trakOuts map[uint32]*trakOut) (err error) {
for _, trak := range traks {
trakID := trak.Tkhd.TrackID
stbl := trak.Mdia.Minf.Stbl
to := trakOuts[trakID]
for _, ch := range stbl.Children {
switch ch.Type() {
case "stts":
cropStts(ch.(*mp4.SttsBox), to.lastSampleNr)
case "stss":
cropStss(ch.(*mp4.StssBox), to.lastSampleNr)
case "ctts":
cropCtts(ch.(*mp4.CttsBox), to.lastSampleNr)
case "stsc":
err = cropStsc(ch.(*mp4.StscBox), to.lastSampleNr)
case "stsz":
cropStsz(ch.(*mp4.StszBox), to.lastSampleNr)
case "sdtp":
cropSdtp(ch.(*mp4.SdtpBox), to.lastSampleNr)
case "stco":
updateStco(ch.(*mp4.StcoBox), to.chunkOffsets)
case "co64":
updateCo64(ch.(*mp4.Co64Box), to.chunkOffsets)
}
}
}
return err
}
func cropStts(b *mp4.SttsBox, lastSampleNr uint32) {
var countedSamples uint32 = 0
var nrEntries int
for i := 0; i < len(b.SampleCount); i++ {
if countedSamples+b.SampleCount[i] >= lastSampleNr {
countedSamples += b.SampleCount[i]
nrEntries = i + 1
continue
}
// Now 0 or more remains in a last entry
nrEntries = i
remaining := lastSampleNr - countedSamples
if remaining > 0 {
b.SampleCount[i] = remaining
nrEntries = i + 1
}
break
}
b.SampleCount = b.SampleCount[:nrEntries]
b.SampleTimeDelta = b.SampleTimeDelta[:nrEntries]
}
func cropStss(b *mp4.StssBox, lastSampleNr uint32) {
nrEntries := b.EntryCount()
nrEntriesToKeep := 0
for i := uint32(0); i < nrEntries; i++ {
if b.SampleNumber[i] > lastSampleNr {
break
}
nrEntriesToKeep++
}
b.SampleNumber = b.SampleNumber[:nrEntriesToKeep]
}
func cropCtts(b *mp4.CttsBox, lastSampleNr uint32) {
lastIdx := sort.Search(len(b.EndSampleNr), func(i int) bool { return b.EndSampleNr[i] >= lastSampleNr })
// Finally cut down the endSampleNr for this index
b.EndSampleNr[lastIdx] = lastSampleNr
b.EndSampleNr = b.EndSampleNr[:lastIdx+1]
b.SampleOffset = b.SampleOffset[:lastIdx]
}
func cropStsc(b *mp4.StscBox, lastSampleNr uint32) error {
entryIdx := b.FindEntryNrForSampleNr(lastSampleNr, 0)
lastEntry := b.Entries[entryIdx]
b.Entries = b.Entries[:entryIdx+1]
if len(b.SampleDescriptionID) > 0 {
b.Entries = b.Entries[:entryIdx+1]
}
samplesLeft := lastSampleNr - lastEntry.FirstSampleNr + 1
nrChunksInLast := samplesLeft / lastEntry.SamplesPerChunk
nrLeft := samplesLeft - nrChunksInLast*lastEntry.SamplesPerChunk
if nrLeft > 0 {
sdid := b.GetSampleDescriptionID(int(lastEntry.FirstChunk))
err := b.AddEntry(lastEntry.FirstChunk+nrChunksInLast, nrLeft, sdid)
if err != nil {
return fmt.Errorf("stsc AddEntry: %w", err)
}
}
return nil
}
func cropStsz(b *mp4.StszBox, lastSampleNr uint32) {
if b.SampleUniformSize == 0 {
b.SampleSize = b.SampleSize[:lastSampleNr]
}
b.SampleNumber = lastSampleNr
}
func cropSdtp(b *mp4.SdtpBox, lastSampleNr uint32) {
if len(b.Entries) > int(lastSampleNr) {
b.Entries = b.Entries[:lastSampleNr]
}
}
func updateStco(b *mp4.StcoBox, offsets []uint64) {
b.ChunkOffset = make([]uint32, len(offsets))
for i := range offsets {
b.ChunkOffset[i] = uint32(offsets[i])
}
}
func updateCo64(b *mp4.Co64Box, offsets []uint64) {
b.ChunkOffset = make([]uint64, len(offsets))
_ = copy(b.ChunkOffset, offsets)
}