mirror of
https://github.com/bluenviron/mediamtx
synced 2025-02-26 16:40:30 +00:00
106 lines
2.1 KiB
Go
106 lines
2.1 KiB
Go
package playback
|
|
|
|
import (
|
|
"io"
|
|
|
|
"github.com/bluenviron/mediacommon/pkg/formats/fmp4"
|
|
"github.com/bluenviron/mediacommon/pkg/formats/pmp4"
|
|
)
|
|
|
|
type muxerMP4Track struct {
|
|
pmp4.Track
|
|
lastDTS int64
|
|
}
|
|
|
|
func findTrackMP4(tracks []*muxerMP4Track, id int) *muxerMP4Track {
|
|
for _, track := range tracks {
|
|
if track.ID == id {
|
|
return track
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type muxerMP4 struct {
|
|
w io.Writer
|
|
|
|
tracks []*muxerMP4Track
|
|
curTrack *muxerMP4Track
|
|
}
|
|
|
|
func (w *muxerMP4) writeInit(init *fmp4.Init) {
|
|
w.tracks = make([]*muxerMP4Track, len(init.Tracks))
|
|
|
|
for i, track := range init.Tracks {
|
|
w.tracks[i] = &muxerMP4Track{
|
|
Track: pmp4.Track{
|
|
ID: track.ID,
|
|
TimeScale: track.TimeScale,
|
|
Codec: track.Codec,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
func (w *muxerMP4) setTrack(trackID int) {
|
|
w.curTrack = findTrackMP4(w.tracks, trackID)
|
|
}
|
|
|
|
func (w *muxerMP4) writeSample(
|
|
dts int64,
|
|
ptsOffset int32,
|
|
isNonSyncSample bool,
|
|
payloadSize uint32,
|
|
getPayload func() ([]byte, error),
|
|
) error {
|
|
// remove GOPs before the GOP of the first frame
|
|
if (dts < 0 || (dts >= 0 && w.curTrack.lastDTS < 0)) && !isNonSyncSample {
|
|
w.curTrack.Samples = nil
|
|
}
|
|
|
|
if w.curTrack.Samples == nil {
|
|
w.curTrack.TimeOffset = int32(dts)
|
|
} else {
|
|
diff := dts - w.curTrack.lastDTS
|
|
if diff < 0 {
|
|
diff = 0
|
|
}
|
|
w.curTrack.Samples[len(w.curTrack.Samples)-1].Duration = uint32(diff)
|
|
}
|
|
|
|
// prevent warning "edit list: 1 Missing key frame while searching for timestamp: 0"
|
|
if !isNonSyncSample {
|
|
ptsOffset = 0
|
|
}
|
|
|
|
w.curTrack.Samples = append(w.curTrack.Samples, &pmp4.Sample{
|
|
PTSOffset: ptsOffset,
|
|
IsNonSyncSample: isNonSyncSample,
|
|
PayloadSize: payloadSize,
|
|
GetPayload: getPayload,
|
|
})
|
|
w.curTrack.lastDTS = dts
|
|
|
|
return nil
|
|
}
|
|
|
|
func (w *muxerMP4) writeFinalDTS(dts int64) {
|
|
diff := dts - w.curTrack.lastDTS
|
|
if diff < 0 {
|
|
diff = 0
|
|
}
|
|
w.curTrack.Samples[len(w.curTrack.Samples)-1].Duration = uint32(diff)
|
|
}
|
|
|
|
func (w *muxerMP4) flush() error {
|
|
h := pmp4.Presentation{
|
|
Tracks: make([]*pmp4.Track, len(w.tracks)),
|
|
}
|
|
|
|
for i, track := range w.tracks {
|
|
h.Tracks[i] = &track.Track
|
|
}
|
|
|
|
return h.Marshal(w.w)
|
|
}
|