Skip to content

Commit

Permalink
muxer: propagate query parameters to media playlist, segments and parts
Browse files Browse the repository at this point in the history
  • Loading branch information
aler9 committed Jun 11, 2024
1 parent b3e2f15 commit e6d7789
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 69 deletions.
81 changes: 70 additions & 11 deletions muxer_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (

const (
multivariantPlaylistMaxAge = "30"
initMaxAge = "30"
segmentMaxAge = "3600"
)

func boolPtr(v bool) *bool {
Expand Down Expand Up @@ -250,6 +252,7 @@ func generateInitFile(
func generateMediaPlaylistMPEGTS(
segments []muxerSegment,
segmentDeleteCount int,
rawQuery string,
) ([]byte, error) {
pl := &playlist.Media{
Version: 3,
Expand All @@ -260,17 +263,36 @@ 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,
})
}
}

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,
Expand All @@ -279,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,
Expand All @@ -307,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
Expand All @@ -334,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 {
Expand All @@ -345,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,
})
}
Expand All @@ -366,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,
}
}

Expand All @@ -391,11 +439,13 @@ func generateMediaPlaylist(
nextPartID uint64,
segmentDeleteCount int,
prefix string,
rawQuery string,
) ([]byte, error) {
if variant == MuxerVariantMPEGTS {
return generateMediaPlaylistMPEGTS(
segments,
segmentDeleteCount,
rawQuery,
)
}

Expand All @@ -407,6 +457,7 @@ func generateMediaPlaylist(
nextPartID,
segmentDeleteCount,
prefix,
rawQuery,
)
}

Expand Down Expand Up @@ -502,7 +553,7 @@ func (s *muxerServer) handle(w http.ResponseWriter, r *http.Request) {
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)
Expand Down Expand Up @@ -543,7 +594,13 @@ func (s *muxerServer) handleMultivariantPlaylist(w http.ResponseWriter, r *http.
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 {
Expand Down Expand Up @@ -592,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)
Expand Down Expand Up @@ -640,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)
Expand Down Expand Up @@ -676,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)
Expand All @@ -700,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 {
Expand Down Expand Up @@ -742,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)
Expand Down
Loading

0 comments on commit e6d7789

Please sign in to comment.