google / google/ExoPlayer

MediaSourceFactory instances can't be re-used by multiple Player instances

Open
#9,099 5 comments 0 reactions 1 assignee Claimed by @icbaker View on GitHub
bug
Dominant language
Java
Stars
21.9k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

- ExoPlayer version number "com.google.android.exoplayer:exoplayer:2.14.1"

```

class TempActivity : AppCompatActivity(R.layout.activity_temp) {

var exoPlayer: SimpleExoPlayer? = null

private lateinit var cacheDashMediaSourceFactory: DashMediaSource.Factory
private lateinit var downloadManager: DownloadManager

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

createSources()

findViewById(R.id.playFirstButton).setOnClickListener {
val mediaSource = buildMediaSource("5fc8c15e69dfc11269541b0e")
play(mediaSource)
}

findViewById(R.id.playSecondButton).setOnClickListener {
val mediaSource = buildMediaSource("609522d13fcc496540bfd5fb")
play(mediaSource)
}

findViewById(R.id.stopButton).setOnClickListener {
pauseAndStop()
}
}

private fun createSources() {
val httpDataSource = DefaultHttpDataSource.Factory()
.setUserAgent(Util.getUserAgent(applicationContext, BuildConfig.APPLICATION_ID))
.setTransferListener(
DefaultBandwidthMeter.Builder(applicationContext)
.setResetOnNetworkTypeChange(false)
.build()
)

val exoDatabaseProvider = ExoDatabaseProvider(applicationContext)

val downloadCache = SimpleCache(File(applicationContext.cacheDir, "media"), NoOpCacheEvictor(), exoDatabaseProvider)

val cacheDataSourceFactory = CacheDataSource.Factory()
.setCache(
downloadCache
)
.setUpstreamDataSourceFactory(
DefaultDataSourceFactory(
applicationContext,
httpDataSource
)
)
.setCacheWriteDataSinkFactory(null)
.setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)

downloadManager = DownloadManager(
applicationContext,
exoDatabaseProvider,
downloadCache,
cacheDataSourceFactory,
Executors.newFixedThreadPool(6)
)
cacheDashMediaSourceFactory = DashMediaSource.Factory(
cacheDataSourceFactory
)
}

private fun getOrCreateExoPlayer(): SimpleExoPlayer {
return exoPlayer ?: SimpleExoPlayer.Builder(applicationContext).build()
.apply {
setAudioAttributes(
AudioAttributes.Builder()
.setContentType(C.CONTENT_TYPE_MUSIC)
.setUsage(C.USAGE_MEDIA)
.build(),
false
)
addListener(exoPlayerEventListener)
}
}

private fun play(mediaSource: DashMediaSource) {
exoPlayer = getOrCreateExoPlayer()
exoPlayer?.volume = 1.0f
/**
* Prepares media to play (happens on background thread) and triggers
* [SimpleExoPlayerEventListener.onPlayerStateChanged] callback when the stream is ready to play.
* */
exoPlayer?.setMediaSource(mediaSource, true)
exoPlayer?.prepare()
exoPlayer?.playWhenReady = true
}

private fun pauseAndStop() {
//region pause
exoPlayer?.playWhenReady = false
//endregion
//region stop
exoPlayer?.release()
exoPlayer = null
//endregion
}

private fun buildMediaSource(mediaId: String): DashMediaSource {
val download = downloadManager.downloadIndex.getDownload(mediaId)
return cacheDashMediaSourceFactory
.createMediaSource(
MediaItem.Builder()
.setMediaId(mediaId)
.setUri(download?.request?.uri)
.setDrmUuid(C.WIDEVINE_UUID)
.setDrmMultiSession(true)
.setMimeType(MimeTypes.APPLICATION_MPD)
.setDrmKeySetId(download?.request?.data)
.build()
)
}

private val exoPlayerEventListener = object : SimpleExoPlayerEventListener() {
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
Log.d(TAG, "onPlayerStateChanged: $playbackState")
}

override fun onPlayerError(error: ExoPlaybackException) {
when (error.type) {
ExoPlaybackException.TYPE_SOURCE,
ExoPlaybackException.TYPE_RENDERER,
ExoPlaybackException.TYPE_REMOTE,
ExoPlaybackException.TYPE_UNEXPECTED -> {
DLog.e(
TAG, "ExoPlayer error type: ${error.type}",
error
)
return
}
}

DLog.e(TAG, "ExoPlayer Unknown error: exception.type: ${error.type}", error)
}
}

companion object {
const val TAG: String = "TempActivity"
}
}

```

Error:
```
SimpleExoPlayerEventListener: ExoPlayer error type: 2
com.google.android.exoplayer2.ExoPlaybackException: Unexpected runtime error
at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:587)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:223)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: java.lang.IllegalStateException
at com.google.android.exoplayer2.util.Assertions.checkState(Assertions.java:84)
at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.initPlaybackLooper(DefaultDrmSessionManager.java:668)
at com.google.android.exoplayer2.drm.DefaultDrmSessionManager.acquireSession(DefaultDrmSessionManager.java:510)
at com.google.android.exoplayer2.source.SampleQueue.onFormatResult(SampleQueue.java:918)
at com.google.android.exoplayer2.source.SampleQueue.peekSampleMetadata(SampleQueue.java:686)
at com.google.android.exoplayer2.source.SampleQueue.read(SampleQueue.java:412)
at com.google.android.exoplayer2.source.chunk.ChunkSampleStream.readData(ChunkSampleStream.java:398)
at com.google.android.exoplayer2.BaseRenderer.readSource(BaseRenderer.java:395)
at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.readSourceOmittingSampleData(MediaCodecRenderer.java:996)
at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:830)
at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:945)
at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:478)
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:223) 
at android.os.HandlerThread.run(HandlerThread.java:67) 
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.