Just set it as media source factory
ExoPlayer.Builder(context)
.setMediaSourceFactory(FirstFailureMediaFactory(realMediaSourceFactory))
....
.build()| package com.bandlab.media.player | |
| import androidx.media3.common.MediaItem | |
| import androidx.media3.datasource.TransferListener | |
| import androidx.media3.exoplayer.analytics.PlayerId | |
| import androidx.media3.exoplayer.source.MediaSource | |
| import java.util.Random | |
| class FirstFailureMediaSourceFactory( | |
| private val delegate: MediaSource.Factory, | |
| ) : MediaSource.Factory by delegate { | |
| override fun createMediaSource(mediaItem: MediaItem): MediaSource { | |
| val originalSource = delegate.createMediaSource(mediaItem) | |
| return FirstFailureMediaSource(originalSource) | |
| } | |
| } | |
| object MediaSourceFailureController { | |
| private var counter: Int = 0 | |
| fun shouldError(): Boolean { | |
| counter++ | |
| if (counter >= 5) { | |
| counter = 0 | |
| return true | |
| } | |
| return false | |
| } | |
| } | |
| private class FirstFailureMediaSource(private val delegate: MediaSource) : MediaSource by delegate { | |
| override fun prepareSource( | |
| caller: MediaSource.MediaSourceCaller, | |
| mediaTransferListener: TransferListener?, | |
| playerId: PlayerId, | |
| ) { | |
| if (MediaSourceFailureController.shouldError()) { | |
| // We throw immediately when the player tries to prepare the source | |
| // This is caught by ExoPlayerImplInternal and wrapped as TYPE_UNEXPECTED | |
| throw NullPointerException("androidx.media3.decoder.mpeghaudio.MpeghAudioSink") | |
| } else { | |
| delegate.prepareSource(caller, mediaTransferListener, playerId) | |
| } | |
| } | |
| } |