androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.65k stars 390 forks source link

Two tracks are getting downloaded by Exoplayer and IMA SDK #1078

Closed nikky12 closed 7 months ago

nikky12 commented 8 months ago

Version

ExoPlayer 2.16.1

More version details

No response

Devices that reproduce the issue

All Android devices

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Yes

Reproduction steps

We are using IMA SDK for playing video ads. We have tried with Single player and using Concatenating media source to have Ads and content media concatenated. But due to this issue https://github.com/google/ExoPlayer/issues/3693, we have to switch to two players One player used for content playback and another is for Ads playback.

Content Player

val renderersFactory = DefaultRenderersFactory(context.applicationContext).setEnableDecoderFallback(true)

        val builder = ExoPlayer.Builder(context, renderersFactory, decoderBehaviour)
                .setLoadControl(loadControl)
                .setOverrideDecoderBehavior(decoderBehaviour)
                .setSeekParameters(SeekParameters.CLOSEST_SYNC)
        trackSelector?.let { builder.setTrackSelector(it) }
        player = builder.build()
player?.apply {
                currentMediaSource?.let {
                    setMediaSources(
                        listOf(it),  /* startWindowIndex= */
                        if (resetPosition) 0 else C.INDEX_UNSET,  /* startPositionMs= */
                        C.TIME_UNSET
                    )
                }
                prepare()
            }

Ads Player

val dataSourceFactory: DataSource.Factory = DefaultDataSourceFactory(context)
        val mediaSourceFactory: MediaSourceFactory = DefaultMediaSourceFactory(dataSourceFactory)
            .setAdsLoaderProvider { adsLoader }
            .setAdViewProvider(imaVideoAdsView?.getAdUiContainer())

        val renderersFactory = DefaultRenderersFactory(context.applicationContext).setEnableDecoderFallback(true)
imaAdsPlayer = ExoPlayer.Builder(context, renderersFactory, overrideDecoderBehavior)
            .setMediaSourceFactory(mediaSourceFactory)
            .setOverrideDecoderBehavior(overrideDecoderBehavior)
            .setSeekParameters(SeekParameters.CLOSEST_SYNC)
            .build()
        imaVideoAdsView?.getAdUiContainer()?.player = imaAdsPlayer
        adsLoader?.setPlayer(imaAdsPlayer)
val contentUri = Uri.parse(playbackItem.contentUrl)
        val adTagUri = Uri.parse(playbackItem.adsMeta?.meta?.url)
        val adsConfig = MediaItem.AdsConfiguration.Builder(adTagUri).build()
        val mediaItem: MediaItem = MediaItem.Builder()
            .setUri(contentUri)
            .setAdsConfiguration(adsConfig)
            .build()

        // Prepare the content and ad to be played with the SimpleExoPlayer.
        imaAdsPlayer?.setMediaItem(mediaItem)
        imaAdsPlayer?.prepare()

Ima Ads player needs two media items - content and ad tag url Since there are two players, two tracks are getting downloaded for content playback. One track in the quality user has selected to play and another that is with Adsplayer.

Do we have a fix for the issue which i mentioned https://github.com/google/ExoPlayer/issues/3693 So that we can move to single player.

Expected result

Below Exception should not come when i use ConcatenatingMediaSource with Ads and content url .

01-11 14:46:43.654 2793-2793/com.intigral.splive W/System.err: java.lang.IllegalArgumentException
01-11 14:46:43.654 2793-2793/com.intigral.splive W/System.err: at com.google.android.exoplayer2.util.Assertions.checkArgument(Assertions.java:37)
01-11 14:46:43.654 2793-2793/com.intigral.splive W/System.err: at com.google.android.exoplayer2.ext.ima.ImaAdsLoader.onTimelineChanged(ImaAdsLoader.java:671)
01-11 14:46:43.654 2793-2793/com.intigral.splive W/System.err: at com.google.android.exoplayer2.ExoPlayerImpl.updatePlaybackInfo(ExoPlayerImpl.java:588)
01-11 14:46:43.654 2793-2793/com.intigral.splive W/System.err: at com.google.android.exoplayer2.ExoPlayerImpl.handlePlaybackInfo(ExoPlayerImpl.java:541)
01-11 14:46:43.654 2793-2793/com.intigral.splive W/System.err: at com.google.android.exoplayer2.ExoPlayerImpl.handleEvent(ExoPlayerImpl.java:483)
01-11 14:46:43.654 2793-2793/com.intigral.splive W/System.err: at com.google.android.exoplayer2.ExoPlayerImpl$1.handleMessage(ExoPlayerImpl.java:100)
01-11 14:46:43.654 2793-2793/com.intigral.splive W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
01-11 14:46:43.654 2793-2793/com.intigral.splive W/System.err: at android.os.Looper.loop(Looper.java:154)
01-11 14:46:43.655 2793-2793/com.intigral.splive W/System.err: at android.app.ActivityThread.main(ActivityThread.java:6077)
01-11 14:46:43.655 2793-2793/com.intigral.splive W/System.err: at java.lang.reflect.Method.invoke(Native Method)
01-11 14:46:43.655 2793-2793/com.intigral.splive W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
01-11 14:46:43.655 2793-2793/com.intigral.splive W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)

Actual result

Above exception is coming

Media

Not applicable

Bug Report

icbaker commented 8 months ago

I think this is essentially a duplicate of https://github.com/google/ExoPlayer/issues/3693.

For your workaround case: Do you need to play the same content with your 'ads' player? What about playing some 'fake' local content, since I believe you will only actually be using this player when it's playing ads - that should avoid you downloading the content twice.

nikky12 commented 8 months ago

@icbaker @tonihei Yes, i need to play the ads on same content. So video url, we are giving to ads player should be of same duration, how would it be possible to play a fake media source? Every video can of different duration, where would i get the fake video Also there is no API to set fake media item with val adsConfig = MediaItem.AdsConfiguration.Builder(adTagUri).build() val mediaItem: MediaItem = MediaItem.Builder() .setUri(contentUri) .setAdsConfiguration(adsConfig) .build()

    // Prepare the content and ad to be played with the SimpleExoPlayer.
    imaAdsPlayer?.setMediaItem(mediaItem)
    imaAdsPlayer?.prepare()
tonihei commented 8 months ago

where would i get the fake video

You can use a SilenceMediaSource and then configure the player with an AdsMediaSource directly instead of using MediaItem. It should look roughly like this:

player.addMediaSource(
    new AdsMediaSource(
        new SilenceMediaSource(/* durationUs= */ [value >= last ad group time]),
        new DataSpec(adTagUri),
        /* adsId= */ "ads",
        new DefaultMediaSourceFactory(context),
        adsLoader,
        adViewProvider));
tonihei commented 7 months ago

I assume the question was answered and will close the issue.