From aa9196e42230cb8664bf69e14b2811cbcc979709 Mon Sep 17 00:00:00 2001 From: Alessandro Ros Date: Tue, 11 Jun 2024 20:03:51 +0200 Subject: [PATCH] muxer: propagate query parameters to media playlist, segments and parts (#165) (https://github.com/bluenviron/mediamtx/issues/3275) --- muxer_server.go | 136 +++++++++++++++++++++++++++++++++++------------- muxer_test.go | 110 ++++++++++++++++++--------------------- 2 files changed, 153 insertions(+), 93 deletions(-) diff --git a/muxer_server.go b/muxer_server.go index cafd3a8..cb1c9b2 100644 --- a/muxer_server.go +++ b/muxer_server.go @@ -22,6 +22,12 @@ import ( "github.com/bluenviron/gohlslib/pkg/playlist" ) +const ( + multivariantPlaylistMaxAge = "30" + initMaxAge = "30" + segmentMaxAge = "3600" +) + func boolPtr(v bool) *bool { return &v } @@ -121,6 +127,7 @@ func generateMultivariantPlaylist( videoTrack *Track, audioTrack *Track, segments []muxerSegment, + rawQuery string, ) ([]byte, error) { maxBandwidth, averageBandwidth := bandwidth(segments) var resolution string @@ -174,6 +181,11 @@ func generateMultivariantPlaylist( } } + mediaPlaylistURI := "stream.m3u8" + if rawQuery != "" { + mediaPlaylistURI += "?" + rawQuery + } + pl := &playlist.Multivariant{ Version: func() int { if variant == MuxerVariantMPEGTS { @@ -197,7 +209,7 @@ func generateMultivariantPlaylist( }(), Resolution: resolution, FrameRate: frameRate, - URI: "stream.m3u8", + URI: mediaPlaylistURI, }}, } @@ -240,6 +252,7 @@ func generateInitFile( func generateMediaPlaylistMPEGTS( segments []muxerSegment, segmentDeleteCount int, + rawQuery string, ) ([]byte, error) { pl := &playlist.Media{ Version: 3, @@ -250,10 +263,15 @@ func generateMediaPlaylistMPEGTS( for _, s := range segments { if seg, ok := s.(*muxerSegmentMPEGTS); ok { + u := seg.name + if rawQuery != "" { + u += "?" + rawQuery + } + pl.Segments = append(pl.Segments, &playlist.MediaSegment{ DateTime: &seg.startNTP, Duration: seg.getDuration(), - URI: seg.name, + URI: u, }) } } @@ -261,6 +279,20 @@ func generateMediaPlaylistMPEGTS( return pl.Marshal() } +func filterOutHLSParams(rawQuery string) string { + if rawQuery != "" { + if q, err := url.ParseQuery(rawQuery); err == nil { + for k := range q { + if strings.HasPrefix(k, "_HLS_") { + delete(q, k) + } + } + rawQuery = q.Encode() + } + } + return rawQuery +} + func generateMediaPlaylistFMP4( isDeltaUpdate bool, variant MuxerVariant, @@ -269,9 +301,11 @@ func generateMediaPlaylistFMP4( nextPartID uint64, segmentDeleteCount int, prefix string, + rawQuery string, ) ([]byte, error) { targetDuration := targetDuration(segments) skipBoundary := time.Duration(targetDuration) * 6 * time.Second + rawQuery = filterOutHLSParams(rawQuery) pl := &playlist.Media{ Version: 10, @@ -297,8 +331,13 @@ func generateMediaPlaylistFMP4( skipped := 0 if !isDeltaUpdate { + u := prefix + "_init.mp4" + if rawQuery != "" { + u += "?" + rawQuery + } + pl.Map = &playlist.MediaMap{ - URI: prefix + "_init.mp4", + URI: u, } } else { var curDuration time.Duration @@ -324,9 +363,14 @@ func generateMediaPlaylistFMP4( switch seg := sog.(type) { case *muxerSegmentFMP4: + u := seg.name + if rawQuery != "" { + u += "?" + rawQuery + } + plse := &playlist.MediaSegment{ Duration: seg.getDuration(), - URI: seg.name, + URI: u, } if (len(segments) - i) <= 2 { @@ -335,9 +379,14 @@ func generateMediaPlaylistFMP4( if variant == MuxerVariantLowLatency && (len(segments)-i) <= 2 { for _, part := range seg.parts { + u = part.getName() + if rawQuery != "" { + u += "?" + rawQuery + } + plse.Parts = append(plse.Parts, &playlist.MediaPart{ Duration: part.finalDuration, - URI: part.getName(), + URI: u, Independent: part.isIndependent, }) } @@ -356,17 +405,26 @@ func generateMediaPlaylistFMP4( if variant == MuxerVariantLowLatency { for _, part := range nextSegmentParts { + u := part.getName() + if rawQuery != "" { + u += "?" + rawQuery + } + pl.Parts = append(pl.Parts, &playlist.MediaPart{ Duration: part.finalDuration, - URI: part.getName(), + URI: u, Independent: part.isIndependent, }) } // preload hint must always be present // otherwise hls.js goes into a loop + u := partName(prefix, nextPartID) + if rawQuery != "" { + u += "?" + rawQuery + } pl.PreloadHint = &playlist.MediaPreloadHint{ - URI: partName(prefix, nextPartID), + URI: u, } } @@ -381,11 +439,13 @@ func generateMediaPlaylist( nextPartID uint64, segmentDeleteCount int, prefix string, + rawQuery string, ) ([]byte, error) { if variant == MuxerVariantMPEGTS { return generateMediaPlaylistMPEGTS( segments, segmentDeleteCount, + rawQuery, ) } @@ -397,6 +457,7 @@ func generateMediaPlaylist( nextPartID, segmentDeleteCount, prefix, + rawQuery, ) } @@ -407,18 +468,17 @@ type muxerServer struct { audioTrack *Track prefix string - mutex sync.Mutex - cond *sync.Cond - closed bool - segments []muxerSegment - segmentsByName map[string]muxerSegment - segmentDeleteCount int - partsByName map[string]*muxerPart - nextSegmentID uint64 - nextSegmentParts []*muxerPart - nextPartID uint64 - multivariantPlaylist []byte - init []byte + mutex sync.Mutex + cond *sync.Cond + closed bool + segments []muxerSegment + segmentsByName map[string]muxerSegment + segmentDeleteCount int + partsByName map[string]*muxerPart + nextSegmentID uint64 + nextSegmentParts []*muxerPart + nextPartID uint64 + init []byte } func (s *muxerServer) initialize() { @@ -486,14 +546,14 @@ func (s *muxerServer) handle(w http.ResponseWriter, r *http.Request) { switch { case name == "index.m3u8": - s.handleMultivariantPlaylist(w) + s.handleMultivariantPlaylist(w, r) case name == "stream.m3u8": q := r.URL.Query() msn := queryVal(q, "_HLS_msn") part := queryVal(q, "_HLS_part") skip := queryVal(q, "_HLS_skip") - s.handleMediaPlaylist(msn, part, skip, w) + s.handleMediaPlaylist(msn, part, skip, w, r) case s.variant != MuxerVariantMPEGTS && name == s.prefix+"_init.mp4": s.handleInitFile(w) @@ -504,7 +564,7 @@ func (s *muxerServer) handle(w http.ResponseWriter, r *http.Request) { } } -func (s *muxerServer) handleMultivariantPlaylist(w http.ResponseWriter) { +func (s *muxerServer) handleMultivariantPlaylist(w http.ResponseWriter, r *http.Request) { buf := func() []byte { s.mutex.Lock() defer s.mutex.Unlock() @@ -513,7 +573,12 @@ func (s *muxerServer) handleMultivariantPlaylist(w http.ResponseWriter) { s.cond.Wait() } - return s.multivariantPlaylist + buf, err := generateMultivariantPlaylist(s.variant, s.videoTrack, s.audioTrack, s.segments, r.URL.RawQuery) + if err != nil { + return nil + } + + return buf }() if buf == nil { @@ -523,13 +588,19 @@ func (s *muxerServer) handleMultivariantPlaylist(w http.ResponseWriter) { // allow caching but use a small period in order to // allow a stream to change tracks or bitrate - w.Header().Set("Cache-Control", "max-age=30") + w.Header().Set("Cache-Control", "max-age="+multivariantPlaylistMaxAge) w.Header().Set("Content-Type", `application/vnd.apple.mpegurl`) w.WriteHeader(http.StatusOK) w.Write(buf) } -func (s *muxerServer) handleMediaPlaylist(msn string, part string, skip string, w http.ResponseWriter) { +func (s *muxerServer) handleMediaPlaylist( + msn string, + part string, + skip string, + w http.ResponseWriter, + r *http.Request, +) { isDeltaUpdate := false if s.variant == MuxerVariantLowLatency { @@ -578,6 +649,7 @@ func (s *muxerServer) handleMediaPlaylist(msn string, part string, skip string, s.nextPartID, s.segmentDeleteCount, s.prefix, + r.URL.RawQuery, ) if err != nil { w.WriteHeader(http.StatusInternalServerError) @@ -626,6 +698,7 @@ func (s *muxerServer) handleMediaPlaylist(msn string, part string, skip string, s.nextPartID, s.segmentDeleteCount, s.prefix, + r.URL.RawQuery, ) if err != nil { w.WriteHeader(http.StatusInternalServerError) @@ -662,7 +735,7 @@ func (s *muxerServer) handleInitFile(w http.ResponseWriter) { // allow caching but use a small period in order to // allow a stream to change track parameters - w.Header().Set("Cache-Control", "max-age=30") + w.Header().Set("Cache-Control", "max-age="+initMaxAge) w.Header().Set("Content-Type", "video/mp4") w.WriteHeader(http.StatusOK) w.Write(init) @@ -686,7 +759,7 @@ func (s *muxerServer) handleSegmentOrPart(fname string, w http.ResponseWriter) { } defer r.Close() - w.Header().Set("Cache-Control", "max-age=3600") + w.Header().Set("Cache-Control", "max-age="+segmentMaxAge) w.Header().Set( "Content-Type", func() string { @@ -728,7 +801,7 @@ func (s *muxerServer) handleSegmentOrPart(fname string, w http.ResponseWriter) { } defer r.Close() - w.Header().Set("Cache-Control", "max-age=3600") + w.Header().Set("Cache-Control", "max-age="+segmentMaxAge) w.Header().Set("Content-Type", "video/mp4") w.WriteHeader(http.StatusOK) io.Copy(w, r) @@ -791,13 +864,6 @@ func (s *muxerServer) publishSegmentInner(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 - // regenerate init.mp4 only if missing or codec parameters have changed if s.variant != MuxerVariantMPEGTS && (s.init == nil || segment.isForceSwitched()) { byts, err := generateInitFile(s.videoTrack, s.audioTrack) diff --git a/muxer_test.go b/muxer_test.go index 4feb8c8..dee716e 100644 --- a/muxer_test.go +++ b/muxer_test.go @@ -68,21 +68,15 @@ func (w *dummyResponseWriter) WriteHeader(statusCode int) { w.statusCode = statusCode } -func doRequest(m *Muxer, path, msn, part, skip string) ([]byte, http.Header, error) { - w := &dummyResponseWriter{ - h: make(http.Header), - } - - v := url.Values{} - v.Set("_HLS_msn", msn) - v.Set("_HLS_part", part) - v.Set("_HLS_skip", skip) +func doRequest(m *Muxer, pathAndQuery string) ([]byte, http.Header, error) { + u, _ := url.Parse("http://localhost/" + pathAndQuery) r := &http.Request{ - URL: &url.URL{ - Path: path, - RawQuery: v.Encode(), - }, + URL: u, + } + + w := &dummyResponseWriter{ + h: make(http.Header), } m.Handle(w, r) @@ -185,7 +179,7 @@ func TestMuxerVideoAudio(t *testing.T) { }) require.NoError(t, err) - byts, h, err := doRequest(m, "/index.m3u8", "", "", "") + byts, h, err := doRequest(m, "/index.m3u8?key=value") require.NoError(t, err) require.Equal(t, "application/vnd.apple.mpegurl", h.Get("Content-Type")) require.Equal(t, "max-age=30", h.Get("Cache-Control")) @@ -198,7 +192,7 @@ func TestMuxerVideoAudio(t *testing.T) { "\n"+ "#EXT-X-STREAM-INF:BANDWIDTH=4512,AVERAGE-BANDWIDTH=3008,"+ "CODECS=\"avc1.42c028,mp4a.40.2\",RESOLUTION=1920x1080,FRAME-RATE=30.000\n"+ - "stream.m3u8\n", string(byts)) + "stream.m3u8?key=value\n", string(byts)) case "fmp4": require.Equal(t, "#EXTM3U\n"+ @@ -207,7 +201,7 @@ func TestMuxerVideoAudio(t *testing.T) { "\n"+ "#EXT-X-STREAM-INF:BANDWIDTH=872,AVERAGE-BANDWIDTH=558,"+ "CODECS=\"avc1.42c028,mp4a.40.2\",RESOLUTION=1920x1080,FRAME-RATE=30.000\n"+ - "stream.m3u8\n", string(byts)) + "stream.m3u8?key=value\n", string(byts)) case "lowLatency": require.Equal(t, "#EXTM3U\n"+ @@ -216,10 +210,10 @@ func TestMuxerVideoAudio(t *testing.T) { "\n"+ "#EXT-X-STREAM-INF:BANDWIDTH=872,AVERAGE-BANDWIDTH=705,"+ "CODECS=\"avc1.42c028,mp4a.40.2\",RESOLUTION=1920x1080,FRAME-RATE=30.000\n"+ - "stream.m3u8\n", string(byts)) + "stream.m3u8?key=value\n", string(byts)) } - byts, h, err = doRequest(m, "stream.m3u8", "", "", "") + byts, h, err = doRequest(m, "stream.m3u8?key=value") require.NoError(t, err) require.Equal(t, "application/vnd.apple.mpegurl", h.Get("Content-Type")) require.Equal(t, "no-cache", h.Get("Cache-Control")) @@ -233,14 +227,14 @@ func TestMuxerVideoAudio(t *testing.T) { `#EXT-X-MEDIA-SEQUENCE:0\n` + `#EXT-X-PROGRAM-DATE-TIME:(.*?)\n` + `#EXTINF:4.00000,\n` + - `(.*?_seg0\.ts)\n` + + `(.*?_seg0\.ts\?key=value)\n` + `#EXT-X-PROGRAM-DATE-TIME:(.*?)\n` + `#EXTINF:1.00000,\n` + - `(.*?_seg1\.ts)\n$`) + `(.*?_seg1\.ts\?key=value)\n$`) require.Regexp(t, re, string(byts)) ma := re.FindStringSubmatch(string(byts)) - _, h, err := doRequest(m, ma[2], "", "", "") + _, h, err := doRequest(m, ma[2]) require.NoError(t, err) require.Equal(t, "video/MP2T", h.Get("Content-Type")) require.Equal(t, "max-age=3600", h.Get("Cache-Control")) @@ -250,22 +244,22 @@ func TestMuxerVideoAudio(t *testing.T) { `#EXT-X-VERSION:10\n` + `#EXT-X-TARGETDURATION:4\n` + `#EXT-X-MEDIA-SEQUENCE:0\n` + - `#EXT-X-MAP:URI="(.*?_init.mp4)"\n` + + `#EXT-X-MAP:URI="(.*?_init.mp4\?key=value)"\n` + `#EXT-X-PROGRAM-DATE-TIME:(.*?)\n` + `#EXTINF:4.00000,\n` + - `(.*?_seg0\.mp4)\n` + + `(.*?_seg0\.mp4\?key=value)\n` + `#EXT-X-PROGRAM-DATE-TIME:(.*?)\n` + `#EXTINF:1.00000,\n` + - `(.*?_seg1\.mp4)\n$`) + `(.*?_seg1\.mp4\?key=value)\n$`) require.Regexp(t, re, string(byts)) ma := re.FindStringSubmatch(string(byts)) - _, h, err := doRequest(m, ma[1], "", "", "") + _, h, err := doRequest(m, ma[1]) require.NoError(t, err) require.Equal(t, "video/mp4", h.Get("Content-Type")) require.Equal(t, "max-age=30", h.Get("Cache-Control")) - _, h, err = doRequest(m, ma[3], "", "", "") + _, h, err = doRequest(m, ma[3]) require.NoError(t, err) require.Equal(t, "video/mp4", h.Get("Content-Type")) require.Equal(t, "max-age=3600", h.Get("Cache-Control")) @@ -278,7 +272,7 @@ func TestMuxerVideoAudio(t *testing.T) { `#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,PART-HOLD-BACK=5.00000,CAN-SKIP-UNTIL=24.00000\n` + `#EXT-X-PART-INF:PART-TARGET=2.00000\n` + `#EXT-X-MEDIA-SEQUENCE:2\n` + - `#EXT-X-MAP:URI="(.*?_init\.mp4)"\n` + + `#EXT-X-MAP:URI="(.*?_init\.mp4\?key=value)"\n` + `#EXT-X-GAP\n` + `#EXTINF:4.00000,\n` + `gap.mp4\n` + @@ -295,19 +289,19 @@ func TestMuxerVideoAudio(t *testing.T) { `#EXTINF:4.00000,\n` + `gap.mp4\n` + `#EXT-X-PROGRAM-DATE-TIME:2010-01-01T01:01:02Z\n` + - `#EXT-X-PART:DURATION=2.00000,URI="(.*?_part0\.mp4)",INDEPENDENT=YES\n` + - `#EXT-X-PART:DURATION=2.00000,URI="(.*?_part1\.mp4)"\n` + + `#EXT-X-PART:DURATION=2.00000,URI="(.*?_part0\.mp4\?key=value)",INDEPENDENT=YES\n` + + `#EXT-X-PART:DURATION=2.00000,URI="(.*?_part1\.mp4\?key=value)"\n` + `#EXTINF:4.00000,\n` + - `(.*?_seg7\.mp4)\n` + + `(.*?_seg7\.mp4\?key=value)\n` + `#EXT-X-PROGRAM-DATE-TIME:2010-01-01T01:01:06Z\n` + - `#EXT-X-PART:DURATION=1.00000,URI="(.*?_part2\.mp4)",INDEPENDENT=YES\n` + + `#EXT-X-PART:DURATION=1.00000,URI="(.*?_part2\.mp4\?key=value)",INDEPENDENT=YES\n` + `#EXTINF:1.00000,\n` + - `(.*?_seg8\.mp4)\n` + - `#EXT-X-PRELOAD-HINT:TYPE=PART,URI="(.*?_part3\.mp4)"\n$`) + `(.*?_seg8\.mp4\?key=value)\n` + + `#EXT-X-PRELOAD-HINT:TYPE=PART,URI="(.*?_part3\.mp4\?key=value)"\n$`) require.Regexp(t, re, string(byts)) ma := re.FindStringSubmatch(string(byts)) - _, h, err := doRequest(m, ma[4], "", "", "") + _, h, err := doRequest(m, ma[4]) require.NoError(t, err) require.Equal(t, "video/mp4", h.Get("Content-Type")) require.Equal(t, "max-age=3600", h.Get("Cache-Control")) @@ -315,7 +309,7 @@ func TestMuxerVideoAudio(t *testing.T) { recv := make(chan struct{}) go func() { - _, _, err2 := doRequest(m, ma[5], "", "", "") + _, _, err2 := doRequest(m, ma[5]) require.NoError(t, err2) close(recv) }() @@ -379,7 +373,7 @@ func TestMuxerVideoOnly(t *testing.T) { }) require.NoError(t, err) - byts, _, err := doRequest(m, "index.m3u8", "", "", "") + byts, _, err := doRequest(m, "index.m3u8") require.NoError(t, err) if ca == "mpegts" { @@ -400,7 +394,7 @@ func TestMuxerVideoOnly(t *testing.T) { "stream.m3u8\n", string(byts)) } - byts, _, err = doRequest(m, "stream.m3u8", "", "", "") + byts, _, err = doRequest(m, "stream.m3u8") require.NoError(t, err) var re *regexp.Regexp @@ -433,13 +427,13 @@ func TestMuxerVideoOnly(t *testing.T) { ma := re.FindStringSubmatch(string(byts)) if ca == "mpegts" { - _, _, err := doRequest(m, ma[2], "", "", "") + _, _, err := doRequest(m, ma[2]) require.NoError(t, err) } else { - _, _, err := doRequest(m, ma[1], "", "", "") + _, _, err := doRequest(m, ma[1]) require.NoError(t, err) - _, _, err = doRequest(m, ma[3], "", "", "") + _, _, err = doRequest(m, ma[3]) require.NoError(t, err) } }) @@ -490,7 +484,7 @@ func TestMuxerAudioOnly(t *testing.T) { }}) require.NoError(t, err) - byts, _, err := doRequest(m, "index.m3u8", "", "", "") + byts, _, err := doRequest(m, "index.m3u8") require.NoError(t, err) if ca == "mpegts" { @@ -509,7 +503,7 @@ func TestMuxerAudioOnly(t *testing.T) { "stream.m3u8\n", string(byts)) } - byts, _, err = doRequest(m, "stream.m3u8", "", "", "") + byts, _, err = doRequest(m, "stream.m3u8") require.NoError(t, err) var re *regexp.Regexp @@ -539,13 +533,13 @@ func TestMuxerAudioOnly(t *testing.T) { ma := re.FindStringSubmatch(string(byts)) if ca == "mpegts" { - _, _, err := doRequest(m, ma[2], "", "", "") + _, _, err := doRequest(m, ma[2]) require.NoError(t, err) } else { - _, _, err := doRequest(m, ma[1], "", "", "") + _, _, err := doRequest(m, ma[1]) require.NoError(t, err) - _, _, err = doRequest(m, ma[3], "", "", "") + _, _, err = doRequest(m, ma[3]) require.NoError(t, err) } }) @@ -567,13 +561,13 @@ func TestMuxerCloseBeforeData(t *testing.T) { m.Close() - b, _, _ := doRequest(m, "index.m3u8", "", "", "") + b, _, _ := doRequest(m, "index.m3u8") require.Equal(t, []byte(nil), b) - b, _, _ = doRequest(m, "stream.m3u8", "", "", "") + b, _, _ = doRequest(m, "stream.m3u8") require.Equal(t, []byte(nil), b) - b, _, _ = doRequest(m, m.prefix+"_init.mp4", "", "", "") + b, _, _ = doRequest(m, m.prefix+"_init.mp4") require.Equal(t, []byte(nil), b) } @@ -622,7 +616,7 @@ func TestMuxerDoubleRead(t *testing.T) { }) require.NoError(t, err) - byts, _, err := doRequest(m, "stream.m3u8", "", "", "") + byts, _, err := doRequest(m, "stream.m3u8") require.NoError(t, err) re := regexp.MustCompile(`^#EXTM3U\n` + @@ -636,10 +630,10 @@ func TestMuxerDoubleRead(t *testing.T) { require.Regexp(t, re, string(byts)) ma := re.FindStringSubmatch(string(byts)) - byts1, _, err := doRequest(m, ma[2], "", "", "") + byts1, _, err := doRequest(m, ma[2]) require.NoError(t, err) - byts2, _, err := doRequest(m, ma[2], "", "", "") + byts2, _, err := doRequest(m, ma[2]) require.NoError(t, err) require.Equal(t, byts1, byts2) } @@ -691,7 +685,7 @@ func TestMuxerSaveToDisk(t *testing.T) { }) require.NoError(t, err) - byts, _, err := doRequest(m, "stream.m3u8", "", "", "") + byts, _, err := doRequest(m, "stream.m3u8") require.NoError(t, err) var re *regexp.Regexp @@ -775,7 +769,7 @@ func TestMuxerDynamicParams(t *testing.T) { }) require.NoError(t, err) - bu, _, err := doRequest(m, "index.m3u8", "", "", "") + bu, _, err := doRequest(m, "index.m3u8") require.NoError(t, err) require.Equal(t, "#EXTM3U\n"+ "#EXT-X-VERSION:9\n"+ @@ -785,7 +779,7 @@ func TestMuxerDynamicParams(t *testing.T) { "CODECS=\"avc1.42c028\",RESOLUTION=1920x1080,FRAME-RATE=30.000\n"+ "stream.m3u8\n", string(bu)) - bu, _, err = doRequest(m, m.prefix+"_init.mp4", "", "", "") + bu, _, err = doRequest(m, m.prefix+"_init.mp4") require.NoError(t, err) func() { @@ -815,7 +809,7 @@ func TestMuxerDynamicParams(t *testing.T) { }) require.NoError(t, err) - bu, _, err = doRequest(m, "index.m3u8", "", "", "") + bu, _, err = doRequest(m, "index.m3u8") require.NoError(t, err) require.Equal(t, "#EXTM3U\n"+ "#EXT-X-VERSION:9\n"+ @@ -825,7 +819,7 @@ func TestMuxerDynamicParams(t *testing.T) { "CODECS=\"avc1.64001f\",RESOLUTION=1280x720,FRAME-RATE=30.000\n"+ "stream.m3u8\n", string(bu)) - bu, _, err = doRequest(m, m.prefix+"_init.mp4", "", "", "") + bu, _, err = doRequest(m, m.prefix+"_init.mp4") require.NoError(t, err) var init fmp4.Init @@ -923,7 +917,7 @@ func TestMuxerFMP4NegativeTimestamp(t *testing.T) { }) require.NoError(t, err) - bu, _, err := doRequest(m, m.prefix+"_seg0.mp4", "", "", "") + bu, _, err := doRequest(m, m.prefix+"_seg0.mp4") require.NoError(t, err) var parts fmp4.Parts @@ -1000,7 +994,7 @@ func TestMuxerFMP4SequenceNumber(t *testing.T) { } for i := 0; i < 3; i++ { - buf, _, err := doRequest(m, m.prefix+"_part"+strconv.FormatInt(int64(i), 10)+".mp4", "", "", "") + buf, _, err := doRequest(m, m.prefix+"_part"+strconv.FormatInt(int64(i), 10)+".mp4") require.NoError(t, err) var parts fmp4.Parts