mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Make AdPlaybackState.withAdDurationsUs work with removed ad groups
The assertion is changed to check that the number of passed in arrays of durations is always matching `adGroupCount` according to the behavior of `withRemoveAdGroupCount(int)`. Issue: androidx/media#2267 PiperOrigin-RevId: 743185176 (cherry picked from commit d133300627a3d5757c7dd63fc008b2cf9afc70ba)
This commit is contained in:
parent
567ee030b3
commit
cb80fe4c7c
@ -13,6 +13,19 @@
|
|||||||
* ExoPlayer:
|
* ExoPlayer:
|
||||||
* Fix sending `CmcdData` in manifest requests for DASH, HLS, and
|
* Fix sending `CmcdData` in manifest requests for DASH, HLS, and
|
||||||
SmoothStreaming ([#2253](https://github.com/androidx/media/pull/2253)).
|
SmoothStreaming ([#2253](https://github.com/androidx/media/pull/2253)).
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
* Fix issue where media item transition fails due to recoverable renderer
|
||||||
|
error during initialization of the next media item
|
||||||
|
([#2229](https://github.com/androidx/media/issues/2229)).
|
||||||
|
* Add `ExoPlayer.setScrubbingModeEnabled(boolean)` method. This optimizes
|
||||||
|
the player for many frequent seeks (for example, from a user dragging a
|
||||||
|
scrubber bar around).
|
||||||
|
* `AdPlaybackState.withAdDurationsUs(long[][])` can be used after ad
|
||||||
|
groups have been removed. The user still needs to pass in an array of
|
||||||
|
durations for removed ad groups which can be empty or null
|
||||||
|
([#2267](https://github.com/androidx/media/issues/2267)).
|
||||||
|
>>>>>>> d133300627 (Make AdPlaybackState.withAdDurationsUs work with removed ad groups)
|
||||||
* Transformer:
|
* Transformer:
|
||||||
* Track Selection:
|
* Track Selection:
|
||||||
* Extractors:
|
* Extractors:
|
||||||
|
@ -1072,14 +1072,23 @@ public final class AdPlaybackState {
|
|||||||
/**
|
/**
|
||||||
* Returns an instance with the specified ad durations, in microseconds.
|
* Returns an instance with the specified ad durations, in microseconds.
|
||||||
*
|
*
|
||||||
* <p>Must only be used if {@link #removedAdGroupCount} is 0.
|
* <p>The number of arrays of durations ({@code adDurations.length}) must always be equal to
|
||||||
|
* {@link #adGroupCount}. This is required even on an instance created with {@link
|
||||||
|
* #withRemovedAdGroupCount(int)}. The array of durations at the index of a removed ad group can
|
||||||
|
* be null or empty.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if {@code adDurations.length != adGroupCount}.
|
||||||
*/
|
*/
|
||||||
@CheckResult
|
@CheckResult
|
||||||
public AdPlaybackState withAdDurationsUs(long[][] adDurationUs) {
|
public AdPlaybackState withAdDurationsUs(long[][] adDurationUs) {
|
||||||
checkState(removedAdGroupCount == 0);
|
checkArgument(adDurationUs.length == adGroupCount);
|
||||||
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
AdGroup[] adGroups = Util.nullSafeArrayCopy(this.adGroups, this.adGroups.length);
|
||||||
for (int adGroupIndex = 0; adGroupIndex < adGroupCount; adGroupIndex++) {
|
for (int correctedAdGroupIndex = 0;
|
||||||
adGroups[adGroupIndex] = adGroups[adGroupIndex].withAdDurationsUs(adDurationUs[adGroupIndex]);
|
correctedAdGroupIndex < adGroupCount - removedAdGroupCount;
|
||||||
|
correctedAdGroupIndex++) {
|
||||||
|
adGroups[correctedAdGroupIndex] =
|
||||||
|
adGroups[correctedAdGroupIndex].withAdDurationsUs(
|
||||||
|
adDurationUs[removedAdGroupCount + correctedAdGroupIndex]);
|
||||||
}
|
}
|
||||||
return new AdPlaybackState(
|
return new AdPlaybackState(
|
||||||
adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount);
|
adsId, adGroups, adResumePositionUs, contentDurationUs, removedAdGroupCount);
|
||||||
|
@ -1036,4 +1036,110 @@ public class AdPlaybackStateTest {
|
|||||||
assertThat(AdPlaybackState.AdGroup.fromBundle(adGroup.toBundle()).ids[1]).isNull();
|
assertThat(AdPlaybackState.AdGroup.fromBundle(adGroup.toBundle()).ids[1]).isNull();
|
||||||
assertThat(AdPlaybackState.AdGroup.fromBundle(adGroup.toBundle())).isEqualTo(adGroup);
|
assertThat(AdPlaybackState.AdGroup.fromBundle(adGroup.toBundle())).isEqualTo(adGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setDurationsUs_withRemovedAdGroups_updatedCorrectlyAndSafely() {
|
||||||
|
AdPlaybackState adPlaybackState =
|
||||||
|
new AdPlaybackState("adsId")
|
||||||
|
.withLivePostrollPlaceholderAppended(false)
|
||||||
|
.withNewAdGroup(/* adGroupIndex= */ 0, 10_000)
|
||||||
|
.withAdCount(/* adGroupIndex= */ 0, 1)
|
||||||
|
.withAvailableAdMediaItem(
|
||||||
|
/* adGroupIndex= */ 0,
|
||||||
|
/* adIndexInAdGroup= */ 0,
|
||||||
|
MediaItem.fromUri("http://example.com/0-0"))
|
||||||
|
.withNewAdGroup(/* adGroupIndex= */ 1, 11_000)
|
||||||
|
.withAdCount(/* adGroupIndex= */ 1, 2)
|
||||||
|
.withAvailableAdMediaItem(
|
||||||
|
/* adGroupIndex= */ 1,
|
||||||
|
/* adIndexInAdGroup= */ 0,
|
||||||
|
MediaItem.fromUri("http://example.com/1-0"))
|
||||||
|
.withAvailableAdMediaItem(
|
||||||
|
/* adGroupIndex= */ 1,
|
||||||
|
/* adIndexInAdGroup= */ 1,
|
||||||
|
MediaItem.fromUri("http://example.com/1-1"))
|
||||||
|
.withNewAdGroup(/* adGroupIndex= */ 2, 12_000)
|
||||||
|
.withAdCount(/* adGroupIndex= */ 2, 1)
|
||||||
|
.withAvailableAdMediaItem(
|
||||||
|
/* adGroupIndex= */ 2,
|
||||||
|
/* adIndexInAdGroup= */ 0,
|
||||||
|
MediaItem.fromUri("http://example.com/2-0"));
|
||||||
|
long[][] adDurationsUs = {
|
||||||
|
new long[] {10L}, new long[] {20L, 21L}, new long[] {30L}, new long[] {C.TIME_END_OF_SOURCE}
|
||||||
|
};
|
||||||
|
|
||||||
|
adPlaybackState =
|
||||||
|
adPlaybackState
|
||||||
|
.withAdDurationsUs(adDurationsUs)
|
||||||
|
.withRemovedAdGroupCount(/* removedAdGroupCount= */ 1);
|
||||||
|
|
||||||
|
assertThat(adPlaybackState.adGroupCount).isEqualTo(4);
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).durationsUs).hasLength(0);
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).count).isEqualTo(0);
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).states).hasLength(0);
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).isPlaceholder).isFalse();
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).mediaItems).hasLength(0);
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 0).ids).hasLength(0);
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 1).durationsUs)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(20L, 21L)
|
||||||
|
.inOrder();
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 2).durationsUs)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(30L);
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 3).durationsUs)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(C.TIME_END_OF_SOURCE);
|
||||||
|
|
||||||
|
adDurationsUs[1][0] = 120L;
|
||||||
|
adDurationsUs[1][1] = 121L;
|
||||||
|
adPlaybackState = adPlaybackState.withAdDurationsUs(adDurationsUs);
|
||||||
|
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 1).durationsUs)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(120L, 121L)
|
||||||
|
.inOrder();
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 2).durationsUs)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(30L);
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 3).durationsUs)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(C.TIME_END_OF_SOURCE);
|
||||||
|
|
||||||
|
adDurationsUs[0] = null;
|
||||||
|
adDurationsUs[1] = null;
|
||||||
|
adDurationsUs[2][0] = C.TIME_UNSET;
|
||||||
|
adPlaybackState =
|
||||||
|
adPlaybackState
|
||||||
|
.withRemovedAdGroupCount(/* removedAdGroupCount= */ 2)
|
||||||
|
.withAdDurationsUs(adDurationsUs);
|
||||||
|
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 1).durationsUs).hasLength(0);
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 2).durationsUs)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(C.TIME_UNSET);
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 3).durationsUs)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(C.TIME_END_OF_SOURCE);
|
||||||
|
|
||||||
|
adDurationsUs[2] = null;
|
||||||
|
adDurationsUs[3][0] = 0L;
|
||||||
|
adPlaybackState =
|
||||||
|
adPlaybackState
|
||||||
|
.withRemovedAdGroupCount(/* removedAdGroupCount= */ 3)
|
||||||
|
.withAdDurationsUs(adDurationsUs);
|
||||||
|
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 2).durationsUs).hasLength(0);
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 3).durationsUs)
|
||||||
|
.asList()
|
||||||
|
.containsExactly(0L);
|
||||||
|
|
||||||
|
adDurationsUs[3] = null;
|
||||||
|
adPlaybackState =
|
||||||
|
adPlaybackState
|
||||||
|
.withRemovedAdGroupCount(/* removedAdGroupCount= */ 4)
|
||||||
|
.withAdDurationsUs(adDurationsUs);
|
||||||
|
|
||||||
|
assertThat(adPlaybackState.getAdGroup(/* adGroupIndex= */ 3).durationsUs).hasLength(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -751,8 +751,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (e.type == ExoPlaybackException.TYPE_RENDERER
|
if (e.type == ExoPlaybackException.TYPE_RENDERER
|
||||||
&& e.mediaPeriodId != null
|
&& renderers[e.rendererIndex % renderers.length].isRendererPrewarming(
|
||||||
&& isRendererPrewarmingMediaPeriod(e.rendererIndex, e.mediaPeriodId)) {
|
/* id= */ e.rendererIndex)) {
|
||||||
// TODO(b/380273486): Investigate recovery for pre-warming renderer errors
|
// TODO(b/380273486): Investigate recovery for pre-warming renderer errors
|
||||||
isPrewarmingDisabledUntilNextTransition = true;
|
isPrewarmingDisabledUntilNextTransition = true;
|
||||||
disableAndResetPrewarmingRenderers();
|
disableAndResetPrewarmingRenderers();
|
||||||
|
@ -36,7 +36,6 @@ import androidx.media3.common.util.ParsableBitArray;
|
|||||||
import androidx.media3.common.util.ParsableByteArray;
|
import androidx.media3.common.util.ParsableByteArray;
|
||||||
import androidx.media3.common.util.UnstableApi;
|
import androidx.media3.common.util.UnstableApi;
|
||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.container.DolbyVisionConfig;
|
|
||||||
import androidx.media3.container.Mp4AlternateGroupData;
|
import androidx.media3.container.Mp4AlternateGroupData;
|
||||||
import androidx.media3.container.Mp4Box;
|
import androidx.media3.container.Mp4Box;
|
||||||
import androidx.media3.container.Mp4Box.LeafBox;
|
import androidx.media3.container.Mp4Box.LeafBox;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user