mediamtx/internal/hls/mpegts/tracks.go
Alessandro Ros e5ab731d14
Improve HLS client (#1179)
* hls source: support fMP4s video streams

* hls source: start reading live streams from (end of playlist - starting point)

* hls client: wait processing of current fMP4 segment before downloading another one

* hls client: support fmp4 trun boxes with default sample duration, flags and size

* hls client: merge fmp4 init file reader and writer

* hls client: merge fmp4 part reader and writer

* hls client: improve precision of go <-> mp4 time conversion

* hls client: fix esds generation in go-mp4

* hls client: support audio in separate playlist

* hls client: support an arbitrary number of tracks in fmp4 init files

* hls client: support EXT-X-BYTERANGE

* hls client: support fmp4 segments with multiple parts at once

* hls client: support an arbitrary number of mpeg-ts tracks

* hls client: synchronize tracks around a primary track

* update go-mp4

* hls: synchronize track reproduction around a leading one

* hls client: reset stream if playback is too late

* hls client: add limit on DTS-RTC difference

* hls client: support again streams that don't provide codecs in master playlist
2022-10-23 14:04:33 +02:00

102 lines
2.0 KiB
Go

package mpegts
import (
"bytes"
"context"
"fmt"
"github.com/aler9/gortsplib"
"github.com/aler9/gortsplib/pkg/mpeg4audio"
"github.com/asticode/go-astits"
)
func findMPEG4AudioConfig(dem *astits.Demuxer, pid uint16) (*mpeg4audio.Config, error) {
for {
data, err := dem.NextData()
if err != nil {
return nil, err
}
if data.PES == nil || data.PID != pid {
continue
}
var adtsPkts mpeg4audio.ADTSPackets
err = adtsPkts.Unmarshal(data.PES.Data)
if err != nil {
return nil, fmt.Errorf("unable to decode ADTS: %s", err)
}
pkt := adtsPkts[0]
return &mpeg4audio.Config{
Type: pkt.Type,
SampleRate: pkt.SampleRate,
ChannelCount: pkt.ChannelCount,
}, nil
}
}
// Track is a MPEG-TS track.
type Track struct {
ES *astits.PMTElementaryStream
Track gortsplib.Track
}
// FindTracks finds the tracks in a MPEG-TS stream.
func FindTracks(byts []byte) ([]*Track, error) {
var tracks []*Track
dem := astits.NewDemuxer(context.Background(), bytes.NewReader(byts))
for {
data, err := dem.NextData()
if err != nil {
return nil, err
}
if data.PMT != nil {
for _, es := range data.PMT.ElementaryStreams {
switch es.StreamType {
case astits.StreamTypeH264Video,
astits.StreamTypeAACAudio:
default:
return nil, fmt.Errorf("track type %d not supported (yet)", es.StreamType)
}
tracks = append(tracks, &Track{
ES: es,
})
}
break
}
}
if tracks == nil {
return nil, fmt.Errorf("no tracks found")
}
for _, t := range tracks {
switch t.ES.StreamType {
case astits.StreamTypeH264Video:
t.Track = &gortsplib.TrackH264{
PayloadType: 96,
}
case astits.StreamTypeAACAudio:
conf, err := findMPEG4AudioConfig(dem, t.ES.ElementaryPID)
if err != nil {
return nil, err
}
t.Track = &gortsplib.TrackMPEG4Audio{
PayloadType: 96,
Config: conf,
SizeLength: 13,
IndexLength: 3,
IndexDeltaLength: 3,
}
}
}
return tracks, nil
}