Skip to content

Commit

Permalink
muxer: regenerate init.mp4 only when its content changes (#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
aler9 authored Sep 27, 2023
1 parent 66221e4 commit f228995
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 10 deletions.
9 changes: 7 additions & 2 deletions muxer_segment.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type muxerSegment interface {
getName() string
getDuration() time.Duration
getSize() uint64
isForceSwitched() bool
reader() (io.ReadCloser, error)
}

Expand All @@ -37,10 +38,14 @@ func (g muxerGap) getDuration() time.Duration {
return g.duration
}

func (g muxerGap) getSize() uint64 {
func (muxerGap) getSize() uint64 {
return 0
}

func (g muxerGap) reader() (io.ReadCloser, error) {
func (muxerGap) isForceSwitched() bool {
return false
}

func (muxerGap) reader() (io.ReadCloser, error) {
return nil, fmt.Errorf("unimplemented")
}
7 changes: 7 additions & 0 deletions muxer_segment_fmp4.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type muxerSegmentFMP4 struct {
audioTrack *Track
audioTimeScale uint32
prefix string
forceSwitched bool
genPartID func() uint64
publishPart func(*muxerPart)

Expand All @@ -39,6 +40,7 @@ func newMuxerSegmentFMP4(
audioTrack *Track,
audioTimeScale uint32,
prefix string,
forceSwitched bool,
factory storage.Factory,
genPartID func() uint64,
publishPart func(*muxerPart),
Expand All @@ -53,6 +55,7 @@ func newMuxerSegmentFMP4(
audioTrack: audioTrack,
audioTimeScale: audioTimeScale,
prefix: prefix,
forceSwitched: forceSwitched,
genPartID: genPartID,
publishPart: publishPart,
name: segmentName(prefix, id, true),
Expand Down Expand Up @@ -93,6 +96,10 @@ func (s *muxerSegmentFMP4) getSize() uint64 {
return s.storage.Size()
}

func (s *muxerSegmentFMP4) isForceSwitched() bool {
return s.forceSwitched
}

func (s *muxerSegmentFMP4) reader() (io.ReadCloser, error) {
return s.storage.Reader()
}
Expand Down
4 changes: 4 additions & 0 deletions muxer_segment_mpegts.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ func (t *muxerSegmentMPEGTS) getSize() uint64 {
return t.storage.Size()
}

func (*muxerSegmentMPEGTS) isForceSwitched() bool {
return false
}

func (t *muxerSegmentMPEGTS) reader() (io.ReadCloser, error) {
return t.storage.Reader()
}
Expand Down
4 changes: 4 additions & 0 deletions muxer_segmenter_fmp4.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ func (m *muxerSegmenterFMP4) writeVideo(
m.audioTrack,
m.audioTimeScale,
m.prefix,
false,
m.factory,
m.genPartID,
m.publishPart,
Expand Down Expand Up @@ -372,6 +373,7 @@ func (m *muxerSegmenterFMP4) writeVideo(
m.audioTrack,
m.audioTimeScale,
m.prefix,
forceSwitch,
m.factory,
m.genPartID,
m.publishPart,
Expand Down Expand Up @@ -461,6 +463,7 @@ func (m *muxerSegmenterFMP4) writeAudio(ntp time.Time, dts time.Duration, au []b
m.audioTrack,
m.audioTimeScale,
m.prefix,
false,
m.factory,
m.genPartID,
m.publishPart,
Expand Down Expand Up @@ -506,6 +509,7 @@ func (m *muxerSegmenterFMP4) writeAudio(ntp time.Time, dts time.Duration, au []b
m.audioTrack,
m.audioTimeScale,
m.prefix,
false,
m.factory,
m.genPartID,
m.publishPart,
Expand Down
6 changes: 5 additions & 1 deletion muxer_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -819,13 +819,15 @@ func (s *muxerServer) publishSegment(segment muxerSegment) error {
s.segmentDeleteCount++
}

// always regenerate multivariant playlist since it contains bandwidth
buf, err := generateMultivariantPlaylist(s.variant, s.videoTrack, s.audioTrack, s.segments)
if err != nil {
return err
}
s.multivariantPlaylist = buf

if s.variant != MuxerVariantMPEGTS {
// regenerate init.mp4 only if missing or codec parameters have changed
if s.variant != MuxerVariantMPEGTS && (s.init == nil || segment.isForceSwitched()) {
if s.init != nil {
s.init.Remove()
s.init = nil
Expand All @@ -838,6 +840,8 @@ func (s *muxerServer) publishSegment(segment muxerSegment) error {
s.init = f
}

// do not pregenerate media playlist since it's too dynamic.

return nil
}()
if err != nil {
Expand Down
43 changes: 36 additions & 7 deletions muxer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

"github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio"
"github.com/bluenviron/mediacommon/pkg/formats/fmp4"
"github.com/stretchr/testify/require"

"github.com/bluenviron/gohlslib/pkg/codecs"
Expand Down Expand Up @@ -805,25 +806,53 @@ func TestMuxerDynamicParams(t *testing.T) {
"CODECS=\"avc1.42c028\",RESOLUTION=1920x1084,FRAME-RATE=30.000\n"+
"stream.m3u8\n", string(bu))

bu, _, err = doRequest(m, m.prefix+"_init.mp4", "", "", "")
require.NoError(t, err)

func() {
var init fmp4.Init
err = init.Unmarshal(bu)
require.NoError(t, err)
require.Equal(t, testSPS, init.Tracks[0].Codec.(*fmp4.CodecH264).SPS)
}()

// SPS (720p)
testSPS2 := []byte{
0x67, 0x64, 0x00, 0x1f, 0xac, 0xd9, 0x40, 0x50,
0x05, 0xbb, 0x01, 0x6c, 0x80, 0x00, 0x00, 0x03,
0x00, 0x80, 0x00, 0x00, 0x1e, 0x07, 0x8c, 0x18,
0xcb,
}

err = m.WriteH26x(testTime, 3*time.Second, [][]byte{
{ // SPS (720p)
0x67, 0x64, 0x00, 0x1f, 0xac, 0xd9, 0x40, 0x50,
0x05, 0xbb, 0x01, 0x6c, 0x80, 0x00, 0x00, 0x03,
0x00, 0x80, 0x00, 0x00, 0x1e, 0x07, 0x8c, 0x18,
0xcb,
},
testSPS2,
{5}, // IDR
{2},
})
require.NoError(t, err)

err = m.WriteH26x(testTime, 5*time.Second, [][]byte{
{5}, // IDR
})
require.NoError(t, err)

bu, _, err = doRequest(m, "index.m3u8", "", "", "")
require.NoError(t, err)
require.Equal(t, "#EXTM3U\n"+
"#EXT-X-VERSION:9\n"+
"#EXT-X-INDEPENDENT-SEGMENTS\n"+
"\n"+
"#EXT-X-STREAM-INF:BANDWIDTH=1144,AVERAGE-BANDWIDTH=989,"+
"#EXT-X-STREAM-INF:BANDWIDTH=912,AVERAGE-BANDWIDTH=742,"+
"CODECS=\"avc1.64001f\",RESOLUTION=1280x720,FRAME-RATE=30.000\n"+
"stream.m3u8\n", string(bu))

bu, _, err = doRequest(m, m.prefix+"_init.mp4", "", "", "")
require.NoError(t, err)

func() {
var init fmp4.Init
err = init.Unmarshal(bu)
require.NoError(t, err)
require.Equal(t, testSPS2, init.Tracks[0].Codec.(*fmp4.CodecH264).SPS)
}()
}

0 comments on commit f228995

Please sign in to comment.