Commit fbccdf59 by andrewlewis Committed by Oliver Woodman

Use AdaptiveMediaSourceEventListener for ExtractorMediaSource

This is a step towards harmonizing the MediaSource Builders and (potentially)
providing MediaSource factories.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=177783157
parent 03b0d9d4
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
* Add optional parameter to `Player.stop` to reset the player when stopping. * Add optional parameter to `Player.stop` to reset the player when stopping.
* Fix handling of playback parameters changes while paused when followed by a * Fix handling of playback parameters changes while paused when followed by a
seek. seek.
* Use the same listener `MediaSourceEventListener` for all MediaSource
implementations.
### 2.6.0 ### ### 2.6.0 ###
......
...@@ -39,7 +39,6 @@ import com.google.android.exoplayer2.metadata.id3.PrivFrame; ...@@ -39,7 +39,6 @@ import com.google.android.exoplayer2.metadata.id3.PrivFrame;
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame; import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
import com.google.android.exoplayer2.metadata.id3.UrlLinkFrame; import com.google.android.exoplayer2.metadata.id3.UrlLinkFrame;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener; import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.ads.AdsMediaSource; import com.google.android.exoplayer2.source.ads.AdsMediaSource;
...@@ -53,12 +52,14 @@ import java.io.IOException; ...@@ -53,12 +52,14 @@ import java.io.IOException;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.Locale; import java.util.Locale;
/** /** Logs player events using {@link Log}. */
* Logs player events using {@link Log}. /* package */ final class EventLogger
*/ implements Player.EventListener,
/* package */ final class EventLogger implements Player.EventListener, MetadataOutput, MetadataOutput,
AudioRendererEventListener, VideoRendererEventListener, AdaptiveMediaSourceEventListener, AudioRendererEventListener,
ExtractorMediaSource.EventListener, AdsMediaSource.AdsListener, VideoRendererEventListener,
AdaptiveMediaSourceEventListener,
AdsMediaSource.EventListener,
DefaultDrmSessionManager.EventListener { DefaultDrmSessionManager.EventListener {
private static final String TAG = "EventLogger"; private static final String TAG = "EventLogger";
...@@ -324,13 +325,6 @@ import java.util.Locale; ...@@ -324,13 +325,6 @@ import java.util.Locale;
Log.d(TAG, "drmKeysLoaded [" + getSessionTimeString() + "]"); Log.d(TAG, "drmKeysLoaded [" + getSessionTimeString() + "]");
} }
// ExtractorMediaSource.EventListener
@Override
public void onLoadError(IOException error) {
printInternalError("loadError", error);
}
// AdaptiveMediaSourceEventListener // AdaptiveMediaSourceEventListener
@Override @Override
......
...@@ -52,8 +52,8 @@ public final class ImaAdsMediaSource implements MediaSource { ...@@ -52,8 +52,8 @@ public final class ImaAdsMediaSource implements MediaSource {
} }
/** /**
* Constructs a new source that inserts ads linearly with the content specified by * Constructs a new source that inserts ads linearly with the content specified by {@code
* {@code contentMediaSource}. * contentMediaSource}.
* *
* @param contentMediaSource The {@link MediaSource} providing the content to play. * @param contentMediaSource The {@link MediaSource} providing the content to play.
* @param dataSourceFactory Factory for data sources used to load ad media. * @param dataSourceFactory Factory for data sources used to load ad media.
...@@ -62,9 +62,13 @@ public final class ImaAdsMediaSource implements MediaSource { ...@@ -62,9 +62,13 @@ public final class ImaAdsMediaSource implements MediaSource {
* @param eventHandler A handler for events. May be null if delivery of events is not required. * @param eventHandler A handler for events. May be null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
*/ */
public ImaAdsMediaSource(MediaSource contentMediaSource, DataSource.Factory dataSourceFactory, public ImaAdsMediaSource(
ImaAdsLoader imaAdsLoader, ViewGroup adUiViewGroup, @Nullable Handler eventHandler, MediaSource contentMediaSource,
@Nullable AdsMediaSource.AdsListener eventListener) { DataSource.Factory dataSourceFactory,
ImaAdsLoader imaAdsLoader,
ViewGroup adUiViewGroup,
@Nullable Handler eventHandler,
@Nullable AdsMediaSource.EventListener eventListener) {
adsMediaSource = new AdsMediaSource(contentMediaSource, dataSourceFactory, imaAdsLoader, adsMediaSource = new AdsMediaSource(contentMediaSource, dataSourceFactory, imaAdsLoader,
adUiViewGroup, eventHandler, eventListener); adUiViewGroup, eventHandler, eventListener);
} }
......
...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source; ...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.source;
import android.net.Uri; import android.net.Uri;
import android.os.Handler; 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.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.FormatHolder; import com.google.android.exoplayer2.FormatHolder;
...@@ -28,6 +29,7 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput; ...@@ -28,6 +29,7 @@ import com.google.android.exoplayer2.extractor.ExtractorOutput;
import com.google.android.exoplayer2.extractor.PositionHolder; import com.google.android.exoplayer2.extractor.PositionHolder;
import com.google.android.exoplayer2.extractor.SeekMap; import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.extractor.TrackOutput; import com.google.android.exoplayer2.extractor.TrackOutput;
import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener; import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener;
import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator; import com.google.android.exoplayer2.upstream.Allocator;
...@@ -74,11 +76,10 @@ import java.util.Arrays; ...@@ -74,11 +76,10 @@ import java.util.Arrays;
private final Uri uri; private final Uri uri;
private final DataSource dataSource; private final DataSource dataSource;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final Handler eventHandler; private final EventDispatcher eventDispatcher;
private final ExtractorMediaSource.EventListener eventListener;
private final Listener listener; private final Listener listener;
private final Allocator allocator; private final Allocator allocator;
private final String customCacheKey; @Nullable private final String customCacheKey;
private final long continueLoadingCheckIntervalBytes; private final long continueLoadingCheckIntervalBytes;
private final Loader loader; private final Loader loader;
private final ExtractorHolder extractorHolder; private final ExtractorHolder extractorHolder;
...@@ -117,8 +118,7 @@ import java.util.Arrays; ...@@ -117,8 +118,7 @@ import java.util.Arrays;
* @param dataSource The data source to read the media. * @param dataSource The data source to read the media.
* @param extractors The extractors to use to read the data source. * @param extractors The extractors to use to read the data source.
* @param minLoadableRetryCount The minimum number of times to retry if a loading error occurs. * @param minLoadableRetryCount The minimum number of times to retry if a loading error occurs.
* @param eventHandler A handler for events. May be null if delivery of events is not required. * @param eventDispatcher A dispatcher to notify of events.
* @param eventListener A listener of events. May be null if delivery of events is not required.
* @param listener A listener to notify when information about the period changes. * @param listener A listener to notify when information about the period changes.
* @param allocator An {@link Allocator} from which to obtain media buffer allocations. * @param allocator An {@link Allocator} from which to obtain media buffer allocations.
* @param customCacheKey A custom key that uniquely identifies the original stream. Used for cache * @param customCacheKey A custom key that uniquely identifies the original stream. Used for cache
...@@ -126,15 +126,20 @@ import java.util.Arrays; ...@@ -126,15 +126,20 @@ import java.util.Arrays;
* @param continueLoadingCheckIntervalBytes The number of bytes that should be loaded between each * @param continueLoadingCheckIntervalBytes The number of bytes that should be loaded between each
* invocation of {@link Callback#onContinueLoadingRequested(SequenceableLoader)}. * invocation of {@link Callback#onContinueLoadingRequested(SequenceableLoader)}.
*/ */
public ExtractorMediaPeriod(Uri uri, DataSource dataSource, Extractor[] extractors, public ExtractorMediaPeriod(
int minLoadableRetryCount, Handler eventHandler, Uri uri,
ExtractorMediaSource.EventListener eventListener, Listener listener, DataSource dataSource,
Allocator allocator, String customCacheKey, int continueLoadingCheckIntervalBytes) { Extractor[] extractors,
int minLoadableRetryCount,
EventDispatcher eventDispatcher,
Listener listener,
Allocator allocator,
@Nullable String customCacheKey,
int continueLoadingCheckIntervalBytes) {
this.uri = uri; this.uri = uri;
this.dataSource = dataSource; this.dataSource = dataSource;
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
this.eventHandler = eventHandler; this.eventDispatcher = eventDispatcher;
this.eventListener = eventListener;
this.listener = listener; this.listener = listener;
this.allocator = allocator; this.allocator = allocator;
this.customCacheKey = customCacheKey; this.customCacheKey = customCacheKey;
...@@ -430,8 +435,22 @@ import java.util.Arrays; ...@@ -430,8 +435,22 @@ import java.util.Arrays;
public int onLoadError(ExtractingLoadable loadable, long elapsedRealtimeMs, public int onLoadError(ExtractingLoadable loadable, long elapsedRealtimeMs,
long loadDurationMs, IOException error) { long loadDurationMs, IOException error) {
copyLengthFromLoader(loadable); copyLengthFromLoader(loadable);
notifyLoadError(error); boolean isErrorFatal = isLoadableExceptionFatal(error);
if (isLoadableExceptionFatal(error)) { eventDispatcher.loadError(
loadable.dataSpec,
C.DATA_TYPE_MEDIA,
C.TRACK_TYPE_UNKNOWN,
/* trackFormat= */ null,
C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null,
/* mediaStartTimeUs= */ 0,
durationUs,
elapsedRealtimeMs,
loadDurationMs,
loadable.bytesLoaded,
error,
/* wasCanceled= */ isErrorFatal);
if (isErrorFatal) {
return Loader.DONT_RETRY_FATAL; return Loader.DONT_RETRY_FATAL;
} }
int extractedSamplesCount = getExtractedSamplesCount(); int extractedSamplesCount = getExtractedSamplesCount();
...@@ -606,17 +625,6 @@ import java.util.Arrays; ...@@ -606,17 +625,6 @@ import java.util.Arrays;
return e instanceof UnrecognizedInputFormatException; return e instanceof UnrecognizedInputFormatException;
} }
private void notifyLoadError(final IOException error) {
if (eventHandler != null && eventListener != null) {
eventHandler.post(new Runnable() {
@Override
public void run() {
eventListener.onLoadError(error);
}
});
}
}
private final class SampleStreamImpl implements SampleStream { private final class SampleStreamImpl implements SampleStream {
private final int track; private final int track;
...@@ -663,7 +671,9 @@ import java.util.Arrays; ...@@ -663,7 +671,9 @@ import java.util.Arrays;
private boolean pendingExtractorSeek; private boolean pendingExtractorSeek;
private long seekTimeUs; private long seekTimeUs;
private DataSpec dataSpec;
private long length; private long length;
private long bytesLoaded;
public ExtractingLoadable(Uri uri, DataSource dataSource, ExtractorHolder extractorHolder, public ExtractingLoadable(Uri uri, DataSource dataSource, ExtractorHolder extractorHolder,
ConditionVariable loadCondition) { ConditionVariable loadCondition) {
...@@ -699,7 +709,8 @@ import java.util.Arrays; ...@@ -699,7 +709,8 @@ import java.util.Arrays;
ExtractorInput input = null; ExtractorInput input = null;
try { try {
long position = positionHolder.position; long position = positionHolder.position;
length = dataSource.open(new DataSpec(uri, position, C.LENGTH_UNSET, customCacheKey)); dataSpec = new DataSpec(uri, position, C.LENGTH_UNSET, customCacheKey);
length = dataSource.open(dataSpec);
if (length != C.LENGTH_UNSET) { if (length != C.LENGTH_UNSET) {
length += position; length += position;
} }
...@@ -723,6 +734,7 @@ import java.util.Arrays; ...@@ -723,6 +734,7 @@ import java.util.Arrays;
result = Extractor.RESULT_CONTINUE; result = Extractor.RESULT_CONTINUE;
} else if (input != null) { } else if (input != null) {
positionHolder.position = input.getPosition(); positionHolder.position = input.getPosition();
bytesLoaded = positionHolder.position - dataSpec.absoluteStreamPosition;
} }
Util.closeQuietly(dataSource); Util.closeQuietly(dataSource);
} }
......
...@@ -17,14 +17,18 @@ package com.google.android.exoplayer2.source; ...@@ -17,14 +17,18 @@ package com.google.android.exoplayer2.source;
import android.net.Uri; import android.net.Uri;
import android.os.Handler; 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.ExoPlayer; import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.Extractor;
import com.google.android.exoplayer2.extractor.ExtractorsFactory; import com.google.android.exoplayer2.extractor.ExtractorsFactory;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.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.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.io.IOException; import java.io.IOException;
...@@ -40,10 +44,12 @@ import java.io.IOException; ...@@ -40,10 +44,12 @@ import java.io.IOException;
* Note that the built-in extractors for AAC, MPEG PS/TS and FLV streams do not support seeking. * Note that the built-in extractors for AAC, MPEG PS/TS and FLV streams do not support seeking.
*/ */
public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPeriod.Listener { public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPeriod.Listener {
/** /**
* Listener of {@link ExtractorMediaSource} events. * Listener of {@link ExtractorMediaSource} events.
*
* @deprecated Use {@link MediaSourceEventListener}.
*/ */
@Deprecated
public interface EventListener { public interface EventListener {
/** /**
...@@ -89,8 +95,7 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe ...@@ -89,8 +95,7 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
private final DataSource.Factory dataSourceFactory; private final DataSource.Factory dataSourceFactory;
private final ExtractorsFactory extractorsFactory; private final ExtractorsFactory extractorsFactory;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final Handler eventHandler; private final EventDispatcher eventDispatcher;
private final EventListener eventListener;
private final String customCacheKey; private final String customCacheKey;
private final int continueLoadingCheckIntervalBytes; private final int continueLoadingCheckIntervalBytes;
...@@ -108,9 +113,9 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe ...@@ -108,9 +113,9 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
private ExtractorsFactory extractorsFactory; private ExtractorsFactory extractorsFactory;
private int minLoadableRetryCount; private int minLoadableRetryCount;
private Handler eventHandler; @Nullable private Handler eventHandler;
private EventListener eventListener; @Nullable private MediaSourceEventListener eventListener;
private String customCacheKey; @Nullable private String customCacheKey;
private int continueLoadingCheckIntervalBytes; private int continueLoadingCheckIntervalBytes;
private boolean isBuildCalled; private boolean isBuildCalled;
...@@ -187,9 +192,25 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe ...@@ -187,9 +192,25 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
* @param eventHandler A handler for events. * @param eventHandler A handler for events.
* @param eventListener A listener of events. * @param eventListener A listener of events.
* @return This builder. * @return This builder.
* @deprecated Use {@link #setEventListener(Handler, MediaSourceEventListener)}.
*/ */
@Deprecated
public Builder setEventListener(Handler eventHandler, EventListener eventListener) { public Builder setEventListener(Handler eventHandler, EventListener eventListener) {
this.eventHandler = eventHandler; this.eventHandler = eventHandler;
this.eventListener = eventListener == null ? null : new EventListenerWrapper(eventListener);
return this;
}
/**
* Sets the listener to respond to {@link ExtractorMediaSource} events and the handler to
* deliver these events.
*
* @param eventHandler A handler for events.
* @param eventListener A listener of events.
* @return This builder.
*/
public Builder setEventListener(Handler eventHandler, MediaSourceEventListener eventListener) {
this.eventHandler = eventHandler;
this.eventListener = eventListener; this.eventListener = eventListener;
return this; return this;
} }
...@@ -270,12 +291,31 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe ...@@ -270,12 +291,31 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory, public ExtractorMediaSource(Uri uri, DataSource.Factory dataSourceFactory,
ExtractorsFactory extractorsFactory, int minLoadableRetryCount, Handler eventHandler, ExtractorsFactory extractorsFactory, int minLoadableRetryCount, Handler eventHandler,
EventListener eventListener, String customCacheKey, int continueLoadingCheckIntervalBytes) { EventListener eventListener, String customCacheKey, int continueLoadingCheckIntervalBytes) {
this(
uri,
dataSourceFactory,
extractorsFactory,
minLoadableRetryCount,
eventHandler,
eventListener == null ? null : new EventListenerWrapper(eventListener),
customCacheKey,
continueLoadingCheckIntervalBytes);
}
private ExtractorMediaSource(
Uri uri,
DataSource.Factory dataSourceFactory,
ExtractorsFactory extractorsFactory,
int minLoadableRetryCount,
@Nullable Handler eventHandler,
@Nullable MediaSourceEventListener eventListener,
@Nullable String customCacheKey,
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.eventHandler = eventHandler; this.eventDispatcher = new EventDispatcher(eventHandler, eventListener);
this.eventListener = eventListener;
this.customCacheKey = customCacheKey; this.customCacheKey = customCacheKey;
this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes; this.continueLoadingCheckIntervalBytes = continueLoadingCheckIntervalBytes;
} }
...@@ -294,9 +334,16 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe ...@@ -294,9 +334,16 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
@Override @Override
public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) { public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) {
Assertions.checkArgument(id.periodIndex == 0); Assertions.checkArgument(id.periodIndex == 0);
return new ExtractorMediaPeriod(uri, dataSourceFactory.createDataSource(), return new ExtractorMediaPeriod(
extractorsFactory.createExtractors(), minLoadableRetryCount, eventHandler, eventListener, uri,
this, allocator, customCacheKey, continueLoadingCheckIntervalBytes); dataSourceFactory.createDataSource(),
extractorsFactory.createExtractors(),
minLoadableRetryCount,
eventDispatcher,
this,
allocator,
customCacheKey,
continueLoadingCheckIntervalBytes);
} }
@Override @Override
...@@ -332,4 +379,94 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe ...@@ -332,4 +379,94 @@ public final class ExtractorMediaSource implements MediaSource, ExtractorMediaPe
new SinglePeriodTimeline(timelineDurationUs, timelineIsSeekable, false), null); new SinglePeriodTimeline(timelineDurationUs, timelineIsSeekable, false), null);
} }
/**
* Wraps a deprecated {@link EventListener}, invoking its callback from the equivalent callback in
* {@link MediaSourceEventListener}.
*/
private static final class EventListenerWrapper implements MediaSourceEventListener {
private final EventListener eventListener;
public EventListenerWrapper(EventListener eventListener) {
this.eventListener = Assertions.checkNotNull(eventListener);
}
@Override
public void onLoadStarted(
DataSpec dataSpec,
int dataType,
int trackType,
Format trackFormat,
int trackSelectionReason,
Object trackSelectionData,
long mediaStartTimeMs,
long mediaEndTimeMs,
long elapsedRealtimeMs) {
// Do nothing.
}
@Override
public void onLoadCompleted(
DataSpec dataSpec,
int dataType,
int trackType,
Format trackFormat,
int trackSelectionReason,
Object trackSelectionData,
long mediaStartTimeMs,
long mediaEndTimeMs,
long elapsedRealtimeMs,
long loadDurationMs,
long bytesLoaded) {
// Do nothing.
}
@Override
public void onLoadCanceled(
DataSpec dataSpec,
int dataType,
int trackType,
Format trackFormat,
int trackSelectionReason,
Object trackSelectionData,
long mediaStartTimeMs,
long mediaEndTimeMs,
long elapsedRealtimeMs,
long loadDurationMs,
long bytesLoaded) {
// Do nothing.
}
@Override
public void onLoadError(
DataSpec dataSpec,
int dataType,
int trackType,
Format trackFormat,
int trackSelectionReason,
Object trackSelectionData,
long mediaStartTimeMs,
long mediaEndTimeMs,
long elapsedRealtimeMs,
long loadDurationMs,
long bytesLoaded,
IOException error,
boolean wasCanceled) {
eventListener.onLoadError(error);
}
@Override
public void onUpstreamDiscarded(int trackType, long mediaStartTimeMs, long mediaEndTimeMs) {
// Do nothing.
}
@Override
public void onDownstreamFormatChanged(
int trackType,
Format trackFormat,
int trackSelectionReason,
Object trackSelectionData,
long mediaTimeMs) {
// Do nothing.
}
}
} }
...@@ -26,9 +26,9 @@ import com.google.android.exoplayer2.ExoPlayer; ...@@ -26,9 +26,9 @@ import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.DeferredMediaPeriod; import com.google.android.exoplayer2.source.DeferredMediaPeriod;
import com.google.android.exoplayer2.source.ExtractorMediaSource; import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.ExtractorMediaSource.EventListener;
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.MediaSourceEventListener;
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.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
...@@ -44,10 +44,8 @@ import java.util.Map; ...@@ -44,10 +44,8 @@ import java.util.Map;
*/ */
public final class AdsMediaSource implements MediaSource { public final class AdsMediaSource implements MediaSource {
/** /** Listener for ads media source events. */
* Listener for events relating to ad loading. public interface EventListener extends MediaSourceEventListener {
*/
public interface AdsListener {
/** /**
* Called if there was an error loading ads. The media source will load the content without ads * Called if there was an error loading ads. The media source will load the content without ads
...@@ -75,15 +73,13 @@ public final class AdsMediaSource implements MediaSource { ...@@ -75,15 +73,13 @@ public final class AdsMediaSource implements MediaSource {
private final MediaSource contentMediaSource; private final MediaSource contentMediaSource;
private final AdsLoader adsLoader; private final AdsLoader adsLoader;
private final ViewGroup adUiViewGroup; private final ViewGroup adUiViewGroup;
@Nullable private final Handler eventHandler;
@Nullable private final EventListener eventListener;
private final Handler mainHandler; private final Handler mainHandler;
private final ComponentListener componentListener; private final ComponentListener componentListener;
private final AdMediaSourceFactory adMediaSourceFactory; private final AdMediaSourceFactory adMediaSourceFactory;
private final Map<MediaSource, List<DeferredMediaPeriod>> deferredMediaPeriodByAdMediaSource; private final Map<MediaSource, List<DeferredMediaPeriod>> deferredMediaPeriodByAdMediaSource;
private final Timeline.Period period; private final Timeline.Period period;
@Nullable
private final Handler eventHandler;
@Nullable
private final AdsListener eventListener;
private Handler playerHandler; private Handler playerHandler;
private ExoPlayer player; private ExoPlayer player;
...@@ -115,10 +111,10 @@ public final class AdsMediaSource implements MediaSource { ...@@ -115,10 +111,10 @@ public final class AdsMediaSource implements MediaSource {
} }
/** /**
* Constructs a new source that inserts ads linearly with the content specified by * Constructs a new source that inserts ads linearly with the content specified by {@code
* {@code contentMediaSource}. * contentMediaSource}.
* <p> *
* Ad media is loaded using {@link ExtractorMediaSource}. If {@code eventListener} is * <p>Ad media is loaded using {@link ExtractorMediaSource}. If {@code eventListener} is
* non-{@code null} it will be notified of both ad tag and ad media load errors. * non-{@code null} it will be notified of both ad tag and ad media load errors.
* *
* @param contentMediaSource The {@link MediaSource} providing the content to play. * @param contentMediaSource The {@link MediaSource} providing the content to play.
...@@ -128,9 +124,13 @@ public final class AdsMediaSource implements MediaSource { ...@@ -128,9 +124,13 @@ public final class AdsMediaSource implements MediaSource {
* @param eventHandler A handler for events. May be null if delivery of events is not required. * @param eventHandler A handler for events. May be null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
*/ */
public AdsMediaSource(MediaSource contentMediaSource, DataSource.Factory dataSourceFactory, public AdsMediaSource(
AdsLoader adsLoader, ViewGroup adUiViewGroup, @Nullable Handler eventHandler, MediaSource contentMediaSource,
@Nullable AdsListener eventListener) { DataSource.Factory dataSourceFactory,
AdsLoader adsLoader,
ViewGroup adUiViewGroup,
@Nullable Handler eventHandler,
@Nullable EventListener eventListener) {
this.contentMediaSource = contentMediaSource; this.contentMediaSource = contentMediaSource;
this.adsLoader = adsLoader; this.adsLoader = adsLoader;
this.adUiViewGroup = adUiViewGroup; this.adUiViewGroup = adUiViewGroup;
...@@ -186,7 +186,7 @@ public final class AdsMediaSource implements MediaSource { ...@@ -186,7 +186,7 @@ public final class AdsMediaSource implements MediaSource {
if (adGroupMediaSources[adGroupIndex].length <= adIndexInAdGroup) { if (adGroupMediaSources[adGroupIndex].length <= adIndexInAdGroup) {
Uri adUri = adPlaybackState.adUris[id.adGroupIndex][id.adIndexInAdGroup]; Uri adUri = adPlaybackState.adUris[id.adGroupIndex][id.adIndexInAdGroup];
final MediaSource adMediaSource = final MediaSource adMediaSource =
adMediaSourceFactory.createAdMediaSource(adUri, mainHandler, componentListener); adMediaSourceFactory.createAdMediaSource(adUri, 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;
...@@ -306,11 +306,8 @@ public final class AdsMediaSource implements MediaSource { ...@@ -306,11 +306,8 @@ public final class AdsMediaSource implements MediaSource {
} }
} }
/** /** Listener for component events. All methods are called on the main thread. */
* Listener for component events. All methods are called on the main thread. private final class ComponentListener implements AdsLoader.EventListener {
*/
private final class ComponentListener implements AdsLoader.EventListener,
AdMediaSourceLoadErrorListener {
@Override @Override
public void onAdPlaybackState(final AdPlaybackState adPlaybackState) { public void onAdPlaybackState(final AdPlaybackState adPlaybackState) {
...@@ -375,20 +372,6 @@ public final class AdsMediaSource implements MediaSource { ...@@ -375,20 +372,6 @@ public final class AdsMediaSource implements MediaSource {
} }
/** /**
* Listener for errors while loading an ad {@link MediaSource}.
*/
private interface AdMediaSourceLoadErrorListener {
/**
* Called when an error occurs loading media data.
*
* @param error The load error.
*/
void onLoadError(IOException error);
}
/**
* Factory for {@link MediaSource}s for loading ad media. * Factory for {@link MediaSource}s for loading ad media.
*/ */
private interface AdMediaSourceFactory { private interface AdMediaSourceFactory {
...@@ -397,15 +380,13 @@ public final class AdsMediaSource implements MediaSource { ...@@ -397,15 +380,13 @@ public final class AdsMediaSource implements MediaSource {
* 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 ad. * @param uri The URI of the ad.
* @param handler A handler for listener events. * @param handler A handler for listener events. May be null if delivery of events is not
* @param listener A listener for ad load errors. To have ad media source load errors notified * required.
* via the ads media source's listener, call this listener's onLoadError method from your * @param listener A listener for events. May be null if delivery of events is not required.
* new media source's load error listener using the specified {@code handler}. Otherwise,
* this parameter can be ignored.
* @return The new media source. * @return The new media source.
*/ */
MediaSource createAdMediaSource(Uri uri, Handler handler, MediaSource createAdMediaSource(
AdMediaSourceLoadErrorListener listener); 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
...@@ -427,15 +408,11 @@ public final class AdsMediaSource implements MediaSource { ...@@ -427,15 +408,11 @@ public final class AdsMediaSource implements MediaSource {
} }
@Override @Override
public MediaSource createAdMediaSource(Uri uri, Handler handler, public MediaSource createAdMediaSource(
final AdMediaSourceLoadErrorListener listener) { Uri uri, @Nullable Handler handler, @Nullable MediaSourceEventListener listener) {
return new ExtractorMediaSource.Builder(uri, dataSourceFactory).setEventListener(handler, return new ExtractorMediaSource.Builder(uri, dataSourceFactory)
new EventListener() { .setEventListener(handler, listener)
@Override .build();
public void onLoadError(IOException error) {
listener.onLoadError(error);
}
}).build();
} }
@Override @Override
......
...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.upstream; ...@@ -17,6 +17,7 @@ package com.google.android.exoplayer2.upstream;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.IntDef; import android.support.annotation.IntDef;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
...@@ -79,7 +80,7 @@ public final class DataSpec { ...@@ -79,7 +80,7 @@ public final class DataSpec {
* A key that uniquely identifies the original stream. Used for cache indexing. May be null if the * A key that uniquely identifies the original stream. Used for cache indexing. May be null if the
* {@link DataSpec} is not intended to be used in conjunction with a cache. * {@link DataSpec} is not intended to be used in conjunction with a cache.
*/ */
public final String key; @Nullable public final String key;
/** /**
* Request flags. Currently {@link #FLAG_ALLOW_GZIP} and * Request flags. Currently {@link #FLAG_ALLOW_GZIP} and
* {@link #FLAG_ALLOW_CACHING_UNKNOWN_LENGTH} are the only supported flags. * {@link #FLAG_ALLOW_CACHING_UNKNOWN_LENGTH} are the only supported flags.
...@@ -113,7 +114,7 @@ public final class DataSpec { ...@@ -113,7 +114,7 @@ public final class DataSpec {
* @param length {@link #length}. * @param length {@link #length}.
* @param key {@link #key}. * @param key {@link #key}.
*/ */
public DataSpec(Uri uri, long absoluteStreamPosition, long length, String key) { public DataSpec(Uri uri, long absoluteStreamPosition, long length, @Nullable String key) {
this(uri, absoluteStreamPosition, absoluteStreamPosition, length, key, 0); this(uri, absoluteStreamPosition, absoluteStreamPosition, length, key, 0);
} }
...@@ -147,8 +148,8 @@ public final class DataSpec { ...@@ -147,8 +148,8 @@ public final class DataSpec {
} }
/** /**
* Construct a {@link DataSpec} where {@link #position} may differ from * Construct a {@link DataSpec} where {@link #position} may differ from {@link
* {@link #absoluteStreamPosition}. * #absoluteStreamPosition}.
* *
* @param uri {@link #uri}. * @param uri {@link #uri}.
* @param postBody {@link #postBody}. * @param postBody {@link #postBody}.
...@@ -158,8 +159,14 @@ public final class DataSpec { ...@@ -158,8 +159,14 @@ public final class DataSpec {
* @param key {@link #key}. * @param key {@link #key}.
* @param flags {@link #flags}. * @param flags {@link #flags}.
*/ */
public DataSpec(Uri uri, byte[] postBody, long absoluteStreamPosition, long position, long length, public DataSpec(
String key, @Flags int flags) { Uri uri,
byte[] postBody,
long absoluteStreamPosition,
long position,
long length,
@Nullable String key,
@Flags int flags) {
Assertions.checkArgument(absoluteStreamPosition >= 0); Assertions.checkArgument(absoluteStreamPosition >= 0);
Assertions.checkArgument(position >= 0); Assertions.checkArgument(position >= 0);
Assertions.checkArgument(length > 0 || length == C.LENGTH_UNSET); Assertions.checkArgument(length > 0 || length == C.LENGTH_UNSET);
......
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