Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve HLS client #1179

Merged
merged 19 commits into from
Oct 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
7fa9f87
hls source: support fMP4s video streams
aler9 Oct 9, 2022
8c002dd
hls source: start reading live streams from (end of playlist - starti…
aler9 Oct 18, 2022
eb19e64
hls client: wait processing of current fMP4 segment before downloadin…
aler9 Oct 20, 2022
95f4aea
hls client: support fmp4 trun boxes with default sample duration, fla…
aler9 Oct 20, 2022
480ad3c
hls client: merge fmp4 init file reader and writer
aler9 Oct 20, 2022
3396547
hls client: merge fmp4 part reader and writer
aler9 Oct 20, 2022
cb5c25b
hls client: improve precision of go <-> mp4 time conversion
aler9 Oct 20, 2022
bdf7632
hls client: fix esds generation in go-mp4
aler9 Oct 21, 2022
1bae319
hls client: support audio in separate playlist
aler9 Oct 21, 2022
71a12ef
hls client: support an arbitrary number of tracks in fmp4 init files
aler9 Oct 21, 2022
521513b
hls client: support EXT-X-BYTERANGE
aler9 Oct 21, 2022
e35e3d3
hls client: support fmp4 segments with multiple parts at once
aler9 Oct 21, 2022
6c80625
hls client: support an arbitrary number of mpeg-ts tracks
aler9 Oct 21, 2022
7c0922c
hls client: synchronize tracks around a primary track
aler9 Oct 22, 2022
19a369a
update go-mp4
aler9 Oct 22, 2022
6718406
hls: synchronize track reproduction around a leading one
aler9 Oct 23, 2022
60ed600
hls client: reset stream if playback is too late
aler9 Oct 23, 2022
514f6d1
hls client: add limit on DTS-RTC difference
aler9 Oct 23, 2022
68b6443
hls client: support again streams that don't provide codecs in master…
aler9 Oct 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.18

require (
code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5
github.com/abema/go-mp4 v0.7.2
github.com/abema/go-mp4 v0.8.0
github.com/aler9/gortsplib v0.0.0-20221009091420-74f941be7166
github.com/asticode/go-astits v1.10.1-0.20220319093903-4abe66a9b757
github.com/fsnotify/fsnotify v1.4.9
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5 h1:tM5+dn2C9xZw1RzgI6WTQW1rGqdUimKB3RFbyu4h6Hc=
code.cloudfoundry.org/bytefmt v0.0.0-20211005130812-5bb3c17173e5/go.mod h1:v4VVB6oBMz/c9fRY6vZrwr5xKRWOH5NPDjQZlPk0Gbs=
github.com/abema/go-mp4 v0.7.2 h1:ugTC8gfEmjyaDKpXs3vi2QzgJbDu9B8m6UMMIpbYbGg=
github.com/abema/go-mp4 v0.7.2/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws=
github.com/abema/go-mp4 v0.8.0 h1:JHYkOvTfBpTnqJHiFFOXe8d6wiFy5MtDnA10fgccNqY=
github.com/abema/go-mp4 v0.8.0/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
Expand Down
1 change: 1 addition & 0 deletions internal/core/hls_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func (ts *testHLSServer) onPlaylist(ctx *gin.Context) {
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:2,
segment.ts
#EXT-X-ENDLIST
`

ctx.Writer.Header().Set("Content-Type", `application/x-mpegURL`)
Expand Down
48 changes: 24 additions & 24 deletions internal/hls/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ import (
)

const (
clientMinDownloadPause = 5 * time.Second
clientQueueSize = 100
clientMinSegmentsBeforeDownloading = 2
clientMPEGTSEntryQueueSize = 100
clientFMP4MaxPartTracksPerSegment = 50
clientLiveStartingInvPosition = 3
clientLiveMaxInvPosition = 5
clientMaxDTSRTCDiff = 10 * time.Second
)

func clientURLAbsolute(base *url.URL, relative string) (*url.URL, error) {
func clientAbsoluteURL(base *url.URL, relative string) (*url.URL, error) {
u, err := url.Parse(relative)
if err != nil {
return nil, err
Expand All @@ -38,40 +40,40 @@ type Client struct {
onAudioData func(time.Duration, []byte)
logger ClientLogger

ctx context.Context
ctxCancel func()
primaryPlaylistURL *url.URL
ctx context.Context
ctxCancel func()
playlistURL *url.URL

// out
outErr chan error
}

// NewClient allocates a Client.
func NewClient(
primaryPlaylistURLStr string,
playlistURLStr string,
fingerprint string,
onTracks func(*gortsplib.TrackH264, *gortsplib.TrackMPEG4Audio) error,
onVideoData func(time.Duration, [][]byte),
onAudioData func(time.Duration, []byte),
logger ClientLogger,
) (*Client, error) {
primaryPlaylistURL, err := url.Parse(primaryPlaylistURLStr)
playlistURL, err := url.Parse(playlistURLStr)
if err != nil {
return nil, err
}

ctx, ctxCancel := context.WithCancel(context.Background())

c := &Client{
fingerprint: fingerprint,
onTracks: onTracks,
onVideoData: onVideoData,
onAudioData: onAudioData,
logger: logger,
ctx: ctx,
ctxCancel: ctxCancel,
primaryPlaylistURL: primaryPlaylistURL,
outErr: make(chan error, 1),
fingerprint: fingerprint,
onTracks: onTracks,
onVideoData: onVideoData,
onAudioData: onAudioData,
logger: logger,
ctx: ctx,
ctxCancel: ctxCancel,
playlistURL: playlistURL,
outErr: make(chan error, 1),
}

go c.run()
Expand All @@ -95,19 +97,17 @@ func (c *Client) run() {

func (c *Client) runInner() error {
rp := newClientRoutinePool()
segmentQueue := newClientSegmentQueue()

dl := newClientDownloader(
c.primaryPlaylistURL,
dl := newClientDownloaderPrimary(
c.playlistURL,
c.fingerprint,
segmentQueue,
c.logger,
rp,
c.onTracks,
c.onVideoData,
c.onAudioData,
rp,
)
rp.add(dl.run)
rp.add(dl)

select {
case err := <-rp.errorChan():
Expand Down
Loading