pub fn player_retry_restarts_stream(item: &MediaItem) -> boolExpand description
Would the player’s own load-error retry restart this stream from its
beginning? If so the retry must be switched off and recovery left to
crate::player::PlayerController::recoverable_error_resume.
ExoPlayer resumes a failed load in place only when it knows where “in place”
is: ProgressiveMediaPeriod.configureRetry keeps the load position when the
content length is known or the extractor produced a seek map with a
duration, and otherwise treats the source as live — the data at the URL is
assumed to have changed, so it resets every sample queue and re-requests the
URL from offset 0.
The handoff transcode satisfies neither condition: it is chunked (no
Content-Length) and a live mp3 encode carries no Xing header, so the
player reports its duration as unset — visible in logcat as every position
tick reading <position> / 0.0. Its URL carries StartTimeTicks = the
handoff point, so restarting it from offset 0 restarts the episode at the
handoff point, and playback then runs on from there. Nothing surfaces: no
error, no STATE_ENDED, so neither the truncation path nor the error path of
DR-129 is consulted, and the app’s only sign of it is a position that jumps
backwards. That is the “it randomly jumps back to where audio-only started”
the user sees, and how random it is depends on whether a network blip happens
to land while a load is in flight rather than while the ~50s buffer covers it.
A retry that can only restart the stream is worth less than no retry at all:
declining it turns the silent rewind into a recoverable error, which
recoverable_error_resume answers by re-opening the stream at the position
playback actually reached (StartTimeTicks rewritten, backoff and attempt
budget included). Every other source keeps the player’s retry: a static file
and an HLS playlist both declare their timeline, so ExoPlayer resumes them
exactly where the load failed.
TRACES: UR-040, UR-004 | DR-203 | UT-200