Commit 3fe0b1a6 by tonihei Committed by Oliver Woodman

Rename SourceInfoRefreshListener to MediaSourceCaller.

This better reflects its usage as a caller identifier and not just a listener.

PiperOrigin-RevId: 257827188
parent 510f1883
...@@ -15,9 +15,10 @@ ...@@ -15,9 +15,10 @@
* Add VR player demo. * Add VR player demo.
* Wrap decoder exceptions in a new `DecoderException` class and report as * Wrap decoder exceptions in a new `DecoderException` class and report as
renderer error. renderer error.
* Do not pass the manifest to callbacks of Player.EventListener and * Do not pass the manifest to callbacks of `Player.EventListener` and
SourceInfoRefreshListener anymore. Instead make it accessible through `SourceInfoRefreshListener` anymore. Instead make it accessible through
Player.getCurrentManifest() and Timeline.Window.manifest. `Player.getCurrentManifest()` and `Timeline.Window.manifest`. Also rename
`SourceInfoRefreshListener` to `MediaSourceCaller`.
* Flac extension: Parse `VORBIS_COMMENT` metadata * Flac extension: Parse `VORBIS_COMMENT` metadata
([#5527](https://github.com/google/ExoPlayer/issues/5527)). ([#5527](https://github.com/google/ExoPlayer/issues/5527)).
......
...@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.Player.DiscontinuityReason; ...@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.Player.DiscontinuityReason;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller;
import com.google.android.exoplayer2.source.SampleStream; import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
...@@ -51,7 +52,7 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -51,7 +52,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
implements Handler.Callback, implements Handler.Callback,
MediaPeriod.Callback, MediaPeriod.Callback,
TrackSelector.InvalidationListener, TrackSelector.InvalidationListener,
MediaSource.SourceInfoRefreshListener, MediaSourceCaller,
PlaybackParameterListener, PlaybackParameterListener,
PlayerMessage.Sender { PlayerMessage.Sender {
...@@ -264,7 +265,7 @@ import java.util.concurrent.atomic.AtomicBoolean; ...@@ -264,7 +265,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
return internalPlaybackThread.getLooper(); return internalPlaybackThread.getLooper();
} }
// MediaSource.SourceInfoRefreshListener implementation. // MediaSource.MediaSourceCaller implementation.
@Override @Override
public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) { public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) {
......
...@@ -31,6 +31,7 @@ import com.google.android.exoplayer2.drm.FrameworkMediaCrypto; ...@@ -31,6 +31,7 @@ import com.google.android.exoplayer2.drm.FrameworkMediaCrypto;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller;
import com.google.android.exoplayer2.source.MediaSourceFactory; import com.google.android.exoplayer2.source.MediaSourceFactory;
import com.google.android.exoplayer2.source.ProgressiveMediaSource; import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
...@@ -800,7 +801,7 @@ public final class DownloadHelper { ...@@ -800,7 +801,7 @@ public final class DownloadHelper {
} }
private static final class MediaPreparer private static final class MediaPreparer
implements MediaSource.SourceInfoRefreshListener, MediaPeriod.Callback, Handler.Callback { implements MediaSourceCaller, MediaPeriod.Callback, Handler.Callback {
private static final int MESSAGE_PREPARE_SOURCE = 0; private static final int MESSAGE_PREPARE_SOURCE = 0;
private static final int MESSAGE_CHECK_FOR_FAILURE = 1; private static final int MESSAGE_CHECK_FOR_FAILURE = 1;
...@@ -892,7 +893,7 @@ public final class DownloadHelper { ...@@ -892,7 +893,7 @@ public final class DownloadHelper {
} }
} }
// MediaSource.SourceInfoRefreshListener implementation. // MediaSource.MediaSourceCaller implementation.
@Override @Override
public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) { public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) {
......
...@@ -32,14 +32,14 @@ import java.util.ArrayList; ...@@ -32,14 +32,14 @@ import java.util.ArrayList;
*/ */
public abstract class BaseMediaSource implements MediaSource { public abstract class BaseMediaSource implements MediaSource {
private final ArrayList<SourceInfoRefreshListener> sourceInfoListeners; private final ArrayList<MediaSourceCaller> mediaSourceCallers;
private final MediaSourceEventListener.EventDispatcher eventDispatcher; private final MediaSourceEventListener.EventDispatcher eventDispatcher;
@Nullable private Looper looper; @Nullable private Looper looper;
@Nullable private Timeline timeline; @Nullable private Timeline timeline;
public BaseMediaSource() { public BaseMediaSource() {
sourceInfoListeners = new ArrayList<>(/* initialCapacity= */ 1); mediaSourceCallers = new ArrayList<>(/* initialCapacity= */ 1);
eventDispatcher = new MediaSourceEventListener.EventDispatcher(); eventDispatcher = new MediaSourceEventListener.EventDispatcher();
} }
...@@ -67,8 +67,8 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -67,8 +67,8 @@ public abstract class BaseMediaSource implements MediaSource {
*/ */
protected final void refreshSourceInfo(Timeline timeline) { protected final void refreshSourceInfo(Timeline timeline) {
this.timeline = timeline; this.timeline = timeline;
for (SourceInfoRefreshListener listener : sourceInfoListeners) { for (MediaSourceCaller caller : mediaSourceCallers) {
listener.onSourceInfoRefreshed(/* source= */ this, timeline); caller.onSourceInfoRefreshed(/* source= */ this, timeline);
} }
} }
...@@ -127,23 +127,22 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -127,23 +127,22 @@ public abstract class BaseMediaSource implements MediaSource {
@Override @Override
public final void prepareSource( public final void prepareSource(
SourceInfoRefreshListener listener, MediaSourceCaller caller, @Nullable TransferListener mediaTransferListener) {
@Nullable TransferListener mediaTransferListener) {
Looper looper = Looper.myLooper(); Looper looper = Looper.myLooper();
Assertions.checkArgument(this.looper == null || this.looper == looper); Assertions.checkArgument(this.looper == null || this.looper == looper);
sourceInfoListeners.add(listener); mediaSourceCallers.add(caller);
if (this.looper == null) { if (this.looper == null) {
this.looper = looper; this.looper = looper;
prepareSourceInternal(mediaTransferListener); prepareSourceInternal(mediaTransferListener);
} else if (timeline != null) { } else if (timeline != null) {
listener.onSourceInfoRefreshed(/* source= */ this, timeline); caller.onSourceInfoRefreshed(/* source= */ this, timeline);
} }
} }
@Override @Override
public final void releaseSource(SourceInfoRefreshListener listener) { public final void releaseSource(MediaSourceCaller caller) {
sourceInfoListeners.remove(listener); mediaSourceCallers.remove(caller);
if (sourceInfoListeners.isEmpty()) { if (mediaSourceCallers.isEmpty()) {
looper = null; looper = null;
timeline = null; timeline = null;
releaseSourceInternal(); releaseSourceInternal();
......
...@@ -61,7 +61,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -61,7 +61,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
@CallSuper @CallSuper
protected void releaseSourceInternal() { protected void releaseSourceInternal() {
for (MediaSourceAndListener childSource : childSources.values()) { for (MediaSourceAndListener childSource : childSources.values()) {
childSource.mediaSource.releaseSource(childSource.listener); childSource.mediaSource.releaseSource(childSource.caller);
childSource.mediaSource.removeEventListener(childSource.eventListener); childSource.mediaSource.removeEventListener(childSource.eventListener);
} }
childSources.clear(); childSources.clear();
...@@ -91,17 +91,12 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -91,17 +91,12 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
*/ */
protected final void prepareChildSource(final T id, MediaSource mediaSource) { protected final void prepareChildSource(final T id, MediaSource mediaSource) {
Assertions.checkArgument(!childSources.containsKey(id)); Assertions.checkArgument(!childSources.containsKey(id));
SourceInfoRefreshListener sourceListener = MediaSourceCaller caller =
new SourceInfoRefreshListener() { (source, timeline) -> onChildSourceInfoRefreshed(id, source, timeline);
@Override
public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) {
onChildSourceInfoRefreshed(id, source, timeline);
}
};
MediaSourceEventListener eventListener = new ForwardingEventListener(id); MediaSourceEventListener eventListener = new ForwardingEventListener(id);
childSources.put(id, new MediaSourceAndListener(mediaSource, sourceListener, eventListener)); childSources.put(id, new MediaSourceAndListener(mediaSource, caller, eventListener));
mediaSource.addEventListener(Assertions.checkNotNull(eventHandler), eventListener); mediaSource.addEventListener(Assertions.checkNotNull(eventHandler), eventListener);
mediaSource.prepareSource(sourceListener, mediaTransferListener); mediaSource.prepareSource(caller, mediaTransferListener);
} }
/** /**
...@@ -111,7 +106,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -111,7 +106,7 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
*/ */
protected final void releaseChildSource(T id) { protected final void releaseChildSource(T id) {
MediaSourceAndListener removedChild = Assertions.checkNotNull(childSources.remove(id)); MediaSourceAndListener removedChild = Assertions.checkNotNull(childSources.remove(id));
removedChild.mediaSource.releaseSource(removedChild.listener); removedChild.mediaSource.releaseSource(removedChild.caller);
removedChild.mediaSource.removeEventListener(removedChild.eventListener); removedChild.mediaSource.removeEventListener(removedChild.eventListener);
} }
...@@ -157,15 +152,13 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource { ...@@ -157,15 +152,13 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
private static final class MediaSourceAndListener { private static final class MediaSourceAndListener {
public final MediaSource mediaSource; public final MediaSource mediaSource;
public final SourceInfoRefreshListener listener; public final MediaSourceCaller caller;
public final MediaSourceEventListener eventListener; public final MediaSourceEventListener eventListener;
public MediaSourceAndListener( public MediaSourceAndListener(
MediaSource mediaSource, MediaSource mediaSource, MediaSourceCaller caller, MediaSourceEventListener eventListener) {
SourceInfoRefreshListener listener,
MediaSourceEventListener eventListener) {
this.mediaSource = mediaSource; this.mediaSource = mediaSource;
this.listener = listener; this.caller = caller;
this.eventListener = eventListener; this.eventListener = eventListener;
} }
} }
......
...@@ -20,6 +20,7 @@ import com.google.android.exoplayer2.ExoPlayer; ...@@ -20,6 +20,7 @@ import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.offline.StreamKey; import com.google.android.exoplayer2.offline.StreamKey;
import com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
...@@ -57,8 +58,7 @@ public interface MediaPeriod extends SequenceableLoader { ...@@ -57,8 +58,7 @@ public interface MediaPeriod extends SequenceableLoader {
* {@link #maybeThrowPrepareError()} will throw an {@link IOException}. * {@link #maybeThrowPrepareError()} will throw an {@link IOException}.
* *
* <p>If preparation succeeds and results in a source timeline change (e.g. the period duration * <p>If preparation succeeds and results in a source timeline change (e.g. the period duration
* becoming known), {@link * becoming known), {@link MediaSourceCaller#onSourceInfoRefreshed(MediaSource, Timeline)} will be
* MediaSource.SourceInfoRefreshListener#onSourceInfoRefreshed(MediaSource, Timeline)} will be
* called before {@code callback.onPrepared}. * called before {@code callback.onPrepared}.
* *
* @param callback Callback to receive updates from this period, including being notified when * @param callback Callback to receive updates from this period, including being notified when
......
...@@ -30,9 +30,9 @@ import java.io.IOException; ...@@ -30,9 +30,9 @@ import java.io.IOException;
* <ul> * <ul>
* <li>To provide the player with a {@link Timeline} defining the structure of its media, and to * <li>To provide the player with a {@link Timeline} defining the structure of its media, and to
* provide a new timeline whenever the structure of the media changes. The MediaSource * provide a new timeline whenever the structure of the media changes. The MediaSource
* provides these timelines by calling {@link SourceInfoRefreshListener#onSourceInfoRefreshed} * provides these timelines by calling {@link MediaSourceCaller#onSourceInfoRefreshed} on the
* on the {@link SourceInfoRefreshListener}s passed to {@link * {@link MediaSourceCaller}s passed to {@link #prepareSource(MediaSourceCaller,
* #prepareSource(SourceInfoRefreshListener, TransferListener)}. * TransferListener)}.
* <li>To provide {@link MediaPeriod} instances for the periods in its timeline. MediaPeriods are * <li>To provide {@link MediaPeriod} instances for the periods in its timeline. MediaPeriods are
* obtained by calling {@link #createPeriod(MediaPeriodId, Allocator, long)}, and provide a * obtained by calling {@link #createPeriod(MediaPeriodId, Allocator, long)}, and provide a
* way for the player to load and read the media. * way for the player to load and read the media.
...@@ -45,25 +45,21 @@ import java.io.IOException; ...@@ -45,25 +45,21 @@ import java.io.IOException;
*/ */
public interface MediaSource { public interface MediaSource {
/** Listener for source events. */ /** A caller of media sources, which will be notified of source events. */
interface SourceInfoRefreshListener { interface MediaSourceCaller {
/** /**
* Called when the timeline has been refreshed. * Called when the {@link Timeline} has been refreshed.
* *
* <p>Called on the playback thread. * <p>Called on the playback thread.
* *
* @param source The {@link MediaSource} whose info has been refreshed. * @param source The {@link MediaSource} whose info has been refreshed.
* @param timeline The source's timeline. * @param timeline The source's timeline.
*/ */
default void onSourceInfoRefreshed(MediaSource source, Timeline timeline) { void onSourceInfoRefreshed(MediaSource source, Timeline timeline);
// Do nothing.
}
} }
/** /** Identifier for a {@link MediaPeriod}. */
* Identifier for a {@link MediaPeriod}.
*/
final class MediaPeriodId { final class MediaPeriodId {
/** The unique id of the timeline period. */ /** The unique id of the timeline period. */
...@@ -239,24 +235,23 @@ public interface MediaSource { ...@@ -239,24 +235,23 @@ public interface MediaSource {
} }
/** /**
* Starts source preparation. * Registers a {@link MediaSourceCaller} and starts source preparation if needed.
* *
* <p>Should not be called directly from application code. * <p>Should not be called directly from application code.
* *
* <p>{@link SourceInfoRefreshListener#onSourceInfoRefreshed(MediaSource, Timeline)} will be * <p>{@link MediaSourceCaller#onSourceInfoRefreshed(MediaSource, Timeline)} will be called once
* called once the source has a {@link Timeline}. * the source has a {@link Timeline}.
* *
* <p>For each call to this method, a call to {@link #releaseSource(SourceInfoRefreshListener)} is * <p>For each call to this method, a call to {@link #releaseSource(MediaSourceCaller)} is needed
* needed to remove the listener and to release the source if no longer required. * to remove the caller and to release the source if no longer required.
* *
* @param listener The listener to be added. * @param caller The {@link MediaSourceCaller} to be registered.
* @param mediaTransferListener The transfer listener which should be informed of any media data * @param mediaTransferListener The transfer listener which should be informed of any media data
* transfers. May be null if no listener is available. Note that this listener should be only * transfers. May be null if no listener is available. Note that this listener should be only
* informed of transfers related to the media loads and not of auxiliary loads for manifests * informed of transfers related to the media loads and not of auxiliary loads for manifests
* and other data. * and other data.
*/ */
void prepareSource( void prepareSource(MediaSourceCaller caller, @Nullable TransferListener mediaTransferListener);
SourceInfoRefreshListener listener, @Nullable TransferListener mediaTransferListener);
/** /**
* Throws any pending error encountered while loading or refreshing source information. * Throws any pending error encountered while loading or refreshing source information.
...@@ -288,12 +283,11 @@ public interface MediaSource { ...@@ -288,12 +283,11 @@ public interface MediaSource {
void releasePeriod(MediaPeriod mediaPeriod); void releasePeriod(MediaPeriod mediaPeriod);
/** /**
* Removes a listener for timeline and/or manifest updates and releases the source if no longer * Unregisters a caller and releases the source if no longer required.
* required.
* *
* <p>Should not be called directly from application code. * <p>Should not be called directly from application code.
* *
* @param listener The listener to be removed. * @param caller The {@link MediaSourceCaller} to be unregistered.
*/ */
void releaseSource(SourceInfoRefreshListener listener); void releaseSource(MediaSourceCaller caller);
} }
...@@ -26,7 +26,7 @@ import com.google.android.exoplayer2.C; ...@@ -26,7 +26,7 @@ import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSource.SourceInfoRefreshListener; import com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller;
import com.google.android.exoplayer2.source.ShuffleOrder.DefaultShuffleOrder; import com.google.android.exoplayer2.source.ShuffleOrder.DefaultShuffleOrder;
import com.google.android.exoplayer2.testutil.DummyMainThread; import com.google.android.exoplayer2.testutil.DummyMainThread;
import com.google.android.exoplayer2.testutil.FakeMediaSource; import com.google.android.exoplayer2.testutil.FakeMediaSource;
...@@ -628,15 +628,15 @@ public final class ConcatenatingMediaSourceTest { ...@@ -628,15 +628,15 @@ public final class ConcatenatingMediaSourceTest {
try { try {
dummyMainThread.runOnMainThread( dummyMainThread.runOnMainThread(
() -> { () -> {
SourceInfoRefreshListener listener = mock(SourceInfoRefreshListener.class); MediaSourceCaller caller = mock(MediaSourceCaller.class);
mediaSource.addMediaSources(Arrays.asList(createMediaSources(2))); mediaSource.addMediaSources(Arrays.asList(createMediaSources(2)));
mediaSource.prepareSource(listener, /* mediaTransferListener= */ null); mediaSource.prepareSource(caller, /* mediaTransferListener= */ null);
mediaSource.moveMediaSource( mediaSource.moveMediaSource(
/* currentIndex= */ 0, /* currentIndex= */ 0,
/* newIndex= */ 1, /* newIndex= */ 1,
new Handler(), new Handler(),
callbackCalledCondition::open); callbackCalledCondition::open);
mediaSource.releaseSource(listener); mediaSource.releaseSource(caller);
}); });
assertThat(callbackCalledCondition.block(MediaSourceTestRunner.TIMEOUT_MS)).isTrue(); assertThat(callbackCalledCondition.block(MediaSourceTestRunner.TIMEOUT_MS)).isTrue();
} finally { } finally {
......
...@@ -366,8 +366,8 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -366,8 +366,8 @@ public final class DashMediaSource extends BaseMediaSource {
/** /**
* The interval in milliseconds between invocations of {@link * The interval in milliseconds between invocations of {@link
* SourceInfoRefreshListener#onSourceInfoRefreshed(MediaSource, Timeline)} when the source's * MediaSourceCaller#onSourceInfoRefreshed(MediaSource, Timeline)} when the source's {@link
* {@link Timeline} is changing dynamically (for example, for incomplete live streams). * Timeline} is changing dynamically (for example, for incomplete live streams).
*/ */
private static final int NOTIFY_MANIFEST_INTERVAL_MS = 5000; private static final int NOTIFY_MANIFEST_INTERVAL_MS = 5000;
/** /**
......
...@@ -28,6 +28,7 @@ import com.google.android.exoplayer2.Timeline; ...@@ -28,6 +28,7 @@ import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.MediaPeriod; import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId; import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
import com.google.android.exoplayer2.source.MediaSource.MediaSourceCaller;
import com.google.android.exoplayer2.source.MediaSourceEventListener; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.MediaSourceEventListener.LoadEventInfo; import com.google.android.exoplayer2.source.MediaSourceEventListener.LoadEventInfo;
import com.google.android.exoplayer2.source.MediaSourceEventListener.MediaLoadData; import com.google.android.exoplayer2.source.MediaSourceEventListener.MediaLoadData;
...@@ -199,10 +200,7 @@ public class MediaSourceTestRunner { ...@@ -199,10 +200,7 @@ public class MediaSourceTestRunner {
runOnPlaybackThread(() -> mediaSource.releasePeriod(mediaPeriod)); runOnPlaybackThread(() -> mediaSource.releasePeriod(mediaPeriod));
} }
/** /** Calls {@link MediaSource#releaseSource(MediaSourceCaller)} on the playback thread. */
* Calls {@link MediaSource#releaseSource(MediaSource.SourceInfoRefreshListener)} on the playback
* thread.
*/
public void releaseSource() { public void releaseSource() {
runOnPlaybackThread(() -> mediaSource.releaseSource(mediaSourceListener)); runOnPlaybackThread(() -> mediaSource.releaseSource(mediaSourceListener));
} }
...@@ -339,10 +337,9 @@ public class MediaSourceTestRunner { ...@@ -339,10 +337,9 @@ public class MediaSourceTestRunner {
playbackThread.quit(); playbackThread.quit();
} }
private class MediaSourceListener private class MediaSourceListener implements MediaSourceCaller, MediaSourceEventListener {
implements MediaSource.SourceInfoRefreshListener, MediaSourceEventListener {
// SourceInfoRefreshListener methods. // MediaSourceCaller methods.
@Override @Override
public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) { public void onSourceInfoRefreshed(MediaSource source, Timeline timeline) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment