-
Notifications
You must be signed in to change notification settings - Fork 426
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
feat: use EXT-X-PART for LL-HLS #1055
Conversation
1c60b25
to
adf44fb
Compare
18a5476
to
15f9cc4
Compare
55ad96c
to
1523e72
Compare
@@ -971,7 +971,7 @@ export const mediaSegmentRequest = ({ | |||
} | |||
|
|||
const segmentRequestOptions = videojs.mergeOptions(xhrOptions, { | |||
uri: segment.resolvedUri, | |||
uri: segment.part && segment.part.resolvedUri || segment.resolvedUri, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't actually use uri anywhere 🤷 but for completeness sake I changed it.
// In that case we need to reset partIndex and resync | ||
if (this.partIndex && (!segment.parts || !segment.parts.length || !segment.parts[this.partIndex])) { | ||
this.logger_(`part fell off on part ${this.partIndex}`); | ||
this.resetLoader(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure of a better way to do this. If we appended part 4 of 8 but parts fell off the manifest, they will no longer be request-able, so we kind of have to reset partIndex and the buffer. Perhaps the solution is to never use the first sequence of parts in a manifest?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may be OK since:
EXT-X-PART tags SHOULD be removed from the Playlist after they are
greater than three Target Durations from the end of the Playlist.
https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.2.2
I imagine if we are close to the live edge we shouldn't fall that far back, and if we do, it may be worth doing something else (like seeking to live, or just reverting to standard playback which should happen with the reset).
@@ -470,15 +475,23 @@ export const playlistWithDuration = function(time, conf) { | |||
segment.discontinuity = true; | |||
} | |||
|
|||
// add parts for the the last 3 segments in llhls playlists | |||
if (conf && conf.llhls && (count - i) <= 3) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add parts if llhls is set.
const remainder = time % targetDuration; | ||
const count = Math.floor(time / targetDuration) + (remainder ? 1 : 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't append remainder after the loop, just do it in the for loop.
1523e72
to
745697a
Compare
// In that case we need to reset partIndex and resync | ||
if (this.partIndex && (!segment.parts || !segment.parts.length || !segment.parts[this.partIndex])) { | ||
this.logger_(`part fell off on part ${this.partIndex}`); | ||
this.resetLoader(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may be OK since:
EXT-X-PART tags SHOULD be removed from the Playlist after they are
greater than three Target Durations from the end of the Playlist.
https://tools.ietf.org/html/draft-pantos-hls-rfc8216bis-08#section-6.2.2
I imagine if we are close to the live edge we shouldn't fall that far back, and if we do, it may be worth doing something else (like seeking to live, or just reverting to standard playback which should happen with the reset).
1b45396
to
e9704a3
Compare
e9704a3
to
a8957ff
Compare
Codecov Report
@@ Coverage Diff @@
## main #1055 +/- ##
==========================================
- Coverage 86.17% 86.10% -0.07%
==========================================
Files 38 38
Lines 8838 8905 +67
Branches 1965 1996 +31
==========================================
+ Hits 7616 7668 +52
- Misses 1222 1237 +15
Continue to review full report at Codecov.
|
// this can happen if we are going to load the first segment, but get a playlist | ||
// update during that. mediaIndex would go from 0 to -1 if mediaSequence in the | ||
// new playlist was incremented by 1. | ||
if (this.mediaIndex < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if this will get us into trouble for short live playlists. Since we should start at the beginning of the playlist, the case may often happen that we end up with a mediaIndex of -1 while still processing the segment. In that case, the next segment we should load is segment 0 from the new playlist, which, if we do mediaIndex++, we'll be OK, unless we are at -2 or below. That may be a case for us to do a resync or seek.
Do other areas of the code have trouble with a mediaIndex of -1?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we start at the end for live playlists?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason that I added this code was:
- I have often seen issues with background tabs and live playlist refreshes happing way too slowly, so the segment we are on falls off of the playlist.
- having a negative media index doesn't really make sense, as we are dealing with zero based arrays. If the segment we are on falls off of the current playlist then the current media index would no longer be a valid media index for referring to the segment that we have appended.
I think ultimately the difference will be that we will never have a negative mediaIndex. So if we were two segments behind mediaIndex would not become -2 and leave us in a bad state. It would become negative and we would get the currentMediaIndex for time.
It's possible that when mediaIndex and pendingSegment are both null, that we should probably try to jump closer to the live point in the stream. Right now we will just keep trying to request a segment at mediaIndex -1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking again, I think we may be OK. My concern was mainly for the case of 3 segment live playlists. We start at the beginning of the first segment in the playlist, and it will probably be pretty often that we'll update our playlist during a segment request. If that happens, we clear out mediaIndex here (since the mediaIndex was 0 and we'd go to -1), so when we get to checkBuffer for the next segment, we'd skip past mediaIndex++, but it looks like we'd still fetch at the end of buffer, so the guess should be OK:
http-streaming/src/segment-loader.js
Lines 1368 to 1378 in 82d83a7
} else if (this.fetchAtBuffer_) { | |
// Find the segment containing the end of the buffer | |
const mediaSourceInfo = Playlist.getMediaInfoForTime( | |
playlist, | |
lastBufferedEnd, | |
syncPoint.segmentIndex, | |
syncPoint.time | |
); | |
nextMediaIndex = mediaSourceInfo.mediaIndex; | |
startOfSegment = mediaSourceInfo.startTime; |
this.logger_(`currently processing part (index ${this.partIndex}) no longer exists.`); | ||
this.resetLoader(); | ||
|
||
this.mediaIndex = mediaIndex; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason that we retain the media index after a reset?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to throw away the partIndex and the data associated with it, but the mediaIndex is still valid.
Example:
We are on mediaIndex 3 and partIndex 2, then a live refresh happens and we are on mediaIndex 2 and it no longer has parts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 would be worth a comment there
Description
Implements support for EXT-X-PART and EXT-X-PRELOAD-HINT
Requires videojs/m3u8-parser#137
Future pull requests
Usefeat: Use ll-hls query directives and support skipping segments #1079#EXT-X-PART-INF
, query parameters for delta updates,#EXT-X-SERVER-CONTROL
, and#EXT-X-SKIP
Usefeat: use serverControl and preloadSegment llhls features behind a flag #1078#EXT-X-PRELOAD-HINT
akapreloadSegment
on the manifestInvestigation
#EXT-X-RENDITION-REPORT
when switching renditions? Is it only relevant in the context of delta updates?