Commit 8f952162 by tonihei Committed by Oliver Woodman

Allow multiple media source event listeners.

This is achieved by moving the listener registration and the creation of the
event dispatcher into BaseMediaSource.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=188461932
parent ebfd9d05
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
date time is still available via the informational date time is still available via the informational
`Timeline.Window.windowStartTimeMs` field `Timeline.Window.windowStartTimeMs` field
([#3865](https://github.com/google/ExoPlayer/issues/3865)). ([#3865](https://github.com/google/ExoPlayer/issues/3865)).
* Allow adding and removing `MediaSourceEventListener`s to MediaSources after
they have been created.
* Enable seeking in MP4 streams where duration is set incorrectly in the track * Enable seeking in MP4 streams where duration is set incorrectly in the track
header ([#3926](https://github.com/google/ExoPlayer/issues/3926)). header ([#3926](https://github.com/google/ExoPlayer/issues/3926)).
* Video: force rendering a frame periodically in `MediaCodecVideoRenderer` and * Video: force rendering a frame periodically in `MediaCodecVideoRenderer` and
......
...@@ -17,8 +17,6 @@ package com.google.android.exoplayer2.imademo; ...@@ -17,8 +17,6 @@ package com.google.android.exoplayer2.imademo;
import android.content.Context; import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.Handler;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.C.ContentType; import com.google.android.exoplayer2.C.ContentType;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
...@@ -27,7 +25,6 @@ import com.google.android.exoplayer2.SimpleExoPlayer; ...@@ -27,7 +25,6 @@ import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader; import com.google.android.exoplayer2.ext.ima.ImaAdsLoader;
import com.google.android.exoplayer2.source.ExtractorMediaSource; import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.ads.AdsMediaSource; import com.google.android.exoplayer2.source.ads.AdsMediaSource;
import com.google.android.exoplayer2.source.dash.DashMediaSource; import com.google.android.exoplayer2.source.dash.DashMediaSource;
import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource; import com.google.android.exoplayer2.source.dash.DefaultDashChunkSource;
...@@ -83,8 +80,7 @@ import com.google.android.exoplayer2.util.Util; ...@@ -83,8 +80,7 @@ import com.google.android.exoplayer2.util.Util;
// This is the MediaSource representing the content media (i.e. not the ad). // This is the MediaSource representing the content media (i.e. not the ad).
String contentUrl = context.getString(R.string.content_url); String contentUrl = context.getString(R.string.content_url);
MediaSource contentMediaSource = MediaSource contentMediaSource = buildMediaSource(Uri.parse(contentUrl));
buildMediaSource(Uri.parse(contentUrl), /* handler= */ null, /* listener= */ null);
// Compose the content media source into a new AdsMediaSource with both ads and content. // Compose the content media source into a new AdsMediaSource with both ads and content.
MediaSource mediaSourceWithAds = MediaSource mediaSourceWithAds =
...@@ -121,9 +117,8 @@ import com.google.android.exoplayer2.util.Util; ...@@ -121,9 +117,8 @@ import com.google.android.exoplayer2.util.Util;
// AdsMediaSource.MediaSourceFactory implementation. // AdsMediaSource.MediaSourceFactory implementation.
@Override @Override
public MediaSource createMediaSource( public MediaSource createMediaSource(Uri uri) {
Uri uri, @Nullable Handler handler, @Nullable MediaSourceEventListener listener) { return buildMediaSource(uri);
return buildMediaSource(uri, handler, listener);
} }
@Override @Override
...@@ -134,25 +129,22 @@ import com.google.android.exoplayer2.util.Util; ...@@ -134,25 +129,22 @@ import com.google.android.exoplayer2.util.Util;
// Internal methods. // Internal methods.
private MediaSource buildMediaSource( private MediaSource buildMediaSource(Uri uri) {
Uri uri, @Nullable Handler handler, @Nullable MediaSourceEventListener listener) {
@ContentType int type = Util.inferContentType(uri); @ContentType int type = Util.inferContentType(uri);
switch (type) { switch (type) {
case C.TYPE_DASH: case C.TYPE_DASH:
return new DashMediaSource.Factory( return new DashMediaSource.Factory(
new DefaultDashChunkSource.Factory(mediaDataSourceFactory), new DefaultDashChunkSource.Factory(mediaDataSourceFactory),
manifestDataSourceFactory) manifestDataSourceFactory)
.createMediaSource(uri, handler, listener); .createMediaSource(uri);
case C.TYPE_SS: case C.TYPE_SS:
return new SsMediaSource.Factory( return new SsMediaSource.Factory(
new DefaultSsChunkSource.Factory(mediaDataSourceFactory), manifestDataSourceFactory) new DefaultSsChunkSource.Factory(mediaDataSourceFactory), manifestDataSourceFactory)
.createMediaSource(uri, handler, listener); .createMediaSource(uri);
case C.TYPE_HLS: case C.TYPE_HLS:
return new HlsMediaSource.Factory(mediaDataSourceFactory) return new HlsMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri);
.createMediaSource(uri, handler, listener);
case C.TYPE_OTHER: case C.TYPE_OTHER:
return new ExtractorMediaSource.Factory(mediaDataSourceFactory) return new ExtractorMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri);
.createMediaSource(uri, handler, listener);
default: default:
throw new IllegalStateException("Unsupported type: " + type); throw new IllegalStateException("Unsupported type: " + type);
} }
......
...@@ -53,7 +53,6 @@ import com.google.android.exoplayer2.source.BehindLiveWindowException; ...@@ -53,7 +53,6 @@ import com.google.android.exoplayer2.source.BehindLiveWindowException;
import com.google.android.exoplayer2.source.ConcatenatingMediaSource; import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
import com.google.android.exoplayer2.source.ExtractorMediaSource; import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.ads.AdsLoader; import com.google.android.exoplayer2.source.ads.AdsLoader;
import com.google.android.exoplayer2.source.ads.AdsMediaSource; import com.google.android.exoplayer2.source.ads.AdsMediaSource;
...@@ -342,7 +341,8 @@ public class PlayerActivity extends Activity ...@@ -342,7 +341,8 @@ public class PlayerActivity extends Activity
} }
MediaSource[] mediaSources = new MediaSource[uris.length]; MediaSource[] mediaSources = new MediaSource[uris.length];
for (int i = 0; i < uris.length; i++) { for (int i = 0; i < uris.length; i++) {
mediaSources[i] = buildMediaSource(uris[i], extensions[i], mainHandler, eventLogger); mediaSources[i] = buildMediaSource(uris[i], extensions[i]);
mediaSources[i].addEventListener(mainHandler, eventLogger);
} }
mediaSource = mediaSource =
mediaSources.length == 1 ? mediaSources[0] : new ConcatenatingMediaSource(mediaSources); mediaSources.length == 1 ? mediaSources[0] : new ConcatenatingMediaSource(mediaSources);
...@@ -372,11 +372,7 @@ public class PlayerActivity extends Activity ...@@ -372,11 +372,7 @@ public class PlayerActivity extends Activity
updateButtonVisibilities(); updateButtonVisibilities();
} }
private MediaSource buildMediaSource( private MediaSource buildMediaSource(Uri uri, String overrideExtension) {
Uri uri,
String overrideExtension,
@Nullable Handler handler,
@Nullable MediaSourceEventListener listener) {
@ContentType int type = TextUtils.isEmpty(overrideExtension) ? Util.inferContentType(uri) @ContentType int type = TextUtils.isEmpty(overrideExtension) ? Util.inferContentType(uri)
: Util.inferContentType("." + overrideExtension); : Util.inferContentType("." + overrideExtension);
switch (type) { switch (type) {
...@@ -384,18 +380,16 @@ public class PlayerActivity extends Activity ...@@ -384,18 +380,16 @@ public class PlayerActivity extends Activity
return new DashMediaSource.Factory( return new DashMediaSource.Factory(
new DefaultDashChunkSource.Factory(mediaDataSourceFactory), new DefaultDashChunkSource.Factory(mediaDataSourceFactory),
buildDataSourceFactory(false)) buildDataSourceFactory(false))
.createMediaSource(uri, handler, listener); .createMediaSource(uri);
case C.TYPE_SS: case C.TYPE_SS:
return new SsMediaSource.Factory( return new SsMediaSource.Factory(
new DefaultSsChunkSource.Factory(mediaDataSourceFactory), new DefaultSsChunkSource.Factory(mediaDataSourceFactory),
buildDataSourceFactory(false)) buildDataSourceFactory(false))
.createMediaSource(uri, handler, listener); .createMediaSource(uri);
case C.TYPE_HLS: case C.TYPE_HLS:
return new HlsMediaSource.Factory(mediaDataSourceFactory) return new HlsMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri);
.createMediaSource(uri, handler, listener);
case C.TYPE_OTHER: case C.TYPE_OTHER:
return new ExtractorMediaSource.Factory(mediaDataSourceFactory) return new ExtractorMediaSource.Factory(mediaDataSourceFactory).createMediaSource(uri);
.createMediaSource(uri, handler, listener);
default: { default: {
throw new IllegalStateException("Unsupported type: " + type); throw new IllegalStateException("Unsupported type: " + type);
} }
...@@ -488,10 +482,8 @@ public class PlayerActivity extends Activity ...@@ -488,10 +482,8 @@ public class PlayerActivity extends Activity
AdsMediaSource.MediaSourceFactory adMediaSourceFactory = AdsMediaSource.MediaSourceFactory adMediaSourceFactory =
new AdsMediaSource.MediaSourceFactory() { new AdsMediaSource.MediaSourceFactory() {
@Override @Override
public MediaSource createMediaSource( public MediaSource createMediaSource(Uri uri) {
Uri uri, @Nullable Handler handler, @Nullable MediaSourceEventListener listener) { return PlayerActivity.this.buildMediaSource(uri, /* overrideExtension= */ null);
return PlayerActivity.this.buildMediaSource(
uri, /* overrideExtension= */ null, handler, listener);
} }
@Override @Override
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.source; package com.google.android.exoplayer2.source;
import android.os.Handler;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
...@@ -22,7 +23,8 @@ import com.google.android.exoplayer2.util.Assertions; ...@@ -22,7 +23,8 @@ import com.google.android.exoplayer2.util.Assertions;
import java.util.ArrayList; import java.util.ArrayList;
/** /**
* Base {@link MediaSource} implementation to handle parallel reuse. * Base {@link MediaSource} implementation to handle parallel reuse and to keep a list of {@link
* MediaSourceEventListener}s.
* *
* <p>Whenever an implementing subclass needs to provide a new timeline and/or manifest, it must * <p>Whenever an implementing subclass needs to provide a new timeline and/or manifest, it must
* call {@link #refreshSourceInfo(Timeline, Object)} to notify all listeners. * call {@link #refreshSourceInfo(Timeline, Object)} to notify all listeners.
...@@ -30,6 +32,7 @@ import java.util.ArrayList; ...@@ -30,6 +32,7 @@ import java.util.ArrayList;
public abstract class BaseMediaSource implements MediaSource { public abstract class BaseMediaSource implements MediaSource {
private final ArrayList<SourceInfoRefreshListener> sourceInfoListeners; private final ArrayList<SourceInfoRefreshListener> sourceInfoListeners;
private final MediaSourceEventListener.EventDispatcher eventDispatcher;
private ExoPlayer player; private ExoPlayer player;
private Timeline timeline; private Timeline timeline;
...@@ -37,6 +40,7 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -37,6 +40,7 @@ public abstract class BaseMediaSource implements MediaSource {
public BaseMediaSource() { public BaseMediaSource() {
sourceInfoListeners = new ArrayList<>(/* initialCapacity= */ 1); sourceInfoListeners = new ArrayList<>(/* initialCapacity= */ 1);
eventDispatcher = new MediaSourceEventListener.EventDispatcher();
} }
/** /**
...@@ -70,6 +74,24 @@ public abstract class BaseMediaSource implements MediaSource { ...@@ -70,6 +74,24 @@ public abstract class BaseMediaSource implements MediaSource {
} }
} }
/**
* Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the
* registered listeners.
*/
protected final MediaSourceEventListener.EventDispatcher getEventDispatcher() {
return eventDispatcher;
}
@Override
public final void addEventListener(Handler handler, MediaSourceEventListener eventListener) {
eventDispatcher.addEventListener(handler, eventListener);
}
@Override
public final void removeEventListener(MediaSourceEventListener eventListener) {
eventDispatcher.removeEventListener(eventListener);
}
@Override @Override
public final void prepareSource( public final void prepareSource(
ExoPlayer player, boolean isTopLevelSource, SourceInfoRefreshListener listener) { ExoPlayer player, boolean isTopLevelSource, SourceInfoRefreshListener listener) {
......
...@@ -187,34 +187,38 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -187,34 +187,38 @@ public final class ExtractorMediaSource extends BaseMediaSource
} }
/** /**
* Returns a new {@link ExtractorMediaSource} using the current parameters. Media source events * Returns a new {@link ExtractorMediaSource} using the current parameters.
* will not be delivered.
* *
* @param uri The {@link Uri}. * @param uri The {@link Uri}.
* @return The new {@link ExtractorMediaSource}. * @return The new {@link ExtractorMediaSource}.
*/ */
@Override
public ExtractorMediaSource createMediaSource(Uri uri) { public ExtractorMediaSource createMediaSource(Uri uri) {
return createMediaSource(uri, null, null); isCreateCalled = true;
if (extractorsFactory == null) {
extractorsFactory = new DefaultExtractorsFactory();
}
return new ExtractorMediaSource(
uri,
dataSourceFactory,
extractorsFactory,
minLoadableRetryCount,
customCacheKey,
continueLoadingCheckIntervalBytes);
} }
/** /**
* Returns a new {@link ExtractorMediaSource} using the current parameters. * @deprecated Use {@link #createMediaSource(Uri)} and {@link #addEventListener(Handler,
* * MediaSourceEventListener)} instead.
* @param uri The {@link Uri}.
* @param eventHandler A handler for events.
* @param eventListener A listener of events.
* @return The new {@link ExtractorMediaSource}.
*/ */
@Override @Deprecated
public ExtractorMediaSource createMediaSource( public ExtractorMediaSource createMediaSource(
Uri uri, @Nullable Handler eventHandler, @Nullable MediaSourceEventListener eventListener) { Uri uri, @Nullable Handler eventHandler, @Nullable MediaSourceEventListener eventListener) {
isCreateCalled = true; ExtractorMediaSource mediaSource = createMediaSource(uri);
if (extractorsFactory == null) { if (eventHandler != null && eventListener != null) {
extractorsFactory = new DefaultExtractorsFactory(); mediaSource.addEventListener(eventHandler, eventListener);
} }
return new ExtractorMediaSource(uri, dataSourceFactory, extractorsFactory, return mediaSource;
minLoadableRetryCount, eventHandler, eventListener, customCacheKey,
continueLoadingCheckIntervalBytes);
} }
@Override @Override
...@@ -297,10 +301,11 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -297,10 +301,11 @@ public final class ExtractorMediaSource extends BaseMediaSource
dataSourceFactory, dataSourceFactory,
extractorsFactory, extractorsFactory,
minLoadableRetryCount, minLoadableRetryCount,
eventHandler,
eventListener == null ? null : new EventListenerWrapper(eventListener),
customCacheKey, customCacheKey,
continueLoadingCheckIntervalBytes); continueLoadingCheckIntervalBytes);
if (eventListener != null && eventHandler != null) {
addEventListener(eventHandler, new EventListenerWrapper(eventListener));
}
} }
private ExtractorMediaSource( private ExtractorMediaSource(
...@@ -308,15 +313,13 @@ public final class ExtractorMediaSource extends BaseMediaSource ...@@ -308,15 +313,13 @@ public final class ExtractorMediaSource extends BaseMediaSource
DataSource.Factory dataSourceFactory, DataSource.Factory dataSourceFactory,
ExtractorsFactory extractorsFactory, ExtractorsFactory extractorsFactory,
int minLoadableRetryCount, int minLoadableRetryCount,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener,
@Nullable String customCacheKey, @Nullable String customCacheKey,
int continueLoadingCheckIntervalBytes) { int continueLoadingCheckIntervalBytes) {
this.uri = uri; this.uri = uri;
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
this.extractorsFactory = extractorsFactory; this.extractorsFactory = extractorsFactory;
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
this.eventDispatcher = new EventDispatcher(eventHandler, eventListener); this.eventDispatcher = getEventDispatcher();
this.customCacheKey = customCacheKey; this.customCacheKey = customCacheKey;
this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes; this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes;
this.timelineDurationUs = C.TIME_UNSET; this.timelineDurationUs = C.TIME_UNSET;
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.source; package com.google.android.exoplayer2.source;
import android.os.Handler;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
...@@ -172,6 +173,23 @@ public interface MediaSource { ...@@ -172,6 +173,23 @@ public interface MediaSource {
} }
/** /**
* Adds a {@link MediaSourceEventListener} to the list of listeners which are notified of media
* source events.
*
* @param handler A handler on the which listener events will be posted.
* @param eventListener The listener to be added.
*/
void addEventListener(Handler handler, MediaSourceEventListener eventListener);
/**
* Removes a {@link MediaSourceEventListener} from the list of listeners which are notified of
* media source events.
*
* @param eventListener The listener to be removed.
*/
void removeEventListener(MediaSourceEventListener eventListener);
/**
* Starts source preparation if not yet started, and adds a listener for timeline and/or manifest * Starts source preparation if not yet started, and adds a listener for timeline and/or manifest
* updates. * updates.
* *
......
...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source; ...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock; import android.os.SystemClock;
import android.support.annotation.CheckResult;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
...@@ -24,6 +25,7 @@ import com.google.android.exoplayer2.Player; ...@@ -24,6 +25,7 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.CopyOnWriteArrayList;
/** Interface for callbacks to be notified of {@link MediaSource} events. */ /** Interface for callbacks to be notified of {@link MediaSource} events. */
public interface MediaSourceEventListener { public interface MediaSourceEventListener {
...@@ -190,30 +192,61 @@ public interface MediaSourceEventListener { ...@@ -190,30 +192,61 @@ public interface MediaSourceEventListener {
*/ */
void onDownstreamFormatChanged(MediaLoadData mediaLoadData); void onDownstreamFormatChanged(MediaLoadData mediaLoadData);
/** Dispatches events to a {@link MediaSourceEventListener}. */ /** Dispatches events to {@link MediaSourceEventListener}s. */
final class EventDispatcher { final class EventDispatcher {
@Nullable private final Handler handler; private final CopyOnWriteArrayList<ListenerAndHandler> listenerAndHandlers;
@Nullable private final MediaSourceEventListener listener;
private final long mediaTimeOffsetMs; private final long mediaTimeOffsetMs;
public EventDispatcher(@Nullable Handler handler, @Nullable MediaSourceEventListener listener) { /** Create event dispatcher. */
this(handler, listener, 0); /* package */ EventDispatcher() {
this(
/* listenerAndHandlers= */ new CopyOnWriteArrayList<ListenerAndHandler>(),
/* mediaTimeOffsetMs= */ 0);
} }
public EventDispatcher( private EventDispatcher(
@Nullable Handler handler, CopyOnWriteArrayList<ListenerAndHandler> listenerAndHandlers, long mediaTimeOffsetMs) {
@Nullable MediaSourceEventListener listener, this.listenerAndHandlers = listenerAndHandlers;
long mediaTimeOffsetMs) {
this.handler = listener != null ? Assertions.checkNotNull(handler) : null;
this.listener = listener;
this.mediaTimeOffsetMs = mediaTimeOffsetMs; this.mediaTimeOffsetMs = mediaTimeOffsetMs;
} }
public EventDispatcher copyWithMediaTimeOffsetMs(long mediaTimeOffsetMs) { /**
return new EventDispatcher(handler, listener, mediaTimeOffsetMs); * Creates a view of the event dispatcher with a media time offset.
*
* @param mediaTimeOffsetMs The offset to be added to all media times, in milliseconds.
* @return A view of the event dispatcher with the added media time offset.
*/
@CheckResult
public EventDispatcher withMediaTimeOffsetMs(long mediaTimeOffsetMs) {
return new EventDispatcher(listenerAndHandlers, mediaTimeOffsetMs);
}
/**
* Adds a listener to the event dispatcher.
*
* @param handler A handler on the which listener events will be posted.
* @param eventListener The listener to be added.
*/
public void addEventListener(Handler handler, MediaSourceEventListener eventListener) {
Assertions.checkArgument(handler != null && eventListener != null);
listenerAndHandlers.add(new ListenerAndHandler(handler, eventListener));
}
/**
* Removes a listener from the event dispatcher.
*
* @param eventListener The listener to be removed.
*/
public void removeEventListener(MediaSourceEventListener eventListener) {
for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
if (listenerAndHandler.listener == eventListener) {
listenerAndHandlers.remove(listenerAndHandler);
}
}
} }
/** Dispatches {@link #onLoadStarted(LoadEventInfo, MediaLoadData)}. */
public void loadStarted(DataSpec dataSpec, int dataType, long elapsedRealtimeMs) { public void loadStarted(DataSpec dataSpec, int dataType, long elapsedRealtimeMs) {
loadStarted( loadStarted(
dataSpec, dataSpec,
...@@ -238,12 +271,12 @@ public interface MediaSourceEventListener { ...@@ -238,12 +271,12 @@ public interface MediaSourceEventListener {
final long mediaStartTimeUs, final long mediaStartTimeUs,
final long mediaEndTimeUs, final long mediaEndTimeUs,
final long elapsedRealtimeMs) { final long elapsedRealtimeMs) {
if (listener != null && handler != null) { for (final ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
handler.post( listenerAndHandler.handler.post(
new Runnable() { new Runnable() {
@Override @Override
public void run() { public void run() {
listener.onLoadStarted( listenerAndHandler.listener.onLoadStarted(
new LoadEventInfo( new LoadEventInfo(
dataSpec, elapsedRealtimeMs, /* loadDurationMs= */ 0, /* bytesLoaded= */ 0), dataSpec, elapsedRealtimeMs, /* loadDurationMs= */ 0, /* bytesLoaded= */ 0),
new MediaLoadData( new MediaLoadData(
...@@ -293,12 +326,12 @@ public interface MediaSourceEventListener { ...@@ -293,12 +326,12 @@ public interface MediaSourceEventListener {
final long elapsedRealtimeMs, final long elapsedRealtimeMs,
final long loadDurationMs, final long loadDurationMs,
final long bytesLoaded) { final long bytesLoaded) {
if (listener != null && handler != null) { for (final ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
handler.post( listenerAndHandler.handler.post(
new Runnable() { new Runnable() {
@Override @Override
public void run() { public void run() {
listener.onLoadCompleted( listenerAndHandler.listener.onLoadCompleted(
new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded), new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded),
new MediaLoadData( new MediaLoadData(
dataType, dataType,
...@@ -347,12 +380,12 @@ public interface MediaSourceEventListener { ...@@ -347,12 +380,12 @@ public interface MediaSourceEventListener {
final long elapsedRealtimeMs, final long elapsedRealtimeMs,
final long loadDurationMs, final long loadDurationMs,
final long bytesLoaded) { final long bytesLoaded) {
if (listener != null && handler != null) { for (final ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
handler.post( listenerAndHandler.handler.post(
new Runnable() { new Runnable() {
@Override @Override
public void run() { public void run() {
listener.onLoadCanceled( listenerAndHandler.listener.onLoadCanceled(
new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded), new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded),
new MediaLoadData( new MediaLoadData(
dataType, dataType,
...@@ -407,12 +440,12 @@ public interface MediaSourceEventListener { ...@@ -407,12 +440,12 @@ public interface MediaSourceEventListener {
final long bytesLoaded, final long bytesLoaded,
final IOException error, final IOException error,
final boolean wasCanceled) { final boolean wasCanceled) {
if (listener != null && handler != null) { for (final ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
handler.post( listenerAndHandler.handler.post(
new Runnable() { new Runnable() {
@Override @Override
public void run() { public void run() {
listener.onLoadError( listenerAndHandler.listener.onLoadError(
new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded), new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded),
new MediaLoadData( new MediaLoadData(
dataType, dataType,
...@@ -432,12 +465,12 @@ public interface MediaSourceEventListener { ...@@ -432,12 +465,12 @@ public interface MediaSourceEventListener {
/** Dispatches {@link #onUpstreamDiscarded(MediaLoadData)}. */ /** Dispatches {@link #onUpstreamDiscarded(MediaLoadData)}. */
public void upstreamDiscarded( public void upstreamDiscarded(
final int trackType, final long mediaStartTimeUs, final long mediaEndTimeUs) { final int trackType, final long mediaStartTimeUs, final long mediaEndTimeUs) {
if (listener != null && handler != null) { for (final ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
handler.post( listenerAndHandler.handler.post(
new Runnable() { new Runnable() {
@Override @Override
public void run() { public void run() {
listener.onUpstreamDiscarded( listenerAndHandler.listener.onUpstreamDiscarded(
new MediaLoadData( new MediaLoadData(
C.DATA_TYPE_MEDIA, C.DATA_TYPE_MEDIA,
trackType, trackType,
...@@ -458,12 +491,12 @@ public interface MediaSourceEventListener { ...@@ -458,12 +491,12 @@ public interface MediaSourceEventListener {
final int trackSelectionReason, final int trackSelectionReason,
final @Nullable Object trackSelectionData, final @Nullable Object trackSelectionData,
final long mediaTimeUs) { final long mediaTimeUs) {
if (listener != null && handler != null) { for (final ListenerAndHandler listenerAndHandler : listenerAndHandlers) {
handler.post( listenerAndHandler.handler.post(
new Runnable() { new Runnable() {
@Override @Override
public void run() { public void run() {
listener.onDownstreamFormatChanged( listenerAndHandler.listener.onDownstreamFormatChanged(
new MediaLoadData( new MediaLoadData(
C.DATA_TYPE_MEDIA, C.DATA_TYPE_MEDIA,
trackType, trackType,
...@@ -481,5 +514,16 @@ public interface MediaSourceEventListener { ...@@ -481,5 +514,16 @@ public interface MediaSourceEventListener {
long mediaTimeMs = C.usToMs(mediaTimeUs); long mediaTimeMs = C.usToMs(mediaTimeUs);
return mediaTimeMs == C.TIME_UNSET ? C.TIME_UNSET : mediaTimeOffsetMs + mediaTimeMs; return mediaTimeMs == C.TIME_UNSET ? C.TIME_UNSET : mediaTimeOffsetMs + mediaTimeMs;
} }
private static final class ListenerAndHandler {
public final Handler handler;
public final MediaSourceEventListener listener;
public ListenerAndHandler(Handler handler, MediaSourceEventListener listener) {
this.handler = handler;
this.listener = listener;
}
}
} }
} }
...@@ -21,7 +21,6 @@ import android.support.annotation.Nullable; ...@@ -21,7 +21,6 @@ import android.support.annotation.Nullable;
import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.DataSpec;
...@@ -102,8 +101,7 @@ public final class SingleSampleMediaSource extends BaseMediaSource { ...@@ -102,8 +101,7 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
} }
/** /**
* Returns a new {@link ExtractorMediaSource} using the current parameters. Media source events * Returns a new {@link ExtractorMediaSource} using the current parameters.
* will not be delivered.
* *
* @param uri The {@link Uri}. * @param uri The {@link Uri}.
* @param format The {@link Format} of the media stream. * @param format The {@link Format} of the media stream.
...@@ -111,35 +109,32 @@ public final class SingleSampleMediaSource extends BaseMediaSource { ...@@ -111,35 +109,32 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
* @return The new {@link ExtractorMediaSource}. * @return The new {@link ExtractorMediaSource}.
*/ */
public SingleSampleMediaSource createMediaSource(Uri uri, Format format, long durationUs) { public SingleSampleMediaSource createMediaSource(Uri uri, Format format, long durationUs) {
return createMediaSource(uri, format, durationUs, null, null); isCreateCalled = true;
return new SingleSampleMediaSource(
uri,
dataSourceFactory,
format,
durationUs,
minLoadableRetryCount,
treatLoadErrorsAsEndOfStream);
} }
/** /**
* Returns a new {@link SingleSampleMediaSource} using the current parameters. * @deprecated Use {@link #createMediaSource(Uri, Format, long)} and {@link
* * #addEventListener(Handler, MediaSourceEventListener)} instead.
* @param uri The {@link Uri}.
* @param format The {@link Format} of the media stream.
* @param durationUs The duration of the media stream in microseconds.
* @param eventHandler A handler for events.
* @param eventListener A listener of events., Format format, long durationUs
* @return The newly built {@link SingleSampleMediaSource}.
*/ */
@Deprecated
public SingleSampleMediaSource createMediaSource( public SingleSampleMediaSource createMediaSource(
Uri uri, Uri uri,
Format format, Format format,
long durationUs, long durationUs,
@Nullable Handler eventHandler, @Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener) { @Nullable MediaSourceEventListener eventListener) {
isCreateCalled = true; SingleSampleMediaSource mediaSource = createMediaSource(uri, format, durationUs);
return new SingleSampleMediaSource( if (eventHandler != null && eventListener != null) {
uri, mediaSource.addEventListener(eventHandler, eventListener);
dataSourceFactory, }
format, return mediaSource;
durationUs,
minLoadableRetryCount,
eventHandler,
eventListener,
treatLoadErrorsAsEndOfStream);
} }
} }
...@@ -188,7 +183,13 @@ public final class SingleSampleMediaSource extends BaseMediaSource { ...@@ -188,7 +183,13 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
Format format, Format format,
long durationUs, long durationUs,
int minLoadableRetryCount) { int minLoadableRetryCount) {
this(uri, dataSourceFactory, format, durationUs, minLoadableRetryCount, null, null, false); this(
uri,
dataSourceFactory,
format,
durationUs,
minLoadableRetryCount,
/* treatLoadErrorsAsEndOfStream= */ false);
} }
/** /**
...@@ -223,9 +224,10 @@ public final class SingleSampleMediaSource extends BaseMediaSource { ...@@ -223,9 +224,10 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
format, format,
durationUs, durationUs,
minLoadableRetryCount, minLoadableRetryCount,
eventHandler,
eventListener == null ? null : new EventListenerWrapper(eventListener, eventSourceId),
treatLoadErrorsAsEndOfStream); treatLoadErrorsAsEndOfStream);
if (eventHandler != null && eventListener != null) {
addEventListener(eventHandler, new EventListenerWrapper(eventListener, eventSourceId));
}
} }
private SingleSampleMediaSource( private SingleSampleMediaSource(
...@@ -234,15 +236,13 @@ public final class SingleSampleMediaSource extends BaseMediaSource { ...@@ -234,15 +236,13 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
Format format, Format format,
long durationUs, long durationUs,
int minLoadableRetryCount, int minLoadableRetryCount,
Handler eventHandler,
MediaSourceEventListener eventListener,
boolean treatLoadErrorsAsEndOfStream) { boolean treatLoadErrorsAsEndOfStream) {
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
this.format = format; this.format = format;
this.durationUs = durationUs; this.durationUs = durationUs;
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
this.treatLoadErrorsAsEndOfStream = treatLoadErrorsAsEndOfStream; this.treatLoadErrorsAsEndOfStream = treatLoadErrorsAsEndOfStream;
this.eventDispatcher = new EventDispatcher(eventHandler, eventListener); this.eventDispatcher = getEventDispatcher();
dataSpec = new DataSpec(uri); dataSpec = new DataSpec(uri);
timeline = new SinglePeriodTimeline(durationUs, true, false); timeline = new SinglePeriodTimeline(durationUs, true, false);
} }
......
...@@ -51,13 +51,9 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> { ...@@ -51,13 +51,9 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
* Creates a new {@link MediaSource} for loading the ad media with the specified {@code uri}. * Creates a new {@link MediaSource} for loading the ad media with the specified {@code uri}.
* *
* @param uri The URI of the media or manifest to play. * @param uri The URI of the media or manifest to play.
* @param handler A handler for listener events. May be null if delivery of events is not
* required.
* @param listener A listener for events. May be null if delivery of events is not required.
* @return The new media source. * @return The new media source.
*/ */
MediaSource createMediaSource( MediaSource createMediaSource(Uri uri);
Uri uri, @Nullable Handler handler, @Nullable MediaSourceEventListener listener);
/** /**
* Returns the content types supported by media sources created by this factory. Each element * Returns the content types supported by media sources created by this factory. Each element
...@@ -224,8 +220,8 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> { ...@@ -224,8 +220,8 @@ public final class AdsMediaSource extends CompositeMediaSource<MediaPeriodId> {
int adIndexInAdGroup = id.adIndexInAdGroup; int adIndexInAdGroup = id.adIndexInAdGroup;
if (adGroupMediaSources[adGroupIndex].length <= adIndexInAdGroup) { if (adGroupMediaSources[adGroupIndex].length <= adIndexInAdGroup) {
Uri adUri = adPlaybackState.adGroups[id.adGroupIndex].uris[id.adIndexInAdGroup]; Uri adUri = adPlaybackState.adGroups[id.adGroupIndex].uris[id.adIndexInAdGroup];
MediaSource adMediaSource = MediaSource adMediaSource = adMediaSourceFactory.createMediaSource(adUri);
adMediaSourceFactory.createMediaSource(adUri, eventHandler, eventListener); adMediaSource.addEventListener(eventHandler, eventListener);
int oldAdCount = adGroupMediaSources[id.adGroupIndex].length; int oldAdCount = adGroupMediaSources[id.adGroupIndex].length;
if (adIndexInAdGroup >= oldAdCount) { if (adIndexInAdGroup >= oldAdCount) {
int adCount = adIndexInAdGroup + 1; int adCount = adIndexInAdGroup + 1;
......
...@@ -167,15 +167,10 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -167,15 +167,10 @@ public final class DashMediaSource extends BaseMediaSource {
* sideloaded manifest. * sideloaded manifest.
* *
* @param manifest The manifest. {@link DashManifest#dynamic} must be false. * @param manifest The manifest. {@link DashManifest#dynamic} must be false.
* @param eventHandler A handler for events.
* @param eventListener A listener of events.
* @return The new {@link DashMediaSource}. * @return The new {@link DashMediaSource}.
* @throws IllegalArgumentException If {@link DashManifest#dynamic} is true. * @throws IllegalArgumentException If {@link DashManifest#dynamic} is true.
*/ */
public DashMediaSource createMediaSource( public DashMediaSource createMediaSource(DashManifest manifest) {
DashManifest manifest,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener) {
Assertions.checkArgument(!manifest.dynamic); Assertions.checkArgument(!manifest.dynamic);
isCreateCalled = true; isCreateCalled = true;
return new DashMediaSource( return new DashMediaSource(
...@@ -186,35 +181,33 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -186,35 +181,33 @@ public final class DashMediaSource extends BaseMediaSource {
chunkSourceFactory, chunkSourceFactory,
compositeSequenceableLoaderFactory, compositeSequenceableLoaderFactory,
minLoadableRetryCount, minLoadableRetryCount,
livePresentationDelayMs, livePresentationDelayMs);
eventHandler,
eventListener);
} }
/** /**
* Returns a new {@link DashMediaSource} using the current parameters. Media source events will * @deprecated Use {@link #createMediaSource(DashManifest)} and {@link
* not be delivered. * #addEventListener(Handler, MediaSourceEventListener)} instead.
*
* @param manifestUri The manifest {@link Uri}.
* @return The new {@link DashMediaSource}.
*/ */
public DashMediaSource createMediaSource(Uri manifestUri) { @Deprecated
return createMediaSource(manifestUri, null, null); public DashMediaSource createMediaSource(
DashManifest manifest,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener) {
DashMediaSource mediaSource = createMediaSource(manifest);
if (eventHandler != null && eventListener != null) {
mediaSource.addEventListener(eventHandler, eventListener);
}
return mediaSource;
} }
/** /**
* Returns a new {@link DashMediaSource} using the current parameters. * Returns a new {@link DashMediaSource} using the current parameters.
* *
* @param manifestUri The manifest {@link Uri}. * @param manifestUri The manifest {@link Uri}.
* @param eventHandler A handler for events.
* @param eventListener A listener of events.
* @return The new {@link DashMediaSource}. * @return The new {@link DashMediaSource}.
*/ */
@Override @Override
public DashMediaSource createMediaSource( public DashMediaSource createMediaSource(Uri manifestUri) {
Uri manifestUri,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener) {
isCreateCalled = true; isCreateCalled = true;
if (manifestParser == null) { if (manifestParser == null) {
manifestParser = new DashManifestParser(); manifestParser = new DashManifestParser();
...@@ -227,9 +220,23 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -227,9 +220,23 @@ public final class DashMediaSource extends BaseMediaSource {
chunkSourceFactory, chunkSourceFactory,
compositeSequenceableLoaderFactory, compositeSequenceableLoaderFactory,
minLoadableRetryCount, minLoadableRetryCount,
livePresentationDelayMs, livePresentationDelayMs);
eventHandler, }
eventListener);
/**
* @deprecated Use {@link #createMediaSource(Uri)} and {@link #addEventListener(Handler,
* MediaSourceEventListener)} instead.
*/
@Deprecated
public DashMediaSource createMediaSource(
Uri manifestUri,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener) {
DashMediaSource mediaSource = createMediaSource(manifestUri);
if (eventHandler != null && eventListener != null) {
mediaSource.addEventListener(eventHandler, eventListener);
}
return mediaSource;
} }
@Override @Override
...@@ -340,9 +347,18 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -340,9 +347,18 @@ public final class DashMediaSource extends BaseMediaSource {
int minLoadableRetryCount, int minLoadableRetryCount,
Handler eventHandler, Handler eventHandler,
MediaSourceEventListener eventListener) { MediaSourceEventListener eventListener) {
this(manifest, null, null, null, chunkSourceFactory, this(
new DefaultCompositeSequenceableLoaderFactory(), minLoadableRetryCount, manifest,
DEFAULT_LIVE_PRESENTATION_DELAY_PREFER_MANIFEST_MS, eventHandler, eventListener); null,
null,
null,
chunkSourceFactory,
new DefaultCompositeSequenceableLoaderFactory(),
minLoadableRetryCount,
DEFAULT_LIVE_PRESENTATION_DELAY_PREFER_MANIFEST_MS);
if (eventHandler != null && eventListener != null) {
addEventListener(eventHandler, eventListener);
}
} }
/** /**
...@@ -427,9 +443,18 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -427,9 +443,18 @@ public final class DashMediaSource extends BaseMediaSource {
long livePresentationDelayMs, long livePresentationDelayMs,
Handler eventHandler, Handler eventHandler,
MediaSourceEventListener eventListener) { MediaSourceEventListener eventListener) {
this(null, manifestUri, manifestDataSourceFactory, manifestParser, chunkSourceFactory, this(
new DefaultCompositeSequenceableLoaderFactory(), minLoadableRetryCount, null,
livePresentationDelayMs, eventHandler, eventListener); manifestUri,
manifestDataSourceFactory,
manifestParser,
chunkSourceFactory,
new DefaultCompositeSequenceableLoaderFactory(),
minLoadableRetryCount,
livePresentationDelayMs);
if (eventHandler != null && eventListener != null) {
addEventListener(eventHandler, eventListener);
}
} }
private DashMediaSource( private DashMediaSource(
...@@ -440,9 +465,7 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -440,9 +465,7 @@ public final class DashMediaSource extends BaseMediaSource {
DashChunkSource.Factory chunkSourceFactory, DashChunkSource.Factory chunkSourceFactory,
CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory, CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory,
int minLoadableRetryCount, int minLoadableRetryCount,
long livePresentationDelayMs, long livePresentationDelayMs) {
Handler eventHandler,
MediaSourceEventListener eventListener) {
this.initialManifestUri = manifestUri; this.initialManifestUri = manifestUri;
this.manifest = manifest; this.manifest = manifest;
this.manifestUri = manifestUri; this.manifestUri = manifestUri;
...@@ -453,7 +476,7 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -453,7 +476,7 @@ public final class DashMediaSource extends BaseMediaSource {
this.livePresentationDelayMs = livePresentationDelayMs; this.livePresentationDelayMs = livePresentationDelayMs;
this.compositeSequenceableLoaderFactory = compositeSequenceableLoaderFactory; this.compositeSequenceableLoaderFactory = compositeSequenceableLoaderFactory;
sideloadedManifest = manifest != null; sideloadedManifest = manifest != null;
eventDispatcher = new EventDispatcher(eventHandler, eventListener); eventDispatcher = getEventDispatcher();
manifestUriLock = new Object(); manifestUriLock = new Object();
periodsById = new SparseArray<>(); periodsById = new SparseArray<>();
playerEmsgCallback = new DefaultPlayerEmsgCallback(); playerEmsgCallback = new DefaultPlayerEmsgCallback();
...@@ -516,8 +539,8 @@ public final class DashMediaSource extends BaseMediaSource { ...@@ -516,8 +539,8 @@ public final class DashMediaSource extends BaseMediaSource {
@Override @Override
public MediaPeriod createPeriod(MediaPeriodId periodId, Allocator allocator) { public MediaPeriod createPeriod(MediaPeriodId periodId, Allocator allocator) {
int periodIndex = periodId.periodIndex; int periodIndex = periodId.periodIndex;
EventDispatcher periodEventDispatcher = eventDispatcher.copyWithMediaTimeOffsetMs( EventDispatcher periodEventDispatcher =
manifest.getPeriod(periodIndex).startMs); eventDispatcher.withMediaTimeOffsetMs(manifest.getPeriod(periodIndex).startMs);
DashMediaPeriod mediaPeriod = DashMediaPeriod mediaPeriod =
new DashMediaPeriod( new DashMediaPeriod(
firstPeriodId + periodIndex, firstPeriodId + periodIndex,
......
...@@ -164,28 +164,12 @@ public final class HlsMediaSource extends BaseMediaSource ...@@ -164,28 +164,12 @@ public final class HlsMediaSource extends BaseMediaSource
} }
/** /**
* Returns a new {@link HlsMediaSource} using the current parameters. Media source events will
* not be delivered.
*
* @return The new {@link HlsMediaSource}.
*/
public HlsMediaSource createMediaSource(Uri playlistUri) {
return createMediaSource(playlistUri, null, null);
}
/**
* Returns a new {@link HlsMediaSource} using the current parameters. * Returns a new {@link HlsMediaSource} using the current parameters.
* *
* @param playlistUri The playlist {@link Uri}.
* @param eventHandler A handler for events.
* @param eventListener A listener of events.
* @return The new {@link HlsMediaSource}. * @return The new {@link HlsMediaSource}.
*/ */
@Override @Override
public HlsMediaSource createMediaSource( public HlsMediaSource createMediaSource(Uri playlistUri) {
Uri playlistUri,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener) {
isCreateCalled = true; isCreateCalled = true;
if (playlistParser == null) { if (playlistParser == null) {
playlistParser = new HlsPlaylistParser(); playlistParser = new HlsPlaylistParser();
...@@ -196,12 +180,26 @@ public final class HlsMediaSource extends BaseMediaSource ...@@ -196,12 +180,26 @@ public final class HlsMediaSource extends BaseMediaSource
extractorFactory, extractorFactory,
compositeSequenceableLoaderFactory, compositeSequenceableLoaderFactory,
minLoadableRetryCount, minLoadableRetryCount,
eventHandler,
eventListener,
playlistParser, playlistParser,
allowChunklessPreparation); allowChunklessPreparation);
} }
/**
* @deprecated Use {@link #createMediaSource(Uri)} and {@link #addEventListener(Handler,
* MediaSourceEventListener)} instead.
*/
@Deprecated
public HlsMediaSource createMediaSource(
Uri playlistUri,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener) {
HlsMediaSource mediaSource = createMediaSource(playlistUri);
if (eventHandler != null && eventListener != null) {
mediaSource.addEventListener(eventHandler, eventListener);
}
return mediaSource;
}
@Override @Override
public int[] getSupportedTypes() { public int[] getSupportedTypes() {
return new int[] {C.TYPE_HLS}; return new int[] {C.TYPE_HLS};
...@@ -294,10 +292,11 @@ public final class HlsMediaSource extends BaseMediaSource ...@@ -294,10 +292,11 @@ public final class HlsMediaSource extends BaseMediaSource
extractorFactory, extractorFactory,
new DefaultCompositeSequenceableLoaderFactory(), new DefaultCompositeSequenceableLoaderFactory(),
minLoadableRetryCount, minLoadableRetryCount,
eventHandler,
eventListener,
playlistParser, playlistParser,
false); false);
if (eventHandler != null && eventListener != null) {
addEventListener(eventHandler, eventListener);
}
} }
private HlsMediaSource( private HlsMediaSource(
...@@ -306,8 +305,6 @@ public final class HlsMediaSource extends BaseMediaSource ...@@ -306,8 +305,6 @@ public final class HlsMediaSource extends BaseMediaSource
HlsExtractorFactory extractorFactory, HlsExtractorFactory extractorFactory,
CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory, CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory,
int minLoadableRetryCount, int minLoadableRetryCount,
Handler eventHandler,
MediaSourceEventListener eventListener,
ParsingLoadable.Parser<HlsPlaylist> playlistParser, ParsingLoadable.Parser<HlsPlaylist> playlistParser,
boolean allowChunklessPreparation) { boolean allowChunklessPreparation) {
this.manifestUri = manifestUri; this.manifestUri = manifestUri;
...@@ -317,7 +314,7 @@ public final class HlsMediaSource extends BaseMediaSource ...@@ -317,7 +314,7 @@ public final class HlsMediaSource extends BaseMediaSource
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
this.playlistParser = playlistParser; this.playlistParser = playlistParser;
this.allowChunklessPreparation = allowChunklessPreparation; this.allowChunklessPreparation = allowChunklessPreparation;
eventDispatcher = new EventDispatcher(eventHandler, eventListener); eventDispatcher = getEventDispatcher();
} }
@Override @Override
......
...@@ -153,15 +153,10 @@ public final class SsMediaSource extends BaseMediaSource ...@@ -153,15 +153,10 @@ public final class SsMediaSource extends BaseMediaSource
* manifest. * manifest.
* *
* @param manifest The manifest. {@link SsManifest#isLive} must be false. * @param manifest The manifest. {@link SsManifest#isLive} must be false.
* @param eventHandler A handler for events.
* @param eventListener A listener of events.
* @return The new {@link SsMediaSource}. * @return The new {@link SsMediaSource}.
* @throws IllegalArgumentException If {@link SsManifest#isLive} is true. * @throws IllegalArgumentException If {@link SsManifest#isLive} is true.
*/ */
public SsMediaSource createMediaSource( public SsMediaSource createMediaSource(SsManifest manifest) {
SsManifest manifest,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener) {
Assertions.checkArgument(!manifest.isLive); Assertions.checkArgument(!manifest.isLive);
isCreateCalled = true; isCreateCalled = true;
return new SsMediaSource( return new SsMediaSource(
...@@ -172,35 +167,33 @@ public final class SsMediaSource extends BaseMediaSource ...@@ -172,35 +167,33 @@ public final class SsMediaSource extends BaseMediaSource
chunkSourceFactory, chunkSourceFactory,
compositeSequenceableLoaderFactory, compositeSequenceableLoaderFactory,
minLoadableRetryCount, minLoadableRetryCount,
livePresentationDelayMs, livePresentationDelayMs);
eventHandler,
eventListener);
} }
/** /**
* Returns a new {@link SsMediaSource} using the current parameters. Media source events will * @deprecated Use {@link #createMediaSource(SsManifest)} and {@link #addEventListener(Handler,
* not be delivered. * MediaSourceEventListener)} instead.
*
* @param manifestUri The manifest {@link Uri}.
* @return The new {@link SsMediaSource}.
*/ */
public SsMediaSource createMediaSource(Uri manifestUri) { @Deprecated
return createMediaSource(manifestUri, null, null); public SsMediaSource createMediaSource(
SsManifest manifest,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener) {
SsMediaSource mediaSource = createMediaSource(manifest);
if (eventHandler != null && eventListener != null) {
mediaSource.addEventListener(eventHandler, eventListener);
}
return mediaSource;
} }
/** /**
* Returns a new {@link SsMediaSource} using the current parameters. * Returns a new {@link SsMediaSource} using the current parameters.
* *
* @param manifestUri The manifest {@link Uri}. * @param manifestUri The manifest {@link Uri}.
* @param eventHandler A handler for events.
* @param eventListener A listener of events.
* @return The new {@link SsMediaSource}. * @return The new {@link SsMediaSource}.
*/ */
@Override @Override
public SsMediaSource createMediaSource( public SsMediaSource createMediaSource(Uri manifestUri) {
Uri manifestUri,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener) {
isCreateCalled = true; isCreateCalled = true;
if (manifestParser == null) { if (manifestParser == null) {
manifestParser = new SsManifestParser(); manifestParser = new SsManifestParser();
...@@ -213,9 +206,23 @@ public final class SsMediaSource extends BaseMediaSource ...@@ -213,9 +206,23 @@ public final class SsMediaSource extends BaseMediaSource
chunkSourceFactory, chunkSourceFactory,
compositeSequenceableLoaderFactory, compositeSequenceableLoaderFactory,
minLoadableRetryCount, minLoadableRetryCount,
livePresentationDelayMs, livePresentationDelayMs);
eventHandler, }
eventListener);
/**
* @deprecated Use {@link #createMediaSource(Uri)} and {@link #addEventListener(Handler,
* MediaSourceEventListener)} instead.
*/
@Deprecated
public SsMediaSource createMediaSource(
Uri manifestUri,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener) {
SsMediaSource mediaSource = createMediaSource(manifestUri);
if (eventHandler != null && eventListener != null) {
mediaSource.addEventListener(eventHandler, eventListener);
}
return mediaSource;
} }
@Override @Override
...@@ -300,9 +307,18 @@ public final class SsMediaSource extends BaseMediaSource ...@@ -300,9 +307,18 @@ public final class SsMediaSource extends BaseMediaSource
int minLoadableRetryCount, int minLoadableRetryCount,
Handler eventHandler, Handler eventHandler,
MediaSourceEventListener eventListener) { MediaSourceEventListener eventListener) {
this(manifest, null, null, null, chunkSourceFactory, this(
new DefaultCompositeSequenceableLoaderFactory(), minLoadableRetryCount, manifest,
DEFAULT_LIVE_PRESENTATION_DELAY_MS, eventHandler, eventListener); null,
null,
null,
chunkSourceFactory,
new DefaultCompositeSequenceableLoaderFactory(),
minLoadableRetryCount,
DEFAULT_LIVE_PRESENTATION_DELAY_MS);
if (eventHandler != null && eventListener != null) {
addEventListener(eventHandler, eventListener);
}
} }
/** /**
...@@ -383,9 +399,18 @@ public final class SsMediaSource extends BaseMediaSource ...@@ -383,9 +399,18 @@ public final class SsMediaSource extends BaseMediaSource
long livePresentationDelayMs, long livePresentationDelayMs,
Handler eventHandler, Handler eventHandler,
MediaSourceEventListener eventListener) { MediaSourceEventListener eventListener) {
this(null, manifestUri, manifestDataSourceFactory, manifestParser, chunkSourceFactory, this(
new DefaultCompositeSequenceableLoaderFactory(), minLoadableRetryCount, null,
livePresentationDelayMs, eventHandler, eventListener); manifestUri,
manifestDataSourceFactory,
manifestParser,
chunkSourceFactory,
new DefaultCompositeSequenceableLoaderFactory(),
minLoadableRetryCount,
livePresentationDelayMs);
if (eventHandler != null && eventListener != null) {
addEventListener(eventHandler, eventListener);
}
} }
private SsMediaSource( private SsMediaSource(
...@@ -396,9 +421,7 @@ public final class SsMediaSource extends BaseMediaSource ...@@ -396,9 +421,7 @@ public final class SsMediaSource extends BaseMediaSource
SsChunkSource.Factory chunkSourceFactory, SsChunkSource.Factory chunkSourceFactory,
CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory, CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory,
int minLoadableRetryCount, int minLoadableRetryCount,
long livePresentationDelayMs, long livePresentationDelayMs) {
Handler eventHandler,
MediaSourceEventListener eventListener) {
Assertions.checkState(manifest == null || !manifest.isLive); Assertions.checkState(manifest == null || !manifest.isLive);
this.manifest = manifest; this.manifest = manifest;
this.manifestUri = manifestUri == null ? null : SsUtil.fixManifestUri(manifestUri); this.manifestUri = manifestUri == null ? null : SsUtil.fixManifestUri(manifestUri);
...@@ -408,7 +431,7 @@ public final class SsMediaSource extends BaseMediaSource ...@@ -408,7 +431,7 @@ public final class SsMediaSource extends BaseMediaSource
this.compositeSequenceableLoaderFactory = compositeSequenceableLoaderFactory; this.compositeSequenceableLoaderFactory = compositeSequenceableLoaderFactory;
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
this.livePresentationDelayMs = livePresentationDelayMs; this.livePresentationDelayMs = livePresentationDelayMs;
this.eventDispatcher = new EventDispatcher(eventHandler, eventListener); this.eventDispatcher = getEventDispatcher();
sideloadedManifest = manifest != null; sideloadedManifest = manifest != null;
mediaPeriods = new ArrayList<>(); mediaPeriods = new ArrayList<>();
} }
......
...@@ -20,7 +20,6 @@ import com.google.android.exoplayer2.Timeline; ...@@ -20,7 +20,6 @@ import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period; import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceEventListener; import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
...@@ -30,7 +29,6 @@ import com.google.android.exoplayer2.upstream.Allocator; ...@@ -30,7 +29,6 @@ import com.google.android.exoplayer2.upstream.Allocator;
*/ */
public class FakeAdaptiveMediaSource extends FakeMediaSource { public class FakeAdaptiveMediaSource extends FakeMediaSource {
private final EventDispatcher eventDispatcher;
private final FakeChunkSource.Factory chunkSourceFactory; private final FakeChunkSource.Factory chunkSourceFactory;
public FakeAdaptiveMediaSource( public FakeAdaptiveMediaSource(
...@@ -41,16 +39,16 @@ public class FakeAdaptiveMediaSource extends FakeMediaSource { ...@@ -41,16 +39,16 @@ public class FakeAdaptiveMediaSource extends FakeMediaSource {
MediaSourceEventListener eventListener, MediaSourceEventListener eventListener,
FakeChunkSource.Factory chunkSourceFactory) { FakeChunkSource.Factory chunkSourceFactory) {
super(timeline, manifest, trackGroupArray); super(timeline, manifest, trackGroupArray);
this.eventDispatcher = new EventDispatcher(eventHandler, eventListener);
this.chunkSourceFactory = chunkSourceFactory; this.chunkSourceFactory = chunkSourceFactory;
addEventListener(eventHandler, eventListener);
} }
@Override @Override
protected FakeMediaPeriod createFakeMediaPeriod(MediaPeriodId id, TrackGroupArray trackGroupArray, protected FakeMediaPeriod createFakeMediaPeriod(MediaPeriodId id, TrackGroupArray trackGroupArray,
Allocator allocator) { Allocator allocator) {
Period period = timeline.getPeriod(id.periodIndex, new Period()); Period period = timeline.getPeriod(id.periodIndex, new Period());
return new FakeAdaptiveMediaPeriod(trackGroupArray, eventDispatcher, allocator, return new FakeAdaptiveMediaPeriod(
chunkSourceFactory, period.durationUs); trackGroupArray, getEventDispatcher(), allocator, chunkSourceFactory, period.durationUs);
} }
} }
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