mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Allow FakeMediaSource to specify the FakeSampleStream data
PiperOrigin-RevId: 319420451
This commit is contained in:
parent
8d131cad7b
commit
752fe1b679
15 changed files with 534 additions and 328 deletions
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2;
|
package com.google.android.exoplayer2;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM;
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertThrows;
|
||||||
|
|
@ -617,7 +619,13 @@ public final class ExoPlayerTest {
|
||||||
DrmSessionManager drmSessionManager,
|
DrmSessionManager drmSessionManager,
|
||||||
EventDispatcher eventDispatcher,
|
EventDispatcher eventDispatcher,
|
||||||
@Nullable TransferListener transferListener) {
|
@Nullable TransferListener transferListener) {
|
||||||
FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher);
|
FakeMediaPeriod mediaPeriod =
|
||||||
|
new FakeMediaPeriod(
|
||||||
|
trackGroupArray,
|
||||||
|
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
|
||||||
|
eventDispatcher,
|
||||||
|
drmSessionManager,
|
||||||
|
/* deferOnPrepared= */ false);
|
||||||
mediaPeriod.setSeekToUsOffset(10);
|
mediaPeriod.setSeekToUsOffset(10);
|
||||||
return mediaPeriod;
|
return mediaPeriod;
|
||||||
}
|
}
|
||||||
|
|
@ -653,7 +661,11 @@ public final class ExoPlayerTest {
|
||||||
DrmSessionManager drmSessionManager,
|
DrmSessionManager drmSessionManager,
|
||||||
EventDispatcher eventDispatcher,
|
EventDispatcher eventDispatcher,
|
||||||
@Nullable TransferListener transferListener) {
|
@Nullable TransferListener transferListener) {
|
||||||
FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher);
|
FakeMediaPeriod mediaPeriod =
|
||||||
|
new FakeMediaPeriod(
|
||||||
|
trackGroupArray,
|
||||||
|
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
|
||||||
|
eventDispatcher);
|
||||||
mediaPeriod.setDiscontinuityPositionUs(10);
|
mediaPeriod.setDiscontinuityPositionUs(10);
|
||||||
return mediaPeriod;
|
return mediaPeriod;
|
||||||
}
|
}
|
||||||
|
|
@ -680,7 +692,11 @@ public final class ExoPlayerTest {
|
||||||
DrmSessionManager drmSessionManager,
|
DrmSessionManager drmSessionManager,
|
||||||
EventDispatcher eventDispatcher,
|
EventDispatcher eventDispatcher,
|
||||||
@Nullable TransferListener transferListener) {
|
@Nullable TransferListener transferListener) {
|
||||||
FakeMediaPeriod mediaPeriod = new FakeMediaPeriod(trackGroupArray, eventDispatcher);
|
FakeMediaPeriod mediaPeriod =
|
||||||
|
new FakeMediaPeriod(
|
||||||
|
trackGroupArray,
|
||||||
|
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
|
||||||
|
eventDispatcher);
|
||||||
// Set a discontinuity at the position this period is supposed to start at anyway.
|
// Set a discontinuity at the position this period is supposed to start at anyway.
|
||||||
mediaPeriod.setDiscontinuityPositionUs(
|
mediaPeriod.setDiscontinuityPositionUs(
|
||||||
timeline.getWindow(/* windowIndex= */ 0, new Window()).positionInFirstPeriodUs);
|
timeline.getWindow(/* windowIndex= */ 0, new Window()).positionInFirstPeriodUs);
|
||||||
|
|
@ -929,8 +945,9 @@ public final class ExoPlayerTest {
|
||||||
fakeMediaPeriodHolder[0] =
|
fakeMediaPeriodHolder[0] =
|
||||||
new FakeMediaPeriod(
|
new FakeMediaPeriod(
|
||||||
trackGroupArray,
|
trackGroupArray,
|
||||||
drmSessionManager,
|
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
|
||||||
eventDispatcher,
|
eventDispatcher,
|
||||||
|
drmSessionManager,
|
||||||
/* deferOnPrepared= */ true);
|
/* deferOnPrepared= */ true);
|
||||||
createPeriodCalledCountDownLatch.countDown();
|
createPeriodCalledCountDownLatch.countDown();
|
||||||
return fakeMediaPeriodHolder[0];
|
return fakeMediaPeriodHolder[0];
|
||||||
|
|
@ -980,8 +997,9 @@ public final class ExoPlayerTest {
|
||||||
fakeMediaPeriodHolder[0] =
|
fakeMediaPeriodHolder[0] =
|
||||||
new FakeMediaPeriod(
|
new FakeMediaPeriod(
|
||||||
trackGroupArray,
|
trackGroupArray,
|
||||||
drmSessionManager,
|
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
|
||||||
eventDispatcher,
|
eventDispatcher,
|
||||||
|
drmSessionManager,
|
||||||
/* deferOnPrepared= */ true);
|
/* deferOnPrepared= */ true);
|
||||||
createPeriodCalledCountDownLatch.countDown();
|
createPeriodCalledCountDownLatch.countDown();
|
||||||
return fakeMediaPeriodHolder[0];
|
return fakeMediaPeriodHolder[0];
|
||||||
|
|
@ -3708,7 +3726,10 @@ public final class ExoPlayerTest {
|
||||||
DrmSessionManager drmSessionManager,
|
DrmSessionManager drmSessionManager,
|
||||||
EventDispatcher eventDispatcher,
|
EventDispatcher eventDispatcher,
|
||||||
@Nullable TransferListener transferListener) {
|
@Nullable TransferListener transferListener) {
|
||||||
return new FakeMediaPeriod(trackGroupArray, eventDispatcher) {
|
return new FakeMediaPeriod(
|
||||||
|
trackGroupArray,
|
||||||
|
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
|
||||||
|
eventDispatcher) {
|
||||||
@Override
|
@Override
|
||||||
public long getBufferedPositionUs() {
|
public long getBufferedPositionUs() {
|
||||||
// Pretend not to have buffered data yet.
|
// Pretend not to have buffered data yet.
|
||||||
|
|
@ -6410,7 +6431,10 @@ public final class ExoPlayerTest {
|
||||||
DrmSessionManager drmSessionManager,
|
DrmSessionManager drmSessionManager,
|
||||||
EventDispatcher eventDispatcher,
|
EventDispatcher eventDispatcher,
|
||||||
@Nullable TransferListener transferListener) {
|
@Nullable TransferListener transferListener) {
|
||||||
return new FakeMediaPeriod(trackGroupArray, eventDispatcher) {
|
return new FakeMediaPeriod(
|
||||||
|
trackGroupArray,
|
||||||
|
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
|
||||||
|
eventDispatcher) {
|
||||||
|
|
||||||
private final List<Allocation> allocations = new ArrayList<>();
|
private final List<Allocation> allocations = new ArrayList<>();
|
||||||
|
|
||||||
|
|
@ -6486,7 +6510,12 @@ public final class ExoPlayerTest {
|
||||||
DrmSessionManager drmSessionManager,
|
DrmSessionManager drmSessionManager,
|
||||||
EventDispatcher eventDispatcher,
|
EventDispatcher eventDispatcher,
|
||||||
@Nullable TransferListener transferListener) {
|
@Nullable TransferListener transferListener) {
|
||||||
return new FakeMediaPeriod(trackGroupArray, drmSessionManager, eventDispatcher) {
|
return new FakeMediaPeriod(
|
||||||
|
trackGroupArray,
|
||||||
|
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
|
||||||
|
eventDispatcher,
|
||||||
|
drmSessionManager,
|
||||||
|
/* deferOnPrepared= */ false) {
|
||||||
private Loader loader = new Loader("oomLoader");
|
private Loader loader = new Loader("oomLoader");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -6505,14 +6534,13 @@ public final class ExoPlayerTest {
|
||||||
// Create 3 samples without end of stream signal to test that all 3 samples are
|
// Create 3 samples without end of stream signal to test that all 3 samples are
|
||||||
// still played before the exception is thrown.
|
// still played before the exception is thrown.
|
||||||
return new FakeSampleStream(
|
return new FakeSampleStream(
|
||||||
selection.getSelectedFormat(),
|
|
||||||
drmSessionManager,
|
drmSessionManager,
|
||||||
eventDispatcher,
|
eventDispatcher,
|
||||||
positionUs,
|
selection.getSelectedFormat(),
|
||||||
/* timeUsIncrement= */ 0,
|
ImmutableList.of(
|
||||||
new FakeSampleStream.FakeSampleStreamItem(new byte[] {0}),
|
oneByteSample(positionUs),
|
||||||
new FakeSampleStream.FakeSampleStreamItem(new byte[] {0}),
|
oneByteSample(positionUs),
|
||||||
new FakeSampleStream.FakeSampleStreamItem(new byte[] {0})) {
|
oneByteSample(positionUs))) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void maybeThrowError() throws IOException {
|
public void maybeThrowError() throws IOException {
|
||||||
|
|
@ -6676,10 +6704,21 @@ public final class ExoPlayerTest {
|
||||||
/* windowOffsetInFirstPeriodUs= */ 1_234_567,
|
/* windowOffsetInFirstPeriodUs= */ 1_234_567,
|
||||||
AdPlaybackState.NONE));
|
AdPlaybackState.NONE));
|
||||||
ExoPlayer player = new TestExoPlayer.Builder(context).setRenderers(renderer).build();
|
ExoPlayer player = new TestExoPlayer.Builder(context).setRenderers(renderer).build();
|
||||||
|
long firstSampleTimeUs = 4_567_890 + 1_234_567;
|
||||||
FakeMediaSource firstMediaSource =
|
FakeMediaSource firstMediaSource =
|
||||||
new FakeMediaSource(/* timeline= */ null, ExoPlayerTestRunner.VIDEO_FORMAT);
|
new FakeMediaSource(
|
||||||
|
/* timeline= */ null,
|
||||||
|
DrmSessionManager.DUMMY,
|
||||||
|
(unusedFormat, unusedMediaPeriodId) ->
|
||||||
|
ImmutableList.of(oneByteSample(firstSampleTimeUs), END_OF_STREAM_ITEM),
|
||||||
|
ExoPlayerTestRunner.VIDEO_FORMAT);
|
||||||
FakeMediaSource secondMediaSource =
|
FakeMediaSource secondMediaSource =
|
||||||
new FakeMediaSource(timelineWithOffsets, ExoPlayerTestRunner.VIDEO_FORMAT);
|
new FakeMediaSource(
|
||||||
|
timelineWithOffsets,
|
||||||
|
DrmSessionManager.DUMMY,
|
||||||
|
(unusedFormat, unusedMediaPeriodId) ->
|
||||||
|
ImmutableList.of(oneByteSample(firstSampleTimeUs), END_OF_STREAM_ITEM),
|
||||||
|
ExoPlayerTestRunner.VIDEO_FORMAT);
|
||||||
player.setMediaSources(ImmutableList.of(firstMediaSource, secondMediaSource));
|
player.setMediaSources(ImmutableList.of(firstMediaSource, secondMediaSource));
|
||||||
|
|
||||||
// Start playback and wait until player is idly waiting for an update of the first source.
|
// Start playback and wait until player is idly waiting for an update of the first source.
|
||||||
|
|
@ -6697,7 +6736,6 @@ public final class ExoPlayerTest {
|
||||||
assertThat(rendererStreamOffsetsUs).hasSize(2);
|
assertThat(rendererStreamOffsetsUs).hasSize(2);
|
||||||
assertThat(firstBufferTimesUsWithOffset).hasSize(2);
|
assertThat(firstBufferTimesUsWithOffset).hasSize(2);
|
||||||
// Assert that the offsets and buffer times match the expected sample time.
|
// Assert that the offsets and buffer times match the expected sample time.
|
||||||
long firstSampleTimeUs = 4_567_890 + 1_234_567;
|
|
||||||
assertThat(firstBufferTimesUsWithOffset.get(0))
|
assertThat(firstBufferTimesUsWithOffset.get(0))
|
||||||
.isEqualTo(rendererStreamOffsetsUs.get(0) + firstSampleTimeUs);
|
.isEqualTo(rendererStreamOffsetsUs.get(0) + firstSampleTimeUs);
|
||||||
assertThat(firstBufferTimesUsWithOffset.get(1))
|
assertThat(firstBufferTimesUsWithOffset.get(1))
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.analytics;
|
package com.google.android.exoplayer2.analytics;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM;
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
|
|
@ -57,6 +59,7 @@ import com.google.android.exoplayer2.testutil.FakeVideoRenderer;
|
||||||
import com.google.android.exoplayer2.testutil.TestUtil;
|
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
@ -822,10 +825,10 @@ public final class AnalyticsCollectorTest {
|
||||||
.containsExactly(window0Period1Seq0, period1Seq0)
|
.containsExactly(window0Period1Seq0, period1Seq0)
|
||||||
.inOrder();
|
.inOrder();
|
||||||
assertThat(listener.getEvents(EVENT_VIDEO_SIZE_CHANGED))
|
assertThat(listener.getEvents(EVENT_VIDEO_SIZE_CHANGED))
|
||||||
.containsExactly(window0Period1Seq0, window1Period0Seq1, period1Seq0)
|
.containsExactly(window0Period1Seq0, window1Period0Seq1)
|
||||||
.inOrder();
|
.inOrder();
|
||||||
assertThat(listener.getEvents(EVENT_RENDERED_FIRST_FRAME))
|
assertThat(listener.getEvents(EVENT_RENDERED_FIRST_FRAME))
|
||||||
.containsExactly(window0Period1Seq0, window1Period0Seq1, period1Seq0)
|
.containsExactly(window0Period1Seq0, window1Period0Seq1)
|
||||||
.inOrder();
|
.inOrder();
|
||||||
assertThat(listener.getEvents(EVENT_VIDEO_FRAME_PROCESSING_OFFSET))
|
assertThat(listener.getEvents(EVENT_VIDEO_FRAME_PROCESSING_OFFSET))
|
||||||
.containsExactly(window0Period1Seq0, period1Seq0)
|
.containsExactly(window0Period1Seq0, period1Seq0)
|
||||||
|
|
@ -926,14 +929,15 @@ public final class AnalyticsCollectorTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void adPlayback() throws Exception {
|
public void adPlayback() throws Exception {
|
||||||
long contentDurationsUs = 10 * C.MICROS_PER_SECOND;
|
long contentDurationsUs = 11 * C.MICROS_PER_SECOND;
|
||||||
|
long windowOffsetInFirstPeriodUs =
|
||||||
|
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US;
|
||||||
AtomicReference<AdPlaybackState> adPlaybackState =
|
AtomicReference<AdPlaybackState> adPlaybackState =
|
||||||
new AtomicReference<>(
|
new AtomicReference<>(
|
||||||
FakeTimeline.createAdPlaybackState(
|
FakeTimeline.createAdPlaybackState(
|
||||||
/* adsPerAdGroup= */ 1, /* adGroupTimesUs...= */
|
/* adsPerAdGroup= */ 1, /* adGroupTimesUs...= */
|
||||||
0,
|
windowOffsetInFirstPeriodUs,
|
||||||
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US
|
windowOffsetInFirstPeriodUs + 5 * C.MICROS_PER_SECOND,
|
||||||
+ 5 * C.MICROS_PER_SECOND,
|
|
||||||
C.TIME_END_OF_SOURCE));
|
C.TIME_END_OF_SOURCE));
|
||||||
AtomicInteger playedAdCount = new AtomicInteger(0);
|
AtomicInteger playedAdCount = new AtomicInteger(0);
|
||||||
Timeline adTimeline =
|
Timeline adTimeline =
|
||||||
|
|
@ -946,7 +950,23 @@ public final class AnalyticsCollectorTest {
|
||||||
contentDurationsUs,
|
contentDurationsUs,
|
||||||
adPlaybackState.get()));
|
adPlaybackState.get()));
|
||||||
FakeMediaSource fakeMediaSource =
|
FakeMediaSource fakeMediaSource =
|
||||||
new FakeMediaSource(adTimeline, ExoPlayerTestRunner.VIDEO_FORMAT);
|
new FakeMediaSource(
|
||||||
|
adTimeline,
|
||||||
|
DrmSessionManager.DUMMY,
|
||||||
|
(unusedFormat, mediaPeriodId) -> {
|
||||||
|
if (mediaPeriodId.isAd()) {
|
||||||
|
return ImmutableList.of(oneByteSample(/* timeUs= */ 0), END_OF_STREAM_ITEM);
|
||||||
|
} else {
|
||||||
|
// Provide a single sample before and after the midroll ad and another after the
|
||||||
|
// postroll.
|
||||||
|
return ImmutableList.of(
|
||||||
|
oneByteSample(windowOffsetInFirstPeriodUs + C.MICROS_PER_SECOND),
|
||||||
|
oneByteSample(windowOffsetInFirstPeriodUs + 6 * C.MICROS_PER_SECOND),
|
||||||
|
oneByteSample(windowOffsetInFirstPeriodUs + contentDurationsUs),
|
||||||
|
END_OF_STREAM_ITEM);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ExoPlayerTestRunner.VIDEO_FORMAT);
|
||||||
ActionSchedule actionSchedule =
|
ActionSchedule actionSchedule =
|
||||||
new ActionSchedule.Builder(TAG)
|
new ActionSchedule.Builder(TAG)
|
||||||
.executeRunnable(
|
.executeRunnable(
|
||||||
|
|
@ -965,7 +985,7 @@ public final class AnalyticsCollectorTest {
|
||||||
adPlaybackState
|
adPlaybackState
|
||||||
.get()
|
.get()
|
||||||
.withPlayedAd(
|
.withPlayedAd(
|
||||||
playedAdCount.getAndIncrement(),
|
/* adGroupIndex= */ playedAdCount.getAndIncrement(),
|
||||||
/* adIndexInAdGroup= */ 0));
|
/* adIndexInAdGroup= */ 0));
|
||||||
fakeMediaSource.setNewSourceInfo(
|
fakeMediaSource.setNewSourceInfo(
|
||||||
new FakeTimeline(
|
new FakeTimeline(
|
||||||
|
|
@ -974,7 +994,7 @@ public final class AnalyticsCollectorTest {
|
||||||
/* id= */ 0,
|
/* id= */ 0,
|
||||||
/* isSeekable= */ true,
|
/* isSeekable= */ true,
|
||||||
/* isDynamic= */ false,
|
/* isDynamic= */ false,
|
||||||
/* durationUs =*/ 10 * C.MICROS_PER_SECOND,
|
contentDurationsUs,
|
||||||
adPlaybackState.get())),
|
adPlaybackState.get())),
|
||||||
/* sendManifestLoadEvents= */ false);
|
/* sendManifestLoadEvents= */ false);
|
||||||
}
|
}
|
||||||
|
|
@ -1185,6 +1205,8 @@ public final class AnalyticsCollectorTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void seekAfterMidroll() throws Exception {
|
public void seekAfterMidroll() throws Exception {
|
||||||
|
long windowOffsetInFirstPeriodUs =
|
||||||
|
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US;
|
||||||
Timeline adTimeline =
|
Timeline adTimeline =
|
||||||
new FakeTimeline(
|
new FakeTimeline(
|
||||||
new TimelineWindowDefinition(
|
new TimelineWindowDefinition(
|
||||||
|
|
@ -1195,10 +1217,23 @@ public final class AnalyticsCollectorTest {
|
||||||
10 * C.MICROS_PER_SECOND,
|
10 * C.MICROS_PER_SECOND,
|
||||||
FakeTimeline.createAdPlaybackState(
|
FakeTimeline.createAdPlaybackState(
|
||||||
/* adsPerAdGroup= */ 1, /* adGroupTimesUs...= */
|
/* adsPerAdGroup= */ 1, /* adGroupTimesUs...= */
|
||||||
TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US
|
windowOffsetInFirstPeriodUs + 5 * C.MICROS_PER_SECOND)));
|
||||||
+ 5 * C.MICROS_PER_SECOND)));
|
|
||||||
FakeMediaSource fakeMediaSource =
|
FakeMediaSource fakeMediaSource =
|
||||||
new FakeMediaSource(adTimeline, ExoPlayerTestRunner.VIDEO_FORMAT);
|
new FakeMediaSource(
|
||||||
|
adTimeline,
|
||||||
|
DrmSessionManager.DUMMY,
|
||||||
|
(unusedFormat, mediaPeriodId) -> {
|
||||||
|
if (mediaPeriodId.isAd()) {
|
||||||
|
return ImmutableList.of(oneByteSample(/* timeUs= */ 0), END_OF_STREAM_ITEM);
|
||||||
|
} else {
|
||||||
|
// Provide a sample before the midroll and another after the seek point below (6s).
|
||||||
|
return ImmutableList.of(
|
||||||
|
oneByteSample(windowOffsetInFirstPeriodUs + C.MICROS_PER_SECOND),
|
||||||
|
oneByteSample(windowOffsetInFirstPeriodUs + 7 * C.MICROS_PER_SECOND),
|
||||||
|
END_OF_STREAM_ITEM);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ExoPlayerTestRunner.VIDEO_FORMAT);
|
||||||
ActionSchedule actionSchedule =
|
ActionSchedule actionSchedule =
|
||||||
new ActionSchedule.Builder(TAG)
|
new ActionSchedule.Builder(TAG)
|
||||||
.pause()
|
.pause()
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import static com.google.android.exoplayer2.RendererCapabilities.ADAPTIVE_NOT_SE
|
||||||
import static com.google.android.exoplayer2.RendererCapabilities.FORMAT_HANDLED;
|
import static com.google.android.exoplayer2.RendererCapabilities.FORMAT_HANDLED;
|
||||||
import static com.google.android.exoplayer2.RendererCapabilities.TUNNELING_NOT_SUPPORTED;
|
import static com.google.android.exoplayer2.RendererCapabilities.TUNNELING_NOT_SUPPORTED;
|
||||||
import static com.google.android.exoplayer2.RendererCapabilities.TUNNELING_SUPPORTED;
|
import static com.google.android.exoplayer2.RendererCapabilities.TUNNELING_SUPPORTED;
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
@ -33,9 +34,11 @@ import com.google.android.exoplayer2.decoder.DecoderException;
|
||||||
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
||||||
import com.google.android.exoplayer2.decoder.SimpleDecoder;
|
import com.google.android.exoplayer2.decoder.SimpleDecoder;
|
||||||
import com.google.android.exoplayer2.decoder.SimpleOutputBuffer;
|
import com.google.android.exoplayer2.decoder.SimpleOutputBuffer;
|
||||||
|
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||||
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
|
import com.google.android.exoplayer2.drm.ExoMediaCrypto;
|
||||||
import com.google.android.exoplayer2.testutil.FakeSampleStream;
|
import com.google.android.exoplayer2.testutil.FakeSampleStream;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
@ -103,7 +106,11 @@ public class DecoderAudioRendererTest {
|
||||||
audioRenderer.enable(
|
audioRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
new Format[] {FORMAT},
|
new Format[] {FORMAT},
|
||||||
new FakeSampleStream(FORMAT, /* eventDispatcher= */ null, /* shouldOutputSample= */ false),
|
new FakeSampleStream(
|
||||||
|
DrmSessionManager.DUMMY,
|
||||||
|
/* eventDispatcher= */ null,
|
||||||
|
FORMAT,
|
||||||
|
ImmutableList.of(END_OF_STREAM_ITEM)),
|
||||||
/* positionUs= */ 0,
|
/* positionUs= */ 0,
|
||||||
/* joining= */ false,
|
/* joining= */ false,
|
||||||
/* mayRenderStartOfStream= */ true,
|
/* mayRenderStartOfStream= */ true,
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.audio;
|
package com.google.android.exoplayer2.audio;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM;
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.format;
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
|
||||||
import static org.junit.Assert.assertThrows;
|
import static org.junit.Assert.assertThrows;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
|
@ -33,8 +36,8 @@ import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||||
import com.google.android.exoplayer2.mediacodec.MediaCodecInfo;
|
import com.google.android.exoplayer2.mediacodec.MediaCodecInfo;
|
||||||
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
|
import com.google.android.exoplayer2.mediacodec.MediaCodecSelector;
|
||||||
import com.google.android.exoplayer2.testutil.FakeSampleStream;
|
import com.google.android.exoplayer2.testutil.FakeSampleStream;
|
||||||
import com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem;
|
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
@ -108,19 +111,18 @@ public class MediaCodecAudioRendererTest {
|
||||||
|
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ AUDIO_AAC,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ AUDIO_AAC,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 0),
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 50),
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 100),
|
||||||
new FakeSampleStreamItem(changedFormat),
|
format(changedFormat),
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 150),
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 200),
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 250),
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
END_OF_STREAM_ITEM));
|
||||||
|
|
||||||
mediaCodecAudioRenderer.enable(
|
mediaCodecAudioRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
|
|
@ -156,19 +158,18 @@ public class MediaCodecAudioRendererTest {
|
||||||
|
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ AUDIO_AAC,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ AUDIO_AAC,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 0),
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 50),
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 100),
|
||||||
new FakeSampleStreamItem(changedFormat),
|
format(changedFormat),
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 150),
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 200),
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 250),
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
END_OF_STREAM_ITEM));
|
||||||
|
|
||||||
mediaCodecAudioRenderer.enable(
|
mediaCodecAudioRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
|
|
@ -224,13 +225,10 @@ public class MediaCodecAudioRendererTest {
|
||||||
|
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ AUDIO_AAC,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ AUDIO_AAC,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(oneByteSample(/* timeUs= */ 0), END_OF_STREAM_ITEM));
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
|
||||||
|
|
||||||
exceptionThrowingRenderer.enable(
|
exceptionThrowingRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamI
|
||||||
import com.google.android.exoplayer2.testutil.TestUtil;
|
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -145,13 +146,12 @@ public class MetadataRendererTest {
|
||||||
renderer.replaceStream(
|
renderer.replaceStream(
|
||||||
new Format[] {EMSG_FORMAT},
|
new Format[] {EMSG_FORMAT},
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
EMSG_FORMAT,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
EMSG_FORMAT,
|
||||||
/* timeUsIncrement= */ 0,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(input),
|
FakeSampleStreamItem.sample(/* timeUs= */ 0, /* flags= */ 0, input),
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM),
|
FakeSampleStreamItem.END_OF_STREAM_ITEM)),
|
||||||
/* offsetUs= */ 0L);
|
/* offsetUs= */ 0L);
|
||||||
renderer.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0); // Read the format
|
renderer.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0); // Read the format
|
||||||
renderer.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0); // Read the data
|
renderer.render(/* positionUs= */ 0, /* elapsedRealtimeUs= */ 0); // Read the data
|
||||||
|
|
|
||||||
|
|
@ -503,14 +503,14 @@ public class DownloadHelperTest {
|
||||||
int periodIndex = TEST_TIMELINE.getIndexOfPeriod(id.periodUid);
|
int periodIndex = TEST_TIMELINE.getIndexOfPeriod(id.periodUid);
|
||||||
return new FakeMediaPeriod(
|
return new FakeMediaPeriod(
|
||||||
trackGroupArrays[periodIndex],
|
trackGroupArrays[periodIndex],
|
||||||
|
TEST_TIMELINE.getWindow(0, new Timeline.Window()).positionInFirstPeriodUs,
|
||||||
new EventDispatcher()
|
new EventDispatcher()
|
||||||
.withParameters(/* windowIndex= */ 0, id, /* mediaTimeOffsetMs= */ 0)) {
|
.withParameters(/* windowIndex= */ 0, id, /* mediaTimeOffsetMs= */ 0)) {
|
||||||
@Override
|
@Override
|
||||||
public List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
|
public List<StreamKey> getStreamKeys(List<TrackSelection> trackSelections) {
|
||||||
List<StreamKey> result = new ArrayList<>();
|
List<StreamKey> result = new ArrayList<>();
|
||||||
for (TrackSelection trackSelection : trackSelections) {
|
for (TrackSelection trackSelection : trackSelections) {
|
||||||
int groupIndex =
|
int groupIndex = trackGroupArrays[periodIndex].indexOf(trackSelection.getTrackGroup());
|
||||||
trackGroupArrays[periodIndex].indexOf(trackSelection.getTrackGroup());
|
|
||||||
for (int i = 0; i < trackSelection.length(); i++) {
|
for (int i = 0; i < trackSelection.length(); i++) {
|
||||||
result.add(
|
result.add(
|
||||||
new StreamKey(periodIndex, groupIndex, trackSelection.getIndexInTrackGroup(i)));
|
new StreamKey(periodIndex, groupIndex, trackSelection.getIndexInTrackGroup(i)));
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.source;
|
package com.google.android.exoplayer2.source;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM;
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
|
@ -22,11 +24,13 @@ import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.FormatHolder;
|
import com.google.android.exoplayer2.FormatHolder;
|
||||||
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
||||||
|
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||||
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
||||||
import com.google.android.exoplayer2.testutil.FakeMediaPeriod;
|
import com.google.android.exoplayer2.testutil.FakeMediaPeriod;
|
||||||
import com.google.android.exoplayer2.trackselection.FixedTrackSelection;
|
import com.google.android.exoplayer2.trackselection.FixedTrackSelection;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
@ -47,8 +51,10 @@ public final class MergingMediaPeriodTest {
|
||||||
public void getTrackGroups_returnsAllChildTrackGroups() throws Exception {
|
public void getTrackGroups_returnsAllChildTrackGroups() throws Exception {
|
||||||
MergingMediaPeriod mergingMediaPeriod =
|
MergingMediaPeriod mergingMediaPeriod =
|
||||||
prepareMergingPeriod(
|
prepareMergingPeriod(
|
||||||
new MergingPeriodDefinition(/* timeOffsetUs= */ 0, childFormat11, childFormat12),
|
new MergingPeriodDefinition(
|
||||||
new MergingPeriodDefinition(/* timeOffsetUs= */ 0, childFormat21, childFormat22));
|
/* timeOffsetUs= */ 0, /* singleSampleTimeUs= */ 0, childFormat11, childFormat12),
|
||||||
|
new MergingPeriodDefinition(
|
||||||
|
/* timeOffsetUs= */ 0, /* singleSampleTimeUs= */ 0, childFormat21, childFormat22));
|
||||||
|
|
||||||
assertThat(mergingMediaPeriod.getTrackGroups().length).isEqualTo(4);
|
assertThat(mergingMediaPeriod.getTrackGroups().length).isEqualTo(4);
|
||||||
assertThat(mergingMediaPeriod.getTrackGroups().get(0).getFormat(0)).isEqualTo(childFormat11);
|
assertThat(mergingMediaPeriod.getTrackGroups().get(0).getFormat(0)).isEqualTo(childFormat11);
|
||||||
|
|
@ -61,8 +67,10 @@ public final class MergingMediaPeriodTest {
|
||||||
public void selectTracks_createsSampleStreamsFromChildPeriods() throws Exception {
|
public void selectTracks_createsSampleStreamsFromChildPeriods() throws Exception {
|
||||||
MergingMediaPeriod mergingMediaPeriod =
|
MergingMediaPeriod mergingMediaPeriod =
|
||||||
prepareMergingPeriod(
|
prepareMergingPeriod(
|
||||||
new MergingPeriodDefinition(/* timeOffsetUs= */ 0, childFormat11, childFormat12),
|
new MergingPeriodDefinition(
|
||||||
new MergingPeriodDefinition(/* timeOffsetUs= */ 0, childFormat21, childFormat22));
|
/* timeOffsetUs= */ 0, /* singleSampleTimeUs= */ 0, childFormat11, childFormat12),
|
||||||
|
new MergingPeriodDefinition(
|
||||||
|
/* timeOffsetUs= */ 0, /* singleSampleTimeUs= */ 0, childFormat21, childFormat22));
|
||||||
|
|
||||||
TrackSelection selectionForChild1 =
|
TrackSelection selectionForChild1 =
|
||||||
new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(1), /* track= */ 0);
|
new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(1), /* track= */ 0);
|
||||||
|
|
@ -97,8 +105,16 @@ public final class MergingMediaPeriodTest {
|
||||||
throws Exception {
|
throws Exception {
|
||||||
MergingMediaPeriod mergingMediaPeriod =
|
MergingMediaPeriod mergingMediaPeriod =
|
||||||
prepareMergingPeriod(
|
prepareMergingPeriod(
|
||||||
new MergingPeriodDefinition(/* timeOffsetUs= */ 0, childFormat11, childFormat12),
|
new MergingPeriodDefinition(
|
||||||
new MergingPeriodDefinition(/* timeOffsetUs= */ -3000, childFormat21, childFormat22));
|
/* timeOffsetUs= */ 0,
|
||||||
|
/* singleSampleTimeUs= */ 123_000,
|
||||||
|
childFormat11,
|
||||||
|
childFormat12),
|
||||||
|
new MergingPeriodDefinition(
|
||||||
|
/* timeOffsetUs= */ -3000,
|
||||||
|
/* singleSampleTimeUs= */ 456_000,
|
||||||
|
childFormat21,
|
||||||
|
childFormat22));
|
||||||
|
|
||||||
TrackSelection selectionForChild1 =
|
TrackSelection selectionForChild1 =
|
||||||
new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(0), /* track= */ 0);
|
new FixedTrackSelection(mergingMediaPeriod.getTrackGroups().get(0), /* track= */ 0);
|
||||||
|
|
@ -122,14 +138,14 @@ public final class MergingMediaPeriodTest {
|
||||||
assertThat(childMediaPeriod1.selectTracksPositionUs).isEqualTo(0);
|
assertThat(childMediaPeriod1.selectTracksPositionUs).isEqualTo(0);
|
||||||
assertThat(streams[0].readData(formatHolder, inputBuffer, /* formatRequired= */ false))
|
assertThat(streams[0].readData(formatHolder, inputBuffer, /* formatRequired= */ false))
|
||||||
.isEqualTo(C.RESULT_BUFFER_READ);
|
.isEqualTo(C.RESULT_BUFFER_READ);
|
||||||
assertThat(inputBuffer.timeUs).isEqualTo(0L);
|
assertThat(inputBuffer.timeUs).isEqualTo(123_000L);
|
||||||
|
|
||||||
FakeMediaPeriodWithSelectTracksPosition childMediaPeriod2 =
|
FakeMediaPeriodWithSelectTracksPosition childMediaPeriod2 =
|
||||||
(FakeMediaPeriodWithSelectTracksPosition) mergingMediaPeriod.getChildPeriod(1);
|
(FakeMediaPeriodWithSelectTracksPosition) mergingMediaPeriod.getChildPeriod(1);
|
||||||
assertThat(childMediaPeriod2.selectTracksPositionUs).isEqualTo(3000L);
|
assertThat(childMediaPeriod2.selectTracksPositionUs).isEqualTo(3000L);
|
||||||
assertThat(streams[1].readData(formatHolder, inputBuffer, /* formatRequired= */ false))
|
assertThat(streams[1].readData(formatHolder, inputBuffer, /* formatRequired= */ false))
|
||||||
.isEqualTo(C.RESULT_BUFFER_READ);
|
.isEqualTo(C.RESULT_BUFFER_READ);
|
||||||
assertThat(inputBuffer.timeUs).isEqualTo(0L);
|
assertThat(inputBuffer.timeUs).isEqualTo(456_000 - 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MergingMediaPeriod prepareMergingPeriod(MergingPeriodDefinition... definitions)
|
private MergingMediaPeriod prepareMergingPeriod(MergingPeriodDefinition... definitions)
|
||||||
|
|
@ -137,10 +153,11 @@ public final class MergingMediaPeriodTest {
|
||||||
MediaPeriod[] mediaPeriods = new MediaPeriod[definitions.length];
|
MediaPeriod[] mediaPeriods = new MediaPeriod[definitions.length];
|
||||||
long[] timeOffsetsUs = new long[definitions.length];
|
long[] timeOffsetsUs = new long[definitions.length];
|
||||||
for (int i = 0; i < definitions.length; i++) {
|
for (int i = 0; i < definitions.length; i++) {
|
||||||
timeOffsetsUs[i] = definitions[i].timeOffsetUs;
|
MergingPeriodDefinition definition = definitions[i];
|
||||||
TrackGroup[] trackGroups = new TrackGroup[definitions[i].formats.length];
|
timeOffsetsUs[i] = definition.timeOffsetUs;
|
||||||
for (int j = 0; j < definitions[i].formats.length; j++) {
|
TrackGroup[] trackGroups = new TrackGroup[definition.formats.length];
|
||||||
trackGroups[j] = new TrackGroup(definitions[i].formats[j]);
|
for (int j = 0; j < definition.formats.length; j++) {
|
||||||
|
trackGroups[j] = new TrackGroup(definition.formats[j]);
|
||||||
}
|
}
|
||||||
mediaPeriods[i] =
|
mediaPeriods[i] =
|
||||||
new FakeMediaPeriodWithSelectTracksPosition(
|
new FakeMediaPeriodWithSelectTracksPosition(
|
||||||
|
|
@ -149,7 +166,10 @@ public final class MergingMediaPeriodTest {
|
||||||
.withParameters(
|
.withParameters(
|
||||||
/* windowIndex= */ i,
|
/* windowIndex= */ i,
|
||||||
new MediaPeriodId(/* periodUid= */ i),
|
new MediaPeriodId(/* periodUid= */ i),
|
||||||
/* mediaTimeOffsetMs= */ 0));
|
/* mediaTimeOffsetMs= */ 0),
|
||||||
|
/* trackDataFactory= */ (unusedFormat, unusedMediaPeriodId) ->
|
||||||
|
ImmutableList.of(
|
||||||
|
oneByteSample(definition.singleSampleTimeUs), END_OF_STREAM_ITEM));
|
||||||
}
|
}
|
||||||
MergingMediaPeriod mergingMediaPeriod =
|
MergingMediaPeriod mergingMediaPeriod =
|
||||||
new MergingMediaPeriod(
|
new MergingMediaPeriod(
|
||||||
|
|
@ -179,8 +199,15 @@ public final class MergingMediaPeriodTest {
|
||||||
public long selectTracksPositionUs;
|
public long selectTracksPositionUs;
|
||||||
|
|
||||||
public FakeMediaPeriodWithSelectTracksPosition(
|
public FakeMediaPeriodWithSelectTracksPosition(
|
||||||
TrackGroupArray trackGroupArray, EventDispatcher eventDispatcher) {
|
TrackGroupArray trackGroupArray,
|
||||||
super(trackGroupArray, eventDispatcher);
|
EventDispatcher eventDispatcher,
|
||||||
|
TrackDataFactory trackDataFactory) {
|
||||||
|
super(
|
||||||
|
trackGroupArray,
|
||||||
|
trackDataFactory,
|
||||||
|
eventDispatcher,
|
||||||
|
DrmSessionManager.DUMMY,
|
||||||
|
/* deferOnPrepared= */ false);
|
||||||
selectTracksPositionUs = C.TIME_UNSET;
|
selectTracksPositionUs = C.TIME_UNSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,11 +226,13 @@ public final class MergingMediaPeriodTest {
|
||||||
|
|
||||||
private static final class MergingPeriodDefinition {
|
private static final class MergingPeriodDefinition {
|
||||||
|
|
||||||
public long timeOffsetUs;
|
public final long timeOffsetUs;
|
||||||
public Format[] formats;
|
public final long singleSampleTimeUs;
|
||||||
|
public final Format[] formats;
|
||||||
|
|
||||||
public MergingPeriodDefinition(long timeOffsetUs, Format... formats) {
|
public MergingPeriodDefinition(long timeOffsetUs, long singleSampleTimeUs, Format... formats) {
|
||||||
this.timeOffsetUs = timeOffsetUs;
|
this.timeOffsetUs = timeOffsetUs;
|
||||||
|
this.singleSampleTimeUs = singleSampleTimeUs;
|
||||||
this.formats = formats;
|
this.formats = formats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.video;
|
package com.google.android.exoplayer2.video;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
|
|
@ -39,6 +40,7 @@ import com.google.android.exoplayer2.drm.ExoMediaCrypto;
|
||||||
import com.google.android.exoplayer2.testutil.FakeSampleStream;
|
import com.google.android.exoplayer2.testutil.FakeSampleStream;
|
||||||
import com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem;
|
import com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.util.concurrent.Phaser;
|
import java.util.concurrent.Phaser;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
@ -183,12 +185,10 @@ public final class DecoderVideoRendererTest {
|
||||||
public void enable_withMayRenderStartOfStream_rendersFirstFrameBeforeStart() throws Exception {
|
public void enable_withMayRenderStartOfStream_rendersFirstFrameBeforeStart() throws Exception {
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ H264_FORMAT,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ H264_FORMAT,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(oneByteSample(/* timeUs= */ 0)));
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
|
||||||
|
|
||||||
renderer.enable(
|
renderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
|
|
@ -212,12 +212,10 @@ public final class DecoderVideoRendererTest {
|
||||||
throws Exception {
|
throws Exception {
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ H264_FORMAT,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ H264_FORMAT,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(oneByteSample(/* timeUs= */ 0)));
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
|
||||||
|
|
||||||
renderer.enable(
|
renderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
|
|
@ -240,12 +238,10 @@ public final class DecoderVideoRendererTest {
|
||||||
public void enable_withoutMayRenderStartOfStream_rendersFirstFrameAfterStart() throws Exception {
|
public void enable_withoutMayRenderStartOfStream_rendersFirstFrameAfterStart() throws Exception {
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ H264_FORMAT,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ H264_FORMAT,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(oneByteSample(/* timeUs= */ 0)));
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
|
||||||
|
|
||||||
renderer.enable(
|
renderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
|
|
@ -271,22 +267,18 @@ public final class DecoderVideoRendererTest {
|
||||||
public void replaceStream_whenStarted_rendersFirstFrameOfNewStream() throws Exception {
|
public void replaceStream_whenStarted_rendersFirstFrameOfNewStream() throws Exception {
|
||||||
FakeSampleStream fakeSampleStream1 =
|
FakeSampleStream fakeSampleStream1 =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ H264_FORMAT,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ H264_FORMAT,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM));
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
|
||||||
FakeSampleStream fakeSampleStream2 =
|
FakeSampleStream fakeSampleStream2 =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ H264_FORMAT,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ H264_FORMAT,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM));
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
|
||||||
renderer.enable(
|
renderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
new Format[] {H264_FORMAT},
|
new Format[] {H264_FORMAT},
|
||||||
|
|
@ -317,22 +309,18 @@ public final class DecoderVideoRendererTest {
|
||||||
public void replaceStream_whenNotStarted_doesNotRenderFirstFrameOfNewStream() throws Exception {
|
public void replaceStream_whenNotStarted_doesNotRenderFirstFrameOfNewStream() throws Exception {
|
||||||
FakeSampleStream fakeSampleStream1 =
|
FakeSampleStream fakeSampleStream1 =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ H264_FORMAT,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ H264_FORMAT,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM));
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
|
||||||
FakeSampleStream fakeSampleStream2 =
|
FakeSampleStream fakeSampleStream2 =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ H264_FORMAT,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ H264_FORMAT,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM));
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
|
||||||
renderer.enable(
|
renderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
new Format[] {H264_FORMAT},
|
new Format[] {H264_FORMAT},
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.video;
|
package com.google.android.exoplayer2.video;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.format;
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
|
@ -45,6 +47,7 @@ import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryExcep
|
||||||
import com.google.android.exoplayer2.testutil.FakeSampleStream;
|
import com.google.android.exoplayer2.testutil.FakeSampleStream;
|
||||||
import com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem;
|
import com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
@ -126,15 +129,14 @@ public class MediaCodecVideoRendererTest {
|
||||||
public void render_dropsLateBuffer() throws Exception {
|
public void render_dropsLateBuffer() throws Exception {
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ VIDEO_H264,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ VIDEO_H264,
|
||||||
/* timeUsIncrement= */ 50_000,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME), // First buffer.
|
oneByteSample(/* timeUs= */ 0), // First buffer.
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME), // Late buffer.
|
oneByteSample(/* timeUs= */ 50_000), // Late buffer.
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME), // Last buffer.
|
oneByteSample(/* timeUs= */ 100_000), // Last buffer.
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
FakeSampleStreamItem.END_OF_STREAM_ITEM));
|
||||||
mediaCodecVideoRenderer.enable(
|
mediaCodecVideoRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
new Format[] {VIDEO_H264},
|
new Format[] {VIDEO_H264},
|
||||||
|
|
@ -163,13 +165,11 @@ public class MediaCodecVideoRendererTest {
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
new Format[] {VIDEO_H264},
|
new Format[] {VIDEO_H264},
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ VIDEO_H264,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ VIDEO_H264,
|
||||||
/* timeUsIncrement= */ 0,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 0), FakeSampleStreamItem.END_OF_STREAM_ITEM)),
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM),
|
|
||||||
/* positionUs= */ 0,
|
/* positionUs= */ 0,
|
||||||
/* joining= */ false,
|
/* joining= */ false,
|
||||||
/* mayRenderStartOfStream= */ true,
|
/* mayRenderStartOfStream= */ true,
|
||||||
|
|
@ -201,12 +201,10 @@ public class MediaCodecVideoRendererTest {
|
||||||
|
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ pAsp1,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ pAsp1,
|
||||||
/* timeUsIncrement= */ 5000,
|
ImmutableList.of(oneByteSample(/* timeUs= */ 0)));
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
|
||||||
|
|
||||||
mediaCodecVideoRenderer.enable(
|
mediaCodecVideoRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
|
|
@ -220,16 +218,12 @@ public class MediaCodecVideoRendererTest {
|
||||||
mediaCodecVideoRenderer.render(/* positionUs= */ 0, SystemClock.elapsedRealtime() * 1000);
|
mediaCodecVideoRenderer.render(/* positionUs= */ 0, SystemClock.elapsedRealtime() * 1000);
|
||||||
mediaCodecVideoRenderer.render(/* positionUs= */ 250, SystemClock.elapsedRealtime() * 1000);
|
mediaCodecVideoRenderer.render(/* positionUs= */ 250, SystemClock.elapsedRealtime() * 1000);
|
||||||
|
|
||||||
fakeSampleStream.addFakeSampleStreamItem(new FakeSampleStreamItem(pAsp2));
|
fakeSampleStream.addFakeSampleStreamItem(format(pAsp2));
|
||||||
fakeSampleStream.addFakeSampleStreamItem(
|
fakeSampleStream.addFakeSampleStreamItem(oneByteSample(/* timeUs= */ 5_000));
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
fakeSampleStream.addFakeSampleStreamItem(oneByteSample(/* timeUs= */ 10_000));
|
||||||
fakeSampleStream.addFakeSampleStreamItem(
|
fakeSampleStream.addFakeSampleStreamItem(format(pAsp3));
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
fakeSampleStream.addFakeSampleStreamItem(oneByteSample(/* timeUs= */ 15_000));
|
||||||
fakeSampleStream.addFakeSampleStreamItem(new FakeSampleStreamItem(pAsp3));
|
fakeSampleStream.addFakeSampleStreamItem(oneByteSample(/* timeUs= */ 20_000));
|
||||||
fakeSampleStream.addFakeSampleStreamItem(
|
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
|
||||||
fakeSampleStream.addFakeSampleStreamItem(
|
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
|
||||||
fakeSampleStream.addFakeSampleStreamItem(FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
fakeSampleStream.addFakeSampleStreamItem(FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
||||||
mediaCodecVideoRenderer.setCurrentStreamFinal();
|
mediaCodecVideoRenderer.setCurrentStreamFinal();
|
||||||
|
|
||||||
|
|
@ -251,12 +245,10 @@ public class MediaCodecVideoRendererTest {
|
||||||
throws Exception {
|
throws Exception {
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ VIDEO_H264,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ VIDEO_H264,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(oneByteSample(/* timeUs= */ 0)));
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
|
||||||
mediaCodecVideoRenderer.enable(
|
mediaCodecVideoRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
new Format[] {VIDEO_H264},
|
new Format[] {VIDEO_H264},
|
||||||
|
|
@ -270,8 +262,7 @@ public class MediaCodecVideoRendererTest {
|
||||||
mediaCodecVideoRenderer.render(/* positionUs= */ 0, SystemClock.elapsedRealtime() * 1000);
|
mediaCodecVideoRenderer.render(/* positionUs= */ 0, SystemClock.elapsedRealtime() * 1000);
|
||||||
mediaCodecVideoRenderer.resetPosition(0);
|
mediaCodecVideoRenderer.resetPosition(0);
|
||||||
mediaCodecVideoRenderer.setCurrentStreamFinal();
|
mediaCodecVideoRenderer.setCurrentStreamFinal();
|
||||||
fakeSampleStream.addFakeSampleStreamItem(
|
fakeSampleStream.addFakeSampleStreamItem(oneByteSample(/* timeUs= */ 0));
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
|
||||||
fakeSampleStream.addFakeSampleStreamItem(FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
fakeSampleStream.addFakeSampleStreamItem(FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
||||||
int positionUs = 10;
|
int positionUs = 10;
|
||||||
do {
|
do {
|
||||||
|
|
@ -286,12 +277,10 @@ public class MediaCodecVideoRendererTest {
|
||||||
public void enable_withMayRenderStartOfStream_rendersFirstFrameBeforeStart() throws Exception {
|
public void enable_withMayRenderStartOfStream_rendersFirstFrameBeforeStart() throws Exception {
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ VIDEO_H264,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ VIDEO_H264,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(oneByteSample(/* timeUs= */ 0)));
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
|
||||||
|
|
||||||
mediaCodecVideoRenderer.enable(
|
mediaCodecVideoRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
|
|
@ -313,12 +302,10 @@ public class MediaCodecVideoRendererTest {
|
||||||
throws Exception {
|
throws Exception {
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ VIDEO_H264,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ VIDEO_H264,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(oneByteSample(/* timeUs= */ 0)));
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
|
||||||
|
|
||||||
mediaCodecVideoRenderer.enable(
|
mediaCodecVideoRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
|
|
@ -339,12 +326,10 @@ public class MediaCodecVideoRendererTest {
|
||||||
public void enable_withoutMayRenderStartOfStream_rendersFirstFrameAfterStart() throws Exception {
|
public void enable_withoutMayRenderStartOfStream_rendersFirstFrameAfterStart() throws Exception {
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ VIDEO_H264,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ VIDEO_H264,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(oneByteSample(/* timeUs= */ 0)));
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME));
|
|
||||||
|
|
||||||
mediaCodecVideoRenderer.enable(
|
mediaCodecVideoRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
|
|
@ -366,22 +351,20 @@ public class MediaCodecVideoRendererTest {
|
||||||
public void replaceStream_whenStarted_rendersFirstFrameOfNewStream() throws Exception {
|
public void replaceStream_whenStarted_rendersFirstFrameOfNewStream() throws Exception {
|
||||||
FakeSampleStream fakeSampleStream1 =
|
FakeSampleStream fakeSampleStream1 =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ VIDEO_H264,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ VIDEO_H264,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME),
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
FakeSampleStreamItem.END_OF_STREAM_ITEM));
|
||||||
FakeSampleStream fakeSampleStream2 =
|
FakeSampleStream fakeSampleStream2 =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ VIDEO_H264,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ VIDEO_H264,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME),
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
FakeSampleStreamItem.END_OF_STREAM_ITEM));
|
||||||
mediaCodecVideoRenderer.enable(
|
mediaCodecVideoRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
new Format[] {VIDEO_H264},
|
new Format[] {VIDEO_H264},
|
||||||
|
|
@ -410,22 +393,20 @@ public class MediaCodecVideoRendererTest {
|
||||||
public void replaceStream_whenNotStarted_doesNotRenderFirstFrameOfNewStream() throws Exception {
|
public void replaceStream_whenNotStarted_doesNotRenderFirstFrameOfNewStream() throws Exception {
|
||||||
FakeSampleStream fakeSampleStream1 =
|
FakeSampleStream fakeSampleStream1 =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ VIDEO_H264,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ VIDEO_H264,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME),
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
FakeSampleStreamItem.END_OF_STREAM_ITEM));
|
||||||
FakeSampleStream fakeSampleStream2 =
|
FakeSampleStream fakeSampleStream2 =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ VIDEO_H264,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ VIDEO_H264,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(new byte[] {0}, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 0, C.BUFFER_FLAG_KEY_FRAME),
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
FakeSampleStreamItem.END_OF_STREAM_ITEM));
|
||||||
mediaCodecVideoRenderer.enable(
|
mediaCodecVideoRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
new Format[] {VIDEO_H264},
|
new Format[] {VIDEO_H264},
|
||||||
|
|
@ -458,26 +439,23 @@ public class MediaCodecVideoRendererTest {
|
||||||
public void onVideoFrameProcessingOffset_isCalledAfterOutputFormatChanges()
|
public void onVideoFrameProcessingOffset_isCalledAfterOutputFormatChanges()
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
Format mp4Uhd = VIDEO_H264.buildUpon().setWidth(3840).setHeight(2160).build();
|
Format mp4Uhd = VIDEO_H264.buildUpon().setWidth(3840).setHeight(2160).build();
|
||||||
byte[] sampleData = new byte[0];
|
|
||||||
FakeSampleStream fakeSampleStream =
|
FakeSampleStream fakeSampleStream =
|
||||||
new FakeSampleStream(
|
new FakeSampleStream(
|
||||||
/* format= */ mp4Uhd,
|
|
||||||
DrmSessionManager.DUMMY,
|
DrmSessionManager.DUMMY,
|
||||||
/* eventDispatcher= */ null,
|
/* eventDispatcher= */ null,
|
||||||
/* firstSampleTimeUs= */ 0,
|
/* initialFormat= */ mp4Uhd,
|
||||||
/* timeUsIncrement= */ 50,
|
ImmutableList.of(
|
||||||
new FakeSampleStreamItem(mp4Uhd),
|
oneByteSample(/* timeUs= */ 0),
|
||||||
new FakeSampleStreamItem(sampleData, C.BUFFER_FLAG_KEY_FRAME),
|
format(VIDEO_H264),
|
||||||
new FakeSampleStreamItem(VIDEO_H264),
|
oneByteSample(/* timeUs= */ 50),
|
||||||
new FakeSampleStreamItem(sampleData, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 100),
|
||||||
new FakeSampleStreamItem(sampleData, C.BUFFER_FLAG_KEY_FRAME),
|
format(mp4Uhd),
|
||||||
new FakeSampleStreamItem(mp4Uhd),
|
oneByteSample(/* timeUs= */ 150),
|
||||||
new FakeSampleStreamItem(sampleData, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 200),
|
||||||
new FakeSampleStreamItem(sampleData, C.BUFFER_FLAG_KEY_FRAME),
|
oneByteSample(/* timeUs= */ 250),
|
||||||
new FakeSampleStreamItem(sampleData, C.BUFFER_FLAG_KEY_FRAME),
|
format(VIDEO_H264),
|
||||||
new FakeSampleStreamItem(VIDEO_H264),
|
oneByteSample(/* timeUs= */ 300),
|
||||||
new FakeSampleStreamItem(sampleData, C.BUFFER_FLAG_KEY_FRAME),
|
FakeSampleStreamItem.END_OF_STREAM_ITEM));
|
||||||
FakeSampleStreamItem.END_OF_STREAM_ITEM);
|
|
||||||
|
|
||||||
mediaCodecVideoRenderer.enable(
|
mediaCodecVideoRenderer.enable(
|
||||||
RendererConfiguration.DEFAULT,
|
RendererConfiguration.DEFAULT,
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,14 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
|
||||||
FakeChunkSource.Factory chunkSourceFactory,
|
FakeChunkSource.Factory chunkSourceFactory,
|
||||||
long durationUs,
|
long durationUs,
|
||||||
@Nullable TransferListener transferListener) {
|
@Nullable TransferListener transferListener) {
|
||||||
super(trackGroupArray, eventDispatcher);
|
super(
|
||||||
|
trackGroupArray,
|
||||||
|
/* trackDataFactory= */ (unusedFormat, unusedMediaPeriodId) -> {
|
||||||
|
throw new RuntimeException("unused track data");
|
||||||
|
},
|
||||||
|
eventDispatcher,
|
||||||
|
DrmSessionManager.DUMMY,
|
||||||
|
/* deferOnPrepared= */ false);
|
||||||
this.allocator = allocator;
|
this.allocator = allocator;
|
||||||
this.chunkSourceFactory = chunkSourceFactory;
|
this.chunkSourceFactory = chunkSourceFactory;
|
||||||
this.transferListener = transferListener;
|
this.transferListener = transferListener;
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,13 @@ public class FakeAdaptiveMediaSource extends FakeMediaSource {
|
||||||
Timeline timeline,
|
Timeline timeline,
|
||||||
TrackGroupArray trackGroupArray,
|
TrackGroupArray trackGroupArray,
|
||||||
FakeChunkSource.Factory chunkSourceFactory) {
|
FakeChunkSource.Factory chunkSourceFactory) {
|
||||||
super(timeline, DrmSessionManager.DUMMY, trackGroupArray);
|
super(
|
||||||
|
timeline,
|
||||||
|
DrmSessionManager.DUMMY,
|
||||||
|
/* trackDataFactory= */ (unusedFormat, unusedMediaPeriodId) -> {
|
||||||
|
throw new RuntimeException("Unused TrackDataFactory");
|
||||||
|
},
|
||||||
|
trackGroupArray);
|
||||||
this.chunkSourceFactory = chunkSourceFactory;
|
this.chunkSourceFactory = chunkSourceFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.testutil;
|
package com.google.android.exoplayer2.testutil;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM;
|
||||||
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
@ -22,17 +24,22 @@ import android.os.Handler;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.SeekParameters;
|
import com.google.android.exoplayer2.SeekParameters;
|
||||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||||
import com.google.android.exoplayer2.source.LoadEventInfo;
|
import com.google.android.exoplayer2.source.LoadEventInfo;
|
||||||
import com.google.android.exoplayer2.source.MediaPeriod;
|
import com.google.android.exoplayer2.source.MediaPeriod;
|
||||||
|
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
||||||
import com.google.android.exoplayer2.source.SampleStream;
|
import com.google.android.exoplayer2.source.SampleStream;
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
|
import com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
import com.google.android.exoplayer2.trackselection.TrackSelection;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -52,6 +59,7 @@ public class FakeMediaPeriod implements MediaPeriod {
|
||||||
private final List<SampleStream> sampleStreams;
|
private final List<SampleStream> sampleStreams;
|
||||||
private final DrmSessionManager drmSessionManager;
|
private final DrmSessionManager drmSessionManager;
|
||||||
private final EventDispatcher eventDispatcher;
|
private final EventDispatcher eventDispatcher;
|
||||||
|
private final TrackDataFactory trackDataFactory;
|
||||||
private final long fakePreparationLoadTaskId;
|
private final long fakePreparationLoadTaskId;
|
||||||
|
|
||||||
@Nullable private Handler playerHandler;
|
@Nullable private Handler playerHandler;
|
||||||
|
|
@ -64,48 +72,71 @@ public class FakeMediaPeriod implements MediaPeriod {
|
||||||
private long discontinuityPositionUs;
|
private long discontinuityPositionUs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a FakeMediaPeriod.
|
* Constructs a FakeMediaPeriod with a single sample for each track in {@code trackGroupArray}.
|
||||||
*
|
*
|
||||||
* @param trackGroupArray The track group array.
|
* @param trackGroupArray The track group array.
|
||||||
|
* @param singleSampleTimeUs The timestamp to use for the single sample in each track, in
|
||||||
|
* microseconds.
|
||||||
* @param eventDispatcher A dispatcher for media source events.
|
* @param eventDispatcher A dispatcher for media source events.
|
||||||
*/
|
*/
|
||||||
public FakeMediaPeriod(TrackGroupArray trackGroupArray, EventDispatcher eventDispatcher) {
|
public FakeMediaPeriod(
|
||||||
this(trackGroupArray, DrmSessionManager.DUMMY, eventDispatcher, /* deferOnPrepared */ false);
|
TrackGroupArray trackGroupArray, long singleSampleTimeUs, EventDispatcher eventDispatcher) {
|
||||||
|
this(
|
||||||
|
trackGroupArray,
|
||||||
|
TrackDataFactory.singleSampleWithTimeUs(singleSampleTimeUs),
|
||||||
|
eventDispatcher,
|
||||||
|
DrmSessionManager.DUMMY,
|
||||||
|
/* deferOnPrepared= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a FakeMediaPeriod.
|
* Constructs a FakeMediaPeriod with a single sample for each track in {@code trackGroupArray}.
|
||||||
*
|
*
|
||||||
* @param trackGroupArray The track group array.
|
* @param trackGroupArray The track group array.
|
||||||
|
* @param singleSampleTimeUs The timestamp to use for the single sample in each track, in
|
||||||
|
* microseconds.
|
||||||
|
* @param eventDispatcher A dispatcher for media source events.
|
||||||
* @param drmSessionManager The {@link DrmSessionManager} used for DRM interactions.
|
* @param drmSessionManager The {@link DrmSessionManager} used for DRM interactions.
|
||||||
* @param eventDispatcher A dispatcher for media source events.
|
* @param deferOnPrepared Whether {@link Callback#onPrepared(MediaPeriod)} should be called only
|
||||||
|
* after {@link #setPreparationComplete()} has been called. If {@code false}
|
||||||
*/
|
*/
|
||||||
public FakeMediaPeriod(
|
public FakeMediaPeriod(
|
||||||
TrackGroupArray trackGroupArray,
|
TrackGroupArray trackGroupArray,
|
||||||
|
long singleSampleTimeUs,
|
||||||
|
EventDispatcher eventDispatcher,
|
||||||
DrmSessionManager drmSessionManager,
|
DrmSessionManager drmSessionManager,
|
||||||
EventDispatcher eventDispatcher) {
|
boolean deferOnPrepared) {
|
||||||
this(trackGroupArray, drmSessionManager, eventDispatcher, /* deferOnPrepared */ false);
|
this(
|
||||||
|
trackGroupArray,
|
||||||
|
TrackDataFactory.singleSampleWithTimeUs(singleSampleTimeUs),
|
||||||
|
eventDispatcher,
|
||||||
|
drmSessionManager,
|
||||||
|
deferOnPrepared);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a FakeMediaPeriod.
|
* Constructs a FakeMediaPeriod.
|
||||||
*
|
*
|
||||||
* @param trackGroupArray The track group array.
|
* @param trackGroupArray The track group array.
|
||||||
* @param drmSessionManager The DrmSessionManager used for DRM interactions.
|
* @param trackDataFactory A source for the underlying sample data for each track in {@code
|
||||||
|
* trackGroupArray}.
|
||||||
* @param eventDispatcher A dispatcher for media source events.
|
* @param eventDispatcher A dispatcher for media source events.
|
||||||
* @param deferOnPrepared Whether {@link MediaPeriod.Callback#onPrepared(MediaPeriod)} should be
|
* @param drmSessionManager The DrmSessionManager used for DRM interactions.
|
||||||
* called only after {@link #setPreparationComplete()} has been called. If {@code false}
|
* @param deferOnPrepared Whether {@link Callback#onPrepared(MediaPeriod)} should be called only
|
||||||
* preparation completes immediately.
|
* after {@link #setPreparationComplete()} has been called. If {@code false} preparation
|
||||||
|
* completes immediately.
|
||||||
*/
|
*/
|
||||||
public FakeMediaPeriod(
|
public FakeMediaPeriod(
|
||||||
TrackGroupArray trackGroupArray,
|
TrackGroupArray trackGroupArray,
|
||||||
DrmSessionManager drmSessionManager,
|
TrackDataFactory trackDataFactory,
|
||||||
EventDispatcher eventDispatcher,
|
EventDispatcher eventDispatcher,
|
||||||
|
DrmSessionManager drmSessionManager,
|
||||||
boolean deferOnPrepared) {
|
boolean deferOnPrepared) {
|
||||||
this.trackGroupArray = trackGroupArray;
|
this.trackGroupArray = trackGroupArray;
|
||||||
this.drmSessionManager = drmSessionManager;
|
this.drmSessionManager = drmSessionManager;
|
||||||
this.eventDispatcher = eventDispatcher;
|
this.eventDispatcher = eventDispatcher;
|
||||||
this.deferOnPrepared = deferOnPrepared;
|
this.deferOnPrepared = deferOnPrepared;
|
||||||
|
this.trackDataFactory = trackDataFactory;
|
||||||
discontinuityPositionUs = C.TIME_UNSET;
|
discontinuityPositionUs = C.TIME_UNSET;
|
||||||
sampleStreams = new ArrayList<>();
|
sampleStreams = new ArrayList<>();
|
||||||
fakePreparationLoadTaskId = LoadEventInfo.getNewId();
|
fakePreparationLoadTaskId = LoadEventInfo.getNewId();
|
||||||
|
|
@ -282,13 +313,16 @@ public class FakeMediaPeriod implements MediaPeriod {
|
||||||
TrackSelection selection,
|
TrackSelection selection,
|
||||||
DrmSessionManager drmSessionManager,
|
DrmSessionManager drmSessionManager,
|
||||||
EventDispatcher eventDispatcher) {
|
EventDispatcher eventDispatcher) {
|
||||||
return new FakeSampleStream(
|
FakeSampleStream sampleStream =
|
||||||
selection.getSelectedFormat(),
|
new FakeSampleStream(
|
||||||
drmSessionManager,
|
drmSessionManager,
|
||||||
eventDispatcher,
|
eventDispatcher,
|
||||||
positionUs,
|
selection.getSelectedFormat(),
|
||||||
/* timeUsIncrement= */ 0,
|
trackDataFactory.create(
|
||||||
FakeSampleStream.SINGLE_SAMPLE_THEN_END_OF_STREAM);
|
selection.getSelectedFormat(),
|
||||||
|
Assertions.checkNotNull(eventDispatcher.mediaPeriodId)));
|
||||||
|
sampleStream.seekTo(positionUs);
|
||||||
|
return sampleStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -300,8 +334,7 @@ public class FakeMediaPeriod implements MediaPeriod {
|
||||||
*/
|
*/
|
||||||
protected void seekSampleStream(SampleStream sampleStream, long positionUs) {
|
protected void seekSampleStream(SampleStream sampleStream, long positionUs) {
|
||||||
// Queue a single sample from the seek position again.
|
// Queue a single sample from the seek position again.
|
||||||
((FakeSampleStream) sampleStream)
|
((FakeSampleStream) sampleStream).seekTo(positionUs);
|
||||||
.resetSampleStreamItems(positionUs, FakeSampleStream.SINGLE_SAMPLE_THEN_END_OF_STREAM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -334,4 +367,27 @@ public class FakeMediaPeriod implements MediaPeriod {
|
||||||
/* mediaStartTimeUs= */ 0,
|
/* mediaStartTimeUs= */ 0,
|
||||||
/* mediaEndTimeUs = */ C.TIME_UNSET);
|
/* mediaEndTimeUs = */ C.TIME_UNSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A factory to create the test data for a particular track. */
|
||||||
|
public interface TrackDataFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of {@link FakeSampleStreamItem}s that will be passed to {@link
|
||||||
|
* FakeSampleStream#FakeSampleStream(DrmSessionManager, EventDispatcher, Format, List)}.
|
||||||
|
*
|
||||||
|
* @param format The format of the track to provide data for.
|
||||||
|
* @param mediaPeriodId The {@link MediaPeriodId} to provide data for.
|
||||||
|
* @return The track data in the form of {@link FakeSampleStreamItem}s.
|
||||||
|
*/
|
||||||
|
List<FakeSampleStreamItem> create(Format format, MediaPeriodId mediaPeriodId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a factory that always provides a single sample with {@code time=sampleTimeUs} and
|
||||||
|
* then end-of-stream.
|
||||||
|
*/
|
||||||
|
static TrackDataFactory singleSampleWithTimeUs(long sampleTimeUs) {
|
||||||
|
return (unusedFormat, unusedMediaPeriodId) ->
|
||||||
|
ImmutableList.of(oneByteSample(sampleTimeUs), END_OF_STREAM_ITEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
|
||||||
import com.google.android.exoplayer2.source.TrackGroup;
|
import com.google.android.exoplayer2.source.TrackGroup;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
import com.google.android.exoplayer2.source.TrackGroupArray;
|
||||||
|
import com.google.android.exoplayer2.testutil.FakeMediaPeriod.TrackDataFactory;
|
||||||
import com.google.android.exoplayer2.upstream.Allocator;
|
import com.google.android.exoplayer2.upstream.Allocator;
|
||||||
import com.google.android.exoplayer2.upstream.DataSpec;
|
import com.google.android.exoplayer2.upstream.DataSpec;
|
||||||
import com.google.android.exoplayer2.upstream.TransferListener;
|
import com.google.android.exoplayer2.upstream.TransferListener;
|
||||||
|
|
@ -46,6 +47,7 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
|
import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fake {@link MediaSource} that provides a given timeline. Creating the period will return a {@link
|
* Fake {@link MediaSource} that provides a given timeline. Creating the period will return a {@link
|
||||||
|
|
@ -78,6 +80,7 @@ public class FakeMediaSource extends BaseMediaSource {
|
||||||
private static final int MANIFEST_LOAD_BYTES = 100;
|
private static final int MANIFEST_LOAD_BYTES = 100;
|
||||||
|
|
||||||
private final TrackGroupArray trackGroupArray;
|
private final TrackGroupArray trackGroupArray;
|
||||||
|
@Nullable private final FakeMediaPeriod.TrackDataFactory trackDataFactory;
|
||||||
private final ArrayList<FakeMediaPeriod> activeMediaPeriods;
|
private final ArrayList<FakeMediaPeriod> activeMediaPeriods;
|
||||||
private final ArrayList<MediaPeriodId> createdMediaPeriods;
|
private final ArrayList<MediaPeriodId> createdMediaPeriods;
|
||||||
private final DrmSessionManager drmSessionManager;
|
private final DrmSessionManager drmSessionManager;
|
||||||
|
|
@ -107,18 +110,35 @@ public class FakeMediaSource extends BaseMediaSource {
|
||||||
*/
|
*/
|
||||||
public FakeMediaSource(
|
public FakeMediaSource(
|
||||||
@Nullable Timeline timeline, DrmSessionManager drmSessionManager, Format... formats) {
|
@Nullable Timeline timeline, DrmSessionManager drmSessionManager, Format... formats) {
|
||||||
this(timeline, drmSessionManager, buildTrackGroupArray(formats));
|
this(timeline, drmSessionManager, /* trackDataFactory= */ null, buildTrackGroupArray(formats));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link FakeMediaSource}. This media source creates {@link FakeMediaPeriod}s with a
|
||||||
|
* {@link TrackGroupArray} using the given {@link Format}s. It passes {@code drmSessionManager}
|
||||||
|
* and {@code trackDataFactory} into the created periods. The provided {@link Timeline} may be
|
||||||
|
* null to prevent an immediate source info refresh message when preparing the media source. It
|
||||||
|
* can be manually set later using {@link #setNewSourceInfo(Timeline)}.
|
||||||
|
*/
|
||||||
|
public FakeMediaSource(
|
||||||
|
@Nullable Timeline timeline,
|
||||||
|
DrmSessionManager drmSessionManager,
|
||||||
|
@Nullable FakeMediaPeriod.TrackDataFactory trackDataFactory,
|
||||||
|
Format... formats) {
|
||||||
|
this(timeline, drmSessionManager, trackDataFactory, buildTrackGroupArray(formats));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link FakeMediaSource}. This media source creates {@link FakeMediaPeriod}s with the
|
* Creates a {@link FakeMediaSource}. This media source creates {@link FakeMediaPeriod}s with the
|
||||||
* given {@link TrackGroupArray}. The provided {@link Timeline} may be null to prevent an
|
* provided {@link TrackGroupArray}, {@link DrmSessionManager} and {@link
|
||||||
|
* FakeMediaPeriod.TrackDataFactory}. The provided {@link Timeline} may be null to prevent an
|
||||||
* immediate source info refresh message when preparing the media source. It can be manually set
|
* immediate source info refresh message when preparing the media source. It can be manually set
|
||||||
* later using {@link #setNewSourceInfo(Timeline)}.
|
* later using {@link #setNewSourceInfo(Timeline)}.
|
||||||
*/
|
*/
|
||||||
public FakeMediaSource(
|
public FakeMediaSource(
|
||||||
@Nullable Timeline timeline,
|
@Nullable Timeline timeline,
|
||||||
DrmSessionManager drmSessionManager,
|
DrmSessionManager drmSessionManager,
|
||||||
|
@Nullable FakeMediaPeriod.TrackDataFactory trackDataFactory,
|
||||||
TrackGroupArray trackGroupArray) {
|
TrackGroupArray trackGroupArray) {
|
||||||
if (timeline != null) {
|
if (timeline != null) {
|
||||||
this.timeline = timeline;
|
this.timeline = timeline;
|
||||||
|
|
@ -127,6 +147,7 @@ public class FakeMediaSource extends BaseMediaSource {
|
||||||
this.activeMediaPeriods = new ArrayList<>();
|
this.activeMediaPeriods = new ArrayList<>();
|
||||||
this.createdMediaPeriods = new ArrayList<>();
|
this.createdMediaPeriods = new ArrayList<>();
|
||||||
this.drmSessionManager = drmSessionManager;
|
this.drmSessionManager = drmSessionManager;
|
||||||
|
this.trackDataFactory = trackDataFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
@ -292,6 +313,7 @@ public class FakeMediaSource extends BaseMediaSource {
|
||||||
* May be null if no listener is available.
|
* May be null if no listener is available.
|
||||||
* @return A new {@link FakeMediaPeriod}.
|
* @return A new {@link FakeMediaPeriod}.
|
||||||
*/
|
*/
|
||||||
|
@RequiresNonNull("this.timeline")
|
||||||
protected FakeMediaPeriod createFakeMediaPeriod(
|
protected FakeMediaPeriod createFakeMediaPeriod(
|
||||||
MediaPeriodId id,
|
MediaPeriodId id,
|
||||||
TrackGroupArray trackGroupArray,
|
TrackGroupArray trackGroupArray,
|
||||||
|
|
@ -299,8 +321,17 @@ public class FakeMediaSource extends BaseMediaSource {
|
||||||
DrmSessionManager drmSessionManager,
|
DrmSessionManager drmSessionManager,
|
||||||
EventDispatcher eventDispatcher,
|
EventDispatcher eventDispatcher,
|
||||||
@Nullable TransferListener transferListener) {
|
@Nullable TransferListener transferListener) {
|
||||||
|
long positionInWindowUs =
|
||||||
|
timeline.getPeriodByUid(id.periodUid, new Period()).getPositionInWindowUs();
|
||||||
|
long defaultFirstSampleTimeUs = positionInWindowUs >= 0 || id.isAd() ? 0 : -positionInWindowUs;
|
||||||
return new FakeMediaPeriod(
|
return new FakeMediaPeriod(
|
||||||
trackGroupArray, drmSessionManager, eventDispatcher, /* deferOnPrepared= */ false);
|
trackGroupArray,
|
||||||
|
trackDataFactory != null
|
||||||
|
? trackDataFactory
|
||||||
|
: TrackDataFactory.singleSampleWithTimeUs(defaultFirstSampleTimeUs),
|
||||||
|
eventDispatcher,
|
||||||
|
drmSessionManager,
|
||||||
|
/* deferOnPrepared= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finishSourcePreparation(boolean sendManifestLoadEvents) {
|
private void finishSourcePreparation(boolean sendManifestLoadEvents) {
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.testutil;
|
package com.google.android.exoplayer2.testutil;
|
||||||
|
|
||||||
|
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
|
import com.google.android.exoplayer2.C.BufferFlags;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
import com.google.android.exoplayer2.FormatHolder;
|
import com.google.android.exoplayer2.FormatHolder;
|
||||||
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
|
||||||
|
|
@ -29,9 +31,11 @@ import com.google.android.exoplayer2.source.SampleStream;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -40,11 +44,20 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
*/
|
*/
|
||||||
public class FakeSampleStream implements SampleStream {
|
public class FakeSampleStream implements SampleStream {
|
||||||
|
|
||||||
|
private static class SampleInfo {
|
||||||
|
private final byte[] data;
|
||||||
|
@C.BufferFlags private final int flags;
|
||||||
|
private final long timeUs;
|
||||||
|
|
||||||
|
private SampleInfo(byte[] data, @C.BufferFlags int flags, long timeUs) {
|
||||||
|
this.data = Arrays.copyOf(data, data.length);
|
||||||
|
this.flags = flags;
|
||||||
|
this.timeUs = timeUs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Item to customize a return value of {@link FakeSampleStream#readData}. */
|
/** Item to customize a return value of {@link FakeSampleStream#readData}. */
|
||||||
public static final class FakeSampleStreamItem {
|
public static final class FakeSampleStreamItem {
|
||||||
@Nullable Format format;
|
|
||||||
@Nullable byte[] sampleData;
|
|
||||||
int flags;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item that designates the end of stream has been reached.
|
* Item that designates the end of stream has been reached.
|
||||||
|
|
@ -52,118 +65,126 @@ public class FakeSampleStream implements SampleStream {
|
||||||
* <p>When this item is read, readData will repeatedly return end of stream.
|
* <p>When this item is read, readData will repeatedly return end of stream.
|
||||||
*/
|
*/
|
||||||
public static final FakeSampleStreamItem END_OF_STREAM_ITEM =
|
public static final FakeSampleStreamItem END_OF_STREAM_ITEM =
|
||||||
new FakeSampleStreamItem(new byte[] {}, C.BUFFER_FLAG_END_OF_STREAM);
|
sample(
|
||||||
|
/* timeUs= */ Long.MAX_VALUE,
|
||||||
|
C.BUFFER_FLAG_END_OF_STREAM,
|
||||||
|
/* sampleData= */ new byte[] {});
|
||||||
|
|
||||||
|
/** Creates an item representing the provided format. */
|
||||||
|
public static FakeSampleStreamItem format(Format format) {
|
||||||
|
return new FakeSampleStreamItem(format, /* sampleInfo= */ null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item that, when {@link #readData(FormatHolder, DecoderInputBuffer, boolean)} is called, will
|
* Creates an item representing a sample with the provided timestamp.
|
||||||
* return {@link C#RESULT_FORMAT_READ} with the new format.
|
|
||||||
*
|
*
|
||||||
* @param format The format to be returned.
|
* <p>The sample will contain a single byte of data.
|
||||||
|
*
|
||||||
|
* @param timeUs The timestamp of the sample.
|
||||||
*/
|
*/
|
||||||
public FakeSampleStreamItem(Format format) {
|
public static FakeSampleStreamItem oneByteSample(long timeUs) {
|
||||||
|
return oneByteSample(timeUs, /* flags= */ 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an item representing a sample with the provided timestamp and flags.
|
||||||
|
*
|
||||||
|
* <p>The sample will contain a single byte of data.
|
||||||
|
*
|
||||||
|
* @param timeUs The timestamp of the sample.
|
||||||
|
* @param flags The buffer flags that will be set when reading this sample through {@link
|
||||||
|
* FakeSampleStream#readData(FormatHolder, DecoderInputBuffer, boolean)}.
|
||||||
|
*/
|
||||||
|
public static FakeSampleStreamItem oneByteSample(long timeUs, @BufferFlags int flags) {
|
||||||
|
return sample(timeUs, flags, new byte[] {0});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an item representing a sample with the provided timestamp, flags and data.
|
||||||
|
*
|
||||||
|
* @param timeUs The timestamp of the sample.
|
||||||
|
* @param flags The buffer flags that will be set when reading this sample through {@link
|
||||||
|
* FakeSampleStream#readData(FormatHolder, DecoderInputBuffer, boolean)}.
|
||||||
|
* @param sampleData The sample data.
|
||||||
|
*/
|
||||||
|
public static FakeSampleStreamItem sample(
|
||||||
|
long timeUs, @BufferFlags int flags, byte[] sampleData) {
|
||||||
|
return new FakeSampleStreamItem(
|
||||||
|
/* format= */ null, new SampleInfo(sampleData.clone(), flags, timeUs));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable private final Format format;
|
||||||
|
@Nullable private final SampleInfo sampleInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance. Exactly one of {@code format} or {@code sampleInfo} must be non-null.
|
||||||
|
*/
|
||||||
|
private FakeSampleStreamItem(@Nullable Format format, @Nullable SampleInfo sampleInfo) {
|
||||||
|
Assertions.checkArgument((format == null) != (sampleInfo == null));
|
||||||
this.format = format;
|
this.format = format;
|
||||||
}
|
this.sampleInfo = sampleInfo;
|
||||||
|
|
||||||
/**
|
|
||||||
* Item that, when {@link #readData(FormatHolder, DecoderInputBuffer, boolean)} is called, will
|
|
||||||
* return {@link C#RESULT_BUFFER_READ} with the sample data.
|
|
||||||
*
|
|
||||||
* @param sampleData The sample data to be read.
|
|
||||||
*/
|
|
||||||
public FakeSampleStreamItem(byte[] sampleData) {
|
|
||||||
this.sampleData = sampleData.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Item that, when {@link #readData(FormatHolder, DecoderInputBuffer, boolean)} is called, will
|
|
||||||
* return {@link C#RESULT_BUFFER_READ} with the sample data.
|
|
||||||
*
|
|
||||||
* @param sampleData The sample data to be read.
|
|
||||||
* @param flags The buffer flags to be set.
|
|
||||||
*/
|
|
||||||
public FakeSampleStreamItem(byte[] sampleData, int flags) {
|
|
||||||
this.sampleData = sampleData.clone();
|
|
||||||
this.flags = flags;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constant array for use when a single sample is to be output, followed by the end of stream. */
|
|
||||||
public static final FakeSampleStreamItem[] SINGLE_SAMPLE_THEN_END_OF_STREAM =
|
|
||||||
new FakeSampleStreamItem[] {
|
|
||||||
new FakeSampleStreamItem(new byte[] {0}), FakeSampleStreamItem.END_OF_STREAM_ITEM
|
|
||||||
};
|
|
||||||
|
|
||||||
private final Format initialFormat;
|
private final Format initialFormat;
|
||||||
private final ArrayDeque<FakeSampleStreamItem> fakeSampleStreamItems;
|
private final List<FakeSampleStreamItem> fakeSampleStreamItems;
|
||||||
private final int timeUsIncrement;
|
|
||||||
private final DrmSessionManager drmSessionManager;
|
private final DrmSessionManager drmSessionManager;
|
||||||
@Nullable private final EventDispatcher eventDispatcher;
|
@Nullable private final EventDispatcher eventDispatcher;
|
||||||
|
|
||||||
|
private int sampleItemIndex;
|
||||||
private @MonotonicNonNull Format downstreamFormat;
|
private @MonotonicNonNull Format downstreamFormat;
|
||||||
private long timeUs;
|
|
||||||
private boolean readEOSBuffer;
|
private boolean readEOSBuffer;
|
||||||
@Nullable private DrmSession currentDrmSession;
|
@Nullable private DrmSession currentDrmSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates fake sample stream which outputs the given {@link Format}, optionally one sample with
|
* Creates a fake sample stream which outputs the given {@link Format} followed by the provided
|
||||||
* zero bytes, then end of stream.
|
* {@link FakeSampleStreamItem items}.
|
||||||
*
|
*
|
||||||
* @param format The {@link Format} to output.
|
|
||||||
* @param eventDispatcher An {@link EventDispatcher} to notify of read events.
|
|
||||||
* @param shouldOutputSample Whether the sample stream should output a sample.
|
|
||||||
*/
|
|
||||||
public FakeSampleStream(
|
|
||||||
Format format, @Nullable EventDispatcher eventDispatcher, boolean shouldOutputSample) {
|
|
||||||
this(
|
|
||||||
format,
|
|
||||||
DrmSessionManager.DUMMY,
|
|
||||||
eventDispatcher,
|
|
||||||
/* firstSampleTimeUs= */ 0,
|
|
||||||
/* timeUsIncrement= */ 0,
|
|
||||||
shouldOutputSample
|
|
||||||
? SINGLE_SAMPLE_THEN_END_OF_STREAM
|
|
||||||
: new FakeSampleStreamItem[] {FakeSampleStreamItem.END_OF_STREAM_ITEM});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a fake sample stream which outputs the given {@link Format}, any amount of {@link
|
|
||||||
* FakeSampleStreamItem items}, then end of stream.
|
|
||||||
*
|
|
||||||
* @param format The {@link Format} to output.
|
|
||||||
* @param drmSessionManager A {@link DrmSessionManager} for DRM interactions.
|
* @param drmSessionManager A {@link DrmSessionManager} for DRM interactions.
|
||||||
* @param eventDispatcher An {@link EventDispatcher} to notify of read events.
|
* @param eventDispatcher An {@link EventDispatcher} to notify of read events.
|
||||||
* @param firstSampleTimeUs The time at which samples will start being output, in microseconds.
|
* @param initialFormat The first {@link Format} to output.
|
||||||
* @param timeUsIncrement The time each sample should increase by, in microseconds.
|
|
||||||
* @param fakeSampleStreamItems The {@link FakeSampleStreamItem items} to customize the return
|
* @param fakeSampleStreamItems The {@link FakeSampleStreamItem items} to customize the return
|
||||||
* values of {@link #readData(FormatHolder, DecoderInputBuffer, boolean)}. Note that once an
|
* values of {@link #readData(FormatHolder, DecoderInputBuffer, boolean)}. This is assumed to
|
||||||
* EOS buffer has been read, that will return every time readData is called.
|
* be in ascending order of sampleTime. Note that once an EOS buffer has been read, that will
|
||||||
|
* return every time readData is called. This should usually end with {@link
|
||||||
|
* FakeSampleStreamItem#END_OF_STREAM_ITEM}.
|
||||||
*/
|
*/
|
||||||
public FakeSampleStream(
|
public FakeSampleStream(
|
||||||
Format format,
|
|
||||||
DrmSessionManager drmSessionManager,
|
DrmSessionManager drmSessionManager,
|
||||||
@Nullable EventDispatcher eventDispatcher,
|
@Nullable EventDispatcher eventDispatcher,
|
||||||
long firstSampleTimeUs,
|
Format initialFormat,
|
||||||
int timeUsIncrement,
|
List<FakeSampleStreamItem> fakeSampleStreamItems) {
|
||||||
FakeSampleStreamItem... fakeSampleStreamItems) {
|
|
||||||
this.initialFormat = format;
|
|
||||||
this.drmSessionManager = drmSessionManager;
|
this.drmSessionManager = drmSessionManager;
|
||||||
this.eventDispatcher = eventDispatcher;
|
this.eventDispatcher = eventDispatcher;
|
||||||
this.fakeSampleStreamItems = new ArrayDeque<>(Arrays.asList(fakeSampleStreamItems));
|
this.initialFormat = initialFormat;
|
||||||
this.timeUs = firstSampleTimeUs;
|
this.fakeSampleStreamItems = new ArrayList<>(fakeSampleStreamItems);
|
||||||
this.timeUsIncrement = timeUsIncrement;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears and assigns new samples provided by this sample stream.
|
* Seeks inside this sample stream.
|
||||||
*
|
*
|
||||||
* @param timeUs The time at which samples will start being output, in microseconds.
|
* <p>Seeks to just before the first sample with {@code sampleTime >= timeUs}, or to the end of
|
||||||
* @param fakeSampleStreamItems The {@link FakeSampleStreamItem items} to provide.
|
* the stream otherwise.
|
||||||
*/
|
*/
|
||||||
public void resetSampleStreamItems(long timeUs, FakeSampleStreamItem... fakeSampleStreamItems) {
|
public void seekTo(long timeUs) {
|
||||||
this.fakeSampleStreamItems.clear();
|
Format applicableFormat = initialFormat;
|
||||||
this.fakeSampleStreamItems.addAll(Arrays.asList(fakeSampleStreamItems));
|
for (int i = 0; i < fakeSampleStreamItems.size(); i++) {
|
||||||
this.timeUs = timeUs;
|
@Nullable SampleInfo sampleInfo = fakeSampleStreamItems.get(i).sampleInfo;
|
||||||
readEOSBuffer = false;
|
if (sampleInfo == null) {
|
||||||
|
applicableFormat = Assertions.checkNotNull(fakeSampleStreamItems.get(i).format);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sampleInfo.timeUs >= timeUs) {
|
||||||
|
sampleItemIndex = i;
|
||||||
|
readEOSBuffer = false;
|
||||||
|
if (downstreamFormat != null && !applicableFormat.equals(downstreamFormat)) {
|
||||||
|
notifyEventDispatcher(applicableFormat);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sampleItemIndex = fakeSampleStreamItems.size();
|
||||||
|
readEOSBuffer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -177,10 +198,10 @@ public class FakeSampleStream implements SampleStream {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isReady() {
|
public boolean isReady() {
|
||||||
if (fakeSampleStreamItems.isEmpty()) {
|
if (sampleItemIndex == fakeSampleStreamItems.size()) {
|
||||||
return readEOSBuffer || downstreamFormat == null;
|
return readEOSBuffer || downstreamFormat == null;
|
||||||
}
|
}
|
||||||
if (fakeSampleStreamItems.peek().format != null) {
|
if (fakeSampleStreamItems.get(sampleItemIndex).format != null) {
|
||||||
// A format can be read.
|
// A format can be read.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -200,29 +221,28 @@ public class FakeSampleStream implements SampleStream {
|
||||||
return C.RESULT_BUFFER_READ;
|
return C.RESULT_BUFFER_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fakeSampleStreamItems.isEmpty()) {
|
if (sampleItemIndex < fakeSampleStreamItems.size()) {
|
||||||
FakeSampleStreamItem fakeSampleStreamItem = fakeSampleStreamItems.remove();
|
FakeSampleStreamItem fakeSampleStreamItem = fakeSampleStreamItems.get(sampleItemIndex);
|
||||||
|
sampleItemIndex++;
|
||||||
if (fakeSampleStreamItem.format != null) {
|
if (fakeSampleStreamItem.format != null) {
|
||||||
onFormatResult(fakeSampleStreamItem.format, formatHolder);
|
onFormatResult(fakeSampleStreamItem.format, formatHolder);
|
||||||
return C.RESULT_FORMAT_READ;
|
return C.RESULT_FORMAT_READ;
|
||||||
} else {
|
} else {
|
||||||
byte[] sampleData = Assertions.checkNotNull(fakeSampleStreamItem.sampleData);
|
SampleInfo sampleInfo = Assertions.checkNotNull(fakeSampleStreamItem.sampleInfo);
|
||||||
if (fakeSampleStreamItem.flags != 0) {
|
if (sampleInfo.flags != 0) {
|
||||||
buffer.setFlags(fakeSampleStreamItem.flags);
|
buffer.setFlags(sampleInfo.flags);
|
||||||
if (buffer.isEndOfStream()) {
|
if (buffer.isEndOfStream()) {
|
||||||
readEOSBuffer = true;
|
readEOSBuffer = true;
|
||||||
return C.RESULT_BUFFER_READ;
|
return C.RESULT_BUFFER_READ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!mayReadSample()) {
|
if (!mayReadSample()) {
|
||||||
// Put the item back so we can consume it next time.
|
sampleItemIndex--;
|
||||||
fakeSampleStreamItems.addFirst(fakeSampleStreamItem);
|
|
||||||
return C.RESULT_NOTHING_READ;
|
return C.RESULT_NOTHING_READ;
|
||||||
}
|
}
|
||||||
buffer.timeUs = timeUs;
|
buffer.timeUs = sampleInfo.timeUs;
|
||||||
timeUs += timeUsIncrement;
|
buffer.ensureSpaceForWrite(sampleInfo.data.length);
|
||||||
buffer.ensureSpaceForWrite(sampleData.length);
|
buffer.data.put(sampleInfo.data);
|
||||||
buffer.data.put(sampleData);
|
|
||||||
return C.RESULT_BUFFER_READ;
|
return C.RESULT_BUFFER_READ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -237,7 +257,7 @@ public class FakeSampleStream implements SampleStream {
|
||||||
downstreamFormat = newFormat;
|
downstreamFormat = newFormat;
|
||||||
@Nullable DrmInitData newDrmInitData = newFormat.drmInitData;
|
@Nullable DrmInitData newDrmInitData = newFormat.drmInitData;
|
||||||
outputFormatHolder.drmSession = currentDrmSession;
|
outputFormatHolder.drmSession = currentDrmSession;
|
||||||
notifyEventDispatcher(outputFormatHolder);
|
notifyEventDispatcher(newFormat);
|
||||||
if (!isFirstFormat && Util.areEqual(oldDrmInitData, newDrmInitData)) {
|
if (!isFirstFormat && Util.areEqual(oldDrmInitData, newDrmInitData)) {
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
return;
|
return;
|
||||||
|
|
@ -260,11 +280,16 @@ public class FakeSampleStream implements SampleStream {
|
||||||
|
|
||||||
private boolean mayReadSample() {
|
private boolean mayReadSample() {
|
||||||
@Nullable DrmSession drmSession = this.currentDrmSession;
|
@Nullable DrmSession drmSession = this.currentDrmSession;
|
||||||
|
@Nullable
|
||||||
|
FakeSampleStreamItem nextSample =
|
||||||
|
Iterables.get(fakeSampleStreamItems, sampleItemIndex, /* defaultValue= */ null);
|
||||||
|
boolean nextSampleIsClear =
|
||||||
|
nextSample != null
|
||||||
|
&& nextSample.sampleInfo != null
|
||||||
|
&& (nextSample.sampleInfo.flags & C.BUFFER_FLAG_ENCRYPTED) == 0;
|
||||||
return drmSession == null
|
return drmSession == null
|
||||||
|| drmSession.getState() == DrmSession.STATE_OPENED_WITH_KEYS
|
|| drmSession.getState() == DrmSession.STATE_OPENED_WITH_KEYS
|
||||||
|| (!fakeSampleStreamItems.isEmpty()
|
|| (nextSampleIsClear && drmSession.playClearSamplesWithoutKeys());
|
||||||
&& (fakeSampleStreamItems.peek().flags & C.BUFFER_FLAG_ENCRYPTED) == 0
|
|
||||||
&& drmSession.playClearSamplesWithoutKeys());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -276,6 +301,7 @@ public class FakeSampleStream implements SampleStream {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int skipData(long positionUs) {
|
public int skipData(long positionUs) {
|
||||||
|
// TODO: Implement this.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -287,14 +313,22 @@ public class FakeSampleStream implements SampleStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyEventDispatcher(FormatHolder formatHolder) {
|
private void notifyEventDispatcher(Format format) {
|
||||||
if (eventDispatcher != null) {
|
if (eventDispatcher != null) {
|
||||||
|
@Nullable SampleInfo sampleInfo = null;
|
||||||
|
for (int i = sampleItemIndex; i < fakeSampleStreamItems.size(); i++) {
|
||||||
|
sampleInfo = fakeSampleStreamItems.get(i).sampleInfo;
|
||||||
|
if (sampleInfo != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long nextSampleTimeUs = sampleInfo != null ? sampleInfo.timeUs : C.TIME_END_OF_SOURCE;
|
||||||
eventDispatcher.downstreamFormatChanged(
|
eventDispatcher.downstreamFormatChanged(
|
||||||
C.TRACK_TYPE_UNKNOWN,
|
C.TRACK_TYPE_UNKNOWN,
|
||||||
formatHolder.format,
|
format,
|
||||||
C.SELECTION_REASON_UNKNOWN,
|
C.SELECTION_REASON_UNKNOWN,
|
||||||
/* trackSelectionData= */ null,
|
/* trackSelectionData= */ null,
|
||||||
/* mediaTimeUs= */ timeUs);
|
/* mediaTimeUs= */ nextSampleTimeUs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,7 @@ public final class FakeTimeline extends Timeline {
|
||||||
public static final long DEFAULT_WINDOW_DURATION_US = 10 * C.MICROS_PER_SECOND;
|
public static final long DEFAULT_WINDOW_DURATION_US = 10 * C.MICROS_PER_SECOND;
|
||||||
|
|
||||||
/** Default offset of a window in its first period in microseconds. */
|
/** Default offset of a window in its first period in microseconds. */
|
||||||
public static final long DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US =
|
public static final long DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US = 123 * C.MICROS_PER_SECOND;
|
||||||
10_000 * C.MICROS_PER_SECOND;
|
|
||||||
|
|
||||||
public final int periodCount;
|
public final int periodCount;
|
||||||
public final Object id;
|
public final Object id;
|
||||||
|
|
@ -187,7 +186,7 @@ public final class FakeTimeline extends Timeline {
|
||||||
public static final MediaItem FAKE_MEDIA_ITEM =
|
public static final MediaItem FAKE_MEDIA_ITEM =
|
||||||
new MediaItem.Builder().setMediaId("FakeTimeline").setUri(Uri.EMPTY).build();
|
new MediaItem.Builder().setMediaId("FakeTimeline").setUri(Uri.EMPTY).build();
|
||||||
|
|
||||||
private static final long AD_DURATION_US = 10 * C.MICROS_PER_SECOND;
|
private static final long AD_DURATION_US = 5 * C.MICROS_PER_SECOND;
|
||||||
|
|
||||||
private final TimelineWindowDefinition[] windowDefinitions;
|
private final TimelineWindowDefinition[] windowDefinitions;
|
||||||
private final Object[] manifests;
|
private final Object[] manifests;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue