Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Correct comment on track selection during seek
The comment "all should be same" is not correct, it is extremely likely they will be the same but not assured. In either case the seek position will work, it just may not land exactly on a sync point in every variant.
- Loading branch information
530dd3f
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.
There is a small problem with this code still, that I can now reproduce pretty easily (but in practice it is rare). The comment is true, iff the playlist snapshot is very fresh, however that may not be the case for non-EVENT live playback.
The steps to reproduce are:
MSG_PLAYLIST_UPDATE_REQUESTED
processed)targetPositionInPlaylistUs
) will be off by as much as time XWhat happens is the the cached playlist snapshots, while valid (see isSnapshotValid() for loading the next segment, is not even close to up to date with the current Period position. This corrects itself after the playlist becomes primary and a couple of Player thread handler cycles.
I'm looking if a similar situation can happen for DASH Renditions. For HLS there are a couple of options that I've tried that fix the problem:
targetPositionInPlaylistUs
(eg it is < durationUs of the selected playlist)HlsPlaylistTracker.isRefreshedPrimary(Uri url)
) that checks the exact condition required (that is playlist is primary and < 1.5 x EXT-X-TARGETDURATION old)@ojw28 or @tonihei what do you think? Now that I better understand how ad insertion and period time works better I hopefully won't make this kind of mistake again
530dd3f
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've opened a pull request with option 2 above (simpler, just a method to get a fresh
HlsMediaPlaylist
) #10477This is the code we are currently testing with (or at least the non re-formatted version from)
530dd3f
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 don't think I can follow why this is the case. It seems the
targetPositionInPlaylistUs
is correct for the stale playlist, but because the playlist is stale we can't resolve the seek positions correctly.For example:
startOfPlaylistInPeriodUs=40_000_000
(containing segments up to 50 seconds in period time).startOfPlaylistInPeriodUs=80_000_000
(containing segments up to 90 seconds in period time).getAdjustedSeekPositionUs
withpositionUs=85_000_000
.targetPositionInPlaylistUs
(for the stale playlist snapshot A) is correctly calculated as45_000_000
.45_000_000
exceeds the10_000_000 us
worth of segments defined in the snapshot. The seek positions are likely resolved to the start time of the last defined segment.The intended outcome is: Recognize that we can't resolve the position correctly and just return the unaltered input
positionUs
.This means option (1) is actually the more direct and better way to solve this? We don't usually expect seeks outside of the defined
Timeline.Window
duration and thisTimeline.Window
is set by the primary playlist. So there shouldn't be a seek that goes beyond the duration of the playlist unless the playlist we are using is stale. For the rare case someone issues a seek request that goes beyond the defined playlist, it's fine to accept the potential performance impact.530dd3f
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.
Yes, that is the correct outcome. Note, at most one seek will suffer this as the playlist becomes primary and refreshes in the next cycle.
Your example works with just considering exceeded duration, assuming the logic is correct (which from your comment here on commit #r79541401 seems it is). The we need a call to
isSnapshotValid()
and that would cover the duration exceeded case.Visually the two cases are:
Case 1 — Switch with valid cached playlist
Case 1 — Switch with an invalid cached playlist
So if all this worked as we expect, then adding this code to
getAdjustedSeekPositionUs()
:Also sadly this does not fix the problem, we are still seeing the issue with Case 1 like updates, still investigating.
Can we keep the discussion here? as the pull request is likely to change. Note though at this point the pull request is the only logic that fixes the
issue. Thanks for helping out with this!
530dd3f
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 see how they are related, but it's hard to verify that
isSnapshotValid()
serves the same purpose as directly checking whether the duration is exceeded. For example,isSnapshotValid()
checkslastSnapshotLoadMs + playlist.durationMs > currentTimeMs
, but what if the snapshot contains segments beforelastSnapshotLoadMs
, then we can easily exceed the duration and still have a "valid" snapshot? Maybe I'm misreading the code :)Have you tried the duration check to see if it solves your problem?
I agree though that we should not add this additional duration check if the playlist has an end tag or is of type VOD or EVENT.
530dd3f
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 duration fix is enough, I've evaluated all the cases with my testing, and convinced myself.
Here's what will be the commit comment on the new pull request:
Seek nearest SYNC does not adjust stale playlists
getPlaylistSnapshot()
can return a cached but potentially quite stale playlistthat may be unsuitable for resolving a seek position.
This change fixes a race conditon that can cause a failed attempt to resolve
a seek position with a stale playlist.
Pre-conditions for the race:
Timeline.Window
The seek request is issued with
Timeline.Window
from playlist B, yet the call togetAdjustedSeekPositionUs()
occurs:
The check is simple, does basic sanity check on
targetPositionInPlaylistUs
(that itis < durationUs of the selected playlist). This covers the positions WWW.
530dd3f
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.
Sounds good, thanks! Also, if you can without too much additional effort, please file the PR against the Media3 project.
530dd3f
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 some coding convention that requires early exits and code hard line breaks at a certain column?
Because the code from the original pull request was reformatted in the merge commit check. This reformatting makes it really hard to cherry-pick to pull requests.
If code re-formatting is required to meet some style guide it would be best to do this all at once in a commit specific to that purpose rather then a merge commit.
530dd3f
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 formatting is done by some internal tooling and there is not much we can do about it. All changes we make to PRs (both automatic formatting and manual code changes) are only part of the merge commit unfortunately.
530dd3f
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.
Thanks, @tonihei yes.. I reworked our code to match the early return style (it is not a bad pattern at all for complex logic like the cases to eliminate when the adjustment cannot be done).
I added a test case for the new condition. Lastly, I changed where the normalization back to playlist time was done, to match what is in current
dev-v2
, this is more clear to me as welland functionally the same.
The hard part is when formatting changes are mixed in with code changes :-( Now the formatting and logic in our branch for this code matches what is in this pull request #10484