mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Detect SampleStream error after PreloadMediaPeriod has prepared
Per the javadoc, the method `MediaPeriod.maybeThrowPrepareError` is only allowed to be called before the period has completed preparation. For later errors in loading the streams, `SampleStream.maybeThrowError` will be called instead. PiperOrigin-RevId: 665831430
This commit is contained in:
parent
059ad62377
commit
410b26fba1
@ -35,8 +35,8 @@ import java.util.Objects;
|
|||||||
|
|
||||||
public final MediaPeriod mediaPeriod;
|
public final MediaPeriod mediaPeriod;
|
||||||
|
|
||||||
|
public boolean prepared;
|
||||||
private boolean prepareInternalCalled;
|
private boolean prepareInternalCalled;
|
||||||
private boolean prepared;
|
|
||||||
@Nullable private Callback callback;
|
@Nullable private Callback callback;
|
||||||
@Nullable private PreloadTrackSelectionHolder preloadTrackSelectionHolder;
|
@Nullable private PreloadTrackSelectionHolder preloadTrackSelectionHolder;
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ import java.util.Objects;
|
|||||||
this.mediaPeriod = mediaPeriod;
|
this.mediaPeriod = mediaPeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ void preload(Callback callback, long positionUs) {
|
public void preload(Callback callback, long positionUs) {
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
if (prepared) {
|
if (prepared) {
|
||||||
callback.onPrepared(PreloadMediaPeriod.this);
|
callback.onPrepared(PreloadMediaPeriod.this);
|
||||||
@ -217,7 +217,7 @@ import java.util.Objects;
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ long selectTracksForPreloading(
|
public long selectTracksForPreloading(
|
||||||
@NullableType ExoTrackSelection[] selections, long positionUs) {
|
@NullableType ExoTrackSelection[] selections, long positionUs) {
|
||||||
@NullableType SampleStream[] preloadedSampleStreams = new SampleStream[selections.length];
|
@NullableType SampleStream[] preloadedSampleStreams = new SampleStream[selections.length];
|
||||||
boolean[] preloadedStreamResetFlags = new boolean[selections.length];
|
boolean[] preloadedStreamResetFlags = new boolean[selections.length];
|
||||||
@ -284,6 +284,17 @@ import java.util.Objects;
|
|||||||
mediaPeriod.reevaluateBuffer(positionUs);
|
mediaPeriod.reevaluateBuffer(positionUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void maybeThrowStreamError() throws IOException {
|
||||||
|
checkState(prepared);
|
||||||
|
if (preloadTrackSelectionHolder != null) {
|
||||||
|
for (SampleStream stream : preloadTrackSelectionHolder.streams) {
|
||||||
|
if (stream != null) {
|
||||||
|
stream.maybeThrowError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class PreloadTrackSelectionHolder {
|
private static class PreloadTrackSelectionHolder {
|
||||||
public final @NullableType ExoTrackSelection[] selections;
|
public final @NullableType ExoTrackSelection[] selections;
|
||||||
public final boolean[] mayRetainStreamFlags;
|
public final boolean[] mayRetainStreamFlags;
|
||||||
|
@ -424,7 +424,12 @@ public final class PreloadMediaSource extends WrappingMediaSource {
|
|||||||
try {
|
try {
|
||||||
maybeThrowSourceInfoRefreshError();
|
maybeThrowSourceInfoRefreshError();
|
||||||
if (preloadingMediaPeriodAndKey != null) {
|
if (preloadingMediaPeriodAndKey != null) {
|
||||||
preloadingMediaPeriodAndKey.first.maybeThrowPrepareError();
|
PreloadMediaPeriod preloadingMediaPeriod = preloadingMediaPeriodAndKey.first;
|
||||||
|
if (!preloadingMediaPeriod.prepared) {
|
||||||
|
preloadingMediaPeriod.maybeThrowPrepareError();
|
||||||
|
} else {
|
||||||
|
preloadingMediaPeriod.maybeThrowStreamError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
preloadHandler.postDelayed(this::checkForPreloadError, CHECK_FOR_PRELOAD_ERROR_INTERVAL_MS);
|
preloadHandler.postDelayed(this::checkForPreloadError, CHECK_FOR_PRELOAD_ERROR_INTERVAL_MS);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -15,7 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package androidx.media3.exoplayer.source.preload;
|
package androidx.media3.exoplayer.source.preload;
|
||||||
|
|
||||||
|
import static androidx.media3.test.utils.robolectric.RobolectricUtil.runMainLooperUntil;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static org.junit.Assert.assertThrows;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyLong;
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
@ -29,6 +31,7 @@ import static org.mockito.Mockito.when;
|
|||||||
import static org.robolectric.Shadows.shadowOf;
|
import static org.robolectric.Shadows.shadowOf;
|
||||||
|
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
import androidx.media3.common.MimeTypes;
|
import androidx.media3.common.MimeTypes;
|
||||||
@ -43,11 +46,15 @@ import androidx.media3.exoplayer.source.SampleStream;
|
|||||||
import androidx.media3.exoplayer.source.TrackGroupArray;
|
import androidx.media3.exoplayer.source.TrackGroupArray;
|
||||||
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
import androidx.media3.exoplayer.trackselection.ExoTrackSelection;
|
||||||
import androidx.media3.exoplayer.trackselection.FixedTrackSelection;
|
import androidx.media3.exoplayer.trackselection.FixedTrackSelection;
|
||||||
|
import androidx.media3.exoplayer.upstream.Allocator;
|
||||||
import androidx.media3.exoplayer.upstream.DefaultAllocator;
|
import androidx.media3.exoplayer.upstream.DefaultAllocator;
|
||||||
import androidx.media3.test.utils.FakeMediaPeriod;
|
import androidx.media3.test.utils.FakeMediaPeriod;
|
||||||
|
import androidx.media3.test.utils.FakeSampleStream;
|
||||||
import androidx.media3.test.utils.FakeTimeline;
|
import androidx.media3.test.utils.FakeTimeline;
|
||||||
import androidx.media3.test.utils.FakeTrackSelection;
|
import androidx.media3.test.utils.FakeTrackSelection;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -1594,4 +1601,68 @@ public final class PreloadMediaPeriodTest {
|
|||||||
.selectTracks(eq(trackSelections), any(), any(), any(), /* positionUs= */ eq(0L));
|
.selectTracks(eq(trackSelections), any(), any(), any(), /* positionUs= */ eq(0L));
|
||||||
assertThat(trackSelectionStartPositionUs).isEqualTo(0L);
|
assertThat(trackSelectionStartPositionUs).isEqualTo(0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void maybeThrowStreamError_preloadedStreamHasError_errorThrows() throws Exception {
|
||||||
|
Format videoFormat =
|
||||||
|
new Format.Builder()
|
||||||
|
.setSampleMimeType(MimeTypes.VIDEO_H264)
|
||||||
|
.setAverageBitrate(800_000)
|
||||||
|
.setWidth(1280)
|
||||||
|
.setHeight(720)
|
||||||
|
.build();
|
||||||
|
MediaSource.MediaPeriodId mediaPeriodId =
|
||||||
|
new MediaSource.MediaPeriodId(/* periodUid= */ new Object());
|
||||||
|
FakeMediaPeriod wrappedMediaPeriod =
|
||||||
|
new FakeMediaPeriod(
|
||||||
|
new TrackGroupArray(new TrackGroup(videoFormat)),
|
||||||
|
new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE),
|
||||||
|
FakeTimeline.TimelineWindowDefinition.DEFAULT_WINDOW_OFFSET_IN_FIRST_PERIOD_US,
|
||||||
|
new MediaSourceEventListener.EventDispatcher()
|
||||||
|
.withParameters(/* windowIndex= */ 0, mediaPeriodId)) {
|
||||||
|
@Override
|
||||||
|
protected FakeSampleStream createSampleStream(
|
||||||
|
Allocator allocator,
|
||||||
|
@Nullable MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
|
||||||
|
DrmSessionManager drmSessionManager,
|
||||||
|
DrmSessionEventListener.EventDispatcher drmEventDispatcher,
|
||||||
|
Format initialFormat,
|
||||||
|
List<FakeSampleStream.FakeSampleStreamItem> fakeSampleStreamItems) {
|
||||||
|
return new FakeSampleStream(
|
||||||
|
allocator,
|
||||||
|
mediaSourceEventDispatcher,
|
||||||
|
drmSessionManager,
|
||||||
|
drmEventDispatcher,
|
||||||
|
initialFormat,
|
||||||
|
fakeSampleStreamItems) {
|
||||||
|
@Override
|
||||||
|
public void maybeThrowError() throws IOException {
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
PreloadMediaPeriod preloadMediaPeriod = new PreloadMediaPeriod(wrappedMediaPeriod);
|
||||||
|
AtomicBoolean onPreparedOfPreloadCallbackCalled = new AtomicBoolean();
|
||||||
|
MediaPeriod.Callback preloadCallback =
|
||||||
|
new MediaPeriod.Callback() {
|
||||||
|
@Override
|
||||||
|
public void onPrepared(MediaPeriod mediaPeriod) {
|
||||||
|
onPreparedOfPreloadCallbackCalled.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onContinueLoadingRequested(MediaPeriod source) {}
|
||||||
|
};
|
||||||
|
preloadMediaPeriod.preload(preloadCallback, /* positionUs= */ 0L);
|
||||||
|
runMainLooperUntil(onPreparedOfPreloadCallbackCalled::get);
|
||||||
|
ExoTrackSelection[] preloadTrackSelections =
|
||||||
|
new ExoTrackSelection[] {
|
||||||
|
new FixedTrackSelection(new TrackGroup(videoFormat), /* track= */ 0)
|
||||||
|
};
|
||||||
|
// PreloadMediaPeriod.selectTracksForPreloading keeps the preloaded stream.
|
||||||
|
preloadMediaPeriod.selectTracksForPreloading(preloadTrackSelections, /* positionUs= */ 0L);
|
||||||
|
|
||||||
|
assertThrows(IOException.class, preloadMediaPeriod::maybeThrowStreamError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,9 @@ import android.os.Looper;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
|
import androidx.media3.common.Format;
|
||||||
import androidx.media3.common.MediaItem;
|
import androidx.media3.common.MediaItem;
|
||||||
|
import androidx.media3.common.MimeTypes;
|
||||||
import androidx.media3.common.Timeline;
|
import androidx.media3.common.Timeline;
|
||||||
import androidx.media3.common.Tracks;
|
import androidx.media3.common.Tracks;
|
||||||
import androidx.media3.common.util.SystemClock;
|
import androidx.media3.common.util.SystemClock;
|
||||||
@ -68,12 +70,15 @@ import androidx.media3.test.utils.FakeAudioRenderer;
|
|||||||
import androidx.media3.test.utils.FakeMediaPeriod;
|
import androidx.media3.test.utils.FakeMediaPeriod;
|
||||||
import androidx.media3.test.utils.FakeMediaSource;
|
import androidx.media3.test.utils.FakeMediaSource;
|
||||||
import androidx.media3.test.utils.FakeMediaSourceFactory;
|
import androidx.media3.test.utils.FakeMediaSourceFactory;
|
||||||
|
import androidx.media3.test.utils.FakeSampleStream;
|
||||||
import androidx.media3.test.utils.FakeTimeline;
|
import androidx.media3.test.utils.FakeTimeline;
|
||||||
import androidx.media3.test.utils.FakeTrackSelector;
|
import androidx.media3.test.utils.FakeTrackSelector;
|
||||||
import androidx.media3.test.utils.FakeVideoRenderer;
|
import androidx.media3.test.utils.FakeVideoRenderer;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
@ -334,15 +339,12 @@ public final class PreloadMediaSourceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void preload_sourceInfoRefreshErrorThrows_onPreloadErrorCalled() throws TimeoutException {
|
public void preload_sourceInfoRefreshErrorThrows_onPreloadErrorCalled() throws TimeoutException {
|
||||||
AtomicReference<PreloadException> preloadExceptionReference = new AtomicReference<>();
|
AtomicReference<PreloadException> preloadExceptionReference = new AtomicReference<>();
|
||||||
AtomicReference<PreloadMediaSource> preloadMediaSourceReference = new AtomicReference<>();
|
|
||||||
IOException causeException = new IOException("Failed to refresh source info");
|
IOException causeException = new IOException("Failed to refresh source info");
|
||||||
TestPreloadControl preloadControl =
|
TestPreloadControl preloadControl =
|
||||||
new TestPreloadControl() {
|
new TestPreloadControl() {
|
||||||
@Override
|
@Override
|
||||||
public void onPreloadError(PreloadException error, PreloadMediaSource mediaSource) {
|
public void onPreloadError(PreloadException error, PreloadMediaSource mediaSource) {
|
||||||
super.onPreloadError(error, mediaSource);
|
|
||||||
preloadExceptionReference.set(error);
|
preloadExceptionReference.set(error);
|
||||||
preloadMediaSourceReference.set(mediaSource);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
MediaSource.Factory mediaSourceFactory =
|
MediaSource.Factory mediaSourceFactory =
|
||||||
@ -393,9 +395,8 @@ public final class PreloadMediaSourceTest {
|
|||||||
.build());
|
.build());
|
||||||
|
|
||||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||||
runMainLooperUntil(() -> preloadMediaSourceReference.get() != null);
|
runMainLooperUntil(() -> preloadExceptionReference.get() != null);
|
||||||
|
|
||||||
assertThat(preloadControl.onPreloadErrorCalled).isTrue();
|
|
||||||
assertThat(preloadExceptionReference.get()).hasCauseThat().isEqualTo(causeException);
|
assertThat(preloadExceptionReference.get()).hasCauseThat().isEqualTo(causeException);
|
||||||
assertThat(preloadControl.onSourcePreparedCalledCount).isEqualTo(0);
|
assertThat(preloadControl.onSourcePreparedCalledCount).isEqualTo(0);
|
||||||
assertThat(preloadControl.onTrackSelectedCalled).isFalse();
|
assertThat(preloadControl.onTrackSelectedCalled).isFalse();
|
||||||
@ -406,15 +407,12 @@ public final class PreloadMediaSourceTest {
|
|||||||
@Test
|
@Test
|
||||||
public void preload_periodPrepareErrorThrows_onPreloadErrorCalled() throws TimeoutException {
|
public void preload_periodPrepareErrorThrows_onPreloadErrorCalled() throws TimeoutException {
|
||||||
AtomicReference<PreloadException> preloadExceptionReference = new AtomicReference<>();
|
AtomicReference<PreloadException> preloadExceptionReference = new AtomicReference<>();
|
||||||
AtomicReference<PreloadMediaSource> preloadMediaSourceReference = new AtomicReference<>();
|
|
||||||
IOException causeException = new IOException("Failed to prepare the period");
|
IOException causeException = new IOException("Failed to prepare the period");
|
||||||
TestPreloadControl preloadControl =
|
TestPreloadControl preloadControl =
|
||||||
new TestPreloadControl() {
|
new TestPreloadControl() {
|
||||||
@Override
|
@Override
|
||||||
public void onPreloadError(PreloadException error, PreloadMediaSource mediaSource) {
|
public void onPreloadError(PreloadException error, PreloadMediaSource mediaSource) {
|
||||||
super.onPreloadError(error, mediaSource);
|
|
||||||
preloadExceptionReference.set(error);
|
preloadExceptionReference.set(error);
|
||||||
preloadMediaSourceReference.set(mediaSource);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
MediaSource.Factory mediaSourceFactory =
|
MediaSource.Factory mediaSourceFactory =
|
||||||
@ -481,9 +479,8 @@ public final class PreloadMediaSourceTest {
|
|||||||
.build());
|
.build());
|
||||||
|
|
||||||
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||||
runMainLooperUntil(() -> preloadMediaSourceReference.get() != null);
|
runMainLooperUntil(() -> preloadExceptionReference.get() != null);
|
||||||
|
|
||||||
assertThat(preloadControl.onPreloadErrorCalled).isTrue();
|
|
||||||
assertThat(preloadExceptionReference.get()).hasCauseThat().isEqualTo(causeException);
|
assertThat(preloadExceptionReference.get()).hasCauseThat().isEqualTo(causeException);
|
||||||
assertThat(preloadControl.onSourcePreparedCalledCount).isGreaterThan(0);
|
assertThat(preloadControl.onSourcePreparedCalledCount).isGreaterThan(0);
|
||||||
assertThat(preloadControl.onTrackSelectedCalled).isFalse();
|
assertThat(preloadControl.onTrackSelectedCalled).isFalse();
|
||||||
@ -491,6 +488,117 @@ public final class PreloadMediaSourceTest {
|
|||||||
assertThat(preloadControl.onUsedByPlayerCalled).isFalse();
|
assertThat(preloadControl.onUsedByPlayerCalled).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void preload_sampleStreamErrorThrows_onPreloadErrorCalled() throws TimeoutException {
|
||||||
|
AtomicReference<PreloadException> preloadExceptionReference = new AtomicReference<>();
|
||||||
|
IOException causeException = new IOException("Failed to read the data");
|
||||||
|
TestPreloadControl preloadControl =
|
||||||
|
new TestPreloadControl() {
|
||||||
|
@Override
|
||||||
|
public void onPreloadError(PreloadException error, PreloadMediaSource mediaSource) {
|
||||||
|
preloadExceptionReference.set(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MediaSource.Factory mediaSourceFactory =
|
||||||
|
new MediaSource.Factory() {
|
||||||
|
@Override
|
||||||
|
public MediaSource.Factory setDrmSessionManagerProvider(
|
||||||
|
DrmSessionManagerProvider drmSessionManagerProvider) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MediaSource.Factory setLoadErrorHandlingPolicy(
|
||||||
|
LoadErrorHandlingPolicy loadErrorHandlingPolicy) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @C.ContentType int[] getSupportedTypes() {
|
||||||
|
return new int[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MediaSource createMediaSource(MediaItem mediaItem) {
|
||||||
|
Format videoFormat =
|
||||||
|
new Format.Builder()
|
||||||
|
.setSampleMimeType(MimeTypes.VIDEO_H264)
|
||||||
|
.setAverageBitrate(800_000)
|
||||||
|
.setWidth(1280)
|
||||||
|
.setHeight(720)
|
||||||
|
.build();
|
||||||
|
return new FakeMediaSource(new FakeTimeline(), videoFormat) {
|
||||||
|
@Override
|
||||||
|
public MediaPeriod createMediaPeriod(
|
||||||
|
MediaPeriodId id,
|
||||||
|
TrackGroupArray trackGroupArray,
|
||||||
|
Allocator allocator,
|
||||||
|
MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
|
||||||
|
DrmSessionManager drmSessionManager,
|
||||||
|
DrmSessionEventListener.EventDispatcher drmEventDispatcher,
|
||||||
|
@Nullable TransferListener transferListener) {
|
||||||
|
return new FakeMediaPeriod(
|
||||||
|
trackGroupArray,
|
||||||
|
allocator,
|
||||||
|
/* trackDataFactory= */ (format, mediaPeriodId) -> ImmutableList.of(),
|
||||||
|
mediaSourceEventDispatcher,
|
||||||
|
drmSessionManager,
|
||||||
|
drmEventDispatcher,
|
||||||
|
/* deferOnPrepared= */ false) {
|
||||||
|
@Override
|
||||||
|
protected FakeSampleStream createSampleStream(
|
||||||
|
Allocator allocator,
|
||||||
|
@Nullable MediaSourceEventListener.EventDispatcher mediaSourceEventDispatcher,
|
||||||
|
DrmSessionManager drmSessionManager,
|
||||||
|
DrmSessionEventListener.EventDispatcher drmEventDispatcher,
|
||||||
|
Format initialFormat,
|
||||||
|
List<FakeSampleStream.FakeSampleStreamItem> fakeSampleStreamItems) {
|
||||||
|
return new FakeSampleStream(
|
||||||
|
allocator,
|
||||||
|
mediaSourceEventDispatcher,
|
||||||
|
drmSessionManager,
|
||||||
|
drmEventDispatcher,
|
||||||
|
initialFormat,
|
||||||
|
fakeSampleStreamItems) {
|
||||||
|
@Override
|
||||||
|
public void maybeThrowError() throws IOException {
|
||||||
|
throw causeException;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
TrackSelector trackSelector =
|
||||||
|
new DefaultTrackSelector(ApplicationProvider.getApplicationContext());
|
||||||
|
trackSelector.init(() -> {}, bandwidthMeter);
|
||||||
|
PreloadMediaSource.Factory preloadMediaSourceFactory =
|
||||||
|
new PreloadMediaSource.Factory(
|
||||||
|
mediaSourceFactory,
|
||||||
|
preloadControl,
|
||||||
|
trackSelector,
|
||||||
|
bandwidthMeter,
|
||||||
|
getRendererCapabilities(renderersFactory),
|
||||||
|
allocator,
|
||||||
|
Util.getCurrentOrMainLooper());
|
||||||
|
PreloadMediaSource preloadMediaSource =
|
||||||
|
preloadMediaSourceFactory.createMediaSource(
|
||||||
|
new MediaItem.Builder()
|
||||||
|
.setUri(Uri.parse("asset://android_asset/media/mp4/sample.mp4"))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
preloadMediaSource.preload(/* startPositionUs= */ 0L);
|
||||||
|
runMainLooperUntil(() -> preloadExceptionReference.get() != null);
|
||||||
|
|
||||||
|
assertThat(preloadExceptionReference.get()).hasCauseThat().isEqualTo(causeException);
|
||||||
|
assertThat(preloadControl.onSourcePreparedCalledCount).isGreaterThan(0);
|
||||||
|
assertThat(preloadControl.onTrackSelectedCalled).isTrue();
|
||||||
|
assertThat(preloadControl.onContinueLoadingRequestedCalled).isFalse();
|
||||||
|
assertThat(preloadControl.onUsedByPlayerCalled).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
prepareSource_beforeSourceInfoRefreshedForPreloading_onlyInvokeExternalCallerOnSourceInfoRefreshed() {
|
prepareSource_beforeSourceInfoRefreshedForPreloading_onlyInvokeExternalCallerOnSourceInfoRefreshed() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user