Skip to content

Commit

Permalink
playback: support serving tracks with any time scale
Browse files Browse the repository at this point in the history
  • Loading branch information
aler9 committed Apr 8, 2024
1 parent b5b44f4 commit f1026b7
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 58 deletions.
4 changes: 3 additions & 1 deletion internal/playback/muxer.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package playback

import "github.com/bluenviron/mediacommon/pkg/formats/fmp4"

type muxer interface {
writeInit(init []byte)
writeInit(init *fmp4.Init)
setTrack(trackID int)
writeSample(dts int64, ptsOffset int32, isNonSyncSample bool, payload []byte) error
writeFinalDTS(dts int64)
Expand Down
47 changes: 31 additions & 16 deletions internal/playback/muxer_fmp4.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ import (
"github.com/bluenviron/mediacommon/pkg/formats/fmp4/seekablebuffer"
)

var partSize = durationGoToMp4(1*time.Second, fmp4Timescale)
const (
partSize = 1 * time.Second
)

type muxerFMP4Track struct {
id int
firstDTS int64
lastDTS int64
samples []*fmp4.PartSample
id int
timeScale uint32
firstDTS int64
lastDTS int64
samples []*fmp4.PartSample
}

func findTrack(tracks []*muxerFMP4Track, id int) *muxerFMP4Track {
Expand All @@ -29,26 +32,29 @@ func findTrack(tracks []*muxerFMP4Track, id int) *muxerFMP4Track {
type muxerFMP4 struct {
w io.Writer

init []byte
init *fmp4.Init
nextSequenceNumber uint32
tracks []*muxerFMP4Track
curTrack *muxerFMP4Track
outBuf seekablebuffer.Buffer
}

func (w *muxerFMP4) writeInit(init []byte) {
func (w *muxerFMP4) writeInit(init *fmp4.Init) {
w.init = init

w.tracks = make([]*muxerFMP4Track, len(init.Tracks))

for i, track := range init.Tracks {
w.tracks[i] = &muxerFMP4Track{
id: track.ID,
timeScale: track.TimeScale,
firstDTS: -1,
}
}
}

func (w *muxerFMP4) setTrack(trackID int) {
w.curTrack = findTrack(w.tracks, trackID)
if w.curTrack == nil {
w.curTrack = &muxerFMP4Track{
id: trackID,
firstDTS: -1,
}
w.tracks = append(w.tracks, w.curTrack)
}
}

func (w *muxerFMP4) writeSample(dts int64, ptsOffset int32, isNonSyncSample bool, payload []byte) error {
Expand All @@ -75,7 +81,9 @@ func (w *muxerFMP4) writeSample(dts int64, ptsOffset int32, isNonSyncSample bool
})
w.curTrack.lastDTS = dts

if (w.curTrack.lastDTS - w.curTrack.firstDTS) > int64(partSize) {
partSizeMP4 := durationGoToMp4(partSize, w.curTrack.timeScale)

if (w.curTrack.lastDTS - w.curTrack.firstDTS) > partSizeMP4 {
err := w.innerFlush(false)
if err != nil {
return err
Expand Down Expand Up @@ -141,11 +149,18 @@ func (w *muxerFMP4) innerFlush(final bool) error {
w.nextSequenceNumber++

if w.init != nil {
_, err := w.w.Write(w.init)
err := w.init.Marshal(&w.outBuf)
if err != nil {
return err
}

_, err = w.w.Write(w.outBuf.Bytes())
if err != nil {
return err
}

w.init = nil
w.outBuf.Reset()
}

err := part.Marshal(&w.outBuf)
Expand Down
7 changes: 4 additions & 3 deletions internal/playback/on_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strconv"
"time"

"github.com/bluenviron/mediacommon/pkg/formats/fmp4"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/bluenviron/mediamtx/internal/logger"
"github.com/gin-gonic/gin"
Expand Down Expand Up @@ -48,7 +49,7 @@ func seekAndMux(
m muxer,
) error {
if recordFormat == conf.RecordFormatFMP4 {
var firstInit []byte
var firstInit *fmp4.Init
var segmentEnd time.Time

err := func() error {
Expand All @@ -67,7 +68,7 @@ func seekAndMux(

segmentStartOffset := start.Sub(segments[0].Start)

segmentMaxElapsed, err := segmentFMP4SeekAndMuxParts(f, segmentStartOffset, duration, m)
segmentMaxElapsed, err := segmentFMP4SeekAndMuxParts(f, segmentStartOffset, duration, firstInit, m)
if err != nil {
return err
}
Expand Down Expand Up @@ -99,7 +100,7 @@ func seekAndMux(

segmentStartOffset := seg.Start.Sub(start)

segmentMaxElapsed, err := segmentFMP4WriteParts(f, segmentStartOffset, duration, m)
segmentMaxElapsed, err := segmentFMP4WriteParts(f, segmentStartOffset, duration, firstInit, m)
if err != nil {
return err
}
Expand Down
5 changes: 3 additions & 2 deletions internal/playback/on_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"os"
"time"

"github.com/bluenviron/mediacommon/pkg/formats/fmp4"
"github.com/bluenviron/mediamtx/internal/conf"
"github.com/gin-gonic/gin"
)
Expand All @@ -27,7 +28,7 @@ type listEntry struct {
func computeDurationAndConcatenate(recordFormat conf.RecordFormat, segments []*Segment) ([]listEntry, error) {
if recordFormat == conf.RecordFormatFMP4 {
out := []listEntry{}
var prevInit []byte
var prevInit *fmp4.Init

for _, seg := range segments {
err := func() error {
Expand All @@ -47,7 +48,7 @@ func computeDurationAndConcatenate(recordFormat conf.RecordFormat, segments []*S
return err
}

maxDuration, err := segmentFMP4ReadMaxDuration(f)
maxDuration, err := segmentFMP4ReadMaxDuration(f, init)
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit f1026b7

Please sign in to comment.