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

Get few seconds black screen when switching to empty mid roll with DRM protected video #8568

Closed
z423821123 opened this issue Feb 9, 2021 · 6 comments

Comments

@z423821123
Copy link

z423821123 commented Feb 9, 2021

[REQUIRED] Issue description

Playing DRM protected video in empty mid roll will appear about 1 seconds black screen. It's easy to reproduce in demo app.

[REQUIRED] Reproduction steps

  1. Add this ads tag uri "https://vastsynthesizer.appspot.com/empty-midroll-2" info DRM protected video in demo app
"name": "Widevine DASH (MP4, H264)",
    "samples": [
      {
        "name": "HD (cenc)",
        "uri": "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd",
        "drm_scheme": "widevine",
        "drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test",
        "ad_tag_uri": "https://vastsynthesizer.appspot.com/empty-midroll-2"
      },
      {
        "name": "UHD (cenc)",
        "uri": "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears_uhd.mpd",
        "drm_scheme": "widevine",
        "drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test"
      },
      {
        "name": "HD (cbcs)",
        "uri": "https://storage.googleapis.com/wvmedia/cbcs/h264/tears/tears_aes_cbcs.mpd",
        "drm_scheme": "widevine",
        "drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test"
      },
      {
        "name": "UHD (cbcs)",
        "uri": "https://storage.googleapis.com/wvmedia/cbcs/h264/tears/tears_aes_cbcs_uhd.mpd",
        "drm_scheme": "widevine",
        "drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test"
      },
      {
        "name": "Secure -> Clear -> Secure (cenc)",
        "uri": "https://storage.googleapis.com/exoplayer-test-media-1/widevine/tears_enc_clear_enc.mpd",
        "drm_scheme": "widevine",
        "drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test",
        "drm_session_for_clear_content": true
      }
    ]
  }

2.Click HD(cenc)
image

3.Found that frame become black about 1 seconds with the second empty mid roll

[REQUIRED] Version

2.13.0

[REQUIRED] Device

Samsung Galaxy S10, Android 10

@icbaker
Copy link
Collaborator

icbaker commented Feb 9, 2021

I can't reproduce what you're seeing with a Pixel 3a XL.

However I suspect it might be related to switching between secure and clear decoders. Can you try adding "drm_session_for_clear_content": true to the same JSON snippet and see what happens?

{
  "name": "HD (cenc)",
  "uri": "https://storage.googleapis.com/wvmedia/cenc/h264/tears/tears.mpd",
  "drm_scheme": "widevine",
  "drm_license_uri": "https://proxy.uat.widevine.com/proxy?provider=widevine_test",
  "ad_tag_uri": "https://vastsynthesizer.appspot.com/empty-midroll-2",
  "drm_session_for_clear_content": true
},

More info: https://exoplayer.dev/drm.html#drm-sessions-for-clear-content

@z423821123
Copy link
Author

z423821123 commented Feb 10, 2021

Still reproduce in demo app when I adding "drm_session_for_clear_content": true to the JSON. I will email the attachment to dev.exoplayer@gmail.com

@icbaker
Copy link
Collaborator

icbaker commented Feb 11, 2021

Thanks for trying that - sorry it didn't work. I took a closer look and realised the drm_session_for_clear_content flag isn't properly propagated all the way down when using the MediaItem API. I've sent a change to fix that.

I determined I couldn't reproduce because the symptom is device specific - a colleague was able to reproduce with their Samsung device.

ojw28 pushed a commit that referenced this issue Feb 12, 2021
The `DrmConfiguration.sessionForClearTypes` property is often used
to ensure a secure decoder is used for clear ads played in encrypted
content. This is because some devices show black frames when switching
decoders.

Before this change the DRM config isn't propagated down when
constructing the ad media source, meaning
`DrmSessionManager.DRM_UNSUPPORTED` is always used, which will
cause playback to switch from secure to clear decoder when transitioning
to an ad break (ignoring the MediaItem `sessionForClearTypes` option.

Issue: #8568

#minor-release

PiperOrigin-RevId: 356951124
ojw28 pushed a commit that referenced this issue Feb 12, 2021
The `DrmConfiguration.sessionForClearTypes` property is often used
to ensure a secure decoder is used for clear ads played in encrypted
content. This is because some devices show black frames when switching
decoders.

Before this change the DRM config isn't propagated down when
constructing the ad media source, meaning
`DrmSessionManager.DRM_UNSUPPORTED` is always used, which will
cause playback to switch from secure to clear decoder when transitioning
to an ad break (ignoring the MediaItem `sessionForClearTypes` option.

Issue: #8568

PiperOrigin-RevId: 356951124
@ojw28 ojw28 closed this as completed Feb 12, 2021
@z423821123
Copy link
Author

z423821123 commented Feb 16, 2021

Thanks for your support,But I tested 2.13.1 and it still getting black frame 1 seconds when the timeline approaches empty vast ad break, and I pass "drm_session_for_clear_content": true value to JSON haven't any help.

I assume that AdsMediaSource has update source information which is AD_STATE_ERROR AdPlaybackState via maybeUpdateSourceInfo().

 private void maybeUpdateSourceInfo() {
    @Nullable Timeline contentTimeline = this.contentTimeline;
    if (adPlaybackState != null && contentTimeline != null) {
      adPlaybackState = adPlaybackState.withAdDurationsUs(getAdDurationsUs());
      Timeline timeline =
          adPlaybackState.adGroupCount == 0
              ? contentTimeline
              : new SinglePeriodAdTimeline(contentTimeline, adPlaybackState);
      refreshSourceInfo(timeline);
    }
  }

@icbaker @ojw28

@icbaker
Copy link
Collaborator

icbaker commented Feb 17, 2021

You're right - there's two different things interacting here and we only fixed one of them.

Specifically when the mid-roll is empty we still release and re-initialize the (secure) video decoder.

With "drm_session_for_clear_content": false you can see the secure decoder being released and replaced by an insecure video decoder for each non-empty midroll (10s and 30s). But at the empty one (12.2s) we just release & immediately reacquire the secure decoder:

videoDecoderInitialized [eventTime=1.19, mediaPos=0.00, window=0, period=0, c2.qti.avc.decoder.secure]               
videoDecoderReleased [eventTime=11.71, mediaPos=0.00, window=0, period=0, adGroup=0, ad=0, c2.qti.avc.decoder.secure]
videoDecoderInitialized [eventTime=11.81, mediaPos=0.00, window=0, period=0, adGroup=0, ad=0, c2.qti.avc.decoder]    
videoDecoderReleased [eventTime=21.75, mediaPos=10.00, window=0, period=0, c2.qti.avc.decoder]                       
videoDecoderInitialized [eventTime=21.87, mediaPos=10.00, window=0, period=0, c2.qti.avc.decoder.secure]             
videoDecoderReleased [eventTime=24.05, mediaPos=12.21, window=0, period=0, c2.qti.avc.decoder.secure]                
videoDecoderInitialized [eventTime=24.38, mediaPos=12.21, window=0, period=0, c2.qti.avc.decoder.secure]             
videoDecoderReleased [eventTime=42.51, mediaPos=0.00, window=0, period=0, adGroup=2, ad=0, c2.qti.avc.decoder.secure]
videoDecoderInitialized [eventTime=42.60, mediaPos=0.00, window=0, period=0, adGroup=2, ad=0, c2.qti.avc.decoder]    
videoDecoderReleased [eventTime=52.56, mediaPos=30.00, window=0, period=0, c2.qti.avc.decoder]                       
videoDecoderInitialized [eventTime=52.66, mediaPos=30.00, window=0, period=0, c2.qti.avc.decoder.secure]             

With "drm_session_for_clear_content": true the secure decoder is kept for both the non-empty midrolls, but it's still released/reacquired at the empty one:

videoDecoderInitialized [eventTime=1.28, mediaPos=0.00, window=0, period=0, c2.qti.avc.decoder.secure]
videoDecoderReleased [eventTime=24.26, mediaPos=12.24, window=0, period=0, c2.qti.avc.decoder.secure]
videoDecoderInitialized [eventTime=24.60, mediaPos=12.24, window=0, period=0, c2.qti.avc.decoder.secure]

This is what's causing the black screen you're seeing.

I foolishly only checked that the decoder was kept for the non-empty midroll when testing (because that fires first) and didn't consider there might be a secondary behaviour that only affects empty ones.

Re-opening to track keeping decoders alive during empty mid-roll ads.

@icbaker
Copy link
Collaborator

icbaker commented May 20, 2021

The secure decoder re-initialization is fixed by removing the TODO and associated logic discussed in #8842 (comment).

I'll dupe this to that (since it affects more than just empty mid-rolls) - please follow that issue for further updates.

@icbaker icbaker closed this as completed May 20, 2021
@google google locked and limited conversation to collaborators Jul 20, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants