You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We modified ImaAdsLoader to support feature we called Smart seek. It means, ads will not start when another ad was played within defined amount of time. In other words, timeline has 5 ad breaks, when you seek between first and second one, IMA will start playing first ad break. Immediately after the end of the ad you seek between second and third one, but at this time, ad will start because media playback does not exceed time threshold to play next ads.
I sent you source code of modified ImaAdsLoader on email. All my modifications are marked with MARK TOM. Please set adWatchThreshold to 25 seconds (25000) and use this VMAP that has ad breaks every 20 seconds. Player plays the preroll, skips first midroll and plays second midroll. We need to update AdPlaybackState before the first midroll and that cause 1 second buffering that is unacceptable for our client.
Could you please help us? Is there any solution how to prevent from buffering when update AdPlaybackState? Can we implement this feature by another way?
Hi @chladto1, I don't think we can allocate resources to help debugging app customizations. @tonihei do you see any way forward to efficiently assist with this?
As @AquilesCanta already pointed out, we can't really help you debug custom solutions in detail.
Is there any solution how to prevent from buffering when update AdPlaybackState?
Updating AdPlaybackState causes the player to reevaluate its internal playback queue. In some cases, this means we need to reset the current rendering and cause a short buffering state. I'm not sure if that's what's causing your buffering, but it seems likely. For example, if the player is currently prebuffering an ad and some parts of this ad's media information has been sent to the decoders, we can't remove the ad without causing a complete decoder reset (and a buffering state). So, depending on when you see the buffering happen, you may be able to improve it by making the update earlier.
Can we implement this feature by another way?
We have some pending feature requests to support more flexible ad group position handling, for example #5067 and #5482. It's unlikely we get around to do any of these soon though.
Generally, it's hard to modify the ad execution logic as it's handled internally by the player in a non-customizable component. The only way you have to influence the decision is to mark existing ads as skipped or failed, which I believe you are already doing.
Ads are marked as skipped (Exo) and getContentVideoProgressUpdate() is returning VIDEO_TIME_NOT_READY as content position (IMA). When conditions are met, skipped ads are replaced by new AdPlaybackState.AdGroup and real content position is provided to IMA.
improve it by making the update earlier
In the test content above, getContentVideoProgressUpdate() returns VIDEO_TIME_NOT_READY for 20 seconds before ads position (IMA) and ads are marked as skipped 1 second before their position (Exo). At this moment, Exo doesn't have URL to load ads, so there is no content to buffering, right? Should I mark ads as skipped even earlier?
When conditions are met, skipped ads are replaced by new AdPlaybackState.AdGroup and real content position is provided to IMA.
There are probably some internal assumptions about "allowed" changes, for example that an ad group that was "skipped" can't suddenly become available for playback again. This may still work, but our internal code wasn't written under such assumptions and may not work correctly in all cases if you that.
In the test content above, getContentVideoProgressUpdate() returns VIDEO_TIME_NOT_READY for 20 seconds before ads position (IMA)
I'm not sure why you need to fake the video progress update. Marking the ad break as skipped should be enough for the player to not play it.
At this moment, Exo doesn't have URL to load ads, so there is no content to buffering, right? Should I mark ads as skipped even earlier?
Your original description didn't make it very clear where and when the buffering is happening exactly. There may also be other reasons, e.g. if the player originally planned to play an ad at a certain position, it may have already clipped the content. While theoretically possible, we don't currently extend this clipping when the ad group is suddenly marked as skipped, but instead you'll see a short buffering at the point where the ad group should have been. If you want to avoid that, you'd need to mark the ad group as skipped before the content that ends at the ad group even starts loading.
I'm not sure why you need to fake the video progress update.
Because of IMA. If I send the real position, IMA start preloading ads and they will be timeouted, because Exo didn't start playing them.
Your original description didn't make it very clear where and when the buffering is happening exactly.
Sorry, buffering will occur when is called AdTagLoader.updateAdPlaybackState() with newly skipped ads. It cause call AdsMediaSource.maybeUpdateSourceInfo() and BaseMediaSource.refreshSourceInfo() which I think the problem is.
If I understood correctly, at the moment, marking ads as skipped without short buffering is not possible, right?
I'm not sure why you need to fake the video progress update.
Because of IMA. If I send the real position, IMA start preloading ads and they will be timeouted, because Exo didn't start playing them.
Just a side note on this: calling AdsManager.discardAdBreak when no ad is playing is supposed to discard the next ad break, so may work as an alternative workaround. (I don't know exactly what callbacks happen next but it may also be necessary to mark the ad break as skipped on the ExoPlayer side when doing this.)
I think you could avoid this by marking it as skipped earlier (e.g. while the previous ad is still playing)
When previous ad is playing, I don't know if a user will seek behind another ad in time threshold. If I do it, I must unset skipped state which probably cause buffering too. I think, in a real situation this probably cause more buffering. In the current implementation, unsetting skipped state is happening only when a user seeking, so additional buffering is invisible to a user.
calling AdsManager.discardAdBreak when no ad is playing is supposed to discard the next ad break
Calling AdsManager.discardAdBreak will discard ad break forever, in our solution ads should be skipped only temporary. It's mean, when a user seeks before previously skipped ads, they should be again playable.
I'll mark this issue as an enhancement to track that skipped midrolls cause short buffering. This may be solvable independent of #5067 and #5482 (e.g. by updating the clip end position of the content).
Activity
AquilesCanta commentedon Apr 13, 2021
Hi @chladto1, I don't think we can allocate resources to help debugging app customizations. @tonihei do you see any way forward to efficiently assist with this?
tonihei commentedon Apr 14, 2021
As @AquilesCanta already pointed out, we can't really help you debug custom solutions in detail.
Updating
AdPlaybackStatecauses the player to reevaluate its internal playback queue. In some cases, this means we need to reset the current rendering and cause a short buffering state. I'm not sure if that's what's causing your buffering, but it seems likely. For example, if the player is currently prebuffering an ad and some parts of this ad's media information has been sent to the decoders, we can't remove the ad without causing a complete decoder reset (and a buffering state). So, depending on when you see the buffering happen, you may be able to improve it by making the update earlier.We have some pending feature requests to support more flexible ad group position handling, for example #5067 and #5482. It's unlikely we get around to do any of these soon though.
Generally, it's hard to modify the ad execution logic as it's handled internally by the player in a non-customizable component. The only way you have to influence the decision is to mark existing ads as skipped or failed, which I believe you are already doing.
chladto1 commentedon Apr 14, 2021
Ads are marked as skipped (Exo) and
getContentVideoProgressUpdate()is returningVIDEO_TIME_NOT_READYas content position (IMA). When conditions are met, skipped ads are replaced by newAdPlaybackState.AdGroupand real content position is provided to IMA.In the test content above,
getContentVideoProgressUpdate()returnsVIDEO_TIME_NOT_READYfor 20 seconds before ads position (IMA) and ads are marked as skipped 1 second before their position (Exo). At this moment, Exo doesn't have URL to load ads, so there is no content to buffering, right? Should I mark ads as skipped even earlier?tonihei commentedon Apr 14, 2021
There are probably some internal assumptions about "allowed" changes, for example that an ad group that was "skipped" can't suddenly become available for playback again. This may still work, but our internal code wasn't written under such assumptions and may not work correctly in all cases if you that.
I'm not sure why you need to fake the video progress update. Marking the ad break as skipped should be enough for the player to not play it.
Your original description didn't make it very clear where and when the buffering is happening exactly. There may also be other reasons, e.g. if the player originally planned to play an ad at a certain position, it may have already clipped the content. While theoretically possible, we don't currently extend this clipping when the ad group is suddenly marked as skipped, but instead you'll see a short buffering at the point where the ad group should have been. If you want to avoid that, you'd need to mark the ad group as skipped before the content that ends at the ad group even starts loading.
chladto1 commentedon Apr 14, 2021
Because of IMA. If I send the real position, IMA start preloading ads and they will be timeouted, because Exo didn't start playing them.
Sorry, buffering will occur when is called
AdTagLoader.updateAdPlaybackState()with newly skipped ads. It cause callAdsMediaSource.maybeUpdateSourceInfo()andBaseMediaSource.refreshSourceInfo()which I think the problem is.If I understood correctly, at the moment, marking ads as skipped without short buffering is not possible, right?
tonihei commentedon Apr 15, 2021
Not in the setup you describe. I think you could avoid this by marking it as skipped earlier (e.g. while the previous ad is still playing)
andrewlewis commentedon Apr 15, 2021
Just a side note on this: calling
AdsManager.discardAdBreakwhen no ad is playing is supposed to discard the next ad break, so may work as an alternative workaround. (I don't know exactly what callbacks happen next but it may also be necessary to mark the ad break as skipped on the ExoPlayer side when doing this.)chladto1 commentedon Apr 16, 2021
When previous ad is playing, I don't know if a user will seek behind another ad in time threshold. If I do it, I must unset skipped state which probably cause buffering too. I think, in a real situation this probably cause more buffering. In the current implementation, unsetting skipped state is happening only when a user seeking, so additional buffering is invisible to a user.
Calling
AdsManager.discardAdBreakwill discard ad break forever, in our solution ads should be skipped only temporary. It's mean, when a user seeks before previously skipped ads, they should be again playable.tonihei commentedon Apr 19, 2021
I'll mark this issue as an enhancement to track that skipped midrolls cause short buffering. This may be solvable independent of #5067 and #5482 (e.g. by updating the clip end position of the content).
[-]Buffering when update AdPlaybackState[/-][+]Short buffering at skipped midrolls[/+][-]Short buffering at skipped midrolls[/-][+]Avoid short buffering at skipped midrolls[/+]