mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Handle LOG AdEvents for ad group load errors.
If IMA loads an empty VAST document for an ad group it notifies via a LOG AdEvent. Handle the event by updating the AdPlaybackState accordingly. The error state will be handled in ExoPlayerImplInternal in a separate change. Issue: #3584 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=184516585
This commit is contained in:
parent
901dd19e3e
commit
aa63ad3af0
@ -81,6 +81,8 @@
|
|||||||
* CacheDataSource: Check periodically if it's possible to read from/write to
|
* CacheDataSource: Check periodically if it's possible to read from/write to
|
||||||
cache after deciding to bypass cache.
|
cache after deciding to bypass cache.
|
||||||
* IMA extension:
|
* IMA extension:
|
||||||
|
* Fix the player getting stuck when an ad group fails to load
|
||||||
|
([#3584](https://github.com/google/ExoPlayer/issues/3584)).
|
||||||
* Work around loadAd not being called beore the LOADED AdEvent arrives
|
* Work around loadAd not being called beore the LOADED AdEvent arrives
|
||||||
([#3552](https://github.com/google/ExoPlayer/issues/3552)).
|
([#3552](https://github.com/google/ExoPlayer/issues/3552)).
|
||||||
* Add support for playing non-Extractor content MediaSources in
|
* Add support for playing non-Extractor content MediaSources in
|
||||||
|
@ -566,6 +566,16 @@
|
|||||||
"name": "VMAP pre-roll single ad, mid-roll standard pods with 5 ads every 10 seconds for 1:40, post-roll single ad",
|
"name": "VMAP pre-roll single ad, mid-roll standard pods with 5 ads every 10 seconds for 1:40, post-roll single ad",
|
||||||
"uri": "https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv",
|
"uri": "https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv",
|
||||||
"ad_tag_uri": "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%3Dpremidpostlongpod&cmsid=496&vid=short_tencue&correlator="
|
"ad_tag_uri": "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%3Dpremidpostlongpod&cmsid=496&vid=short_tencue&correlator="
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "VMAP empty midroll",
|
||||||
|
"uri": "https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv",
|
||||||
|
"ad_tag_uri": "http://vastsynthesizer.appspot.com/empty-midroll"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "VMAP full, empty, full midrolls",
|
||||||
|
"uri": "https://storage.googleapis.com/exoplayer-test-media-1/mkv/android-screens-lavf-56.36.100-aac-avc-main-1280x720.mkv",
|
||||||
|
"ad_tag_uri": "http://vastsynthesizer.appspot.com/empty-midroll-2"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -516,6 +516,9 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
|||||||
case LOG:
|
case LOG:
|
||||||
Map<String, String> adData = adEvent.getAdData();
|
Map<String, String> adData = adEvent.getAdData();
|
||||||
Log.i(TAG, "Log AdEvent: " + adData);
|
Log.i(TAG, "Log AdEvent: " + adData);
|
||||||
|
if ("adLoadError".equals(adData.get("type"))) {
|
||||||
|
handleAdGroupLoadError();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ALL_ADS_COMPLETED:
|
case ALL_ADS_COMPLETED:
|
||||||
default:
|
default:
|
||||||
@ -894,6 +897,23 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleAdGroupLoadError() {
|
||||||
|
AdPlaybackState.AdGroup adGroup = adPlaybackState.adGroups[expectedAdGroupIndex];
|
||||||
|
// Ad group load error can be notified more than once, so check if it was already handled.
|
||||||
|
// TODO: Update the expected ad group index based on the position returned by
|
||||||
|
// getContentProgress so that it's possible to detect when more than one ad group fails to load
|
||||||
|
// consecutively.
|
||||||
|
if (adGroup.count == C.LENGTH_UNSET
|
||||||
|
|| adGroup.states[0] == AdPlaybackState.AD_STATE_UNAVAILABLE) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "Removing ad group " + expectedAdGroupIndex + " as it failed to load");
|
||||||
|
}
|
||||||
|
adPlaybackState = adPlaybackState.withAdCount(expectedAdGroupIndex, 1);
|
||||||
|
adPlaybackState = adPlaybackState.withAdLoadError(expectedAdGroupIndex, 0);
|
||||||
|
updateAdPlaybackState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void checkForContentComplete() {
|
private void checkForContentComplete() {
|
||||||
if (contentDurationMs != C.TIME_UNSET && pendingContentPositionMs == C.TIME_UNSET
|
if (contentDurationMs != C.TIME_UNSET && pendingContentPositionMs == C.TIME_UNSET
|
||||||
&& player.getContentPosition() + END_OF_CONTENT_POSITION_THRESHOLD_MS >= contentDurationMs
|
&& player.getContentPosition() + END_OF_CONTENT_POSITION_THRESHOLD_MS >= contentDurationMs
|
||||||
@ -939,6 +959,21 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
|||||||
return adGroupTimesUs.length == 0 ? C.INDEX_UNSET : (adGroupTimesUs.length - 1);
|
return adGroupTimesUs.length == 0 ? C.INDEX_UNSET : (adGroupTimesUs.length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the next ad index in the specified ad group to load, or {@link C#INDEX_UNSET} if all
|
||||||
|
* ads in the ad group have loaded.
|
||||||
|
*/
|
||||||
|
private int getAdIndexInAdGroupToLoad(int adGroupIndex) {
|
||||||
|
@AdState int[] states = adPlaybackState.adGroups[adGroupIndex].states;
|
||||||
|
int adIndexInAdGroup = 0;
|
||||||
|
// IMA loads ads in order.
|
||||||
|
while (adIndexInAdGroup < states.length
|
||||||
|
&& states[adIndexInAdGroup] != AdPlaybackState.AD_STATE_UNAVAILABLE) {
|
||||||
|
adIndexInAdGroup++;
|
||||||
|
}
|
||||||
|
return adIndexInAdGroup == states.length ? C.INDEX_UNSET : adIndexInAdGroup;
|
||||||
|
}
|
||||||
|
|
||||||
private static long[] getAdGroupTimesUs(List<Float> cuePoints) {
|
private static long[] getAdGroupTimesUs(List<Float> cuePoints) {
|
||||||
if (cuePoints.isEmpty()) {
|
if (cuePoints.isEmpty()) {
|
||||||
// If no cue points are specified, there is a preroll ad.
|
// If no cue points are specified, there is a preroll ad.
|
||||||
@ -955,18 +990,4 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A
|
|||||||
return adGroupTimesUs;
|
return adGroupTimesUs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the next ad index in the specified ad group to load, or {@link C#INDEX_UNSET} if all
|
|
||||||
* ads in the ad group have loaded.
|
|
||||||
*/
|
|
||||||
private int getAdIndexInAdGroupToLoad(int adGroupIndex) {
|
|
||||||
@AdState int[] states = adPlaybackState.adGroups[adGroupIndex].states;
|
|
||||||
int adIndexInAdGroup = 0;
|
|
||||||
// IMA loads ads in order.
|
|
||||||
while (adIndexInAdGroup < states.length
|
|
||||||
&& states[adIndexInAdGroup] != AdPlaybackState.AD_STATE_UNAVAILABLE) {
|
|
||||||
adIndexInAdGroup++;
|
|
||||||
}
|
|
||||||
return adIndexInAdGroup == states.length ? C.INDEX_UNSET : adIndexInAdGroup;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user