Add method to reset ad group from final states to be playable again.
The player will not play ads in final states (played, skipped, error) again. To allow ads loader customizations to play ads again, we can add a method that resets the state back to available or unavailable (depending on whether we have the URI for the ad). Issue: google/ExoPlayer#9615 PiperOrigin-RevId: 411042842
This commit is contained in:
parent
e935e0370d
commit
9ab021543b
@ -299,6 +299,28 @@ public final class AdPlaybackState implements Bundleable {
|
|||||||
timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an instance with all ads in final states (played, skipped, error) reset to either
|
||||||
|
* available or unavailable, which allows to play them again.
|
||||||
|
*/
|
||||||
|
@CheckResult
|
||||||
|
public AdGroup withAllAdsReset() {
|
||||||
|
if (count == C.LENGTH_UNSET) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
int count = this.states.length;
|
||||||
|
@AdState int[] states = Arrays.copyOf(this.states, count);
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (states[i] == AD_STATE_PLAYED
|
||||||
|
|| states[i] == AD_STATE_SKIPPED
|
||||||
|
|| states[i] == AD_STATE_ERROR) {
|
||||||
|
states[i] = uris[i] == null ? AD_STATE_UNAVAILABLE : AD_STATE_AVAILABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new AdGroup(
|
||||||
|
timeUs, count, states, uris, durationsUs, contentResumeOffsetUs, isServerSideInserted);
|
||||||
|
}
|
||||||
|
|
||||||
@CheckResult
|
@CheckResult
|
||||||
private static @AdState int[] copyStatesWithSpaceForAdCount(@AdState int[] states, int count) {
|
private static @AdState int[] copyStatesWithSpaceForAdCount(@AdState int[] states, int count) {
|
||||||
int oldStateCount = states.length;
|
int oldStateCount = states.length;
|
||||||
@ -782,6 +804,19 @@ public final class AdPlaybackState implements Bundleable {
|
|||||||
adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount);
|
adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an instance with all ads in the specified ad group reset from final states (played,
|
||||||
|
* skipped, error) to either available or unavailable, which allows to play them again.
|
||||||
|
*/
|
||||||
|
@CheckResult
|
||||||
|
public AdPlaybackState withResetAdGroup(@IntRange(from = 0) int adGroupIndex) {
|
||||||
|
int adjustedIndex = adGroupIndex - removedAdGroupCount;
|
||||||
|
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||||
|
adGroups[adjustedIndex] = adGroups[adjustedIndex].withAllAdsReset();
|
||||||
|
return new AdPlaybackState(
|
||||||
|
adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(@Nullable Object o) {
|
public boolean equals(@Nullable Object o) {
|
||||||
if (this == o) {
|
if (this == o) {
|
||||||
|
@ -16,7 +16,10 @@
|
|||||||
package androidx.media3.common;
|
package androidx.media3.common;
|
||||||
|
|
||||||
import static androidx.media3.common.AdPlaybackState.AD_STATE_AVAILABLE;
|
import static androidx.media3.common.AdPlaybackState.AD_STATE_AVAILABLE;
|
||||||
|
import static androidx.media3.common.AdPlaybackState.AD_STATE_ERROR;
|
||||||
import static androidx.media3.common.AdPlaybackState.AD_STATE_PLAYED;
|
import static androidx.media3.common.AdPlaybackState.AD_STATE_PLAYED;
|
||||||
|
import static androidx.media3.common.AdPlaybackState.AD_STATE_SKIPPED;
|
||||||
|
import static androidx.media3.common.AdPlaybackState.AD_STATE_UNAVAILABLE;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
@ -253,6 +256,60 @@ public class AdPlaybackStateTest {
|
|||||||
assertThat(state.getAdGroup(1).count).isEqualTo(0);
|
assertThat(state.getAdGroup(1).count).isEqualTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void withResetAdGroup_beforeSetAdCount_doesNothing() {
|
||||||
|
AdPlaybackState state = new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US);
|
||||||
|
|
||||||
|
state = state.withResetAdGroup(/* adGroupIndex= */ 1);
|
||||||
|
|
||||||
|
assertThat(state.getAdGroup(1).count).isEqualTo(C.LENGTH_UNSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void withResetAdGroup_resetsAdsInFinalStates() {
|
||||||
|
AdPlaybackState state = new AdPlaybackState(TEST_ADS_ID, TEST_AD_GROUP_TIMES_US);
|
||||||
|
state = state.withAdCount(/* adGroupIndex= */ 1, /* adCount= */ 5);
|
||||||
|
state =
|
||||||
|
state.withAdDurationsUs(
|
||||||
|
/* adGroupIndex= */ 1, /* adDurationsUs...= */ 1_000L, 2_000L, 3_000L, 4_000L, 5_000L);
|
||||||
|
state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 1, Uri.EMPTY);
|
||||||
|
state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2, Uri.EMPTY);
|
||||||
|
state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 3, Uri.EMPTY);
|
||||||
|
state = state.withAdUri(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 4, Uri.EMPTY);
|
||||||
|
state = state.withPlayedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 2);
|
||||||
|
state = state.withSkippedAd(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 3);
|
||||||
|
state = state.withAdLoadError(/* adGroupIndex= */ 1, /* adIndexInAdGroup= */ 4);
|
||||||
|
// Verify setup.
|
||||||
|
assertThat(state.getAdGroup(/* adGroupIndex= */ 1).states)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(
|
||||||
|
AD_STATE_UNAVAILABLE,
|
||||||
|
AD_STATE_AVAILABLE,
|
||||||
|
AD_STATE_PLAYED,
|
||||||
|
AD_STATE_SKIPPED,
|
||||||
|
AD_STATE_ERROR)
|
||||||
|
.inOrder();
|
||||||
|
|
||||||
|
state = state.withResetAdGroup(/* adGroupIndex= */ 1);
|
||||||
|
|
||||||
|
assertThat(state.getAdGroup(/* adGroupIndex= */ 1).states)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(
|
||||||
|
AD_STATE_UNAVAILABLE,
|
||||||
|
AD_STATE_AVAILABLE,
|
||||||
|
AD_STATE_AVAILABLE,
|
||||||
|
AD_STATE_AVAILABLE,
|
||||||
|
AD_STATE_AVAILABLE)
|
||||||
|
.inOrder();
|
||||||
|
assertThat(state.getAdGroup(/* adGroupIndex= */ 1).uris)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(null, Uri.EMPTY, Uri.EMPTY, Uri.EMPTY, Uri.EMPTY)
|
||||||
|
.inOrder();
|
||||||
|
assertThat(state.getAdGroup(/* adGroupIndex= */ 1).durationsUs)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(1_000L, 2_000L, 3_000L, 4_000L, 5_000L);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void roundTripViaBundle_yieldsEqualFieldsExceptAdsId() {
|
public void roundTripViaBundle_yieldsEqualFieldsExceptAdsId() {
|
||||||
AdPlaybackState originalState =
|
AdPlaybackState originalState =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user