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

Unexpected exception handling load completed - java.lang.IndexOutOfBoundsException during Player re-prepare #10838

Closed
1 task done
ValliKarunakaran opened this issue Dec 6, 2022 · 3 comments
Assignees
Labels

Comments

@ValliKarunakaran
Copy link

ValliKarunakaran commented Dec 6, 2022

ExoPlayer Version

2.18.1

Devices that reproduce the issue

Samsung Galaxy M31
OS Version 12

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Yes

Reproduction steps

1)Play the Live content with SSAI enabled/multi-period and pause the playback
2) Resume the playback after few minutes(to say 8 mins or more).

Expected result

playback should recover from behindlivewindowexception and continues to play from the nearliveedge

Actual result

Exception During playback

LoadTask: Unexpected exception handling load completed
12-05 17:20:59.206 10829 29189 20310 E LoadTask:   java.lang.IndexOutOfBoundsException: Index: 3, Size: 1
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at java.util.ArrayList.get(ArrayList.java:437)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.dash.manifest.DashManifest.getPeriod(DashManifest.java:126)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.dash.DashMediaSource.createPeriod(DashMediaSource.java:465)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.MaskingMediaPeriod.createPeriod(MaskingMediaPeriod.java:128)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.MaskingMediaSource.onChildSourceInfoRefreshed(MaskingMediaSource.java:203)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.MaskingMediaSource.onChildSourceInfoRefreshed(MaskingMediaSource.java:38)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.CompositeMediaSource.lambda$prepareChildSource$0$CompositeMediaSource(CompositeMediaSource.java:115)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.-$$Lambda$CompositeMediaSource$lU5TDdLYJk4FzgCLkUChati_nlA.onSourceInfoRefreshed(Unknown Source:4)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.BaseMediaSource.refreshSourceInfo(BaseMediaSource.java:88)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.dash.DashMediaSource.processManifest(DashMediaSource.java:847)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.dash.DashMediaSource.onUtcTimestampResolved(DashMediaSource.java:774)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.dash.DashMediaSource.onUtcTimestampLoadCompleted(DashMediaSource.java:676)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.dash.DashMediaSource$UtcTimestampCallback.onLoadCompleted(DashMediaSource.java:1330)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.source.dash.DashMediaSource$UtcTimestampCallback.onLoadCompleted(DashMediaSource.java:1325)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at com.google.android.exoplayer2.upstream.Loader$LoadTask.handleMessage(Loader.java:478)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at android.os.Handler.dispatchMessage(Handler.java:106)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at android.os.Looper.loopOnce(Looper.java:226)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at android.os.Looper.loop(Looper.java:313)
12-05 17:20:59.206 10829 29189 20310 E LoadTask:       at android.os.HandlerThread.run(HandlerThread.java:67)

Media

Not Applicable

Bug Report

  • You will email the zip file produced by adb bugreport to [email protected] after filing this issue.
@marcbaechinger
Copy link
Contributor

That's odd indeed.

Can you give me a bit more details how this can be reproduced?

From your description it sounds like you handle a PlaybackException and then you prepare the player again. Like something like this:

@Override
public void onPlayerError(PlaybackException error) {
  if (eror.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
    // Re-initialize player at the current live window default position.
    player.seekToDefaultPosition();
    player.prepare();
  } else {
    // Handle other errors.
  }
}

Then this exception is thrown when the player is re-prepared. Is this correct?

It would be great to have a chance to repro this, so if you have a live stream that you can share with us, that would be super helpful. If you're unable to share bug reports or test content publicly, please send them to [email protected] using a subject in the format "Issue #10838".

If it's not possible to send a stream, can you try whether you can avoid this exception by creating setting the source again in the case of the exception? Something like that instead of the above:

@Override
public void onPlayerError(PlaybackException error) {
  if (eror.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) {
    player.setMediaItem(mediaItemOfLiveStream); // can use setMediaSource(liveSource) also
    player.prepare();
  } 
}

I have a hypothesis why this exception happens, and if you can avoid the exception with doing the above this would be a data point for me to dig some deeper there.

@ValliKarunakaran
Copy link
Author

thanks @marcbaechinger. As you mentioned, I added the mediasource to the player while re-preparing the player.
setMediaSource(liveSource)
It works fine. I did not get IndexOutOfBoundsException during player re-prepare.
Can I go ahead with the above fix and will it work for all streams during re-prepare?

@marcbaechinger
Copy link
Contributor

Yes, if that works I'm pretty sure it works reliably if you set a new media source.

However, we need to fix that on our end because it is not working as intended that an app needs to replace the media source.

tof-tof pushed a commit to androidx/media that referenced this issue Jun 9, 2023
When the source is prepared again after stop, the period uid
is calculated by subtracting the `firstPeriodId` from the
period uid that is passed in to `createPeriod`. When this
happens after stop, the uid from the old period uid that
is still stored and has the value of the last played uid.

Hence the `firstPeriodId` must not be reset when released.

Issue: google/ExoPlayer#10838
PiperOrigin-RevId: 539028570
tof-tof pushed a commit that referenced this issue Jun 9, 2023
When the source is prepared again after stop, the period uid
is calculated by subtracting the `firstPeriodId` from the
period uid that is passed in to `createPeriod`. When this
happens after stop, the uid from the old period uid that
is still stored and has the value of the last played uid.

Hence the `firstPeriodId` must not be reset when released.

Issue: #10838
PiperOrigin-RevId: 539028570
tof-tof pushed a commit to androidx/media that referenced this issue Jun 12, 2023
When the source is prepared again after stop, the period uid
is calculated by subtracting the `firstPeriodId` from the
period uid that is passed in to `createPeriod`. When this
happens after stop, the uid from the old period uid that
is still stored and has the value of the last played uid.

Hence the `firstPeriodId` must not be reset when released.

Issue: google/ExoPlayer#10838
PiperOrigin-RevId: 539028570
(cherry picked from commit 319854d)
tof-tof pushed a commit that referenced this issue Jun 14, 2023
When the source is prepared again after stop, the period uid
is calculated by subtracting the `firstPeriodId` from the
period uid that is passed in to `createPeriod`. When this
happens after stop, the uid from the old period uid that
is still stored and has the value of the last played uid.

Hence the `firstPeriodId` must not be reset when released.

Issue: #10838
PiperOrigin-RevId: 539028570
(cherry picked from commit de2ad14)
@google google locked and limited conversation to collaborators Aug 14, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants