Skip to content

Video freeze when seekTo is called after midroll ads #10274

Closed

Description

@usopphammer

Our QA team observes the same bug - #7161
When we call Player.seekTo() method a video freezes and the player doesn't react to any media event. It's very hard to reproduce, on my devices it happens 1 time out of 1000.

We use the latest 2.17 version of the Player. There are no deprecated classes in our code. Timeouts are set by default.
It happens for any ads, even for ads from this list https://developers.google.com/interactive-media-ads/docs/sdks/html5/client-side/tags

Do you have any ideas about what can be a root cause? Any possible fix or workaround?

Activity

  1. self-assigned this
    on May 19, 2022
  2. icbaker commented on May 19, 2022

    @icbaker
    Collaborator

    Can you provide a little more information about your setup? Specifically:

    • Is the content between the ads protected with DRM?
      • If so, how do you configure the DRM playback? A sample code snippet of instantiating a MediaItem or MediaSource would be helpful here, as well as any direct DrmSessionManager configuration e.g. via DefaultDrmSessionManager.Builder.
    • Precisely how are you triggering Player.seekTo() 'after midroll ads'? Are you reacting to an event, e.g. from Player.Listener or AnalyticsListener or are you using just time-based triggering e.g. with ExoPlayer.createMessage?
  3. denis-solomko-deltatre commented on May 30, 2022

    @denis-solomko-deltatre

    @icbaker

    1. Yes we use DRM

    DRM creation

    private fun buildDrmSessionManager(
            context: Context,
            drmSchemeUuid: UUID?,
            drmLicenseUrl: String
    ): DefaultDrmSessionManager {
    
            val drmCallback = HttpMediaDrmCallback(
                drmLicenseUrl,
                DefaultHttpDataSource.Factory().setUserAgent(getUserAgent(context))
            )
    
            releaseMediaDrm()
    
            try {
                frameworkMediaDrm = FrameworkMediaDrm.newInstance(drmSchemeUuid!!)
            } catch (exception: UnsupportedDrmException) {
                AxisLogger.instance().e(exception.message)
            }
    
            return DefaultDrmSessionManager.Builder()
                .setUuidAndExoMediaDrmProvider(drmSchemeUuid!!, FrameworkMediaDrm.DEFAULT_PROVIDER)
                .build(drmCallback)
    }
    

    MediaSource creation

     /**
       * Builds the [MediaSource] object containing the main video Media Source.
       *
       * @param videoUri the videoUrl
       * @return MediaSource instance
       */
    private fun buildDASHMediaSource(
            uri: Uri,
            drmSessionManager: DrmSessionManager // a previously created DRM session manager
    ): MediaSource {
            return DashMediaSource.Factory(
                DefaultDashChunkSource.Factory(mediaDataSourceFactory!!),
                mediaDataSourceFactory
            )
                .setDefaultSettings(drmSessionManager, createLoadErrorPolicy())
                .createMediaSource(createMediaItem(uri))
    }
    

    AdsMediaSource creation

     private fun createAdsMediaSource(
            playerView: StyledPlayerView,
            mediaSource: MediaSource, // a previously created dash media source
            drmEngine: DrmSessionManager, // a previously created DRM session manager
            adTagUri: Uri,
    ): MediaSource {
    
            adsLoader = ImaAdsLoader.Builder(playerView.context).build().apply {
                setPlayer(playerView.player)
            }
    
            val adMediaSourceFactory = AdsMediaSourceFactory(this::buildDASHMediaSource)
                .setDrmSessionManagerProvider {drmEngine }
    
            return mediaSource.mediaItem.localConfiguration?.let {
                // this code duplicates DefaultMediaSourceFactory.maybeWrapWithAdsMediaSource
                val adTagDataSpec = DataSpec(adTagUri)
                val adsId = ImmutableList.of(mediaSource.mediaItem.mediaId, it.uri, adTagUri)
                AdsMediaSource(mediaSource, adTagDataSpec, adsId, adMediaSourceFactory, adsLoader!!, playerView)
            }
                ?: mediaSource
    }
    

    our AdsMediaSourceFactory

    class AdsMediaSourceFactory(
        val buildMediaSourceFactoryMethod: (Uri, DrmSessionManager) -> MediaSource
    ) : MediaSource.Factory {
    
        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 {
            return intArrayOf(C.TYPE_DASH, C.TYPE_OTHER)
        }
    
        override fun createMediaSource(mediaItem: MediaItem): MediaSource {
            val drmSessionManager = drmSessionManagerProvider?.get(mediaItem)
                ?: throw IllegalStateException("drmSessionManager is null")
    
            return mediaItem.localConfiguration?.uri
                ?.let {
                    buildMediaSourceFactoryMethod(it, drmSessionManager)
                } ?: let {
                    throw IllegalStateException("uri is null")
                }
        }
    }
    
    1. we trigger seekTo in a button click listener
  4. icbaker commented on May 30, 2022

    @icbaker
    Collaborator

    Are you able to try depending on ExoPlayer locally? If so please try applying this patch on top of r2.17.1 and see if it fixes the issue.

    We think there's a theoretical problem with the way we handle seeking after a format switch (like ad -> content) in DRM content - but we've not been able to reproduce a problem at all in our demo app. We're reluctant to submit the fix to the library without being able to directly see it fix something - so since you seem to have a repro case it would be great if you could report back with your findings (either to let us know that it worked, or that it didn't make a difference (or that it made things worse!)). Thanks!

  5. icbaker commented on Jun 15, 2022

    @icbaker
    Collaborator

    I'm closing this because I hope it's fixed with the commit linked above, which will be included in the next release.

  6. denis-solomko-deltatre commented on Jun 15, 2022

    @denis-solomko-deltatre

    @icbaker I sent a build for our qa team, but unfortunately, they haven't checked it yet as they have a lot of other work to do. They will be able to test it only next week. Please don't close the ticket now, I will write an update later.

  7. denis-solomko-deltatre commented on Jun 16, 2022

    @denis-solomko-deltatre

    @icbaker I've received info from ous QAs. The bug is not reproducible with this approach. Thanks!

  8. denis-solomko-deltatre commented on Jun 16, 2022

    @denis-solomko-deltatre

    @icbaker Could you tell me when the next release will be?

  9. icbaker commented on Jun 20, 2022

    @icbaker
    Collaborator
  10. locked and limited conversation to collaborators on Aug 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions