playback: cache streamed audio to stop redundant refetches

A streamed MP3 with no Xing/Info/VBRI header gets an estimated duration
from Mp3Extractor. At end of stream the extractor rewrites it, which
refreshes the timeline; MediaPeriodQueue.updateQueuedPeriods then sees
the playing period's duration change, drops every period after it and
re-enqueues the next one, so the next track is opened from byte 0 again.
After a seek near the end that repeats a few times.

Route streamed bytes through a bounded SimpleCache (DefaultDataSource ->
CacheDataSource -> KnownLengthDataSource -> OkHttp). A re-opened next
period is served from the bytes the prefetch already committed, so the
redundant network fetches stop without changing playback length or
gapless padding. DefaultDataSource still handles file:/content:, so
downloads bypass the cache.

The cache is a process-scoped 64 MiB LRU in cacheDir/stream-cache; a
construction failure falls back to no cache so playback still starts.
This commit is contained in:
austinried
2026-10-09 13:36:55 +00:00
parent 0cef3657bc
commit e806eaef89
5 changed files with 105 additions and 4 deletions
+2
View File
@@ -244,7 +244,9 @@ dependencies {
implementation(libs.androidx.datastore.preferences)
implementation(libs.androidx.media3.exoplayer)
implementation(libs.androidx.media3.session)
implementation(libs.androidx.media3.datasource)
implementation(libs.androidx.media3.datasource.okhttp)
implementation(libs.androidx.media3.database)
implementation(libs.okhttp)
implementation(libs.coil.compose)
implementation(libs.coil.network.okhttp)