Add window index and media period id to media source event listener events.

This allows to distinguish between media source events of multi-window and
multi-period media sources. In this change, only media sources currently reporting
events are changed. Proper support in composite sources will be added in a later
change.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=188847366
This commit is contained in:
tonihei 2018-03-13 02:45:33 -07:00 committed by Oliver Woodman
parent 00a7306fd8
commit 4f56636328
8 changed files with 159 additions and 48 deletions

View File

@ -76,10 +76,45 @@ public abstract class BaseMediaSource implements MediaSource {
/** /**
* Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the * Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the
* registered listeners. * registered listeners with the specified media period id.
*
* @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events. May be null, if
* the events do not belong to a specific media period.
* @return An event dispatcher with pre-configured media period id.
*/ */
protected final MediaSourceEventListener.EventDispatcher getEventDispatcher() { protected final MediaSourceEventListener.EventDispatcher createEventDispatcher(
return eventDispatcher; @Nullable MediaPeriodId mediaPeriodId) {
return eventDispatcher.withParameters(
/* windowIndex= */ 0, mediaPeriodId, /* mediaTimeOffsetMs= */ 0);
}
/**
* Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the
* registered listeners with the specified media period id and time offset.
*
* @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events.
* @param mediaTimeOffsetMs The offset to be added to all media times, in milliseconds.
* @return An event dispatcher with pre-configured media period id and time offset.
*/
protected final MediaSourceEventListener.EventDispatcher createEventDispatcher(
MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) {
Assertions.checkArgument(mediaPeriodId != null);
return eventDispatcher.withParameters(/* windowIndex= */ 0, mediaPeriodId, mediaTimeOffsetMs);
}
/**
* Returns a {@link MediaSourceEventListener.EventDispatcher} which dispatches all events to the
* registered listeners with the specified window index, media period id and time offset.
*
* @param windowIndex The timeline window index to be reported with the events.
* @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events. May be null, if
* the events do not belong to a specific media period.
* @param mediaTimeOffsetMs The offset to be added to all media times, in milliseconds.
* @return An event dispatcher with pre-configured media period id and time offset.
*/
protected final MediaSourceEventListener.EventDispatcher createEventDispatcher(
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) {
return eventDispatcher.withParameters(windowIndex, mediaPeriodId, mediaTimeOffsetMs);
} }
@Override @Override

View File

@ -24,7 +24,6 @@ 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.MediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.ads.AdsMediaSource; import com.google.android.exoplayer2.source.ads.AdsMediaSource;
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;
@ -95,7 +94,6 @@ public final class ExtractorMediaSource extends BaseMediaSource
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 EventDispatcher eventDispatcher;
private final String customCacheKey; private final String customCacheKey;
private final int continueLoadingCheckIntervalBytes; private final int continueLoadingCheckIntervalBytes;
@ -319,7 +317,6 @@ public final class ExtractorMediaSource extends BaseMediaSource
this.dataSourceFactory = dataSourceFactory; this.dataSourceFactory = dataSourceFactory;
this.extractorsFactory = extractorsFactory; this.extractorsFactory = extractorsFactory;
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
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;
@ -343,7 +340,7 @@ public final class ExtractorMediaSource extends BaseMediaSource
dataSourceFactory.createDataSource(), dataSourceFactory.createDataSource(),
extractorsFactory.createExtractors(), extractorsFactory.createExtractors(),
minLoadableRetryCount, minLoadableRetryCount,
eventDispatcher, createEventDispatcher(id),
this, this,
allocator, allocator,
customCacheKey, customCacheKey,

View File

@ -22,6 +22,7 @@ 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.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.source.MediaSource.MediaPeriodId;
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;
@ -62,6 +63,14 @@ public interface MediaSourceEventListener {
/** Descriptor for data being loaded or selected by a media source. */ /** Descriptor for data being loaded or selected by a media source. */
final class MediaLoadData { final class MediaLoadData {
/** The window index in the timeline of the media source this data belongs to. */
public final int windowIndex;
/**
* The {@link MediaPeriodId} this data belongs to. Null if the data does not belong to a
* specific media period.
*/
public final @Nullable MediaPeriodId mediaPeriodId;
/** One of the {@link C} {@code DATA_TYPE_*} constants defining the type of data. */ /** One of the {@link C} {@code DATA_TYPE_*} constants defining the type of data. */
public final int dataType; public final int dataType;
/** /**
@ -84,17 +93,23 @@ public interface MediaSourceEventListener {
* the data does not belong to a track. * the data does not belong to a track.
*/ */
public final @Nullable Object trackSelectionData; public final @Nullable Object trackSelectionData;
/** The start time of the media, or {@link C#TIME_UNSET} if the data is not for media. */ /**
* The start time of the media, or {@link C#TIME_UNSET} if the data does not belong to a
* specific media period.
*/
public final long mediaStartTimeMs; public final long mediaStartTimeMs;
/** /**
* The end time of the media, or {@link C#TIME_UNSET} if the data is not for media or the end * The end time of the media, or {@link C#TIME_UNSET} if the data does not belong to a specific
* time is unknown. * media period or the end time is unknown.
*/ */
public final long mediaEndTimeMs; public final long mediaEndTimeMs;
/** /**
* Creates media load data. * Creates media load data.
* *
* @param windowIndex The window index in the timeline of the media source this load belongs to.
* @param mediaPeriodId The {@link MediaPeriodId} this load belongs to. Null if the data does
* not belong to a specific media period.
* @param dataType One of the {@link C} {@code DATA_TYPE_*} constants defining the type of data. * @param dataType One of the {@link C} {@code DATA_TYPE_*} constants defining the type of data.
* @param trackType One of the {@link C} {@code TRACK_TYPE_*} constants if the data corresponds * @param trackType One of the {@link C} {@code TRACK_TYPE_*} constants if the data corresponds
* to media of a specific type. {@link C#TRACK_TYPE_UNKNOWN} otherwise. * to media of a specific type. {@link C#TRACK_TYPE_UNKNOWN} otherwise.
@ -104,12 +119,14 @@ public interface MediaSourceEventListener {
* data belongs to a track. {@link C#SELECTION_REASON_UNKNOWN} otherwise. * data belongs to a track. {@link C#SELECTION_REASON_UNKNOWN} otherwise.
* @param trackSelectionData Optional data associated with the selection of the track to which * @param trackSelectionData Optional data associated with the selection of the track to which
* the data belongs. Null if the data does not belong to a track. * the data belongs. Null if the data does not belong to a track.
* @param mediaStartTimeMs The start time of the media, or {@link C#TIME_UNSET} if the data is * @param mediaStartTimeMs The start time of the media, or {@link C#TIME_UNSET} if the data does
* not for media. * not belong to a specific media period.
* @param mediaEndTimeMs The end time of the media, or {@link C#TIME_UNSET} if the data is not * @param mediaEndTimeMs The end time of the media, or {@link C#TIME_UNSET} if the data does not
* for media or the end time is unknown. * belong to a specific media period or the end time is unknown.
*/ */
public MediaLoadData( public MediaLoadData(
int windowIndex,
@Nullable MediaPeriodId mediaPeriodId,
int dataType, int dataType,
int trackType, int trackType,
@Nullable Format trackFormat, @Nullable Format trackFormat,
@ -117,6 +134,8 @@ public interface MediaSourceEventListener {
@Nullable Object trackSelectionData, @Nullable Object trackSelectionData,
long mediaStartTimeMs, long mediaStartTimeMs,
long mediaEndTimeMs) { long mediaEndTimeMs) {
this.windowIndex = windowIndex;
this.mediaPeriodId = mediaPeriodId;
this.dataType = dataType; this.dataType = dataType;
this.trackType = trackType; this.trackType = trackType;
this.trackFormat = trackFormat; this.trackFormat = trackFormat;
@ -196,30 +215,44 @@ public interface MediaSourceEventListener {
final class EventDispatcher { final class EventDispatcher {
private final CopyOnWriteArrayList<ListenerAndHandler> listenerAndHandlers; private final CopyOnWriteArrayList<ListenerAndHandler> listenerAndHandlers;
private final int windowIndex;
private final @Nullable MediaPeriodId mediaPeriodId;
private final long mediaTimeOffsetMs; private final long mediaTimeOffsetMs;
/** Create event dispatcher. */ /** Creates an event dispatcher. */
/* package */ EventDispatcher() { /* package */ EventDispatcher() {
this( this(
/* listenerAndHandlers= */ new CopyOnWriteArrayList<ListenerAndHandler>(), /* listenerAndHandlers= */ new CopyOnWriteArrayList<ListenerAndHandler>(),
/* windowIndex= */ 0,
/* mediaPeriodId= */ null,
/* mediaTimeOffsetMs= */ 0); /* mediaTimeOffsetMs= */ 0);
} }
private EventDispatcher( private EventDispatcher(
CopyOnWriteArrayList<ListenerAndHandler> listenerAndHandlers, long mediaTimeOffsetMs) { CopyOnWriteArrayList<ListenerAndHandler> listenerAndHandlers,
int windowIndex,
@Nullable MediaPeriodId mediaPeriodId,
long mediaTimeOffsetMs) {
this.listenerAndHandlers = listenerAndHandlers; this.listenerAndHandlers = listenerAndHandlers;
this.windowIndex = windowIndex;
this.mediaPeriodId = mediaPeriodId;
this.mediaTimeOffsetMs = mediaTimeOffsetMs; this.mediaTimeOffsetMs = mediaTimeOffsetMs;
} }
/** /**
* Creates a view of the event dispatcher with a media time offset. * Creates a view of the event dispatcher with pre-configured window index, media period id, and
* media time offset.
* *
* @param windowIndex The timeline window index to be reported with the events.
* @param mediaPeriodId The {@link MediaPeriodId} to be reported with the events.
* @param mediaTimeOffsetMs The offset to be added to all media times, in milliseconds. * @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. * @return A view of the event dispatcher with the pre-configured parameters.
*/ */
@CheckResult @CheckResult
public EventDispatcher withMediaTimeOffsetMs(long mediaTimeOffsetMs) { /* package */ EventDispatcher withParameters(
return new EventDispatcher(listenerAndHandlers, mediaTimeOffsetMs); int windowIndex, @Nullable MediaPeriodId mediaPeriodId, long mediaTimeOffsetMs) {
return new EventDispatcher(
listenerAndHandlers, windowIndex, mediaPeriodId, mediaTimeOffsetMs);
} }
/** /**
@ -280,6 +313,8 @@ public interface MediaSourceEventListener {
new LoadEventInfo( new LoadEventInfo(
dataSpec, elapsedRealtimeMs, /* loadDurationMs= */ 0, /* bytesLoaded= */ 0), dataSpec, elapsedRealtimeMs, /* loadDurationMs= */ 0, /* bytesLoaded= */ 0),
new MediaLoadData( new MediaLoadData(
windowIndex,
mediaPeriodId,
dataType, dataType,
trackType, trackType,
trackFormat, trackFormat,
@ -334,6 +369,8 @@ public interface MediaSourceEventListener {
listenerAndHandler.listener.onLoadCompleted( listenerAndHandler.listener.onLoadCompleted(
new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded), new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded),
new MediaLoadData( new MediaLoadData(
windowIndex,
mediaPeriodId,
dataType, dataType,
trackType, trackType,
trackFormat, trackFormat,
@ -388,6 +425,8 @@ public interface MediaSourceEventListener {
listenerAndHandler.listener.onLoadCanceled( listenerAndHandler.listener.onLoadCanceled(
new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded), new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded),
new MediaLoadData( new MediaLoadData(
windowIndex,
mediaPeriodId,
dataType, dataType,
trackType, trackType,
trackFormat, trackFormat,
@ -448,6 +487,8 @@ public interface MediaSourceEventListener {
listenerAndHandler.listener.onLoadError( listenerAndHandler.listener.onLoadError(
new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded), new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded),
new MediaLoadData( new MediaLoadData(
windowIndex,
mediaPeriodId,
dataType, dataType,
trackType, trackType,
trackFormat, trackFormat,
@ -472,6 +513,8 @@ public interface MediaSourceEventListener {
public void run() { public void run() {
listenerAndHandler.listener.onUpstreamDiscarded( listenerAndHandler.listener.onUpstreamDiscarded(
new MediaLoadData( new MediaLoadData(
windowIndex,
mediaPeriodId,
C.DATA_TYPE_MEDIA, C.DATA_TYPE_MEDIA,
trackType, trackType,
/* trackFormat= */ null, /* trackFormat= */ null,
@ -498,6 +541,8 @@ public interface MediaSourceEventListener {
public void run() { public void run() {
listenerAndHandler.listener.onDownstreamFormatChanged( listenerAndHandler.listener.onDownstreamFormatChanged(
new MediaLoadData( new MediaLoadData(
windowIndex,
mediaPeriodId,
C.DATA_TYPE_MEDIA, C.DATA_TYPE_MEDIA,
trackType, trackType,
trackFormat, trackFormat,

View File

@ -148,7 +148,6 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
private final DataSource.Factory dataSourceFactory; private final DataSource.Factory dataSourceFactory;
private final Format format; private final Format format;
private final long durationUs; private final long durationUs;
private final MediaSourceEventListener.EventDispatcher eventDispatcher;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final boolean treatLoadErrorsAsEndOfStream; private final boolean treatLoadErrorsAsEndOfStream;
private final Timeline timeline; private final Timeline timeline;
@ -242,7 +241,6 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
this.durationUs = durationUs; this.durationUs = durationUs;
this.minLoadableRetryCount = minLoadableRetryCount; this.minLoadableRetryCount = minLoadableRetryCount;
this.treatLoadErrorsAsEndOfStream = treatLoadErrorsAsEndOfStream; this.treatLoadErrorsAsEndOfStream = treatLoadErrorsAsEndOfStream;
this.eventDispatcher = getEventDispatcher();
dataSpec = new DataSpec(uri); dataSpec = new DataSpec(uri);
timeline = new SinglePeriodTimeline(durationUs, true, false); timeline = new SinglePeriodTimeline(durationUs, true, false);
} }
@ -268,7 +266,7 @@ public final class SingleSampleMediaSource extends BaseMediaSource {
format, format,
durationUs, durationUs,
minLoadableRetryCount, minLoadableRetryCount,
eventDispatcher, createEventDispatcher(id),
treatLoadErrorsAsEndOfStream); treatLoadErrorsAsEndOfStream);
} }

View File

@ -281,7 +281,7 @@ public final class DashMediaSource extends BaseMediaSource {
private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory; private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final long livePresentationDelayMs; private final long livePresentationDelayMs;
private final EventDispatcher eventDispatcher; private final EventDispatcher manifestEventDispatcher;
private final ParsingLoadable.Parser<? extends DashManifest> manifestParser; private final ParsingLoadable.Parser<? extends DashManifest> manifestParser;
private final ManifestCallback manifestCallback; private final ManifestCallback manifestCallback;
private final Object manifestUriLock; private final Object manifestUriLock;
@ -476,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 = getEventDispatcher(); manifestEventDispatcher = createEventDispatcher(/* mediaPeriodId= */ null);
manifestUriLock = new Object(); manifestUriLock = new Object();
periodsById = new SparseArray<>(); periodsById = new SparseArray<>();
playerEmsgCallback = new DefaultPlayerEmsgCallback(); playerEmsgCallback = new DefaultPlayerEmsgCallback();
@ -540,7 +540,7 @@ public final class DashMediaSource extends BaseMediaSource {
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 periodEventDispatcher =
eventDispatcher.withMediaTimeOffsetMs(manifest.getPeriod(periodIndex).startMs); createEventDispatcher(periodId, manifest.getPeriod(periodIndex).startMs);
DashMediaPeriod mediaPeriod = DashMediaPeriod mediaPeriod =
new DashMediaPeriod( new DashMediaPeriod(
firstPeriodId + periodIndex, firstPeriodId + periodIndex,
@ -612,8 +612,12 @@ public final class DashMediaSource extends BaseMediaSource {
/* package */ void onManifestLoadCompleted(ParsingLoadable<DashManifest> loadable, /* package */ void onManifestLoadCompleted(ParsingLoadable<DashManifest> loadable,
long elapsedRealtimeMs, long loadDurationMs) { long elapsedRealtimeMs, long loadDurationMs) {
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs, manifestEventDispatcher.loadCompleted(
loadDurationMs, loadable.bytesLoaded()); loadable.dataSpec,
loadable.type,
elapsedRealtimeMs,
loadDurationMs,
loadable.bytesLoaded());
DashManifest newManifest = loadable.getResult(); DashManifest newManifest = loadable.getResult();
int periodCount = manifest == null ? 0 : manifest.getPeriodCount(); int periodCount = manifest == null ? 0 : manifest.getPeriodCount();
@ -691,30 +695,50 @@ public final class DashMediaSource extends BaseMediaSource {
/* package */ int onManifestLoadError(ParsingLoadable<DashManifest> loadable, /* package */ int onManifestLoadError(ParsingLoadable<DashManifest> loadable,
long elapsedRealtimeMs, long loadDurationMs, IOException error) { long elapsedRealtimeMs, long loadDurationMs, IOException error) {
boolean isFatal = error instanceof ParserException; boolean isFatal = error instanceof ParserException;
eventDispatcher.loadError(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs, manifestEventDispatcher.loadError(
loadable.bytesLoaded(), error, isFatal); loadable.dataSpec,
loadable.type,
elapsedRealtimeMs,
loadDurationMs,
loadable.bytesLoaded(),
error,
isFatal);
return isFatal ? Loader.DONT_RETRY_FATAL : Loader.RETRY; return isFatal ? Loader.DONT_RETRY_FATAL : Loader.RETRY;
} }
/* package */ void onUtcTimestampLoadCompleted(ParsingLoadable<Long> loadable, /* package */ void onUtcTimestampLoadCompleted(ParsingLoadable<Long> loadable,
long elapsedRealtimeMs, long loadDurationMs) { long elapsedRealtimeMs, long loadDurationMs) {
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs, manifestEventDispatcher.loadCompleted(
loadDurationMs, loadable.bytesLoaded()); loadable.dataSpec,
loadable.type,
elapsedRealtimeMs,
loadDurationMs,
loadable.bytesLoaded());
onUtcTimestampResolved(loadable.getResult() - elapsedRealtimeMs); onUtcTimestampResolved(loadable.getResult() - elapsedRealtimeMs);
} }
/* package */ int onUtcTimestampLoadError(ParsingLoadable<Long> loadable, long elapsedRealtimeMs, /* package */ int onUtcTimestampLoadError(ParsingLoadable<Long> loadable, long elapsedRealtimeMs,
long loadDurationMs, IOException error) { long loadDurationMs, IOException error) {
eventDispatcher.loadError(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs, manifestEventDispatcher.loadError(
loadable.bytesLoaded(), error, true); loadable.dataSpec,
loadable.type,
elapsedRealtimeMs,
loadDurationMs,
loadable.bytesLoaded(),
error,
true);
onUtcTimestampResolutionError(error); onUtcTimestampResolutionError(error);
return Loader.DONT_RETRY; return Loader.DONT_RETRY;
} }
/* package */ void onLoadCanceled(ParsingLoadable<?> loadable, long elapsedRealtimeMs, /* package */ void onLoadCanceled(ParsingLoadable<?> loadable, long elapsedRealtimeMs,
long loadDurationMs) { long loadDurationMs) {
eventDispatcher.loadCanceled(loadable.dataSpec, loadable.type, elapsedRealtimeMs, manifestEventDispatcher.loadCanceled(
loadDurationMs, loadable.bytesLoaded()); loadable.dataSpec,
loadable.type,
elapsedRealtimeMs,
loadDurationMs,
loadable.bytesLoaded());
} }
// Internal methods. // Internal methods.
@ -889,7 +913,7 @@ public final class DashMediaSource extends BaseMediaSource {
private <T> void startLoading(ParsingLoadable<T> loadable, private <T> void startLoading(ParsingLoadable<T> loadable,
Loader.Callback<ParsingLoadable<T>> callback, int minRetryCount) { Loader.Callback<ParsingLoadable<T>> callback, int minRetryCount) {
long elapsedRealtimeMs = loader.startLoading(loadable, callback, minRetryCount); long elapsedRealtimeMs = loader.startLoading(loadable, callback, minRetryCount);
eventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs); manifestEventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs);
} }
private long getNowUnixTimeUs() { private long getNowUnixTimeUs() {

View File

@ -216,7 +216,6 @@ public final class HlsMediaSource extends BaseMediaSource
private final HlsDataSourceFactory dataSourceFactory; private final HlsDataSourceFactory dataSourceFactory;
private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory; private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final EventDispatcher eventDispatcher;
private final ParsingLoadable.Parser<HlsPlaylist> playlistParser; private final ParsingLoadable.Parser<HlsPlaylist> playlistParser;
private final boolean allowChunklessPreparation; private final boolean allowChunklessPreparation;
@ -314,11 +313,11 @@ 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 = getEventDispatcher();
} }
@Override @Override
public void prepareSourceInternal(ExoPlayer player, boolean isTopLevelSource) { public void prepareSourceInternal(ExoPlayer player, boolean isTopLevelSource) {
EventDispatcher eventDispatcher = createEventDispatcher(/* mediaPeriodId= */ null);
playlistTracker = new HlsPlaylistTracker(manifestUri, dataSourceFactory, eventDispatcher, playlistTracker = new HlsPlaylistTracker(manifestUri, dataSourceFactory, eventDispatcher,
minLoadableRetryCount, this, playlistParser); minLoadableRetryCount, this, playlistParser);
playlistTracker.start(); playlistTracker.start();
@ -332,6 +331,7 @@ public final class HlsMediaSource extends BaseMediaSource
@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);
EventDispatcher eventDispatcher = createEventDispatcher(id);
return new HlsMediaPeriod( return new HlsMediaPeriod(
extractorFactory, extractorFactory,
playlistTracker, playlistTracker,

View File

@ -258,7 +258,7 @@ public final class SsMediaSource extends BaseMediaSource
private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory; private final CompositeSequenceableLoaderFactory compositeSequenceableLoaderFactory;
private final int minLoadableRetryCount; private final int minLoadableRetryCount;
private final long livePresentationDelayMs; private final long livePresentationDelayMs;
private final EventDispatcher eventDispatcher; private final EventDispatcher manifestEventDispatcher;
private final ParsingLoadable.Parser<? extends SsManifest> manifestParser; private final ParsingLoadable.Parser<? extends SsManifest> manifestParser;
private final ArrayList<SsMediaPeriod> mediaPeriods; private final ArrayList<SsMediaPeriod> mediaPeriods;
@ -431,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 = getEventDispatcher(); this.manifestEventDispatcher = createEventDispatcher(/* mediaPeriodId= */ null);
sideloadedManifest = manifest != null; sideloadedManifest = manifest != null;
mediaPeriods = new ArrayList<>(); mediaPeriods = new ArrayList<>();
} }
@ -460,6 +460,7 @@ public final class SsMediaSource extends BaseMediaSource
@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);
EventDispatcher eventDispatcher = createEventDispatcher(id);
SsMediaPeriod period = new SsMediaPeriod(manifest, chunkSourceFactory, SsMediaPeriod period = new SsMediaPeriod(manifest, chunkSourceFactory,
compositeSequenceableLoaderFactory, minLoadableRetryCount, eventDispatcher, compositeSequenceableLoaderFactory, minLoadableRetryCount, eventDispatcher,
manifestLoaderErrorThrower, allocator); manifestLoaderErrorThrower, allocator);
@ -493,8 +494,12 @@ public final class SsMediaSource extends BaseMediaSource
@Override @Override
public void onLoadCompleted(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs, public void onLoadCompleted(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs,
long loadDurationMs) { long loadDurationMs) {
eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, elapsedRealtimeMs, manifestEventDispatcher.loadCompleted(
loadDurationMs, loadable.bytesLoaded()); loadable.dataSpec,
loadable.type,
elapsedRealtimeMs,
loadDurationMs,
loadable.bytesLoaded());
manifest = loadable.getResult(); manifest = loadable.getResult();
manifestLoadStartTimestamp = elapsedRealtimeMs - loadDurationMs; manifestLoadStartTimestamp = elapsedRealtimeMs - loadDurationMs;
processManifest(); processManifest();
@ -504,7 +509,7 @@ public final class SsMediaSource extends BaseMediaSource
@Override @Override
public void onLoadCanceled(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs, public void onLoadCanceled(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs,
long loadDurationMs, boolean released) { long loadDurationMs, boolean released) {
eventDispatcher.loadCanceled( manifestEventDispatcher.loadCanceled(
loadable.dataSpec, loadable.dataSpec,
loadable.type, loadable.type,
elapsedRealtimeMs, elapsedRealtimeMs,
@ -516,8 +521,14 @@ public final class SsMediaSource extends BaseMediaSource
public int onLoadError(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs, public int onLoadError(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs,
long loadDurationMs, IOException error) { long loadDurationMs, IOException error) {
boolean isFatal = error instanceof ParserException; boolean isFatal = error instanceof ParserException;
eventDispatcher.loadError(loadable.dataSpec, loadable.type, elapsedRealtimeMs, loadDurationMs, manifestEventDispatcher.loadError(
loadable.bytesLoaded(), error, isFatal); loadable.dataSpec,
loadable.type,
elapsedRealtimeMs,
loadDurationMs,
loadable.bytesLoaded(),
error,
isFatal);
return isFatal ? Loader.DONT_RETRY_FATAL : Loader.RETRY; return isFatal ? Loader.DONT_RETRY_FATAL : Loader.RETRY;
} }
@ -584,7 +595,7 @@ public final class SsMediaSource extends BaseMediaSource
ParsingLoadable<SsManifest> loadable = new ParsingLoadable<>(manifestDataSource, ParsingLoadable<SsManifest> loadable = new ParsingLoadable<>(manifestDataSource,
manifestUri, C.DATA_TYPE_MANIFEST, manifestParser); manifestUri, C.DATA_TYPE_MANIFEST, manifestParser);
long elapsedRealtimeMs = manifestLoader.startLoading(loadable, this, minLoadableRetryCount); long elapsedRealtimeMs = manifestLoader.startLoading(loadable, this, minLoadableRetryCount);
eventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs); manifestEventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs);
} }
} }

View File

@ -47,8 +47,9 @@ public class FakeAdaptiveMediaSource extends FakeMediaSource {
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());
MediaSourceEventListener.EventDispatcher eventDispatcher = createEventDispatcher(id);
return new FakeAdaptiveMediaPeriod( return new FakeAdaptiveMediaPeriod(
trackGroupArray, getEventDispatcher(), allocator, chunkSourceFactory, period.durationUs); trackGroupArray, eventDispatcher, allocator, chunkSourceFactory, period.durationUs);
} }
} }