From 6c0d676050a77073b3762562a6048cc3f78ccb2b Mon Sep 17 00:00:00 2001 From: tonihei Date: Mon, 26 Mar 2018 07:40:00 -0700 Subject: [PATCH] Add callbacks for media period life cycle. This adds callbacks for creating, releasing, and starting to read from media periods. Such events allow listeners to keep a list of active media periods. This is useful to determine when no further events for a certain media period are expected. It also allows listeners to associate renderer events unambigiously with a reading media period. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=190462717 --- RELEASENOTES.md | 2 + .../source/CompositeMediaSource.java | 21 ++++++ .../DefaultMediaSourceEventListener.java | 15 ++++ .../source/ExtractorMediaPeriod.java | 7 ++ .../exoplayer2/source/MediaPeriod.java | 3 +- .../source/MediaSourceEventListener.java | 72 +++++++++++++++++++ .../source/SingleSampleMediaPeriod.java | 7 ++ .../android/exoplayer2/util/EventLogger.java | 15 ++++ .../source/dash/DashMediaPeriod.java | 7 ++ .../exoplayer2/source/hls/HlsMediaPeriod.java | 7 ++ .../source/smoothstreaming/SsMediaPeriod.java | 7 ++ .../testutil/FakeAdaptiveMediaPeriod.java | 2 +- .../exoplayer2/testutil/FakeMediaPeriod.java | 7 ++ .../testutil/MediaSourceTestRunner.java | 27 +++++++ 14 files changed, 197 insertions(+), 2 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2dd17d00fc..b3040ab995 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -24,6 +24,8 @@ * Allow adding and removing `MediaSourceEventListener`s to MediaSources after they have been created. Listening to events is now supported for all media sources including composite sources. + * Added callbacks to `MediaSourceEventListener` to get notified when media + periods are created, released and being read from. * Audio: * Factor out `AudioTrack` position tracking from `DefaultAudioSink`. * Fix an issue where the playback position would pause just after playback diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/CompositeMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/CompositeMediaSource.java index 78b0009ffb..f5c4b3a16d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/CompositeMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/CompositeMediaSource.java @@ -185,6 +185,20 @@ public abstract class CompositeMediaSource extends BaseMediaSource { this.id = id; } + @Override + public void onMediaPeriodCreated(int windowIndex, MediaPeriodId mediaPeriodId) { + if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { + eventDispatcher.mediaPeriodCreated(); + } + } + + @Override + public void onMediaPeriodReleased(int windowIndex, MediaPeriodId mediaPeriodId) { + if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { + eventDispatcher.mediaPeriodReleased(); + } + } + @Override public void onLoadStarted( int windowIndex, @@ -232,6 +246,13 @@ public abstract class CompositeMediaSource extends BaseMediaSource { } } + @Override + public void onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId) { + if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) { + eventDispatcher.readingStarted(); + } + } + @Override public void onUpstreamDiscarded( int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceEventListener.java b/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceEventListener.java index 0b197e2422..fd7c037fb9 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceEventListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/DefaultMediaSourceEventListener.java @@ -25,6 +25,16 @@ import java.io.IOException; */ public abstract class DefaultMediaSourceEventListener implements MediaSourceEventListener { + @Override + public void onMediaPeriodCreated(int windowIndex, MediaPeriodId mediaPeriodId) { + // Do nothing. + } + + @Override + public void onMediaPeriodReleased(int windowIndex, MediaPeriodId mediaPeriodId) { + // Do nothing. + } + @Override public void onLoadStarted( int windowIndex, @@ -63,6 +73,11 @@ public abstract class DefaultMediaSourceEventListener implements MediaSourceEven // Do nothing. } + @Override + public void onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId) { + // Do nothing. + } + @Override public void onUpstreamDiscarded( int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java index 9c410355c7..ed27a24350 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java @@ -100,6 +100,7 @@ import java.util.Arrays; private boolean seenFirstTrackSelection; private boolean notifyDiscontinuity; + private boolean notifiedReadingStarted; private int enabledTrackCount; private TrackGroupArray tracks; private long durationUs; @@ -176,6 +177,7 @@ import java.util.Arrays; minLoadableRetryCount == ExtractorMediaSource.MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA ? ExtractorMediaSource.DEFAULT_MIN_LOADABLE_RETRY_COUNT_ON_DEMAND : minLoadableRetryCount; + eventDispatcher.mediaPeriodCreated(); } public void release() { @@ -189,6 +191,7 @@ import java.util.Arrays; loader.release(this); handler.removeCallbacksAndMessages(null); released = true; + eventDispatcher.mediaPeriodReleased(); } @Override @@ -319,6 +322,10 @@ import java.util.Arrays; @Override public long readDiscontinuity() { + if (!notifiedReadingStarted) { + eventDispatcher.readingStarted(); + notifiedReadingStarted = true; + } if (notifyDiscontinuity && (loadingFinished || getExtractedSamplesCount() > extractedSamplesCountAtStartOfLoad)) { notifyDiscontinuity = false; diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java index 63a1ef53d0..8d7bd768bb 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaPeriod.java @@ -131,7 +131,8 @@ public interface MediaPeriod extends SequenceableLoader { *

After this method has returned a value other than {@link C#TIME_UNSET}, all {@link * SampleStream}s provided by the period are guaranteed to start from a key frame. * - *

This method should only be called after the period has been prepared. + *

This method should only be called after the period has been prepared. It must be called + * before attempting to read from any {@link SampleStream}s provided by the period. * * @return If a discontinuity was read then the playback position in microseconds after the * discontinuity. Else {@link C#TIME_UNSET}. diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java index ef2bc5f15c..2991d0a845 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java @@ -133,6 +133,22 @@ public interface MediaSourceEventListener { } } + /** + * Called when a media period is created by the media source. + * + * @param windowIndex The window index in the timeline this media period belongs to. + * @param mediaPeriodId The {@link MediaPeriodId} of the created media period. + */ + void onMediaPeriodCreated(int windowIndex, MediaPeriodId mediaPeriodId); + + /** + * Called when a media period is released by the media source. + * + * @param windowIndex The window index in the timeline this media period belongs to. + * @param mediaPeriodId The {@link MediaPeriodId} of the released media period. + */ + void onMediaPeriodReleased(int windowIndex, MediaPeriodId mediaPeriodId); + /** * Called when a load begins. * @@ -208,6 +224,14 @@ public interface MediaSourceEventListener { IOException error, boolean wasCanceled); + /** + * Called when a media period is first being read from. + * + * @param windowIndex The window index in the timeline this media period belongs to. + * @param mediaPeriodId The {@link MediaPeriodId} of the media period being read from. + */ + void onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId); + /** * Called when data is removed from the back of a media buffer, typically so that it can be * re-buffered in a different format. @@ -301,6 +325,38 @@ public interface MediaSourceEventListener { } } + /** Dispatches {@link #onMediaPeriodCreated(int, MediaPeriodId)}. */ + public void mediaPeriodCreated() { + Assertions.checkState(mediaPeriodId != null); + for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) { + final MediaSourceEventListener listener = listenerAndHandler.listener; + postOrRun( + listenerAndHandler.handler, + new Runnable() { + @Override + public void run() { + listener.onMediaPeriodCreated(windowIndex, mediaPeriodId); + } + }); + } + } + + /** Dispatches {@link #onMediaPeriodReleased(int, MediaPeriodId)}. */ + public void mediaPeriodReleased() { + Assertions.checkState(mediaPeriodId != null); + for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) { + final MediaSourceEventListener listener = listenerAndHandler.listener; + postOrRun( + listenerAndHandler.handler, + new Runnable() { + @Override + public void run() { + listener.onMediaPeriodReleased(windowIndex, mediaPeriodId); + } + }); + } + } + /** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ public void loadStarted(DataSpec dataSpec, int dataType, long elapsedRealtimeMs) { loadStarted( @@ -560,6 +616,22 @@ public interface MediaSourceEventListener { } } + /** Dispatches {@link #onReadingStarted(int, MediaPeriodId)}. */ + public void readingStarted() { + Assertions.checkState(mediaPeriodId != null); + for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) { + final MediaSourceEventListener listener = listenerAndHandler.listener; + postOrRun( + listenerAndHandler.handler, + new Runnable() { + @Override + public void run() { + listener.onReadingStarted(windowIndex, mediaPeriodId); + } + }); + } + } + /** Dispatches {@link #onUpstreamDiscarded(int, MediaPeriodId, MediaLoadData)}. */ public void upstreamDiscarded(int trackType, long mediaStartTimeUs, long mediaEndTimeUs) { upstreamDiscarded( diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java index 7c141bcf61..0a089e5b7c 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java @@ -56,6 +56,7 @@ import java.util.Arrays; /* package */ final Format format; /* package */ final boolean treatLoadErrorsAsEndOfStream; + /* package */ boolean notifiedReadingStarted; /* package */ boolean loadingFinished; /* package */ boolean loadingSucceeded; /* package */ byte[] sampleData; @@ -80,10 +81,12 @@ import java.util.Arrays; tracks = new TrackGroupArray(new TrackGroup(format)); sampleStreams = new ArrayList<>(); loader = new Loader("Loader:SingleSampleMediaPeriod"); + eventDispatcher.mediaPeriodCreated(); } public void release() { loader.release(); + eventDispatcher.mediaPeriodReleased(); } @Override @@ -154,6 +157,10 @@ import java.util.Arrays; @Override public long readDiscontinuity() { + if (!notifiedReadingStarted) { + eventDispatcher.readingStarted(); + notifiedReadingStarted = true; + } return C.TIME_UNSET; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java b/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java index 785a31ca90..1e1b8489d1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/util/EventLogger.java @@ -362,6 +362,16 @@ public class EventLogger // MediaSourceEventListener + @Override + public void onMediaPeriodCreated(int windowIndex, MediaPeriodId mediaPeriodId) { + // Do nothing. + } + + @Override + public void onMediaPeriodReleased(int windowIndex, MediaPeriodId mediaPeriodId) { + // Do nothing. + } + @Override public void onLoadStarted( int windowIndex, @@ -400,6 +410,11 @@ public class EventLogger // Do nothing. } + @Override + public void onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId) { + // Do nothing. + } + @Override public void onUpstreamDiscarded( int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java index 00baf15228..d2982481e0 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaPeriod.java @@ -79,6 +79,7 @@ import java.util.List; private DashManifest manifest; private int periodIndex; private List eventStreams; + private boolean notifiedReadingStarted; public DashMediaPeriod( int id, @@ -114,6 +115,7 @@ import java.util.List; eventStreams); trackGroups = result.first; trackGroupInfos = result.second; + eventDispatcher.mediaPeriodCreated(); } /** @@ -148,6 +150,7 @@ import java.util.List; for (ChunkSampleStream sampleStream : sampleStreams) { sampleStream.release(this); } + eventDispatcher.mediaPeriodReleased(); } // ChunkSampleStream.ReleaseCallback implementation. @@ -325,6 +328,10 @@ import java.util.List; @Override public long readDiscontinuity() { + if (!notifiedReadingStarted) { + eventDispatcher.readingStarted(); + notifiedReadingStarted = true; + } return C.TIME_UNSET; } diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java index 11602c722f..8076fd8359 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaPeriod.java @@ -65,6 +65,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper private HlsSampleStreamWrapper[] sampleStreamWrappers; private HlsSampleStreamWrapper[] enabledSampleStreamWrappers; private SequenceableLoader compositeSequenceableLoader; + private boolean notifiedReadingStarted; public HlsMediaPeriod( HlsExtractorFactory extractorFactory, @@ -88,6 +89,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper continueLoadingHandler = new Handler(); sampleStreamWrappers = new HlsSampleStreamWrapper[0]; enabledSampleStreamWrappers = new HlsSampleStreamWrapper[0]; + eventDispatcher.mediaPeriodCreated(); } public void release() { @@ -96,6 +98,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) { sampleStreamWrapper.release(); } + eventDispatcher.mediaPeriodReleased(); } @Override @@ -221,6 +224,10 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper @Override public long readDiscontinuity() { + if (!notifiedReadingStarted) { + eventDispatcher.readingStarted(); + notifiedReadingStarted = true; + } return C.TIME_UNSET; } diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java index a600741362..9a0d57ff31 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaPeriod.java @@ -56,6 +56,7 @@ import java.util.ArrayList; private SsManifest manifest; private ChunkSampleStream[] sampleStreams; private SequenceableLoader compositeSequenceableLoader; + private boolean notifiedReadingStarted; public SsMediaPeriod(SsManifest manifest, SsChunkSource.Factory chunkSourceFactory, CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory, @@ -82,6 +83,7 @@ import java.util.ArrayList; sampleStreams = newSampleStreamArray(0); compositeSequenceableLoader = compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(sampleStreams); + eventDispatcher.mediaPeriodCreated(); } public void updateManifest(SsManifest manifest) { @@ -96,6 +98,7 @@ import java.util.ArrayList; for (ChunkSampleStream sampleStream : sampleStreams) { sampleStream.release(); } + eventDispatcher.mediaPeriodReleased(); } @Override @@ -167,6 +170,10 @@ import java.util.ArrayList; @Override public long readDiscontinuity() { + if (!notifiedReadingStarted) { + eventDispatcher.readingStarted(); + notifiedReadingStarted = true; + } return C.TIME_UNSET; } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveMediaPeriod.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveMediaPeriod.java index 0cf847e227..1008c0d561 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveMediaPeriod.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeAdaptiveMediaPeriod.java @@ -58,10 +58,10 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod @Override public void release() { - super.release(); for (ChunkSampleStream sampleStream : sampleStreams) { sampleStream.release(); } + super.release(); } @Override diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java index 19ceeb25e9..40d9b1ef9f 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java @@ -48,6 +48,7 @@ public class FakeMediaPeriod implements MediaPeriod { @Nullable private Callback prepareCallback; private boolean deferOnPrepared; + private boolean notifiedReadingStarted; private boolean prepared; private long seekOffsetUs; private long discontinuityPositionUs; @@ -73,6 +74,7 @@ public class FakeMediaPeriod implements MediaPeriod { this.eventDispatcher = eventDispatcher; this.deferOnPrepared = deferOnPrepared; discontinuityPositionUs = C.TIME_UNSET; + eventDispatcher.mediaPeriodCreated(); } /** @@ -112,6 +114,7 @@ public class FakeMediaPeriod implements MediaPeriod { public void release() { prepared = false; + eventDispatcher.mediaPeriodReleased(); } @Override @@ -182,6 +185,10 @@ public class FakeMediaPeriod implements MediaPeriod { @Override public long readDiscontinuity() { assertThat(prepared).isTrue(); + if (!notifiedReadingStarted) { + eventDispatcher.readingStarted(); + notifiedReadingStarted = true; + } long positionDiscontinuityUs = this.discontinuityPositionUs; this.discontinuityPositionUs = C.TIME_UNSET; return positionDiscontinuityUs; diff --git a/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/MediaSourceTestRunner.java b/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/MediaSourceTestRunner.java index 3872f294a1..ee3a3a2d32 100644 --- a/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/MediaSourceTestRunner.java +++ b/testutils_robolectric/src/main/java/com/google/android/exoplayer2/testutil/MediaSourceTestRunner.java @@ -47,6 +47,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; /** A runner for {@link MediaSource} tests. */ public class MediaSourceTestRunner { @@ -62,6 +63,9 @@ public class MediaSourceTestRunner { private final LinkedBlockingDeque timelines; private final CopyOnWriteArrayList> completedLoads; + private final AtomicReference lastCreatedMediaPeriod; + private final AtomicReference lastReleasedMediaPeriod; + private Timeline timeline; /** @@ -79,6 +83,8 @@ public class MediaSourceTestRunner { mediaSourceListener = new MediaSourceListener(); timelines = new LinkedBlockingDeque<>(); completedLoads = new CopyOnWriteArrayList<>(); + lastCreatedMediaPeriod = new AtomicReference<>(); + lastReleasedMediaPeriod = new AtomicReference<>(); mediaSource.addEventListener(playbackHandler, mediaSourceListener); } @@ -282,16 +288,20 @@ public class MediaSourceTestRunner { private void assertPrepareAndReleasePeriod(MediaPeriodId mediaPeriodId) throws InterruptedException { MediaPeriod mediaPeriod = createPeriod(mediaPeriodId); + assertThat(lastCreatedMediaPeriod.getAndSet(/* newValue= */ null)).isEqualTo(mediaPeriodId); CountDownLatch preparedCondition = preparePeriod(mediaPeriod, 0); assertThat(preparedCondition.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue(); // MediaSource is supposed to support multiple calls to createPeriod with the same id without an // intervening call to releasePeriod. MediaPeriod secondMediaPeriod = createPeriod(mediaPeriodId); + assertThat(lastCreatedMediaPeriod.getAndSet(/* newValue= */ null)).isEqualTo(mediaPeriodId); CountDownLatch secondPreparedCondition = preparePeriod(secondMediaPeriod, 0); assertThat(secondPreparedCondition.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue(); // Release the periods. releasePeriod(mediaPeriod); + assertThat(lastReleasedMediaPeriod.getAndSet(/* newValue= */ null)).isEqualTo(mediaPeriodId); releasePeriod(secondMediaPeriod); + assertThat(lastReleasedMediaPeriod.getAndSet(/* newValue= */ null)).isEqualTo(mediaPeriodId); } /** @@ -354,6 +364,18 @@ public class MediaSourceTestRunner { // MediaSourceEventListener methods. + @Override + public void onMediaPeriodCreated(int windowIndex, MediaPeriodId mediaPeriodId) { + Assertions.checkState(Looper.myLooper() == playbackThread.getLooper()); + lastCreatedMediaPeriod.set(mediaPeriodId); + } + + @Override + public void onMediaPeriodReleased(int windowIndex, MediaPeriodId mediaPeriodId) { + Assertions.checkState(Looper.myLooper() == playbackThread.getLooper()); + lastReleasedMediaPeriod.set(mediaPeriodId); + } + @Override public void onLoadStarted( int windowIndex, @@ -393,6 +415,11 @@ public class MediaSourceTestRunner { Assertions.checkState(Looper.myLooper() == playbackThread.getLooper()); } + @Override + public void onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId) { + Assertions.checkState(Looper.myLooper() == playbackThread.getLooper()); + } + @Override public void onUpstreamDiscarded( int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {