-
Notifications
You must be signed in to change notification settings - Fork 574
Description
Version
Media3 1.1.1 / ExoPlayer 2.19.1
More version details
use ExoPlayer 2.19.1
Devices that reproduce the issue
Samsung S22 running Android 14
Samsung Z Filp5 running Android 14
Devices that do not reproduce the issue
No response
Reproducible in the demo app?
Not tested
Reproduction steps
Reproduction Steps
- Start playback of a streaming audio source (e.g. a live radio stream).
- Throttle the network to simulate poor connectivity:
- Go to Settings > Developer options
- Under Networking, set “Network download speed” to 128 kbps.
- Observe playback:
- During playback, the player intermittently enters an infinite buffering state.
- Restore network to a good connection:
- Even with normal network speeds (e.g. exiting the tunnel or disabling throttling), the player remains stuck buffering.
Expected result
Playback should stop and onPlayerError(…)
should fire when LoadErrorHandlingPolicy.getRetryDelayMsFor()
returns C.TIME_UNSET
.
The following code is the LoadErrorHandlingPolicy I applied.
internal class XXXLoadErrorHandlingPolicy : DefaultLoadErrorHandlingPolicy() {
override fun getFallbackSelectionFor(
fallbackOptions: LoadErrorHandlingPolicy.FallbackOptions,
loadErrorInfo: LoadErrorHandlingPolicy.LoadErrorInfo
): LoadErrorHandlingPolicy.FallbackSelection? {
Log.d("LoadErrorHandlingPolicy", "getFallbackSelectionFor - fallbackOptions.numberOfExcludedTracks: ${fallbackOptions.numberOfExcludedTracks}")
Log.d("LoadErrorHandlingPolicy", "getFallbackSelectionFor - fallbackOptions.numberOfLocations: ${fallbackOptions.numberOfLocations}")
Log.d("LoadErrorHandlingPolicy", "getFallbackSelectionFor - fallbackOptions.numberOfTracks: ${fallbackOptions.numberOfTracks}")
Log.d("LoadErrorHandlingPolicy", "getFallbackSelectionFor - fallbackOptions.numberOfExcludedLocations: ${fallbackOptions.numberOfExcludedLocations}")
Log.d("LoadErrorHandlingPolicy", "getFallbackSelectionFor - loadErrorInfo.exception: ${loadErrorInfo.exception}")
Log.d("LoadErrorHandlingPolicy", "getFallbackSelectionFor - loadErrorInfo.loadEventInfo.uri: ${loadErrorInfo.loadEventInfo.uri}")
Log.d("LoadErrorHandlingPolicy", "getFallbackSelectionFor - loadErrorInfo.mediaLoadData.dataType: ${loadErrorInfo.mediaLoadData.dataType}")
return super.getFallbackSelectionFor(fallbackOptions, loadErrorInfo).also {
Log.d("LoadErrorHandlingPolicy", "getFallbackSelectionFor - return: $it")
}
}
override fun isEligibleForFallback(exception: IOException): Boolean {
Log.d("LoadErrorHandlingPolicy", "isEligibleForFallback - exception: $exception")
return super.isEligibleForFallback(exception)
}
override fun getRetryDelayMsFor(loadErrorInfo: LoadErrorHandlingPolicy.LoadErrorInfo): Long {
val exception = loadErrorInfo.exception
Log.d("LoadErrorHandlingPolicy", "getRetryDelayMsFor - exception: $exception")
Log.d("LoadErrorHandlingPolicy", "getRetryDelayMsFor - exception.cause: ${exception.cause}")
Log.d("LoadErrorHandlingPolicy", "getRetryDelayMsFor - exception.message: ${exception.message}")
Log.d("LoadErrorHandlingPolicy", "getRetryDelayMsFor - exception.localizedMessage: ${exception.localizedMessage}")
Log.d("LoadErrorHandlingPolicy", "getRetryDelayMsFor - loadErrorInfo.errorCount: ${loadErrorInfo.errorCount}")
Log.d("LoadErrorHandlingPolicy", "getRetryDelayMsFor - loadErrorInfo.mediaLoadData.dataType: ${loadErrorInfo.mediaLoadData.dataType}")
Log.d("LoadErrorHandlingPolicy", "getRetryDelayMsFor - loadErrorInfo.loadEventInfo.uri: ${loadErrorInfo.loadEventInfo.uri}")
return C.TIME_UNSET
}
override fun getMinimumLoadableRetryCount(dataType: Int): Int {
Log.d("LoadErrorHandlingPolicy", "getMinimumLoadableRetryCount - dataType: $dataType")
return super.getMinimumLoadableRetryCount(dataType)
}
}
Below is the log I encountered when this issue occurred (I’ve also included logs from the PlayerEventsListener’s onEvents function).
After the log below, no further output is printed and playback remains stuck buffering (even after restoring the network to normal).
Actual result
I expected onPlayerError() to be invoked after getRetryDelayMsFor() returned C.TIME_UNSET, and intended to perform the retry logic inside that callback. However, despite returning C.TIME_UNSET, the onPlayerError() callback was never called.
When playing a streaming audio source, I use three URIs in sequence—playlist.m3u8, chunklist.m3u8, and the .aac segment URLs. However, if a load error occurs specifically on the chunklist.m3u8 URI under poor network conditions, onPlayerError() is never invoked. Through extensive testing, I’ve confirmed that this only happens when the network is throttled; under a good connection, even HTTP errors like 404 or 500 correctly trigger onPlayerError().
Media
the media is confidential and cannot be shared publicly. sry
Bug Report
- You will email the zip file produced by
adb bugreport
to android-media-github@google.com after filing this issue.