Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suppress player error during ad playback #2067

Open
1 task
cdongieux opened this issue Jan 22, 2025 · 5 comments
Open
1 task

Suppress player error during ad playback #2067

cdongieux opened this issue Jan 22, 2025 · 5 comments
Assignees

Comments

@cdongieux
Copy link

Version

Media3 1.5.1

More version details

No response

Devices that reproduce the issue

Any device

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Yes

Reproduction steps

When playing a content with ads (handled by IMA SDK and media3-exoplayer-ima), and a playback error occurs during an ad playback, then the player stops instead of playing next ads and/or content.

Code example:

    String vmapPayload = "<?xml version='1.0' encoding='utf-8'?>\n"
        + "<vmap:VMAP\n"
        + "    xmlns:vmap=\"http://www.iab.net/vmap-1.0\" version=\"1.0\">\n"
        + "    <vmap:AdBreak breakId=\"0.0.0.2097493962\" breakType=\"linear\" timeOffset=\"start\">\n"
        + "        <vmap:AdSource allowMultipleAds=\"true\" followRedirects=\"true\" id=\"1\">\n"
        + "            <vmap:VASTAdData>\n"
        + "                <VAST\n"
        + "                    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" version=\"3.0\" xsi:noNamespaceSchemaLocation=\"vast.xsd\">\n"
        + "                    <Ad id=\"preroll_1_10s\" sequence=\"1\">\n"
        + "                        <InLine>\n"
        + "                            <AdTitle>Preroll 1 10s</AdTitle>\n"
        + "                            <Creatives>\n"
        + "                                <Creative>\n"
        + "                                    <Linear>\n"
        + "                                        <Duration>00:00:10</Duration>\n"
        + "                                        <MediaFiles>\n"
        + "                                            <MediaFile delivery=\"progressive\" width=\"1920\" height=\"1080\" type=\"video/mp4\">https://redirector.gvt1.com/videoplayback/id/5bad011a1282b323/itag/15/source/gfp_video_ads/requiressl/yes/xpc/EgVovf3BOg%3D%3D/acao/yes/mime/video%2Fmp4/ctier/L/ip/0.0.0.0/ipbits/0/expire/1737562261/sparams/ip,ipbits,expire,id,itag,source,requiressl,xpc,acao,mime,ctier/signature/14D60A0FBE5C83B49C4F42C64F092762E1C4E5E4.629F613FC722416BE01AC39AEEF4C75D044752C4/key/ck2/file/file.mp4</MediaFile>\n"
        + "                                        </MediaFiles>\n"
        + "                                    </Linear>\n"
        + "                                </Creative>\n"
        + "                            </Creatives>\n"
        + "                        </InLine>\n"
        + "                    </Ad>\n"
        + "                    <Ad id=\"failing_playback\" sequence=\"2\">\n"
        + "                        <InLine>\n"
        + "                            <AdTitle>Failing playback</AdTitle>\n"
        + "                            <Creatives>\n"
        + "                                <Creative>\n"
        + "                                    <Linear>\n"
        + "                                        <Duration>00:10:00</Duration>\n"
        + "                                        <MediaFiles>\n"
        + "                                            <MediaFile bitrate=\"3551\" delivery=\"progressive\" height=\"720\" type=\"video/mp4\" width=\"1280\">https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd</MediaFile>\n"
        + "                                        </MediaFiles>\n"
        + "                                    </Linear>\n"
        + "                                </Creative>\n"
        + "                            </Creatives>\n"
        + "                        </InLine>\n"
        + "                    </Ad>\n"
        + "                    <Ad id=\"bumper_5s\" sequence=\"3\">\n"
        + "                        <InLine>\n"
        + "                            <AdTitle>Bumper 5s</AdTitle>\n"
        + "                            <Creatives>\n"
        + "                                <Creative>\n"
        + "                                    <Linear>\n"
        + "                                        <Duration>00:00:05</Duration>\n"
        + "                                        <MediaFiles>\n"
        + "                                            <MediaFile bitrate=\"3579\" delivery=\"progressive\" height=\"720\" type=\"video/mp4\" width=\"1280\">https://redirector.gvt1.com/videoplayback/id/74a5ae2cc4775d2a/itag/15/source/gfp_video_ads/requiressl/yes/xpc/EgVovf3BOg%3D%3D/acao/yes/mime/video%2Fmp4/ctier/L/ip/0.0.0.0/ipbits/0/expire/1737562262/sparams/ip,ipbits,expire,id,itag,source,requiressl,xpc,acao,mime,ctier/signature/7B2E333F108DC54595B3E668E084900C5947352E.1230133A2A6C78A4976A3FA3F8051A091E6F7DE5/key/ck2/file/file.mp4</MediaFile>\n"
        + "                                        </MediaFiles>\n"
        + "                                    </Linear>\n"
        + "                                </Creative>\n"
        + "                            </Creatives>\n"
        + "                        </InLine>\n"
        + "                    </Ad>\n"
        + "                </VAST>\n"
        + "            </vmap:VASTAdData>\n"
        + "        </vmap:AdSource>\n"
        + "    </vmap:AdBreak>\n"
        + "</vmap:VMAP>";
    player.setMediaItem(
        new MediaItem.Builder()
            .setUri("https://storage.googleapis.com/wvmedia/clear/h264/tears/tears.mpd")
            .setDrmConfiguration(
                new MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID)
                    .setLicenseUri("https://www.google.com/") // causes ad 2 to fail
                    .build()
            )
            .setAdsConfiguration(
                new MediaItem.AdsConfiguration.Builder(Util.getDataUriForString("text/xml", vmapPayload))
                    .build()
            )
            .build()
    );

In this example, the 2nd ad fails to play because it is DRM protected and the given license URL is wrong.

Expected result

Ads following the failed ad play, then the content plays.

Actual result

The player stops with an error.

Media

Not applicable

Bug Report

  • You will email the zip file produced by adb bugreport to [email protected] after filing this issue.
@cdongieux
Copy link
Author

cdongieux commented Jan 22, 2025

Sorry, 1st and 3rd media URI produce a HTTP 403 error, it is not intended. I guess they are no longer available now. I extracted these URLs from this adsTag https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpreonlybumper&cmsid=496&vid=short_onecue&correlator=

@tonihei
Copy link
Collaborator

tonihei commented Jan 24, 2025

Thanks for reporting. The player already skips ads that fail to load initially or have issues preparing. There is currently no mechanism to catch and ignore errors occurring later in the pipeline though (this includes DRM load errors).

Is the failed DRM resolution a real example or was this just a way to test out if the player skips an ad?

@cdongieux
Copy link
Author

There is currently no mechanism to catch and ignore errors occurring later in the pipeline though

As apps embedding Media3 to play content with ads have often absolutely no control on what kind of ad media are delivered, the player might stop because of an unsupported media. It may be because of a low-end device not supporting non-traditional formats, or it may be because an ads provider could give a corrupted media file.

So I think this use case should be handled by Media3, or at least there should be a warning on the documentation about this. What's your opinion?

As a workaround, I setup a listener for Player.Listener.onPlayerError(PlaybackException):

    fun handlePlayerError(): Boolean {
        return if (player.isPlayingAd) {
            player.playWhenReady = true
            player.prepare()
            true
        } else {
            false
        }
    }

It seems to work fine, as next ads are played, and the content too.

Is the failed DRM resolution a real example or was this just a way to test out if the player skips an ad?

No, it was just a way to test this behavior.

Maybe ImaAdsLoader.setPlayer(Player) would be a good entry point to set up a Player.Listener.onPlayerError(PlaybackException).

@tonihei
Copy link
Collaborator

tonihei commented Jan 27, 2025

So I think this use case should be handled by Media3

Yes, I agree. We already handle the equivalent case for errors during initial media preparation (where most network related issues occur), so it's only logical to extend that to all errors happening during ad playback. And ideally this happens without ever surfacing the errors as a regular player error via Player.Listener similar to the current handling. I mark it as a feature request.

@tonihei tonihei changed the title [IMA] Player stops if an ad fails to play Suppress player error during ad playback Jan 27, 2025
@cdongieux
Copy link
Author

Great! Thanks a lot!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants