Android Casting is playing Video Ads in Mobile and Video Content in TV Simulatneously

We have Integrated Bitmovin player in android with casting and ads features. Ad is preroll ad. While casting, Video ad is playing in Mobile and Video content is playing in TV. Let’s say I have video ad of 20 secs, While casting this 20 secs Video ad is playing in mobile and Video content is playing in TV (for 20 secs). After the Video Ad is completed in the mobile, actual video content is started in the mobile and now in TV two audios are coming. One is Audio with Video Content starting from 0 secs and other Audio which is continues from 21 secs. Below is the video attached. Kindly help us in resolving this.
Thanks in advance.

Hi @meworldet.com , this sounds like a bug. Could you maybe create a minimal reproducible sample based on our casting sample to help us reproduce the issue?

Hi @Lukas - This issue is not happening for all the videos. Only for few specific videos, we are seeing this issue. We have implemented the Casting example
but , only for few videos, we are seeing this issue.

It would be great if you could provide one of the failing streams. If you do not want to share it publicly, please send it in a private direct to me.

We have almost the same issue, we don’t have a Custom Receiver for the ads, so we are watching ads on device, but if Chromecast is on, ads will be played on phone/device and Content will be played on TV/Chromecast, and if we pause the ads, Content is paused too and if we resume the ads, Content is resumed too.

We don’t know if player can control ads play/pause “toggle” before content when Chromecast is on.

Hi @gledezma , thanks for sharing your issue. Can you please share following additional information?

  • Bitmovin Player Version
  • IMA SDK dependency version
  • If possible VAST/VMAP Ad URL?
  • Bitmovin player configuration including PlaybackConfig and Advertising Configuration?
  • Is isAutoplayEnabled configuration set to true?
  • Android version where this issue is reproduced.

In general Bitmovin player takes care of disabling/stopping client side Ads playing on Android device when casting is started/enabled. So this is either a configuration issue or a potential bug. Above information will help us triage this better. If you can also share a sample application where we can reproduce this behaviour, that will be best next step for us investigate.

Here is the information:

  • Bitmovin Player Version: 3.23.0
  • IMA SDK Version: 3.27.1 / play services ads 18.0.1
  • Vast Ad URL: Riivi Vast
  • Player Config:
private fun getAdConfig(dataMediaResponse: MediaPlaylist): AdvertisingConfig {
        url = getVastUrl(mediaPlaylist = dataMediaResponse)
        /*Log.e("URL vast", url)*/

        val adSource = AdSource(
            AdSourceType.Ima,
            url)

        val arrayAds = arrayOf(adSource)

        val addItem = AdItem(arrayAds, "pre", replaceContentDuration = 0.0, preloadOffset = 1.0)

        return AdvertisingConfig(addItem)
}
        val adConfig = getAdConfig(dataMediaResponse)

        val playerConfig = PlayerConfig(
                advertisingConfig = adConfig,
                styleConfig = StyleConfig(
                    isUiEnabled = false,
                    isHideFirstFrame = true,
                ),
                playbackConfig = PlaybackConfig(
                    isAutoplayEnabled = true
                )
            )

            //set playList config, here is the content
            val playlistConfig = PlaylistConfig(
                playlistJwPlayer,
                PlaylistOptions(
                    preloadAllSources = false
                )
            )

            //New Player instance & add player to Player View.
            val player = Player.create(this, playerConfig = playerConfig).also {
                bView.bitmovinPlayerView.player = it
            }
  • Autoplay is enabled via PlaybackConfig
  • Android Version: 12 - Real Device - Moto G30

The way we can reproduce the issue, is just playing any content and sending it to Chromecast. Then reentering the PlayerView Activity and Pausing/Resuming the ads when they are played with Chromecast on.

Thanks in advance

Thanks @gledezma for sharing the information. A few observations, questions and suggestions.

  • The shared VAST Ad Riivi Vast does not work for me but this should not be a bottleneck at the moment.

  • I tried the use case with Bitmovin player sample including default Bitmovin player UI and am not able to reproduce the behaviour. Did you also check with default Bitmovin UI and are you able to reproduce the same behaviour?

  • You are using isUiEnabled = false, in StyleConfig . Does this mean that your application is using custom Native player UI instead of Bitmovin player UI? If yes,

    • Can you please share what does bView.bitmovinPlayerView represent in your application?
    • Can you please share the PlayerActivity’s layout resource file?
  • Additionally, you seem to create Player object explicitly in code using Player.create API. This is correct but if you are using PlayerView as part of your player activity’s layout, please add app:initialize_player="false" attribute to prevent the default Player object from being created implicitly. This is demonstarted in BasicPlaybackKotlin public sample app.

<com.bitmovin.player.PlayerView
        android:id="@+id/playerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        app:initialize_player="false">
  • The params replaceContentDuration = 0.0, preloadOffset = 1.0 in AdItem are not needed for preroll Ad. Although I do not suspect these to be root cause, but to rule this out, can you please try without these params?

I hope above information helps. Please try out above suggestions and also share your feedback about questions.

Yes, we are using a custom overlay layout

bView.bitmovinPlayerView is the Bitmovin PlayerView component from the lib.

This is the xml layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/parentPlayer"
    android:animateLayoutChanges="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.bitmovin.player.PlayerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/bitmovinPlayerView"
        app:initialize_player="false"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

    </com.bitmovin.player.PlayerView>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent">

        <RelativeLayout
            android:layout_width="400dp"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:background="@android:color/transparent"
            android:id="@+id/playerContainer">


        </RelativeLayout>

    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/playerUI"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true"
        android:animateLayoutChanges="true"
        android:focusable="true">

        <ImageButton
            android:id="@+id/playButton"
            android:layout_width="80dp"
            android:layout_height="80dp"
            android:layout_centerInParent="true"
            android:background="@android:color/transparent"
            android:contentDescription="@null"
            android:foreground="@drawable/ripple_button_player"
            android:insetLeft="0dp"
            android:insetTop="0dp"
            android:insetRight="0dp"
            android:insetBottom="0dp"
            android:src="@drawable/ic_play_button" />

        <com.google.android.material.button.MaterialButton
            android:id="@+id/buttonBack"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentStart="true"
            android:layout_alignParentTop="true"
            android:layout_marginStart="8dp"
            android:layout_marginTop="8dp"
            android:insetLeft="0dp"
            android:insetTop="0dp"
            android:insetRight="0dp"
            android:insetBottom="0dp"
            app:backgroundTint="@android:color/transparent"
            app:cornerRadius="25dp"
            app:icon="@drawable/ic_button_back"
            app:iconGravity="textStart"
            app:iconPadding="0dp"
            app:iconSize="50dp"
            app:iconTint="@android:color/white"
            app:rippleColor="@color/brand_primary_opacity_input" />

        <com.google.android.material.button.MaterialButton
            android:id="@+id/buttonToStart"
            style="@style/Widget.MaterialComponents.Button.TextButton.Icon"
            android:layout_width="186dp"
            android:layout_height="52dp"
            android:layout_marginStart="21dp"
            android:layout_marginTop="8dp"
            android:layout_toEndOf="@+id/buttonBack"
            android:contentDescription="@null"
            android:text="@string/fromBeginning"
            android:textAllCaps="false"
            android:textColor="@android:color/white"
            android:textSize="14sp"
            android:visibility="gone"
            app:backgroundTint="#14FFFFFF"
            app:cornerRadius="21dp"
            app:icon="@drawable/ic_goback"
            app:iconSize="14dp"
            app:iconTint="@android:color/white"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:rippleColor="@color/brand_primary_opacity_input"
            app:shapeAppearance="@style/fromBeginning"
            tools:visibility="visible" />

        <ImageView
            android:id="@+id/riiviLogo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_alignParentEnd="true"
            android:layout_marginTop="12dp"
            android:layout_marginEnd="16dp"
            android:src="@drawable/ic_riivi_logo_player" />

        <TextView
            android:id="@+id/playerTitle"
            style="@style/PlayerTitle"
            android:layout_width="wrap_content"
            android:layout_height="28dp"
            android:layout_above="@+id/playerSerieTitle"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            android:gravity="center_vertical|start"
            tools:text="Título de Contenido" />

        <TextView
            android:id="@+id/playerSerieTitle"
            style="@style/PlayerSerieTitle"
            android:layout_width="wrap_content"
            android:layout_height="24dp"
            android:gravity="center_vertical|start"
            android:layout_above="@+id/playerControl"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            android:text=""
            android:visibility="gone"
            tools:text="Título de Contenido" />

        <com.google.android.material.card.MaterialCardView
            android:id="@+id/buttonNextEp"
            style="@null"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_above="@+id/playerControl"
            android:layout_alignParentEnd="true"
            android:layout_marginEnd="16dp"
            android:clickable="true"
            android:focusable="true"
            android:visibility="gone"
            android:layout_marginTop="6dp"
            app:cardCornerRadius="8dp"
            app:cardElevation="0dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:visibility="visible">

            <androidx.constraintlayout.widget.ConstraintLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/selector_button_next_ep">

                <FrameLayout
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:background="@android:color/transparent"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintTop_toTopOf="parent">

                    <LinearLayout
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal"
                        android:background="@android:color/transparent">

                        <TextView
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content"
                            android:fontFamily="@font/poppins_semibold"
                            android:gravity="center"
                            android:padding="6dp"
                            android:background="@android:color/transparent"
                            android:layout_marginTop="4dp"
                            android:layout_marginBottom="4dp"
                            android:layout_marginStart="8dp"
                            android:text="@string/btnNextEpisode"
                            android:textColor="@android:color/white"
                            android:textSize="16sp"
                            android:textStyle="bold" />

                        <ImageView
                            android:layout_width="20dp"
                            android:layout_height="20dp"
                            android:layout_gravity="center_vertical"
                            android:layout_marginStart="8dp"
                            android:layout_marginEnd="8dp"
                            android:background="@drawable/ic_play_margin_left" />
                    </LinearLayout>

                </FrameLayout>
            </androidx.constraintlayout.widget.ConstraintLayout>

        </com.google.android.material.card.MaterialCardView>

        <RelativeLayout
            android:id="@+id/thumbnail"
            android:layout_above="@+id/playerControl"
            android:layout_width="102dp"
            android:layout_height="62dp"
            android:visibility="invisible"
            android:background="@drawable/thumbnail_frame">

            <ImageView
                android:id="@+id/thumbnailImg"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_centerInParent="true"
                android:layout_margin="2dp"
                android:scaleType="centerCrop" />
        </RelativeLayout>

        <LinearLayout
            android:id="@+id/playerControl"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:layout_marginTop="8dp"
            android:gravity="center_horizontal"
            android:orientation="vertical"
            android:layout_alignParentBottom="true">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/positionView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="14sp"
                    android:textStyle="bold"
                    android:paddingStart="16dp"
                    android:paddingEnd="4dp"
                    android:includeFontPadding="false"
                    android:textColor="@android:color/white"
                    android:text="00:00" />

                <SeekBar
                    android:id="@+id/seekbar"
                    android:layout_width="0dp"
                    android:layout_weight="1"
                    android:layout_height="14dp"
                    android:paddingTop="5dp"
                    android:paddingBottom="5dp"
                    android:background="@android:color/transparent"
                    android:thumb="@drawable/ic_thumb"
                    android:progressDrawable="@drawable/gradient_player_seekbar"
                    tools:progress="30"
                    tools:secondaryProgress="40"/>

                <TextView
                    android:id="@+id/durationView"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="14sp"
                    android:textStyle="bold"
                    android:paddingStart="4dp"
                    android:paddingEnd="16dp"
                    android:includeFontPadding="false"
                    android:textColor="@android:color/white"
                    android:text="00:00" />

            </LinearLayout>

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <ImageButton
                    android:id="@+id/buttonSubtitle"
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:layout_marginStart="12dp"
                    android:background="@android:color/transparent"
                    android:foreground="@drawable/ripple_button_player"
                    android:visibility="gone"
                    android:src="@drawable/ic_subs"
                    tools:visibility="visible"/>

                <androidx.mediarouter.app.MediaRouteButton
                    android:id="@+id/buttonChromecast"
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:layout_alignParentEnd="true"
                    android:layout_marginEnd="16dp"
                    android:background="@android:color/transparent"
                    android:foreground="@drawable/ripple_button_player"
                    android:src="@drawable/ic_chromecast"
                    android:visibility="gone"
                    tools:visibility="visible" />

            </RelativeLayout>

        </LinearLayout>

    </RelativeLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:id="@+id/containerSuggestEpisode"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            android:background="?attr/selectableItemBackground"
            android:clickable="true"
            android:focusable="true"
            android:orientation="vertical"
            android:visibility="gone"
            tools:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.0">

            <include
                android:id="@+id/itemSuggestEpisode"
                layout="@layout/item_suggest_episode"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:visibility="visible" />
        </LinearLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

We have some additional buttons like back button, return to the start and next episode that are over the PlayerView. The RelativeLayout with android:id="@+id/playerUI" is the overlay player controls. The RelativeLayout with android:id="@+id/playerContainer" is the subtitle view container.

Also: we tried with and without replaceContentDuration = 0.0, preloadOffset = 1.0 params. Same issue. And we are not setting an additional AdViewGroup via API.

Hi @gledezma . Thanks for sharing the Player view information. There are couple of observations/questions.

  • You mentioned earlier that way to reproduce the issue, you need to re-enter PlayerView and pausing/resuming Ads. In general casting UX, when the content is casted, player does not show playback controls for local playback but instead cast UI to control casting playback. You can check this with BasicCastingSample. So it is not clear why in your UX, the app allows to control playback of local player.

  • Do you destroy and re-create player object when exiting and returning to player activity or do you re-use the previously created player object? In either case, on re-entering the PlayerView when casting is already started earlier, then the player view should show cast UI instead of local playback controls.

  • Can you test with BasicCastingSample and check if you are able to reproduce the issue. You can also check the cast UX and compare with your application.

  • Please do also test with the latest (3.24.1) player SDK.