有没有办法向ExoPlayer添加多个DataSource.Factory?

问题描述 投票:0回答:1

我的应用程序支持多种不同类型的媒体;流式传输和下载。问题是,我有多个 DataSourceFactories 来支持每种媒体类型以及它们正在流式传输或下载的事实。

例如

  • 对于流式 MP4,这些源是使用 ProgressiveMediaSource 创建的
  • 对于下载的 MP4,MP4 以混淆格式存储,因此我有一个自定义数据源来读取和反混淆字节
  • 对于流 HLS 和 DASH,我使用 OkHttpDataSource
  • 对于下载的 HLS 和 DASH,我使用 CacheDataSource

对于 HLS 和 DASH 来说,情况还不错。我可以传递 CacheDataSource 并将其设置为 MediaSourceFactory 中的数据源。如果缓存未命中,它将去命中上游数据源,即 OkHttpDataSource。

对于 MP4 来说事情变得更加复杂。

现在,我的代码如下所示:

val cacheFactory = CacheDataSource.Factory()
    .setCache(cache)
    .setUpstreamDataSourceFactory(httpFactory)
    .setCacheWriteDataSinkFactory(null)
    .setCacheReadDataSourceFactory(FileDataSource.Factory())
    .setFlags(CacheDataSource.FLAG_IGNORE_CACHE_ON_ERROR)

val audioAttributes = AudioAttributes.Builder()
    .setUsage(C.USAGE_MEDIA)
    .setContentType(C.AUDIO_CONTENT_TYPE_SPEECH)
    .build()

return ExoPlayer.Builder(context, DefaultRenderersFactory(context))
    .setMediaSourceFactory(
        DefaultMediaSourceFactory(context)
            .setDrmSessionManagerProvider { drmSessionManager }
            .setDataSourceFactory(cacheFactory)
    )

正如我所说,这对于 HLS 和 DASH 来说效果很好,因为它们都使用相同的缓存和上游数据源。它也适用于流式传输 MP4,因为 DefaultMediaSourceFactory 支持开箱即用。但它不适用于下载的 MP4,因为它有自定义数据源。

有什么方法可以让这些一起工作吗?

exoplayer exoplayer2.x exoplayer-media-item
1个回答
0
投票

好吧,我想我已经成功了。我最终创建了自己的

MediaSource.Factory
自定义实现。根据我获得的内容类型,我会遵循适当的
MediaSource.Factory
。我的实现看起来像这样......

class CustomMediaSourceFactory @Inject constructor(
    @Named("hls") private val hlsFactory: DataSource.Factory,
    private val dashStreamingFactory: DashMediaSource.Factory,
    @Named("mp4") private val mp4DataSourceFactory:  DataSource.Factory,
    private val adaptiveStreamDownloadSource: AdaptiveStreamDownloadSource,
    @Named("adaptiveStreamDownloadInternalDataSource") private val adaptiveStreamDownloadDataSource: CacheDataSource.Factory,
    private val dashMediaSourceProvider: DashMediaSourceProvider,
    private val extractorsFactory: ExtractorsFactory,
    private val loadErrorHandlingPolicy: LoadErrorHandlingPolicy
) : MediaSource.Factory {

    private val hlsStreamingFactory: HlsMediaSource.Factory by lazy(LazyThreadSafetyMode.NONE) {
        HlsMediaSource.Factory(hlsFactory)
            .setAllowChunklessPreparation(true)
            .setLoadErrorHandlingPolicy(loadErrorHandlingPolicy)
    }
    private val mp4Factory: ProgressiveMediaSource.Factory by lazy(LazyThreadSafetyMode.NONE) {
        ProgressiveMediaSource.Factory(mp4DataSourceFactory, extractorsFactory)
            .setLoadErrorHandlingPolicy(loadErrorHandlingPolicy)
    }

    private var drmSessionManagerProvider: DrmSessionManagerProvider? = null

    override fun setDrmSessionManagerProvider(drmSessionManagerProvider: DrmSessionManagerProvider): MediaSource.Factory {
        this.drmSessionManagerProvider = drmSessionManagerProvider
        return this
    }

    override fun setLoadErrorHandlingPolicy(loadErrorHandlingPolicy: LoadErrorHandlingPolicy): MediaSource.Factory {
        return this
    }

    override fun getSupportedTypes(): IntArray = intArrayOf(
        CONTENT_TYPE_DASH,
        CONTENT_TYPE_HLS,
        CONTENT_TYPE_OTHER
    )

    override fun createMediaSource(mediaItem: MediaItem): MediaSource {
        val type = Util.inferContentTypeForUriAndMimeType(
            mediaItem.localConfiguration!!.uri, mediaItem.localConfiguration!!.mimeType)

        return when (type) {
            CONTENT_TYPE_OTHER -> mp4Factory.createMediaSource(mediaItem)
            CONTENT_TYPE_HLS -> handleAdaptiveMediaSourceCreation(mediaItem, hlsStreamingFactory)
            CONTENT_TYPE_DASH -> handleAdaptiveMediaSourceCreation(mediaItem, dashStreamingFactory)
            else -> throw IllegalArgumentException("MediaItem must be one of type DASH, HLS or MP4")
        }
    }

我希望这可以帮助其他面临类似问题的人。

© www.soinside.com 2019 - 2024. All rights reserved.