-
Notifications
You must be signed in to change notification settings - Fork 6k
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
Start position of 0 always resolves to default position for live playbacks #7975
Comments
@AquilesCanta I've seen this too with our 2.12.3 upgrade. Since the MediaItem API did not exist with an initial start position we wait until the first timeline update occurs with a non-empty timeline to issue the seek. What I see is the position is overwritten with the default window start for live after the track selection. It is not reproduced 100%, and if you enable chunk less prepare, even less frequent, so almost certainly it is a timing issue. I'm looking into the issue, I'll send you some logs to and tag this issue number. |
This is easy to reproduce with current Modify the demo player to force an initial seek: startWindow = 0;
startPosition = 0;
boolean haveStartPosition = startWindow != C.INDEX_UNSET;
if (haveStartPosition) {
player.seekTo(startWindow, startPosition);
}
player.setMediaItems(mediaItems, /* resetPosition= */ !haveStartPosition); You can see with some debug prints that ExoPlayer issues the seek internally when the first source refresh occurs, but then wipes it out when the For live you probably want to wait till after the prepare completes to process the Here's the logs that show this: Initial seek is processed:
Prepare starts, pending seek already processed and renderPosition is 0.
Prepare completes and sets position to default live start position, overwriting the initial requested seek.
|
@tonihei this is caused by the fix for BLWE issue #8675 On further testing with the code from my comment above, I found only seek to 0 is ignored. Here is why: if (unpreparedMaskingMediaPeriod != null) {
long periodPreparePositionUs = unpreparedMaskingMediaPeriod.getPreparePositionUs();
timeline.getPeriodByUid(unpreparedMaskingMediaPeriod.id.periodUid, period);
long windowPreparePositionUs = period.getPositionInWindowUs() + periodPreparePositionUs;
long oldWindowDefaultPositionUs =
timeline.getWindow(/* windowIndex= */ 0, window).getDefaultPositionUs();
if (windowPreparePositionUs != oldWindowDefaultPositionUs) {
windowStartPositionUs = windowPreparePositionUs;
} The 0 value for the initial seek is what fails (all the test cases use non-zero). The See my comment here: bc9fb86#r53184789 I didn't attempt a pull request for this, as the fix will probably alter lots of assumptions the ad insertion logic has that I'm not aware of, comments on the For now, @DavidMihola a simple work around is to seek to anything but 0, not ideal but you miss the first frame or so at worst. Note this is only an issue for live. FWIW, |
Thanks @stevemayhew for the excellent analysis. I can repro and see the difference when using I agree is that the expression
This boils down to your conclusion that the Please note, that the long comment some lines further up, that explains the three possible cases actually state exactly that:
Am I correct that your live stream has a live window with indefinite availability? So the assumption in the comment about seeking to zero being unlikely is not correct? |
@marcbaechinger exactly... I've started on a test case in My thought from there was to look at enforcing these states for
Some logic ( Let me know if the test case would be welcome with a pull request, otherwise I have plenty to work on ;-) The seek to 1 is dirty, but it "works" |
Ok, if you have other things to do, give me some time to look into this on our end. Not saying that a pull with unit test is not welcome. :) I need to wrap my head around this some more. I agree that defaulting to 0 is problematic/scary but wanted to see if there are other ways to recognize that case (looking at hasRealTimeline or similar). I'm not fully understanding yet what all the implications would be either. It also seemed to work for DASH live with a seekTo(0) what I wanted to confirm/understand. |
No worries.. I'll definitely finish up the unit test that demonstrates the bug (first step to fixing it ;-) ) this way whatever solution we decide on has an way to verify it really fixes the issue without having to find a live stream to test. The use of C.TIME_UNSET (in fact, the origin of Live start offset uses this same |
@marcbaechinger I added to the pull request #9174 with a couple of choices for unit and functional (EPII level) tests. My gut feels it is best pushed to the unit test level and re-work the way the logic in the The logic in EPII looks like it already has a few too many complicated use cases. Is there a spec around for how the playlist transition from one to the next MediaSource is supposed to propagate position? |
PS I suspect the reason DASH works is tied up in how the HLS playlist updates, so possibly we could push the fix down into HLS somehow, I've not looked at that yet |
Generalized this bug to also track the problem described in #9386, which has the same root cause. The root cause (as identified above) is that There is a known workaround to use The potential fix will need to introduce #9386 and #9174 contain unit tests we can use once we submit a fix for this problem. |
Exactly, the seekTo(1) is fine for us. I agree with your suggestion for the fix, looked more involved then I wanted to attempt in a pull request |
…playing at the beginning Use this factory to workaround the following issue: google#7975
MaskingMediaSource needs to resolve the prepare position set for a MaskingPeriod while the source was still unprepared to the first actual prepare position. It currently assumes that the period-window offset and the default position is zero. This assumption is correct when a PlaceholderTimeline is used, but it may not be true if the real timeline is already known (e.g. when re-preparing a live stream after a playback error). Fix this by using the known timeline at the time of the preparation. Also: - Update a test that should have caught this to use lazy re-preparation. - Change the demo app code to use the recommended way to restart playback after a BehindLiveWindowException. Issue: #8675 PiperOrigin-RevId: 361604191
Using 0 as the unset prepare position is the root cause of a number of issues, as outliine in the ExoPlayer issue google/ExoPlayer#7975 The premise of this fix is that once the prepare override is used (the initial call to `selectTracks()`) it is never needed again, so simply invalidate it after use.
Using 0 as the unset prepare position is the root cause of a number of issues, as outliine in the ExoPlayer issue google/ExoPlayer#7975 The premise of this fix is that once the prepare override is used (the initial call to `selectTracks()`) it is never needed again, so simply invalidate it after use.
Using 0 as the unset prepare position is the root cause of a number of issues, as outliine in the ExoPlayer issue google/ExoPlayer#7975 The premise of this fix is that once the prepare override is used (the initial call to `selectTracks()`) it is never needed again, so simply invalidate it after use.
Using 0 as the unset prepare position is the root cause of a number of issues, as outliine in the ExoPlayer issue google/ExoPlayer#7975 The premise of this fix is that once the prepare override is used (the initial call to `selectTracks()`) it is never needed again, so simply invalidate it after use.
[REQUIRED] Searched documentation and issues
Since the problem only appeared after updating from 2.11.8 to 2.12.0 I searched the recent issues for "seek" and "startPosition" but didn't find anything that seemed related.
[REQUIRED] Question
In our TV app we offer users the possibility to watch the current program from the beginning, i. e. instead of simple live stream with a short live window we have a stream with a fixed start but which grows in length every time a new segment is available on the streaming server.
Since the default position in those streams seems to be right at the live edge we have always passed the start position (
simpleExoPlayer.seekTo(0)
) explicitly beforeprepare()
ing the player. Up until and including 2.11.8 this has worked without any problems.Since updating to 2.12.0 a few days ago this "initial seek position" seems to be ignored and the player starts at the default position, at the live edge. I saw that the
prepare(mediaSource, false, true)
which we were using so far is now deprecated. But replacing it withdoes not resolve the problem. Even here, it seems that the
startPositionInMs
is ignored.Unfortunately, I cannot provide a public test stream to demonstrate the problem, but this is the HLS master playlist:
and this is the start of one of the variant playlists:
As I said, the variant playlists grow for three more lines every four seconds, when the next segment becomes available.
It may well be a configuration issue with our streams (this time, for once, the newly configured DASH streams work better for the same scenario, but we cannot migrate all streams from HLS to DASH at the moment) - but since it still worked with 2.11.8 I thought there might be a way to get it to work with 2.12.0.
The text was updated successfully, but these errors were encountered: