-
Notifications
You must be signed in to change notification settings - Fork 769
IllegalArgumentException in SampleQueue.discardUpstreamSampleMetadata if download canceled #3143
Description
Version
Media3 1.8.0
More version details
No response
Devices that reproduce the issue
Devices from crashlytics:
- Galaxy A26 Android 16
- Oppo RMX3834 Android 14
- Samsung Galaxy S21 Android 15
- Galaxy A54 5G Android 14
- Galaxy M11 Android 12
- Redmi Note 12 Pro Android 13
- Redmi A5 Android 15
- Realme 14 Pro 5G Android 16
and many others
Devices that do not reproduce the issue
No response
Reproducible in the demo app?
Not tested
Reproduction steps
Hello!
I've overrided 'ExoTrackSelection.shouldCancelChunkLoad' to cancel chunks when they are loading for too long. During tests of this feature I've found crashes in crashlytics with stacktrace:
androidx.media3.common.util.Assertions.checkArgument (Assertions.java:40)
androidx.media3.exoplayer.source.SampleQueue.discardUpstreamSampleMetadata (SampleQueue.java:894)
androidx.media3.exoplayer.source.SampleQueue.discardUpstreamSamples (SampleQueue.java:267)
androidx.media3.exoplayer.source.chunk.ChunkSampleStream.discardUpstreamMediaChunksFromIndex (ChunkSampleStream.java:892)
androidx.media3.exoplayer.source.chunk.ChunkSampleStream.onLoadCanceled (ChunkSampleStream.java:514)
androidx.media3.exoplayer.source.chunk.ChunkSampleStream.onLoadCanceled (ChunkSampleStream.java:59)
androidx.media3.exoplayer.upstream.Loader$LoadTask.handleMessage (Loader.java:513)
android.os.Handler.dispatchMessage (Handler.java:115)
android.os.Looper.loopOnce (Looper.java:298)
android.os.Looper.loop (Looper.java:408)
android.os.HandlerThread.run (HandlerThread.java:85)
I checked behaviour of devices which failed and found that many of them (all of them which logs I've read - about 10-20 devices) made multiple 10-seconds "seek" actions right before crash.
Looks like cancel and seek can make discard in the same time and they can conflict between each other.
I have 2 assumptions, why '0 <= discardCount && discardCount <= (length - readPosition)' can return 'false':
-
discardUpstreamSamples doesn't have 'synchronized' modifier. And it tries to execute in one time with 'commitSample()' (or other call) from another Thread.
-
Maybe seekTo() or reset() calls interleave with discardUpstreamSampleMetadata(). One of logs which I collected during tries to reproduce.
seekTo() position=469
discardSamples() 468 samples thread=ov-playback-thread
seekTo() position=470
discardSamples() 469 samples thread=ov-playback-thread
seekTo() position=470
discardSamples() 469 samples thread=ov-playback-thread
seekTo() position=470
discardSamples() 469 samples thread=ov-playback-thread
reset()
reset()
reset()
reset()
cancel!
discardUpstreamMediaChunksFromIndex() for primary
discardUpstreamSampleMetadata() discardCount=192 length=716 readPosition=4 thread=ov-playback-thread
Expected result
App works without crash
Actual result
App crashes
Media
n/a
Bug Report
- You will email the zip file produced by
adb bugreportto android-media-github@google.com after filing this issue.