forked from bluenviron/gohlslib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmuxer_part.go
125 lines (102 loc) · 2.57 KB
/
muxer_part.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
125
package gohlslib
import (
"io"
"strconv"
"time"
"github.com/bluenviron/gohlslib/pkg/storage"
"github.com/bluenviron/mediacommon/pkg/formats/fmp4"
)
func partName(prefix string, id uint64) string {
return prefix + "_part" + strconv.FormatUint(id, 10) + ".mp4"
}
type muxerPart struct {
startDTS time.Duration
videoTrack *Track
audioTrack *Track
audioTimeScale uint32
id uint64
storage storage.Part
name string
isIndependent bool
videoSamples []*fmp4.PartSample
audioSamples []*fmp4.PartSample
finalDuration time.Duration
videoStartDTSFilled bool
videoStartDTS time.Duration
audioStartDTSFilled bool
audioStartDTS time.Duration
}
func newMuxerPart(
startDTS time.Duration,
videoTrack *Track,
audioTrack *Track,
audioTimeScale uint32,
prefix string,
id uint64,
storage storage.Part,
) *muxerPart {
p := &muxerPart{
startDTS: startDTS,
videoTrack: videoTrack,
audioTrack: audioTrack,
audioTimeScale: audioTimeScale,
id: id,
storage: storage,
name: partName(prefix, id),
}
if videoTrack == nil {
p.isIndependent = true
}
return p
}
func (p *muxerPart) getName() string {
return p.name
}
func (p *muxerPart) reader() (io.ReadCloser, error) {
return p.storage.Reader()
}
func (p *muxerPart) computeDuration(nextDTS time.Duration) time.Duration {
return nextDTS - p.startDTS
}
func (p *muxerPart) finalize(nextDTS time.Duration) error {
part := fmp4.Part{}
if p.videoSamples != nil {
part.Tracks = append(part.Tracks, &fmp4.PartTrack{
ID: 1,
BaseTime: durationGoToMp4(p.videoStartDTS, 90000),
Samples: p.videoSamples,
})
}
if p.audioSamples != nil {
part.Tracks = append(part.Tracks, &fmp4.PartTrack{
ID: 1 + len(part.Tracks),
BaseTime: durationGoToMp4(p.audioStartDTS, p.audioTimeScale),
Samples: p.audioSamples,
})
}
err := part.Marshal(p.storage.Writer())
if err != nil {
return err
}
p.finalDuration = p.computeDuration(nextDTS)
p.videoSamples = nil
p.audioSamples = nil
return nil
}
func (p *muxerPart) writeVideo(sample *augmentedVideoSample) {
if !p.videoStartDTSFilled {
p.videoStartDTSFilled = true
p.videoStartDTS = sample.dts
}
if !sample.IsNonSyncSample {
p.isIndependent = true
}
p.videoSamples = append(p.videoSamples, &sample.PartSample)
}
func (p *muxerPart) writeAudio(sample *augmentedAudioSample) {
if !p.audioStartDTSFilled {
p.audioStartDTSFilled = true
p.audioStartDTS = sample.dts
}
p.audioSamples = append(p.audioSamples, &sample.PartSample)
}