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
This commit is contained in:
tonihei 2018-03-26 07:40:00 -07:00 committed by Oliver Woodman
parent 2a85e792f8
commit 6c0d676050
14 changed files with 197 additions and 2 deletions

View File

@ -24,6 +24,8 @@
* Allow adding and removing `MediaSourceEventListener`s to MediaSources after * Allow adding and removing `MediaSourceEventListener`s to MediaSources after
they have been created. Listening to events is now supported for all they have been created. Listening to events is now supported for all
media sources including composite sources. media sources including composite sources.
* Added callbacks to `MediaSourceEventListener` to get notified when media
periods are created, released and being read from.
* Audio: * Audio:
* Factor out `AudioTrack` position tracking from `DefaultAudioSink`. * Factor out `AudioTrack` position tracking from `DefaultAudioSink`.
* Fix an issue where the playback position would pause just after playback * Fix an issue where the playback position would pause just after playback

View File

@ -185,6 +185,20 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
this.id = id; 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 @Override
public void onLoadStarted( public void onLoadStarted(
int windowIndex, int windowIndex,
@ -232,6 +246,13 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
} }
} }
@Override
public void onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
eventDispatcher.readingStarted();
}
}
@Override @Override
public void onUpstreamDiscarded( public void onUpstreamDiscarded(
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {

View File

@ -25,6 +25,16 @@ import java.io.IOException;
*/ */
public abstract class DefaultMediaSourceEventListener implements MediaSourceEventListener { 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 @Override
public void onLoadStarted( public void onLoadStarted(
int windowIndex, int windowIndex,
@ -63,6 +73,11 @@ public abstract class DefaultMediaSourceEventListener implements MediaSourceEven
// Do nothing. // Do nothing.
} }
@Override
public void onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId) {
// Do nothing.
}
@Override @Override
public void onUpstreamDiscarded( public void onUpstreamDiscarded(
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {

View File

@ -100,6 +100,7 @@ import java.util.Arrays;
private boolean seenFirstTrackSelection; private boolean seenFirstTrackSelection;
private boolean notifyDiscontinuity; private boolean notifyDiscontinuity;
private boolean notifiedReadingStarted;
private int enabledTrackCount; private int enabledTrackCount;
private TrackGroupArray tracks; private TrackGroupArray tracks;
private long durationUs; private long durationUs;
@ -176,6 +177,7 @@ import java.util.Arrays;
minLoadableRetryCount == ExtractorMediaSource.MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA minLoadableRetryCount == ExtractorMediaSource.MIN_RETRY_COUNT_DEFAULT_FOR_MEDIA
? ExtractorMediaSource.DEFAULT_MIN_LOADABLE_RETRY_COUNT_ON_DEMAND ? ExtractorMediaSource.DEFAULT_MIN_LOADABLE_RETRY_COUNT_ON_DEMAND
: minLoadableRetryCount; : minLoadableRetryCount;
eventDispatcher.mediaPeriodCreated();
} }
public void release() { public void release() {
@ -189,6 +191,7 @@ import java.util.Arrays;
loader.release(this); loader.release(this);
handler.removeCallbacksAndMessages(null); handler.removeCallbacksAndMessages(null);
released = true; released = true;
eventDispatcher.mediaPeriodReleased();
} }
@Override @Override
@ -319,6 +322,10 @@ import java.util.Arrays;
@Override @Override
public long readDiscontinuity() { public long readDiscontinuity() {
if (!notifiedReadingStarted) {
eventDispatcher.readingStarted();
notifiedReadingStarted = true;
}
if (notifyDiscontinuity if (notifyDiscontinuity
&& (loadingFinished || getExtractedSamplesCount() > extractedSamplesCountAtStartOfLoad)) { && (loadingFinished || getExtractedSamplesCount() > extractedSamplesCountAtStartOfLoad)) {
notifyDiscontinuity = false; notifyDiscontinuity = false;

View File

@ -131,7 +131,8 @@ public interface MediaPeriod extends SequenceableLoader {
* <p>After this method has returned a value other than {@link C#TIME_UNSET}, all {@link * <p>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. * SampleStream}s provided by the period are guaranteed to start from a key frame.
* *
* <p>This method should only be called after the period has been prepared. * <p>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 * @return If a discontinuity was read then the playback position in microseconds after the
* discontinuity. Else {@link C#TIME_UNSET}. * discontinuity. Else {@link C#TIME_UNSET}.

View File

@ -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. * Called when a load begins.
* *
@ -208,6 +224,14 @@ public interface MediaSourceEventListener {
IOException error, IOException error,
boolean wasCanceled); 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 * Called when data is removed from the back of a media buffer, typically so that it can be
* re-buffered in a different format. * 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)}. */ /** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */
public void loadStarted(DataSpec dataSpec, int dataType, long elapsedRealtimeMs) { public void loadStarted(DataSpec dataSpec, int dataType, long elapsedRealtimeMs) {
loadStarted( 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)}. */ /** Dispatches {@link #onUpstreamDiscarded(int, MediaPeriodId, MediaLoadData)}. */
public void upstreamDiscarded(int trackType, long mediaStartTimeUs, long mediaEndTimeUs) { public void upstreamDiscarded(int trackType, long mediaStartTimeUs, long mediaEndTimeUs) {
upstreamDiscarded( upstreamDiscarded(

View File

@ -56,6 +56,7 @@ import java.util.Arrays;
/* package */ final Format format; /* package */ final Format format;
/* package */ final boolean treatLoadErrorsAsEndOfStream; /* package */ final boolean treatLoadErrorsAsEndOfStream;
/* package */ boolean notifiedReadingStarted;
/* package */ boolean loadingFinished; /* package */ boolean loadingFinished;
/* package */ boolean loadingSucceeded; /* package */ boolean loadingSucceeded;
/* package */ byte[] sampleData; /* package */ byte[] sampleData;
@ -80,10 +81,12 @@ import java.util.Arrays;
tracks = new TrackGroupArray(new TrackGroup(format)); tracks = new TrackGroupArray(new TrackGroup(format));
sampleStreams = new ArrayList<>(); sampleStreams = new ArrayList<>();
loader = new Loader("Loader:SingleSampleMediaPeriod"); loader = new Loader("Loader:SingleSampleMediaPeriod");
eventDispatcher.mediaPeriodCreated();
} }
public void release() { public void release() {
loader.release(); loader.release();
eventDispatcher.mediaPeriodReleased();
} }
@Override @Override
@ -154,6 +157,10 @@ import java.util.Arrays;
@Override @Override
public long readDiscontinuity() { public long readDiscontinuity() {
if (!notifiedReadingStarted) {
eventDispatcher.readingStarted();
notifiedReadingStarted = true;
}
return C.TIME_UNSET; return C.TIME_UNSET;
} }

View File

@ -362,6 +362,16 @@ public class EventLogger
// MediaSourceEventListener // MediaSourceEventListener
@Override
public void onMediaPeriodCreated(int windowIndex, MediaPeriodId mediaPeriodId) {
// Do nothing.
}
@Override
public void onMediaPeriodReleased(int windowIndex, MediaPeriodId mediaPeriodId) {
// Do nothing.
}
@Override @Override
public void onLoadStarted( public void onLoadStarted(
int windowIndex, int windowIndex,
@ -400,6 +410,11 @@ public class EventLogger
// Do nothing. // Do nothing.
} }
@Override
public void onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId) {
// Do nothing.
}
@Override @Override
public void onUpstreamDiscarded( public void onUpstreamDiscarded(
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {

View File

@ -79,6 +79,7 @@ import java.util.List;
private DashManifest manifest; private DashManifest manifest;
private int periodIndex; private int periodIndex;
private List<EventStream> eventStreams; private List<EventStream> eventStreams;
private boolean notifiedReadingStarted;
public DashMediaPeriod( public DashMediaPeriod(
int id, int id,
@ -114,6 +115,7 @@ import java.util.List;
eventStreams); eventStreams);
trackGroups = result.first; trackGroups = result.first;
trackGroupInfos = result.second; trackGroupInfos = result.second;
eventDispatcher.mediaPeriodCreated();
} }
/** /**
@ -148,6 +150,7 @@ import java.util.List;
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) { for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
sampleStream.release(this); sampleStream.release(this);
} }
eventDispatcher.mediaPeriodReleased();
} }
// ChunkSampleStream.ReleaseCallback implementation. // ChunkSampleStream.ReleaseCallback implementation.
@ -325,6 +328,10 @@ import java.util.List;
@Override @Override
public long readDiscontinuity() { public long readDiscontinuity() {
if (!notifiedReadingStarted) {
eventDispatcher.readingStarted();
notifiedReadingStarted = true;
}
return C.TIME_UNSET; return C.TIME_UNSET;
} }

View File

@ -65,6 +65,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
private HlsSampleStreamWrapper[] sampleStreamWrappers; private HlsSampleStreamWrapper[] sampleStreamWrappers;
private HlsSampleStreamWrapper[] enabledSampleStreamWrappers; private HlsSampleStreamWrapper[] enabledSampleStreamWrappers;
private SequenceableLoader compositeSequenceableLoader; private SequenceableLoader compositeSequenceableLoader;
private boolean notifiedReadingStarted;
public HlsMediaPeriod( public HlsMediaPeriod(
HlsExtractorFactory extractorFactory, HlsExtractorFactory extractorFactory,
@ -88,6 +89,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
continueLoadingHandler = new Handler(); continueLoadingHandler = new Handler();
sampleStreamWrappers = new HlsSampleStreamWrapper[0]; sampleStreamWrappers = new HlsSampleStreamWrapper[0];
enabledSampleStreamWrappers = new HlsSampleStreamWrapper[0]; enabledSampleStreamWrappers = new HlsSampleStreamWrapper[0];
eventDispatcher.mediaPeriodCreated();
} }
public void release() { public void release() {
@ -96,6 +98,7 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) { for (HlsSampleStreamWrapper sampleStreamWrapper : sampleStreamWrappers) {
sampleStreamWrapper.release(); sampleStreamWrapper.release();
} }
eventDispatcher.mediaPeriodReleased();
} }
@Override @Override
@ -221,6 +224,10 @@ public final class HlsMediaPeriod implements MediaPeriod, HlsSampleStreamWrapper
@Override @Override
public long readDiscontinuity() { public long readDiscontinuity() {
if (!notifiedReadingStarted) {
eventDispatcher.readingStarted();
notifiedReadingStarted = true;
}
return C.TIME_UNSET; return C.TIME_UNSET;
} }

View File

@ -56,6 +56,7 @@ import java.util.ArrayList;
private SsManifest manifest; private SsManifest manifest;
private ChunkSampleStream<SsChunkSource>[] sampleStreams; private ChunkSampleStream<SsChunkSource>[] sampleStreams;
private SequenceableLoader compositeSequenceableLoader; private SequenceableLoader compositeSequenceableLoader;
private boolean notifiedReadingStarted;
public SsMediaPeriod(SsManifest manifest, SsChunkSource.Factory chunkSourceFactory, public SsMediaPeriod(SsManifest manifest, SsChunkSource.Factory chunkSourceFactory,
CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory, CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory,
@ -82,6 +83,7 @@ import java.util.ArrayList;
sampleStreams = newSampleStreamArray(0); sampleStreams = newSampleStreamArray(0);
compositeSequenceableLoader = compositeSequenceableLoader =
compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(sampleStreams); compositeSequenceableLoaderFactory.createCompositeSequenceableLoader(sampleStreams);
eventDispatcher.mediaPeriodCreated();
} }
public void updateManifest(SsManifest manifest) { public void updateManifest(SsManifest manifest) {
@ -96,6 +98,7 @@ import java.util.ArrayList;
for (ChunkSampleStream<SsChunkSource> sampleStream : sampleStreams) { for (ChunkSampleStream<SsChunkSource> sampleStream : sampleStreams) {
sampleStream.release(); sampleStream.release();
} }
eventDispatcher.mediaPeriodReleased();
} }
@Override @Override
@ -167,6 +170,10 @@ import java.util.ArrayList;
@Override @Override
public long readDiscontinuity() { public long readDiscontinuity() {
if (!notifiedReadingStarted) {
eventDispatcher.readingStarted();
notifiedReadingStarted = true;
}
return C.TIME_UNSET; return C.TIME_UNSET;
} }

View File

@ -58,10 +58,10 @@ public class FakeAdaptiveMediaPeriod extends FakeMediaPeriod
@Override @Override
public void release() { public void release() {
super.release();
for (ChunkSampleStream<FakeChunkSource> sampleStream : sampleStreams) { for (ChunkSampleStream<FakeChunkSource> sampleStream : sampleStreams) {
sampleStream.release(); sampleStream.release();
} }
super.release();
} }
@Override @Override

View File

@ -48,6 +48,7 @@ public class FakeMediaPeriod implements MediaPeriod {
@Nullable private Callback prepareCallback; @Nullable private Callback prepareCallback;
private boolean deferOnPrepared; private boolean deferOnPrepared;
private boolean notifiedReadingStarted;
private boolean prepared; private boolean prepared;
private long seekOffsetUs; private long seekOffsetUs;
private long discontinuityPositionUs; private long discontinuityPositionUs;
@ -73,6 +74,7 @@ public class FakeMediaPeriod implements MediaPeriod {
this.eventDispatcher = eventDispatcher; this.eventDispatcher = eventDispatcher;
this.deferOnPrepared = deferOnPrepared; this.deferOnPrepared = deferOnPrepared;
discontinuityPositionUs = C.TIME_UNSET; discontinuityPositionUs = C.TIME_UNSET;
eventDispatcher.mediaPeriodCreated();
} }
/** /**
@ -112,6 +114,7 @@ public class FakeMediaPeriod implements MediaPeriod {
public void release() { public void release() {
prepared = false; prepared = false;
eventDispatcher.mediaPeriodReleased();
} }
@Override @Override
@ -182,6 +185,10 @@ public class FakeMediaPeriod implements MediaPeriod {
@Override @Override
public long readDiscontinuity() { public long readDiscontinuity() {
assertThat(prepared).isTrue(); assertThat(prepared).isTrue();
if (!notifiedReadingStarted) {
eventDispatcher.readingStarted();
notifiedReadingStarted = true;
}
long positionDiscontinuityUs = this.discontinuityPositionUs; long positionDiscontinuityUs = this.discontinuityPositionUs;
this.discontinuityPositionUs = C.TIME_UNSET; this.discontinuityPositionUs = C.TIME_UNSET;
return positionDiscontinuityUs; return positionDiscontinuityUs;

View File

@ -47,6 +47,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/** A runner for {@link MediaSource} tests. */ /** A runner for {@link MediaSource} tests. */
public class MediaSourceTestRunner { public class MediaSourceTestRunner {
@ -62,6 +63,9 @@ public class MediaSourceTestRunner {
private final LinkedBlockingDeque<Timeline> timelines; private final LinkedBlockingDeque<Timeline> timelines;
private final CopyOnWriteArrayList<Pair<Integer, MediaPeriodId>> completedLoads; private final CopyOnWriteArrayList<Pair<Integer, MediaPeriodId>> completedLoads;
private final AtomicReference<MediaPeriodId> lastCreatedMediaPeriod;
private final AtomicReference<MediaPeriodId> lastReleasedMediaPeriod;
private Timeline timeline; private Timeline timeline;
/** /**
@ -79,6 +83,8 @@ public class MediaSourceTestRunner {
mediaSourceListener = new MediaSourceListener(); mediaSourceListener = new MediaSourceListener();
timelines = new LinkedBlockingDeque<>(); timelines = new LinkedBlockingDeque<>();
completedLoads = new CopyOnWriteArrayList<>(); completedLoads = new CopyOnWriteArrayList<>();
lastCreatedMediaPeriod = new AtomicReference<>();
lastReleasedMediaPeriod = new AtomicReference<>();
mediaSource.addEventListener(playbackHandler, mediaSourceListener); mediaSource.addEventListener(playbackHandler, mediaSourceListener);
} }
@ -282,16 +288,20 @@ public class MediaSourceTestRunner {
private void assertPrepareAndReleasePeriod(MediaPeriodId mediaPeriodId) private void assertPrepareAndReleasePeriod(MediaPeriodId mediaPeriodId)
throws InterruptedException { throws InterruptedException {
MediaPeriod mediaPeriod = createPeriod(mediaPeriodId); MediaPeriod mediaPeriod = createPeriod(mediaPeriodId);
assertThat(lastCreatedMediaPeriod.getAndSet(/* newValue= */ null)).isEqualTo(mediaPeriodId);
CountDownLatch preparedCondition = preparePeriod(mediaPeriod, 0); CountDownLatch preparedCondition = preparePeriod(mediaPeriod, 0);
assertThat(preparedCondition.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue(); assertThat(preparedCondition.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue();
// MediaSource is supposed to support multiple calls to createPeriod with the same id without an // MediaSource is supposed to support multiple calls to createPeriod with the same id without an
// intervening call to releasePeriod. // intervening call to releasePeriod.
MediaPeriod secondMediaPeriod = createPeriod(mediaPeriodId); MediaPeriod secondMediaPeriod = createPeriod(mediaPeriodId);
assertThat(lastCreatedMediaPeriod.getAndSet(/* newValue= */ null)).isEqualTo(mediaPeriodId);
CountDownLatch secondPreparedCondition = preparePeriod(secondMediaPeriod, 0); CountDownLatch secondPreparedCondition = preparePeriod(secondMediaPeriod, 0);
assertThat(secondPreparedCondition.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue(); assertThat(secondPreparedCondition.await(TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue();
// Release the periods. // Release the periods.
releasePeriod(mediaPeriod); releasePeriod(mediaPeriod);
assertThat(lastReleasedMediaPeriod.getAndSet(/* newValue= */ null)).isEqualTo(mediaPeriodId);
releasePeriod(secondMediaPeriod); releasePeriod(secondMediaPeriod);
assertThat(lastReleasedMediaPeriod.getAndSet(/* newValue= */ null)).isEqualTo(mediaPeriodId);
} }
/** /**
@ -354,6 +364,18 @@ public class MediaSourceTestRunner {
// MediaSourceEventListener methods. // 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 @Override
public void onLoadStarted( public void onLoadStarted(
int windowIndex, int windowIndex,
@ -393,6 +415,11 @@ public class MediaSourceTestRunner {
Assertions.checkState(Looper.myLooper() == playbackThread.getLooper()); Assertions.checkState(Looper.myLooper() == playbackThread.getLooper());
} }
@Override
public void onReadingStarted(int windowIndex, MediaPeriodId mediaPeriodId) {
Assertions.checkState(Looper.myLooper() == playbackThread.getLooper());
}
@Override @Override
public void onUpstreamDiscarded( public void onUpstreamDiscarded(
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) { int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {