mirror of
https://github.com/antebudimir/tempus.git
synced 2026-01-02 10:23:33 +00:00
fix: Resolve playback issues with live radio MPEG & HLS streams (#89)
This commit is contained in:
commit
d72855e160
5 changed files with 105 additions and 45 deletions
|
|
@ -78,16 +78,16 @@ public final class DownloadUtil {
|
||||||
return httpDataSourceFactory;
|
return httpDataSourceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized DataSource.Factory getDataSourceFactory(Context context) {
|
public static synchronized DataSource.Factory getUpstreamDataSourceFactory(Context context) {
|
||||||
if (dataSourceFactory == null) {
|
|
||||||
context = context.getApplicationContext();
|
|
||||||
|
|
||||||
DefaultDataSource.Factory upstreamFactory = new DefaultDataSource.Factory(context, getHttpDataSourceFactory());
|
DefaultDataSource.Factory upstreamFactory = new DefaultDataSource.Factory(context, getHttpDataSourceFactory());
|
||||||
|
dataSourceFactory = buildReadOnlyCacheDataSource(upstreamFactory, getDownloadCache(context));
|
||||||
|
return dataSourceFactory;
|
||||||
|
}
|
||||||
|
|
||||||
if (Preferences.getStreamingCacheSize() > 0) {
|
public static synchronized DataSource.Factory getCacheDataSourceFactory(Context context) {
|
||||||
CacheDataSource.Factory streamCacheFactory = new CacheDataSource.Factory()
|
CacheDataSource.Factory streamCacheFactory = new CacheDataSource.Factory()
|
||||||
.setCache(getStreamingCache(context))
|
.setCache(getStreamingCache(context))
|
||||||
.setUpstreamDataSourceFactory(upstreamFactory);
|
.setUpstreamDataSourceFactory(getUpstreamDataSourceFactory(context));
|
||||||
|
|
||||||
ResolvingDataSource.Factory resolvingFactory = new ResolvingDataSource.Factory(
|
ResolvingDataSource.Factory resolvingFactory = new ResolvingDataSource.Factory(
|
||||||
new StreamingCacheDataSource.Factory(streamCacheFactory),
|
new StreamingCacheDataSource.Factory(streamCacheFactory),
|
||||||
|
|
@ -97,13 +97,7 @@ public final class DownloadUtil {
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
dataSourceFactory = buildReadOnlyCacheDataSource(resolvingFactory, getDownloadCache(context));
|
dataSourceFactory = buildReadOnlyCacheDataSource(resolvingFactory, getDownloadCache(context));
|
||||||
} else {
|
|
||||||
dataSourceFactory = buildReadOnlyCacheDataSource(upstreamFactory, getDownloadCache(context));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dataSourceFactory;
|
return dataSourceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
package com.cappielloantonio.tempo.util
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.media3.common.C
|
||||||
|
import androidx.media3.common.MediaItem
|
||||||
|
import androidx.media3.common.MimeTypes
|
||||||
|
import androidx.media3.common.util.UnstableApi
|
||||||
|
import androidx.media3.datasource.DataSource
|
||||||
|
import androidx.media3.exoplayer.drm.DrmSessionManagerProvider
|
||||||
|
import androidx.media3.exoplayer.hls.HlsMediaSource
|
||||||
|
import androidx.media3.exoplayer.source.MediaSource
|
||||||
|
import androidx.media3.exoplayer.source.ProgressiveMediaSource
|
||||||
|
import androidx.media3.exoplayer.upstream.LoadErrorHandlingPolicy
|
||||||
|
import androidx.media3.extractor.DefaultExtractorsFactory
|
||||||
|
import androidx.media3.extractor.ExtractorsFactory
|
||||||
|
|
||||||
|
@UnstableApi
|
||||||
|
class DynamicMediaSourceFactory(
|
||||||
|
private val context: Context
|
||||||
|
) : MediaSource.Factory {
|
||||||
|
|
||||||
|
override fun createMediaSource(mediaItem: MediaItem): MediaSource {
|
||||||
|
val mediaType: String? = mediaItem.mediaMetadata.extras?.getString("type", "")
|
||||||
|
|
||||||
|
val streamingCacheSize = Preferences.getStreamingCacheSize()
|
||||||
|
val bypassCache = mediaType == Constants.MEDIA_TYPE_RADIO
|
||||||
|
|
||||||
|
val useUpstream = when {
|
||||||
|
streamingCacheSize.toInt() == 0 -> true
|
||||||
|
streamingCacheSize > 0 && bypassCache -> true
|
||||||
|
streamingCacheSize > 0 && !bypassCache -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
|
||||||
|
val dataSourceFactory: DataSource.Factory = if (useUpstream) {
|
||||||
|
DownloadUtil.getUpstreamDataSourceFactory(context)
|
||||||
|
} else {
|
||||||
|
DownloadUtil.getCacheDataSourceFactory(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
return when {
|
||||||
|
mediaItem.localConfiguration?.mimeType == MimeTypes.APPLICATION_M3U8 ||
|
||||||
|
mediaItem.localConfiguration?.uri?.lastPathSegment?.endsWith(".m3u8", ignoreCase = true) == true -> {
|
||||||
|
HlsMediaSource.Factory(dataSourceFactory).createMediaSource(mediaItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
val extractorsFactory: ExtractorsFactory = DefaultExtractorsFactory()
|
||||||
|
ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory)
|
||||||
|
.createMediaSource(mediaItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setDrmSessionManagerProvider(drmSessionManagerProvider: DrmSessionManagerProvider): MediaSource.Factory {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setLoadErrorHandlingPolicy(loadErrorHandlingPolicy: LoadErrorHandlingPolicy): MediaSource.Factory {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSupportedTypes(): IntArray {
|
||||||
|
return intArrayOf(
|
||||||
|
C.CONTENT_TYPE_HLS,
|
||||||
|
C.CONTENT_TYPE_OTHER
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,7 +12,6 @@ import androidx.media3.common.*
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.exoplayer.DefaultLoadControl
|
import androidx.media3.exoplayer.DefaultLoadControl
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
|
|
||||||
import androidx.media3.exoplayer.source.TrackGroupArray
|
import androidx.media3.exoplayer.source.TrackGroupArray
|
||||||
import androidx.media3.exoplayer.trackselection.TrackSelectionArray
|
import androidx.media3.exoplayer.trackselection.TrackSelectionArray
|
||||||
import androidx.media3.session.*
|
import androidx.media3.session.*
|
||||||
|
|
@ -21,6 +20,7 @@ import com.cappielloantonio.tempo.R
|
||||||
import com.cappielloantonio.tempo.ui.activity.MainActivity
|
import com.cappielloantonio.tempo.ui.activity.MainActivity
|
||||||
import com.cappielloantonio.tempo.util.Constants
|
import com.cappielloantonio.tempo.util.Constants
|
||||||
import com.cappielloantonio.tempo.util.DownloadUtil
|
import com.cappielloantonio.tempo.util.DownloadUtil
|
||||||
|
import com.cappielloantonio.tempo.util.DynamicMediaSourceFactory
|
||||||
import com.cappielloantonio.tempo.util.Preferences
|
import com.cappielloantonio.tempo.util.Preferences
|
||||||
import com.cappielloantonio.tempo.util.ReplayGainUtil
|
import com.cappielloantonio.tempo.util.ReplayGainUtil
|
||||||
import com.google.common.collect.ImmutableList
|
import com.google.common.collect.ImmutableList
|
||||||
|
|
@ -209,7 +209,7 @@ class MediaService : MediaLibraryService() {
|
||||||
private fun initializePlayer() {
|
private fun initializePlayer() {
|
||||||
player = ExoPlayer.Builder(this)
|
player = ExoPlayer.Builder(this)
|
||||||
.setRenderersFactory(getRenderersFactory())
|
.setRenderersFactory(getRenderersFactory())
|
||||||
.setMediaSourceFactory(getMediaSourceFactory())
|
.setMediaSourceFactory(DynamicMediaSourceFactory(this))
|
||||||
.setAudioAttributes(AudioAttributes.DEFAULT, true)
|
.setAudioAttributes(AudioAttributes.DEFAULT, true)
|
||||||
.setHandleAudioBecomingNoisy(true)
|
.setHandleAudioBecomingNoisy(true)
|
||||||
.setWakeMode(C.WAKE_MODE_NETWORK)
|
.setWakeMode(C.WAKE_MODE_NETWORK)
|
||||||
|
|
@ -384,7 +384,4 @@ class MediaService : MediaLibraryService() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRenderersFactory() = DownloadUtil.buildRenderersFactory(this, false)
|
private fun getRenderersFactory() = DownloadUtil.buildRenderersFactory(this, false)
|
||||||
|
|
||||||
private fun getMediaSourceFactory() =
|
|
||||||
DefaultMediaSourceFactory(this).setDataSourceFactory(DownloadUtil.getDataSourceFactory(this))
|
|
||||||
}
|
}
|
||||||
|
|
@ -16,13 +16,13 @@ import androidx.media3.common.Tracks
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.exoplayer.DefaultLoadControl
|
import androidx.media3.exoplayer.DefaultLoadControl
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
|
|
||||||
import androidx.media3.session.MediaLibraryService
|
import androidx.media3.session.MediaLibraryService
|
||||||
import androidx.media3.session.MediaSession.ControllerInfo
|
import androidx.media3.session.MediaSession.ControllerInfo
|
||||||
import com.cappielloantonio.tempo.repository.AutomotiveRepository
|
import com.cappielloantonio.tempo.repository.AutomotiveRepository
|
||||||
import com.cappielloantonio.tempo.ui.activity.MainActivity
|
import com.cappielloantonio.tempo.ui.activity.MainActivity
|
||||||
import com.cappielloantonio.tempo.util.Constants
|
import com.cappielloantonio.tempo.util.Constants
|
||||||
import com.cappielloantonio.tempo.util.DownloadUtil
|
import com.cappielloantonio.tempo.util.DownloadUtil
|
||||||
|
import com.cappielloantonio.tempo.util.DynamicMediaSourceFactory
|
||||||
import com.cappielloantonio.tempo.util.Preferences
|
import com.cappielloantonio.tempo.util.Preferences
|
||||||
import com.cappielloantonio.tempo.util.ReplayGainUtil
|
import com.cappielloantonio.tempo.util.ReplayGainUtil
|
||||||
import com.google.android.gms.cast.framework.CastContext
|
import com.google.android.gms.cast.framework.CastContext
|
||||||
|
|
@ -100,7 +100,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
|
||||||
private fun initializePlayer() {
|
private fun initializePlayer() {
|
||||||
player = ExoPlayer.Builder(this)
|
player = ExoPlayer.Builder(this)
|
||||||
.setRenderersFactory(getRenderersFactory())
|
.setRenderersFactory(getRenderersFactory())
|
||||||
.setMediaSourceFactory(getMediaSourceFactory())
|
.setMediaSourceFactory(DynamicMediaSourceFactory(this))
|
||||||
.setAudioAttributes(AudioAttributes.DEFAULT, true)
|
.setAudioAttributes(AudioAttributes.DEFAULT, true)
|
||||||
.setHandleAudioBecomingNoisy(true)
|
.setHandleAudioBecomingNoisy(true)
|
||||||
.setWakeMode(C.WAKE_MODE_NETWORK)
|
.setWakeMode(C.WAKE_MODE_NETWORK)
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,13 @@ import androidx.media3.common.Tracks
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.exoplayer.DefaultLoadControl
|
import androidx.media3.exoplayer.DefaultLoadControl
|
||||||
import androidx.media3.exoplayer.ExoPlayer
|
import androidx.media3.exoplayer.ExoPlayer
|
||||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
|
|
||||||
import androidx.media3.session.MediaLibraryService
|
import androidx.media3.session.MediaLibraryService
|
||||||
import androidx.media3.session.MediaSession.ControllerInfo
|
import androidx.media3.session.MediaSession.ControllerInfo
|
||||||
import com.cappielloantonio.tempo.repository.AutomotiveRepository
|
import com.cappielloantonio.tempo.repository.AutomotiveRepository
|
||||||
import com.cappielloantonio.tempo.ui.activity.MainActivity
|
import com.cappielloantonio.tempo.ui.activity.MainActivity
|
||||||
import com.cappielloantonio.tempo.util.Constants
|
import com.cappielloantonio.tempo.util.Constants
|
||||||
import com.cappielloantonio.tempo.util.DownloadUtil
|
import com.cappielloantonio.tempo.util.DownloadUtil
|
||||||
|
import com.cappielloantonio.tempo.util.DynamicMediaSourceFactory
|
||||||
import com.cappielloantonio.tempo.util.Preferences
|
import com.cappielloantonio.tempo.util.Preferences
|
||||||
import com.cappielloantonio.tempo.util.ReplayGainUtil
|
import com.cappielloantonio.tempo.util.ReplayGainUtil
|
||||||
import com.google.android.gms.cast.framework.CastContext
|
import com.google.android.gms.cast.framework.CastContext
|
||||||
|
|
@ -115,7 +115,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
|
||||||
private fun initializePlayer() {
|
private fun initializePlayer() {
|
||||||
player = ExoPlayer.Builder(this)
|
player = ExoPlayer.Builder(this)
|
||||||
.setRenderersFactory(getRenderersFactory())
|
.setRenderersFactory(getRenderersFactory())
|
||||||
.setMediaSourceFactory(getMediaSourceFactory())
|
.setMediaSourceFactory(DynamicMediaSourceFactory(this))
|
||||||
.setAudioAttributes(AudioAttributes.DEFAULT, true)
|
.setAudioAttributes(AudioAttributes.DEFAULT, true)
|
||||||
.setHandleAudioBecomingNoisy(true)
|
.setHandleAudioBecomingNoisy(true)
|
||||||
.setWakeMode(C.WAKE_MODE_NETWORK)
|
.setWakeMode(C.WAKE_MODE_NETWORK)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue