mirror of
https://github.com/samsonjs/media.git
synced 2026-04-03 10:55:48 +00:00
Do not manipulate the duration of SSAI periods in FakeTimeline
#minor-release PiperOrigin-RevId: 428727560
This commit is contained in:
parent
76c87462e2
commit
190aa84d01
3 changed files with 84 additions and 55 deletions
|
|
@ -15,8 +15,12 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2;
|
||||
|
||||
import static com.google.android.exoplayer2.testutil.ExoPlayerTestRunner.AUDIO_FORMAT;
|
||||
import static com.google.android.exoplayer2.testutil.ExoPlayerTestRunner.VIDEO_FORMAT;
|
||||
import static com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
|
|
@ -33,6 +37,7 @@ import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
|||
import com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller;
|
||||
import com.google.android.exoplayer2.source.SinglePeriodTimeline;
|
||||
import com.google.android.exoplayer2.source.ads.AdPlaybackState;
|
||||
import com.google.android.exoplayer2.source.ads.ServerSideAdInsertionMediaSource;
|
||||
import com.google.android.exoplayer2.source.ads.SinglePeriodAdTimeline;
|
||||
import com.google.android.exoplayer2.testutil.FakeMediaSource;
|
||||
import com.google.android.exoplayer2.testutil.FakeShuffleOrder;
|
||||
|
|
@ -44,6 +49,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectorResult;
|
|||
import com.google.android.exoplayer2.upstream.Allocator;
|
||||
import com.google.android.exoplayer2.util.Clock;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
|
@ -818,10 +825,11 @@ public final class MediaPeriodQueueTest {
|
|||
|
||||
@Test
|
||||
public void
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_behindAdInMultiPeriodTimeline_rollForward() {
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_behindAdInMultiPeriodTimeline_rollForward()
|
||||
throws InterruptedException {
|
||||
Object windowId = new Object();
|
||||
FakeTimeline timeline =
|
||||
FakeTimeline.createMultiPeriodAdTimeline(
|
||||
Timeline timeline =
|
||||
createMultiPeriodServerSideInsertedTimeline(
|
||||
windowId,
|
||||
/* numberOfPlayedAds= */ 0,
|
||||
/* isAdPeriodFlags...= */ true,
|
||||
|
|
@ -852,10 +860,11 @@ public final class MediaPeriodQueueTest {
|
|||
|
||||
@Test
|
||||
public void
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_behindAdInMultiPeriodAllAdsPlayed_seekNotAdjusted() {
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_behindAdInMultiPeriodAllAdsPlayed_seekNotAdjusted()
|
||||
throws InterruptedException {
|
||||
Object windowId = new Object();
|
||||
FakeTimeline timeline =
|
||||
FakeTimeline.createMultiPeriodAdTimeline(
|
||||
Timeline timeline =
|
||||
createMultiPeriodServerSideInsertedTimeline(
|
||||
windowId,
|
||||
/* numberOfPlayedAds= */ 4,
|
||||
/* isAdPeriodFlags...= */ true,
|
||||
|
|
@ -886,10 +895,11 @@ public final class MediaPeriodQueueTest {
|
|||
|
||||
@Test
|
||||
public void
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_behindAdInMultiPeriodFirstTwoAdsPlayed_rollForward() {
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_behindAdInMultiPeriodFirstTwoAdsPlayed_rollForward()
|
||||
throws InterruptedException {
|
||||
Object windowId = new Object();
|
||||
FakeTimeline timeline =
|
||||
FakeTimeline.createMultiPeriodAdTimeline(
|
||||
Timeline timeline =
|
||||
createMultiPeriodServerSideInsertedTimeline(
|
||||
windowId,
|
||||
/* numberOfPlayedAds= */ 2,
|
||||
/* isAdPeriodFlags...= */ true,
|
||||
|
|
@ -911,10 +921,11 @@ public final class MediaPeriodQueueTest {
|
|||
|
||||
@Test
|
||||
public void
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_beforeAdInMultiPeriodTimeline_seekNotAdjusted() {
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_beforeAdInMultiPeriodTimeline_seekNotAdjusted()
|
||||
throws InterruptedException {
|
||||
Object windowId = new Object();
|
||||
FakeTimeline timeline =
|
||||
FakeTimeline.createMultiPeriodAdTimeline(
|
||||
Timeline timeline =
|
||||
createMultiPeriodServerSideInsertedTimeline(
|
||||
windowId, /* numberOfPlayedAds= */ 0, /* isAdPeriodFlags...= */ false, true);
|
||||
|
||||
MediaPeriodId mediaPeriodId =
|
||||
|
|
@ -929,10 +940,11 @@ public final class MediaPeriodQueueTest {
|
|||
|
||||
@Test
|
||||
public void
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_toUnplayedAdInMultiPeriodTimeline_resolvedAsAd() {
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_toUnplayedAdInMultiPeriodTimeline_resolvedAsAd()
|
||||
throws InterruptedException {
|
||||
Object windowId = new Object();
|
||||
FakeTimeline timeline =
|
||||
FakeTimeline.createMultiPeriodAdTimeline(
|
||||
Timeline timeline =
|
||||
createMultiPeriodServerSideInsertedTimeline(
|
||||
windowId, /* numberOfPlayedAds= */ 0, /* isAdPeriodFlags...= */ false, true, false);
|
||||
|
||||
MediaPeriodId mediaPeriodId =
|
||||
|
|
@ -947,10 +959,11 @@ public final class MediaPeriodQueueTest {
|
|||
|
||||
@Test
|
||||
public void
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_toPlayedAdInMultiPeriodTimeline_skipPlayedAd() {
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_toPlayedAdInMultiPeriodTimeline_skipPlayedAd()
|
||||
throws InterruptedException {
|
||||
Object windowId = new Object();
|
||||
FakeTimeline timeline =
|
||||
FakeTimeline.createMultiPeriodAdTimeline(
|
||||
Timeline timeline =
|
||||
createMultiPeriodServerSideInsertedTimeline(
|
||||
windowId, /* numberOfPlayedAds= */ 1, /* isAdPeriodFlags...= */ false, true, false);
|
||||
|
||||
MediaPeriodId mediaPeriodId =
|
||||
|
|
@ -965,12 +978,12 @@ public final class MediaPeriodQueueTest {
|
|||
|
||||
@Test
|
||||
public void
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_toStartOfWindowPlayedAdPreroll_skipsPlayedPrerolls() {
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_toStartOfWindowPlayedAdPreroll_skipsPlayedPrerolls()
|
||||
throws InterruptedException {
|
||||
Object windowId = new Object();
|
||||
FakeTimeline timeline =
|
||||
FakeTimeline.createMultiPeriodAdTimeline(
|
||||
Timeline timeline =
|
||||
createMultiPeriodServerSideInsertedTimeline(
|
||||
windowId, /* numberOfPlayedAds= */ 2, /* isAdPeriodFlags...= */ true, true, false);
|
||||
|
||||
MediaPeriodId mediaPeriodId =
|
||||
mediaPeriodQueue.resolveMediaPeriodIdForAdsAfterPeriodPositionChange(
|
||||
timeline, new Pair<>(windowId, 0), /* positionUs= */ 0);
|
||||
|
|
@ -983,10 +996,11 @@ public final class MediaPeriodQueueTest {
|
|||
|
||||
@Test
|
||||
public void
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_toPlayedPostrolls_skipsAllButLastPostroll() {
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_toPlayedPostrolls_skipsAllButLastPostroll()
|
||||
throws InterruptedException {
|
||||
Object windowId = new Object();
|
||||
FakeTimeline timeline =
|
||||
FakeTimeline.createMultiPeriodAdTimeline(
|
||||
Timeline timeline =
|
||||
createMultiPeriodServerSideInsertedTimeline(
|
||||
windowId,
|
||||
/* numberOfPlayedAds= */ 4,
|
||||
/* isAdPeriodFlags...= */ false,
|
||||
|
|
@ -1007,10 +1021,11 @@ public final class MediaPeriodQueueTest {
|
|||
|
||||
@Test
|
||||
public void
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_consecutiveContentPeriods_rollForward() {
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_consecutiveContentPeriods_rollForward()
|
||||
throws InterruptedException {
|
||||
Object windowId = new Object();
|
||||
FakeTimeline timeline =
|
||||
FakeTimeline.createMultiPeriodAdTimeline(
|
||||
Timeline timeline =
|
||||
createMultiPeriodServerSideInsertedTimeline(
|
||||
windowId,
|
||||
/* numberOfPlayedAds= */ 0,
|
||||
/* isAdPeriodFlags...= */ true,
|
||||
|
|
@ -1030,10 +1045,11 @@ public final class MediaPeriodQueueTest {
|
|||
|
||||
@Test
|
||||
public void
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_onlyConsecutiveContentPeriods_seekNotAdjusted() {
|
||||
resolveMediaPeriodIdForAdsAfterPeriodPositionChange_onlyConsecutiveContentPeriods_seekNotAdjusted()
|
||||
throws InterruptedException {
|
||||
Object windowId = new Object();
|
||||
FakeTimeline timeline =
|
||||
FakeTimeline.createMultiPeriodAdTimeline(
|
||||
Timeline timeline =
|
||||
createMultiPeriodServerSideInsertedTimeline(
|
||||
windowId,
|
||||
/* numberOfPlayedAds= */ 0,
|
||||
/* isAdPeriodFlags...= */ false,
|
||||
|
|
@ -1245,4 +1261,29 @@ public final class MediaPeriodQueueTest {
|
|||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
private static Timeline createMultiPeriodServerSideInsertedTimeline(
|
||||
Object windowId, int numberOfPlayedAds, boolean... isAdPeriodFlags)
|
||||
throws InterruptedException {
|
||||
FakeTimeline timeline =
|
||||
FakeTimeline.createMultiPeriodAdTimeline(windowId, numberOfPlayedAds, isAdPeriodFlags);
|
||||
ServerSideAdInsertionMediaSource serverSideAdInsertionMediaSource =
|
||||
new ServerSideAdInsertionMediaSource(
|
||||
new FakeMediaSource(timeline, VIDEO_FORMAT, AUDIO_FORMAT), contentTimeline -> false);
|
||||
serverSideAdInsertionMediaSource.setAdPlaybackStates(
|
||||
timeline.getAdPlaybackStates(/* windowIndex= */ 0));
|
||||
AtomicReference<Timeline> serverSideAdInsertionTimelineRef = new AtomicReference<>();
|
||||
CountDownLatch countDownLatch = new CountDownLatch(/* count= */ 1);
|
||||
serverSideAdInsertionMediaSource.prepareSource(
|
||||
(source, serverSideInsertedAdTimeline) -> {
|
||||
serverSideAdInsertionTimelineRef.set(serverSideInsertedAdTimeline);
|
||||
countDownLatch.countDown();
|
||||
},
|
||||
/* mediaTransferListener= */ null,
|
||||
new PlayerId());
|
||||
if (!countDownLatch.await(/* timeout= */ 2, SECONDS)) {
|
||||
fail();
|
||||
}
|
||||
return serverSideAdInsertionTimelineRef.get();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ package com.google.android.exoplayer2.testutil;
|
|||
|
||||
import static com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_DURATION_US;
|
||||
import static com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US;
|
||||
import static com.google.android.exoplayer2.util.Util.sum;
|
||||
import static java.lang.Math.min;
|
||||
|
||||
import android.net.Uri;
|
||||
|
|
@ -321,14 +320,15 @@ public final class FakeTimeline extends Timeline {
|
|||
public static FakeTimeline createMultiPeriodAdTimeline(
|
||||
Object windowId, int numberOfPlayedAds, boolean... isAdPeriodFlags) {
|
||||
long periodDurationUs = DEFAULT_WINDOW_DURATION_US / isAdPeriodFlags.length;
|
||||
AdPlaybackState contentPeriodState = new AdPlaybackState(/* adsId= */ "adsId");
|
||||
AdPlaybackState firstAdPeriodState =
|
||||
new AdPlaybackState(/* adsId= */ "adsId", /* adGroupTimesUs... */ 0)
|
||||
contentPeriodState
|
||||
.withNewAdGroup(/* adGroupIndex= */ 0, /* adGroupTimesUs */ 0)
|
||||
.withAdCount(/* adGroupIndex= */ 0, 1)
|
||||
.withAdDurationsUs(
|
||||
/* adGroupIndex= */ 0, DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US + periodDurationUs)
|
||||
.withIsServerSideInserted(/* adGroupIndex= */ 0, true);
|
||||
AdPlaybackState commonAdPeriodState = firstAdPeriodState.withAdDurationsUs(0, periodDurationUs);
|
||||
AdPlaybackState contentPeriodState = new AdPlaybackState(/* adsId= */ "adsId");
|
||||
|
||||
List<AdPlaybackState> adPlaybackStates = new ArrayList<>();
|
||||
int playedAdsCounter = 0;
|
||||
|
|
@ -522,9 +522,7 @@ public final class FakeTimeline extends Timeline {
|
|||
id,
|
||||
uid,
|
||||
windowIndex,
|
||||
periodDurationUs == C.TIME_UNSET
|
||||
? C.TIME_UNSET
|
||||
: periodDurationUs - getServerSideAdInsertionAdDurationUs(adPlaybackState),
|
||||
periodDurationUs,
|
||||
positionInWindowUs,
|
||||
adPlaybackState,
|
||||
windowDefinition.isPlaceholder);
|
||||
|
|
@ -575,15 +573,4 @@ public final class FakeTimeline extends Timeline {
|
|||
}
|
||||
return windowDefinitions;
|
||||
}
|
||||
|
||||
private static long getServerSideAdInsertionAdDurationUs(AdPlaybackState adPlaybackState) {
|
||||
long adDurationUs = 0;
|
||||
for (int i = 0; i < adPlaybackState.adGroupCount; i++) {
|
||||
AdPlaybackState.AdGroup adGroup = adPlaybackState.getAdGroup(i);
|
||||
if (adGroup.isServerSideInserted) {
|
||||
adDurationUs += sum(adGroup.durationsUs);
|
||||
}
|
||||
}
|
||||
return adDurationUs;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,20 +45,21 @@ public class FakeTimelineTest {
|
|||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true);
|
||||
|
||||
assertThat(timeline.getWindowCount()).isEqualTo(1);
|
||||
assertThat(timeline.getPeriodCount()).isEqualTo(7);
|
||||
assertThat(timeline.getPeriodCount()).isEqualTo(8);
|
||||
// Assert content periods and window duration.
|
||||
Timeline.Period contentPeriod1 = timeline.getPeriod(/* periodIndex= */ 1, period);
|
||||
Timeline.Period contentPeriod5 = timeline.getPeriod(/* periodIndex= */ 5, period);
|
||||
assertThat(contentPeriod1.durationUs).isEqualTo(DEFAULT_WINDOW_DURATION_US / 7);
|
||||
assertThat(contentPeriod5.durationUs).isEqualTo(DEFAULT_WINDOW_DURATION_US / 7);
|
||||
assertThat(contentPeriod1.durationUs).isEqualTo(DEFAULT_WINDOW_DURATION_US / 8);
|
||||
assertThat(contentPeriod5.durationUs).isEqualTo(DEFAULT_WINDOW_DURATION_US / 8);
|
||||
assertThat(contentPeriod1.getAdGroupCount()).isEqualTo(0);
|
||||
assertThat(contentPeriod5.getAdGroupCount()).isEqualTo(0);
|
||||
timeline.getWindow(/* windowIndex= */ 0, window);
|
||||
assertThat(window.uid).isEqualTo(windowId);
|
||||
assertThat(window.durationUs).isEqualTo(contentPeriod1.durationUs + contentPeriod5.durationUs);
|
||||
assertThat(window.durationUs).isEqualTo(DEFAULT_WINDOW_DURATION_US);
|
||||
assertThat(window.positionInFirstPeriodUs).isEqualTo(DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US);
|
||||
// Assert ad periods.
|
||||
int[] adIndices = {0, 2, 3, 4, 6};
|
||||
|
|
@ -67,7 +68,6 @@ public class FakeTimelineTest {
|
|||
Timeline.Period adPeriod = timeline.getPeriod(periodIndex, period);
|
||||
assertThat(adPeriod.isServerSideInsertedAdGroup(0)).isTrue();
|
||||
assertThat(adPeriod.getAdGroupCount()).isEqualTo(1);
|
||||
assertThat(adPeriod.durationUs).isEqualTo(0);
|
||||
if (adPeriod.getAdGroupCount() > 0) {
|
||||
if (adCounter < numberOfPlayedAds) {
|
||||
assertThat(adPeriod.getAdState(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0))
|
||||
|
|
@ -79,8 +79,9 @@ public class FakeTimelineTest {
|
|||
adCounter++;
|
||||
}
|
||||
long expectedDurationUs =
|
||||
(DEFAULT_WINDOW_DURATION_US / 7)
|
||||
(DEFAULT_WINDOW_DURATION_US / 8)
|
||||
+ (periodIndex == 0 ? DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US : 0);
|
||||
assertThat(adPeriod.durationUs).isEqualTo(expectedDurationUs);
|
||||
assertThat(adPeriod.getAdDurationUs(/* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0))
|
||||
.isEqualTo(expectedDurationUs);
|
||||
}
|
||||
|
|
@ -100,7 +101,7 @@ public class FakeTimelineTest {
|
|||
|
||||
timeline.getWindow(/* windowIndex= */ 0, window);
|
||||
// Assert content periods and window duration.
|
||||
assertThat(window.durationUs).isEqualTo(DEFAULT_WINDOW_DURATION_US / 2);
|
||||
assertThat(window.durationUs).isEqualTo(DEFAULT_WINDOW_DURATION_US);
|
||||
assertThat(window.positionInFirstPeriodUs).isEqualTo(DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue