mirror of
https://github.com/bluenviron/mediamtx
synced 2024-12-12 01:35:02 +00:00
0b5519d30c
this has become useless after the introduction of the new authentication system, that already allows to select which paths are available for playback
117 lines
2.4 KiB
Go
117 lines
2.4 KiB
Go
package playback
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/bluenviron/mediacommon/pkg/formats/fmp4"
|
|
"github.com/bluenviron/mediamtx/internal/conf"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type listEntryDuration time.Duration
|
|
|
|
func (d listEntryDuration) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(time.Duration(d).Seconds())
|
|
}
|
|
|
|
type listEntry struct {
|
|
Start time.Time `json:"start"`
|
|
Duration listEntryDuration `json:"duration"`
|
|
}
|
|
|
|
func computeDurationAndConcatenate(recordFormat conf.RecordFormat, segments []*Segment) ([]listEntry, error) {
|
|
if recordFormat == conf.RecordFormatFMP4 {
|
|
out := []listEntry{}
|
|
var prevInit *fmp4.Init
|
|
|
|
for _, seg := range segments {
|
|
err := func() error {
|
|
f, err := os.Open(seg.Fpath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
|
|
init, err := segmentFMP4ReadInit(f)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = f.Seek(0, io.SeekStart)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
maxDuration, err := segmentFMP4ReadMaxDuration(f, init)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(out) != 0 && segmentFMP4CanBeConcatenated(
|
|
prevInit,
|
|
out[len(out)-1].Start.Add(time.Duration(out[len(out)-1].Duration)),
|
|
init,
|
|
seg.Start) {
|
|
prevStart := out[len(out)-1].Start
|
|
curEnd := seg.Start.Add(maxDuration)
|
|
out[len(out)-1].Duration = listEntryDuration(curEnd.Sub(prevStart))
|
|
} else {
|
|
out = append(out, listEntry{
|
|
Start: seg.Start,
|
|
Duration: listEntryDuration(maxDuration),
|
|
})
|
|
}
|
|
|
|
prevInit = init
|
|
|
|
return nil
|
|
}()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("MPEG-TS format is not supported yet")
|
|
}
|
|
|
|
func (p *Server) onList(ctx *gin.Context) {
|
|
pathName := ctx.Query("path")
|
|
|
|
if !p.doAuth(ctx, pathName) {
|
|
return
|
|
}
|
|
|
|
pathConf, err := p.safeFindPathConf(pathName)
|
|
if err != nil {
|
|
p.writeError(ctx, http.StatusBadRequest, err)
|
|
return
|
|
}
|
|
|
|
segments, err := FindSegments(pathConf, pathName)
|
|
if err != nil {
|
|
if errors.Is(err, errNoSegmentsFound) {
|
|
p.writeError(ctx, http.StatusNotFound, err)
|
|
} else {
|
|
p.writeError(ctx, http.StatusBadRequest, err)
|
|
}
|
|
return
|
|
}
|
|
|
|
out, err := computeDurationAndConcatenate(pathConf.RecordFormat, segments)
|
|
if err != nil {
|
|
p.writeError(ctx, http.StatusInternalServerError, err)
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, out)
|
|
}
|