-
Notifications
You must be signed in to change notification settings - Fork 793
Resync on poor initial segment choice #1016
Conversation
|
||
// Don't do a rendition switch unless the SegmentLoader is already walking forward | ||
if (isWalkingForward) { | ||
this.trigger('progress'); |
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 understand this is to limit ping-ponging between renditions without at least appending another segment, but i worry this could cause unwanted timeout errors. I could imagine that in a live scenario where we are close to the live point, and we do a rendition switch, now if this is a new rendition, we have to wait for a sync point, then another load + append, and another load + append before we are considered walkingForward. If in this intermediate time, we reach the end of the buffer and waiting on buffering, we may not fire progress events for some time if bandwidth conditions cause those loads to take a long time. This could cause a timeout when we otherwise would be notifying the player that we are making some type of progress
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 discussed this with Matt in person. Basically, there are trade-offs either way. With this in place we may not respond to bandwidth issues as quickly but we ensure that we are always in a stable playback mode before we do switch. This is less important for VOD but it's a different story for live. One problem is that seekable
can become stalled because we are changing playlists without having sync. Another problem is that we can conservatively guess multiple times in a row and will end up fetching the same segment over and over at different renditions (worst-case being ping-ponging as Matt put it.) This change should always result in a sync point being established and some forward progress being made before a rendition is allowed to change. Timeout-caused rendition changes will still happen immediately so that the player can take emergency action.
Don't forget to migrate the change from here to this PR |
a229782
to
74b4c40
Compare
src/segment-loader.js
Outdated
this.logger_('handleUpdateEnd_', this.mediaIndex); | ||
this.state = 'READY'; | ||
|
||
// If we previously appended a segment that ends more than 3 targetDurations before |
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.
Might read better as just "If we just appended"
src/segment-loader.js
Outdated
// the currentTime_ that means that our conservative guess was too conservative. | ||
// In that case, reset the loader state so that we try to use any information gained | ||
// from the previous request to create a new, more accurate, sync-point. | ||
if (segment && |
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 it possible for segment to be null here?
src/sync-controller.js
Outdated
|
||
// Once the distance begins to increase, we have passed | ||
// currentTime and can stop looking for better candidates | ||
if (lastDistance && lastDistance < distance) { |
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.
In a case where currentTime is equal to segment.start and we have a distance of 0, it seems that the next iteration will skip over this and skip over the next conditional to set the sync point to the next segment.
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 not sure I understand. How can you ever have two segments with the same start-time?
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 two segments with the same start time, but if currentTime
is equal to segment.start
then distance
is 0 and the syncPoint
would be set to the following segment (if one exists) because when lastDistance
is 0 for the next iteration, this condition is false and the next condition (where it checks for !lastDistance
) would result in true (leading to an overwrite of syncPoint).
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.
Oh, your complaint was that I need to do lastDistance !== null
... Why did you just say so! 😆
src/sync-controller.js
Outdated
|
||
// Once the distance begins to increase, we have passed | ||
// currentTime and can stop looking for better candidates | ||
if (lastDistance && lastDistance < distance) { |
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.
Same comment as above re: case of distance 0.
{ timeline: 1 }, | ||
{ timeline: 1 }, | ||
{ timeline: 1, start: 30 }, |
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 good to have a test with exact start as currentTime as well
74b4c40
to
e6177e6
Compare
…s closest to currentTime to ensure the most accurate decisions
…ecting the sync-point that is closest to the currentTime regardless of the order of sync-strategies
…te a better sync-point and guess again
…red value for Flash compatibility
1d5a079
to
18a8622
Compare
Description
The
SegmentLoader
is designed to generate a conservative guess that is always at or before the target time so that we can enter a mode where we fetch a contiguous set of segments and will be guaranteed to hit the "play head".With very long playlists (> 2 hours) this conservative guess can be quite a bit off. For instance, a playlist with a duration of 5 hours can result in a guess that is a minute or more behind the playhead. The reason for this is that the only known segments will be early in the playlist and we attempt to make a guess some 5 hours and thousands of segments later often without very accurate timing info.
This PR addresses this by allowing the
SegmentLoader
to guess again but using the information learned from the original poor guess. In testing, this second guess is usually pretty close to perfect since the original guess was (relatively) fairly close to begin with.To accomplish this some enhancements were necessary to
SyncController
as well. TheSegment
strategy did not take into account thecurrentTime
and would always return the latest (in time) segment with timing information. Now we always return the segment closest to the time ensuring that guesses are more accurate.Some minor reorganizing was done to
SegmentLoader
in the earlier commits so that function order better reflects the flow of execution and puts related functions near each other for easier development and understanding.SyncController
was improved in other small ways and no longer returns the very first sync-point found but tries all strategies and returns the one closest to thecurrentTime
which is the most accurate sync-point to base calculations off of.Specific Changes proposed
Please list the specific changes involved in this pull request.
Requirements Checklist