From dd14500ebad24a209770b5a12cead9644daecafa Mon Sep 17 00:00:00 2001 From: tonihei Date: Thu, 28 Jun 2018 04:36:33 -0700 Subject: [PATCH] Add url (after redirection) to LoadEventInfo. This url is readily available when creating media source events (from the data source) but so far not published to external listeners. This change adds a new field to LoadEventInfo which corresponds to DataSource.getUri(). Issue:#2054 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=202459049 --- RELEASENOTES.md | 3 + .../source/ExtractorMediaPeriod.java | 45 +++-- .../source/MediaSourceEventListener.java | 155 +++++++++--------- .../source/SingleSampleMediaPeriod.java | 30 ++-- .../exoplayer2/source/ads/AdsMediaSource.java | 2 + .../source/chunk/ChunkSampleStream.java | 63 +++++-- .../exoplayer2/upstream/ParsingLoadable.java | 23 ++- .../exoplayer2/upstream/StatsDataSource.java | 5 + .../source/dash/DashMediaSource.java | 12 +- .../source/hls/HlsSampleStreamWrapper.java | 63 +++++-- .../playlist/DefaultHlsPlaylistTracker.java | 16 +- .../source/smoothstreaming/SsMediaSource.java | 6 +- .../exoplayer2/testutil/FakeMediaPeriod.java | 2 + .../exoplayer2/testutil/FakeMediaSource.java | 7 +- 14 files changed, 280 insertions(+), 152 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 5cd9535b08..1ac2a4da39 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -50,6 +50,9 @@ ([#4403](https://github.com/google/ExoPlayer/issues/4413)). * Add support for multiple audio and video tracks in MPEG-PS streams ([#4406](https://github.com/google/ExoPlayer/issues/4406)). +* Add uri field to `LoadEventInfo` in `MediaSourceEventListener` or + `AnalyticsListener` callbacks. This uri is the redirected uri if redirection + occurred ([#2054](https://github.com/google/ExoPlayer/issues/2054)). ### 2.8.2 ### diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java index 37b3ee4c53..f88a95e694 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ExtractorMediaPeriod.java @@ -40,6 +40,7 @@ import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.Loader; import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction; import com.google.android.exoplayer2.upstream.Loader.Loadable; +import com.google.android.exoplayer2.upstream.StatsDataSource; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.ConditionVariable; import com.google.android.exoplayer2.util.MimeTypes; @@ -491,6 +492,7 @@ import java.util.Arrays; } eventDispatcher.loadCompleted( loadable.dataSpec, + loadable.dataSource.getLastOpenedUri(), C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, /* trackFormat= */ null, @@ -500,7 +502,7 @@ import java.util.Arrays; durationUs, elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded); + loadable.dataSource.getBytesRead()); copyLengthFromLoader(loadable); loadingFinished = true; callback.onContinueLoadingRequested(this); @@ -511,6 +513,7 @@ import java.util.Arrays; long loadDurationMs, boolean released) { eventDispatcher.loadCanceled( loadable.dataSpec, + loadable.dataSource.getLastOpenedUri(), C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, /* trackFormat= */ null, @@ -520,7 +523,7 @@ import java.util.Arrays; durationUs, elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded); + loadable.dataSource.getBytesRead()); if (!released) { copyLengthFromLoader(loadable); for (SampleQueue sampleQueue : sampleQueues) { @@ -539,9 +542,23 @@ import java.util.Arrays; long loadDurationMs, IOException error, int errorCount) { - boolean isErrorFatal = isLoadableExceptionFatal(error); + copyLengthFromLoader(loadable); + LoadErrorAction retryAction; + if (isLoadableExceptionFatal(error)) { + retryAction = Loader.DONT_RETRY_FATAL; + } else { + int extractedSamplesCount = getExtractedSamplesCount(); + boolean madeProgress = extractedSamplesCount > extractedSamplesCountAtStartOfLoad; + retryAction = + configureRetry(loadable, extractedSamplesCount) + ? (madeProgress ? Loader.RETRY_RESET_ERROR_COUNT : Loader.RETRY) + : Loader.DONT_RETRY; + } + boolean wasCanceled = + retryAction == Loader.DONT_RETRY || retryAction == Loader.DONT_RETRY_FATAL; eventDispatcher.loadError( loadable.dataSpec, + loadable.dataSource.getLastOpenedUri(), C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, /* trackFormat= */ null, @@ -551,18 +568,10 @@ import java.util.Arrays; durationUs, elapsedRealtimeMs, loadDurationMs, - loadable.bytesLoaded, + loadable.dataSource.getBytesRead(), error, - /* wasCanceled= */ isErrorFatal); - copyLengthFromLoader(loadable); - if (isErrorFatal) { - return Loader.DONT_RETRY_FATAL; - } - int extractedSamplesCount = getExtractedSamplesCount(); - boolean madeProgress = extractedSamplesCount > extractedSamplesCountAtStartOfLoad; - return configureRetry(loadable, extractedSamplesCount) - ? (madeProgress ? Loader.RETRY_RESET_ERROR_COUNT : Loader.RETRY) - : Loader.DONT_RETRY; + wasCanceled); + return retryAction; } // ExtractorOutput implementation. Called by the loading thread. @@ -663,6 +672,7 @@ import java.util.Arrays; long elapsedRealtimeMs = loader.startLoading(loadable, this, actualMinLoadableRetryCount); eventDispatcher.loadStarted( loadable.dataSpec, + loadable.dataSpec.uri, C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, /* trackFormat= */ null, @@ -803,7 +813,7 @@ import java.util.Arrays; /* package */ final class ExtractingLoadable implements Loadable { private final Uri uri; - private final DataSource dataSource; + private final StatsDataSource dataSource; private final ExtractorHolder extractorHolder; private final ConditionVariable loadCondition; private final PositionHolder positionHolder; @@ -814,17 +824,17 @@ import java.util.Arrays; private long seekTimeUs; private DataSpec dataSpec; private long length; - private long bytesLoaded; public ExtractingLoadable(Uri uri, DataSource dataSource, ExtractorHolder extractorHolder, ConditionVariable loadCondition) { this.uri = Assertions.checkNotNull(uri); - this.dataSource = Assertions.checkNotNull(dataSource); + this.dataSource = new StatsDataSource(dataSource); this.extractorHolder = Assertions.checkNotNull(extractorHolder); this.loadCondition = loadCondition; this.positionHolder = new PositionHolder(); this.pendingExtractorSeek = true; this.length = C.LENGTH_UNSET; + dataSpec = new DataSpec(uri, positionHolder.position, C.LENGTH_UNSET, customCacheKey); } public void setLoadPosition(long position, long timeUs) { @@ -870,7 +880,6 @@ import java.util.Arrays; result = Extractor.RESULT_CONTINUE; } else if (input != null) { positionHolder.position = input.getPosition(); - bytesLoaded = positionHolder.position - dataSpec.absoluteStreamPosition; } Util.closeQuietly(dataSource); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java index 9d1ba10866..844534a43d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/MediaSourceEventListener.java @@ -15,6 +15,7 @@ */ package com.google.android.exoplayer2.source; +import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; @@ -35,8 +36,14 @@ public interface MediaSourceEventListener { /** Media source load event information. */ final class LoadEventInfo { - /** Defines the data being loaded. */ + /** Defines the requested data. */ public final DataSpec dataSpec; + /** + * The {@link Uri} from which data is being read. The uri will be identical to the one in {@link + * #dataSpec}.uri unless redirection has occurred. If redirection has occurred, this is the uri + * after redirection. + */ + public final Uri uri; /** The value of {@link SystemClock#elapsedRealtime} at the time of the load event. */ public final long elapsedRealtimeMs; /** The duration of the load up to the event time. */ @@ -47,15 +54,20 @@ public interface MediaSourceEventListener { /** * Creates load event info. * - * @param dataSpec Defines the data being loaded. + * @param dataSpec Defines the requested data. + * @param uri The {@link Uri} from which data is being read. The uri must be identical to the + * one in {@code dataSpec.uri} unless redirection has occurred. If redirection has occurred, + * this is the uri after redirection. * @param elapsedRealtimeMs The value of {@link SystemClock#elapsedRealtime} at the time of the * load event. * @param loadDurationMs The duration of the load up to the event time. - * @param bytesLoaded The number of bytes that were loaded up to the event time. + * @param bytesLoaded The number of bytes that were loaded up to the event time. For compressed + * network responses, this is the decompressed size. */ public LoadEventInfo( - DataSpec dataSpec, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) { + DataSpec dataSpec, Uri uri, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) { this.dataSpec = dataSpec; + this.uri = uri; this.elapsedRealtimeMs = elapsedRealtimeMs; this.loadDurationMs = loadDurationMs; this.bytesLoaded = bytesLoaded; @@ -155,7 +167,8 @@ public interface MediaSourceEventListener { * @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 load does not * belong to a specific media period. - * @param loadEventInfo The {@link LoadEventInfo} defining the load event. + * @param loadEventInfo The {@link LoadEventInfo} corresponding to the event. The value of {@link + * LoadEventInfo#uri} won't reflect potential redirection yet. * @param mediaLoadData The {@link MediaLoadData} defining the data being loaded. */ void onLoadStarted( @@ -170,7 +183,10 @@ public interface MediaSourceEventListener { * @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 load does not * belong to a specific media period. - * @param loadEventInfo The {@link LoadEventInfo} defining the load event. + * @param loadEventInfo The {@link LoadEventInfo} corresponding to the event. The values of {@link + * LoadEventInfo#elapsedRealtimeMs} and {@link LoadEventInfo#bytesLoaded} are relative to the + * corresponding {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)} + * event. * @param mediaLoadData The {@link MediaLoadData} defining the data being loaded. */ void onLoadCompleted( @@ -185,7 +201,10 @@ public interface MediaSourceEventListener { * @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 load does not * belong to a specific media period. - * @param loadEventInfo The {@link LoadEventInfo} defining the load event. + * @param loadEventInfo The {@link LoadEventInfo} corresponding to the event. The values of {@link + * LoadEventInfo#elapsedRealtimeMs} and {@link LoadEventInfo#bytesLoaded} are relative to the + * corresponding {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)} + * event. * @param mediaLoadData The {@link MediaLoadData} defining the data being loaded. */ void onLoadCanceled( @@ -211,7 +230,10 @@ public interface MediaSourceEventListener { * @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 load does not * belong to a specific media period. - * @param loadEventInfo The {@link LoadEventInfo} defining the load event. + * @param loadEventInfo The {@link LoadEventInfo} corresponding to the event. The values of {@link + * LoadEventInfo#elapsedRealtimeMs} and {@link LoadEventInfo#bytesLoaded} are relative to the + * corresponding {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)} + * event. * @param mediaLoadData The {@link MediaLoadData} defining the data being loaded. * @param error The load error. * @param wasCanceled Whether the load was canceled as a result of the error. @@ -268,7 +290,7 @@ public interface MediaSourceEventListener { /** Creates an event dispatcher. */ public EventDispatcher() { this( - /* listenerAndHandlers= */ new CopyOnWriteArrayList(), + /* listenerAndHandlers= */ new CopyOnWriteArrayList<>(), /* windowIndex= */ 0, /* mediaPeriodId= */ null, /* mediaTimeOffsetMs= */ 0); @@ -327,40 +349,31 @@ public interface MediaSourceEventListener { /** Dispatches {@link #onMediaPeriodCreated(int, MediaPeriodId)}. */ public void mediaPeriodCreated() { - Assertions.checkState(mediaPeriodId != null); + MediaPeriodId mediaPeriodId = Assertions.checkNotNull(this.mediaPeriodId); for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) { final MediaSourceEventListener listener = listenerAndHandler.listener; postOrRun( listenerAndHandler.handler, - new Runnable() { - @Override - public void run() { - listener.onMediaPeriodCreated(windowIndex, mediaPeriodId); - } - }); + () -> listener.onMediaPeriodCreated(windowIndex, mediaPeriodId)); } } /** Dispatches {@link #onMediaPeriodReleased(int, MediaPeriodId)}. */ public void mediaPeriodReleased() { - Assertions.checkState(mediaPeriodId != null); + MediaPeriodId mediaPeriodId = Assertions.checkNotNull(this.mediaPeriodId); for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) { final MediaSourceEventListener listener = listenerAndHandler.listener; postOrRun( listenerAndHandler.handler, - new Runnable() { - @Override - public void run() { - listener.onMediaPeriodReleased(windowIndex, mediaPeriodId); - } - }); + () -> listener.onMediaPeriodReleased(windowIndex, mediaPeriodId)); } } /** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ - public void loadStarted(DataSpec dataSpec, int dataType, long elapsedRealtimeMs) { + public void loadStarted(DataSpec dataSpec, Uri uri, int dataType, long elapsedRealtimeMs) { loadStarted( dataSpec, + uri, dataType, C.TRACK_TYPE_UNKNOWN, null, @@ -374,6 +387,7 @@ public interface MediaSourceEventListener { /** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ public void loadStarted( DataSpec dataSpec, + Uri uri, int dataType, int trackType, @Nullable Format trackFormat, @@ -384,7 +398,7 @@ public interface MediaSourceEventListener { long elapsedRealtimeMs) { loadStarted( new LoadEventInfo( - dataSpec, elapsedRealtimeMs, /* loadDurationMs= */ 0, /* bytesLoaded= */ 0), + dataSpec, uri, elapsedRealtimeMs, /* loadDurationMs= */ 0, /* bytesLoaded= */ 0), new MediaLoadData( dataType, trackType, @@ -396,29 +410,26 @@ public interface MediaSourceEventListener { } /** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ - public void loadStarted(final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + public void loadStarted(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) { for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) { final MediaSourceEventListener listener = listenerAndHandler.listener; postOrRun( listenerAndHandler.handler, - new Runnable() { - @Override - public void run() { - listener.onLoadStarted(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData); - } - }); + () -> listener.onLoadStarted(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData)); } } /** Dispatches {@link #onLoadCompleted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ public void loadCompleted( DataSpec dataSpec, + Uri uri, int dataType, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) { loadCompleted( dataSpec, + uri, dataType, C.TRACK_TYPE_UNKNOWN, null, @@ -434,6 +445,7 @@ public interface MediaSourceEventListener { /** Dispatches {@link #onLoadCompleted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ public void loadCompleted( DataSpec dataSpec, + Uri uri, int dataType, int trackType, @Nullable Format trackFormat, @@ -445,7 +457,7 @@ public interface MediaSourceEventListener { long loadDurationMs, long bytesLoaded) { loadCompleted( - new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded), + new LoadEventInfo(dataSpec, uri, elapsedRealtimeMs, loadDurationMs, bytesLoaded), new MediaLoadData( dataType, trackType, @@ -457,30 +469,27 @@ public interface MediaSourceEventListener { } /** Dispatches {@link #onLoadCompleted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ - public void loadCompleted( - final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + public void loadCompleted(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) { for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) { final MediaSourceEventListener listener = listenerAndHandler.listener; postOrRun( listenerAndHandler.handler, - new Runnable() { - @Override - public void run() { - listener.onLoadCompleted(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData); - } - }); + () -> + listener.onLoadCompleted(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData)); } } /** Dispatches {@link #onLoadCanceled(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ public void loadCanceled( DataSpec dataSpec, + Uri uri, int dataType, long elapsedRealtimeMs, long loadDurationMs, long bytesLoaded) { loadCanceled( dataSpec, + uri, dataType, C.TRACK_TYPE_UNKNOWN, null, @@ -496,6 +505,7 @@ public interface MediaSourceEventListener { /** Dispatches {@link #onLoadCanceled(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ public void loadCanceled( DataSpec dataSpec, + Uri uri, int dataType, int trackType, @Nullable Format trackFormat, @@ -507,7 +517,7 @@ public interface MediaSourceEventListener { long loadDurationMs, long bytesLoaded) { loadCanceled( - new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded), + new LoadEventInfo(dataSpec, uri, elapsedRealtimeMs, loadDurationMs, bytesLoaded), new MediaLoadData( dataType, trackType, @@ -519,17 +529,13 @@ public interface MediaSourceEventListener { } /** Dispatches {@link #onLoadCanceled(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ - public void loadCanceled(final LoadEventInfo loadEventInfo, final MediaLoadData mediaLoadData) { + public void loadCanceled(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) { for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) { - final MediaSourceEventListener listener = listenerAndHandler.listener; + MediaSourceEventListener listener = listenerAndHandler.listener; postOrRun( listenerAndHandler.handler, - new Runnable() { - @Override - public void run() { - listener.onLoadCanceled(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData); - } - }); + () -> + listener.onLoadCanceled(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData)); } } @@ -539,6 +545,7 @@ public interface MediaSourceEventListener { */ public void loadError( DataSpec dataSpec, + Uri uri, int dataType, long elapsedRealtimeMs, long loadDurationMs, @@ -547,6 +554,7 @@ public interface MediaSourceEventListener { boolean wasCanceled) { loadError( dataSpec, + uri, dataType, C.TRACK_TYPE_UNKNOWN, null, @@ -567,6 +575,7 @@ public interface MediaSourceEventListener { */ public void loadError( DataSpec dataSpec, + Uri uri, int dataType, int trackType, @Nullable Format trackFormat, @@ -580,7 +589,7 @@ public interface MediaSourceEventListener { IOException error, boolean wasCanceled) { loadError( - new LoadEventInfo(dataSpec, elapsedRealtimeMs, loadDurationMs, bytesLoaded), + new LoadEventInfo(dataSpec, uri, elapsedRealtimeMs, loadDurationMs, bytesLoaded), new MediaLoadData( dataType, trackType, @@ -598,37 +607,28 @@ public interface MediaSourceEventListener { * boolean)}. */ public void loadError( - final LoadEventInfo loadEventInfo, - final MediaLoadData mediaLoadData, - final IOException error, - final boolean wasCanceled) { + LoadEventInfo loadEventInfo, + MediaLoadData mediaLoadData, + IOException error, + boolean wasCanceled) { for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) { final MediaSourceEventListener listener = listenerAndHandler.listener; postOrRun( listenerAndHandler.handler, - new Runnable() { - @Override - public void run() { + () -> listener.onLoadError( - windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData, error, wasCanceled); - } - }); + windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData, error, wasCanceled)); } } /** Dispatches {@link #onReadingStarted(int, MediaPeriodId)}. */ public void readingStarted() { - Assertions.checkState(mediaPeriodId != null); + MediaPeriodId mediaPeriodId = Assertions.checkNotNull(this.mediaPeriodId); for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) { final MediaSourceEventListener listener = listenerAndHandler.listener; postOrRun( listenerAndHandler.handler, - new Runnable() { - @Override - public void run() { - listener.onReadingStarted(windowIndex, mediaPeriodId); - } - }); + () -> listener.onReadingStarted(windowIndex, mediaPeriodId)); } } @@ -646,17 +646,13 @@ public interface MediaSourceEventListener { } /** Dispatches {@link #onUpstreamDiscarded(int, MediaPeriodId, MediaLoadData)}. */ - public void upstreamDiscarded(final MediaLoadData mediaLoadData) { + public void upstreamDiscarded(MediaLoadData mediaLoadData) { + MediaPeriodId mediaPeriodId = Assertions.checkNotNull(this.mediaPeriodId); for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) { final MediaSourceEventListener listener = listenerAndHandler.listener; postOrRun( listenerAndHandler.handler, - new Runnable() { - @Override - public void run() { - listener.onUpstreamDiscarded(windowIndex, mediaPeriodId, mediaLoadData); - } - }); + () -> listener.onUpstreamDiscarded(windowIndex, mediaPeriodId, mediaLoadData)); } } @@ -679,17 +675,12 @@ public interface MediaSourceEventListener { } /** Dispatches {@link #onDownstreamFormatChanged(int, MediaPeriodId, MediaLoadData)}. */ - public void downstreamFormatChanged(final MediaLoadData mediaLoadData) { + public void downstreamFormatChanged(MediaLoadData mediaLoadData) { for (ListenerAndHandler listenerAndHandler : listenerAndHandlers) { final MediaSourceEventListener listener = listenerAndHandler.listener; postOrRun( listenerAndHandler.handler, - new Runnable() { - @Override - public void run() { - listener.onDownstreamFormatChanged(windowIndex, mediaPeriodId, mediaLoadData); - } - }); + () -> listener.onDownstreamFormatChanged(windowIndex, mediaPeriodId, mediaLoadData)); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java index 43f09e4a67..4de2a10f2e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SingleSampleMediaPeriod.java @@ -27,6 +27,7 @@ import com.google.android.exoplayer2.upstream.DataSpec; import com.google.android.exoplayer2.upstream.Loader; import com.google.android.exoplayer2.upstream.Loader.LoadErrorAction; import com.google.android.exoplayer2.upstream.Loader.Loadable; +import com.google.android.exoplayer2.upstream.StatsDataSource; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import java.io.IOException; @@ -144,6 +145,7 @@ import java.util.Arrays; minLoadableRetryCount); eventDispatcher.loadStarted( dataSpec, + dataSpec.uri, C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, format, @@ -192,8 +194,13 @@ import java.util.Arrays; @Override public void onLoadCompleted(SourceLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) { + sampleSize = (int) loadable.dataSource.getBytesRead(); + sampleData = loadable.sampleData; + loadingFinished = true; + loadingSucceeded = true; eventDispatcher.loadCompleted( loadable.dataSpec, + loadable.dataSource.getLastOpenedUri(), C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, format, @@ -203,11 +210,7 @@ import java.util.Arrays; durationUs, elapsedRealtimeMs, loadDurationMs, - loadable.sampleSize); - sampleSize = loadable.sampleSize; - sampleData = loadable.sampleData; - loadingFinished = true; - loadingSucceeded = true; + sampleSize); } @Override @@ -215,6 +218,7 @@ import java.util.Arrays; boolean released) { eventDispatcher.loadCanceled( loadable.dataSpec, + loadable.dataSource.getLastOpenedUri(), C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, /* trackFormat= */ null, @@ -224,7 +228,7 @@ import java.util.Arrays; durationUs, elapsedRealtimeMs, loadDurationMs, - loadable.sampleSize); + loadable.dataSource.getBytesRead()); } @Override @@ -237,6 +241,7 @@ import java.util.Arrays; boolean cancel = treatLoadErrorsAsEndOfStream && errorCount >= minLoadableRetryCount; eventDispatcher.loadError( loadable.dataSpec, + loadable.dataSource.getLastOpenedUri(), C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, format, @@ -246,7 +251,7 @@ import java.util.Arrays; durationUs, elapsedRealtimeMs, loadDurationMs, - loadable.sampleSize, + loadable.dataSource.getBytesRead(), error, /* wasCanceled= */ cancel); if (cancel) { @@ -336,14 +341,13 @@ import java.util.Arrays; public final DataSpec dataSpec; - private final DataSource dataSource; + private final StatsDataSource dataSource; - private int sampleSize; private byte[] sampleData; public SourceLoadable(DataSpec dataSpec, DataSource dataSource) { this.dataSpec = dataSpec; - this.dataSource = dataSource; + this.dataSource = new StatsDataSource(dataSource); } @Override @@ -353,15 +357,15 @@ import java.util.Arrays; @Override public void load() throws IOException, InterruptedException { - // We always load from the beginning, so reset the sampleSize to 0. - sampleSize = 0; + // We always load from the beginning, so reset bytesRead to 0. + dataSource.resetBytesRead(); try { // Create and open the input. dataSource.open(dataSpec); // Load the sample data. int result = 0; while (result != C.RESULT_END_OF_INPUT) { - sampleSize += result; + int sampleSize = (int) dataSource.getBytesRead(); if (sampleData == null) { sampleData = new byte[INITIAL_SAMPLE_SIZE]; } else if (sampleSize == sampleData.length) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java index 44c6bdc20d..5d765c78f5 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/ads/AdsMediaSource.java @@ -539,6 +539,7 @@ public final class AdsMediaSource extends CompositeMediaSource { createEventDispatcher(/* mediaPeriodId= */ null) .loadError( dataSpec, + dataSpec.uri, C.DATA_TYPE_AD, C.TRACK_TYPE_UNKNOWN, /* loadDurationMs= */ 0, @@ -580,6 +581,7 @@ public final class AdsMediaSource extends CompositeMediaSource { createEventDispatcher(mediaPeriodId) .loadError( new DataSpec(adUri), + adUri, C.DATA_TYPE_AD, C.TRACK_TYPE_UNKNOWN, /* loadDurationMs= */ 0, diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java index 2d183ac1e0..325a75ea28 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/chunk/ChunkSampleStream.java @@ -386,9 +386,18 @@ public class ChunkSampleStream implements SampleStream, S @Override public void onLoadCompleted(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs) { chunkSource.onChunkLoadCompleted(loadable); - eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, primaryTrackType, - loadable.trackFormat, loadable.trackSelectionReason, loadable.trackSelectionData, - loadable.startTimeUs, loadable.endTimeUs, elapsedRealtimeMs, loadDurationMs, + eventDispatcher.loadCompleted( + loadable.dataSpec, + loadable.getUri(), + loadable.type, + primaryTrackType, + loadable.trackFormat, + loadable.trackSelectionReason, + loadable.trackSelectionData, + loadable.startTimeUs, + loadable.endTimeUs, + elapsedRealtimeMs, + loadDurationMs, loadable.bytesLoaded()); callback.onContinueLoadingRequested(this); } @@ -396,9 +405,18 @@ public class ChunkSampleStream implements SampleStream, S @Override public void onLoadCanceled(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs, boolean released) { - eventDispatcher.loadCanceled(loadable.dataSpec, loadable.type, primaryTrackType, - loadable.trackFormat, loadable.trackSelectionReason, loadable.trackSelectionData, - loadable.startTimeUs, loadable.endTimeUs, elapsedRealtimeMs, loadDurationMs, + eventDispatcher.loadCanceled( + loadable.dataSpec, + loadable.getUri(), + loadable.type, + primaryTrackType, + loadable.trackFormat, + loadable.trackSelectionReason, + loadable.trackSelectionData, + loadable.startTimeUs, + loadable.endTimeUs, + elapsedRealtimeMs, + loadDurationMs, loadable.bytesLoaded()); if (!released) { primarySampleQueue.reset(); @@ -436,10 +454,21 @@ public class ChunkSampleStream implements SampleStream, S } } } - eventDispatcher.loadError(loadable.dataSpec, loadable.type, primaryTrackType, - loadable.trackFormat, loadable.trackSelectionReason, loadable.trackSelectionData, - loadable.startTimeUs, loadable.endTimeUs, elapsedRealtimeMs, loadDurationMs, bytesLoaded, - error, canceled); + eventDispatcher.loadError( + loadable.dataSpec, + loadable.getUri(), + loadable.type, + primaryTrackType, + loadable.trackFormat, + loadable.trackSelectionReason, + loadable.trackSelectionData, + loadable.startTimeUs, + loadable.endTimeUs, + elapsedRealtimeMs, + loadDurationMs, + bytesLoaded, + error, + canceled); if (canceled) { callback.onContinueLoadingRequested(this); return Loader.DONT_RETRY; @@ -493,9 +522,17 @@ public class ChunkSampleStream implements SampleStream, S mediaChunks.add(mediaChunk); } long elapsedRealtimeMs = loader.startLoading(loadable, this, minLoadableRetryCount); - eventDispatcher.loadStarted(loadable.dataSpec, loadable.type, primaryTrackType, - loadable.trackFormat, loadable.trackSelectionReason, loadable.trackSelectionData, - loadable.startTimeUs, loadable.endTimeUs, elapsedRealtimeMs); + eventDispatcher.loadStarted( + loadable.dataSpec, + loadable.dataSpec.uri, + loadable.type, + primaryTrackType, + loadable.trackFormat, + loadable.trackSelectionReason, + loadable.trackSelectionData, + loadable.startTimeUs, + loadable.endTimeUs, + elapsedRealtimeMs); return true; } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java index 4a17b070a6..17d479daab 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/ParsingLoadable.java @@ -77,11 +77,10 @@ public final class ParsingLoadable implements Loadable { */ public final int type; - private final DataSource dataSource; + private final StatsDataSource dataSource; private final Parser parser; private volatile @Nullable T result; - private volatile long bytesLoaded; /** * @param dataSource A {@link DataSource} to use when loading the data. @@ -105,7 +104,7 @@ public final class ParsingLoadable implements Loadable { */ public ParsingLoadable(DataSource dataSource, DataSpec dataSpec, int type, Parser parser) { - this.dataSource = dataSource; + this.dataSource = new StatsDataSource(dataSource); this.dataSpec = dataSpec; this.type = type; this.parser = parser; @@ -118,12 +117,19 @@ public final class ParsingLoadable implements Loadable { /** * Returns the number of bytes loaded. In the case that the network response was compressed, the - * value returned is the size of the data after decompression. - * - * @return The number of bytes loaded. + * value returned is the size of the data after decompression. Must only be called after + * the load completed, failed, or was canceled. */ public long bytesLoaded() { - return bytesLoaded; + return dataSource.getBytesRead(); + } + + /** + * Returns the {@link Uri} from which data was read. If redirection occurred, this is the + * redirected uri. Must only be called after the load completed, failed, or was canceled. + */ + public Uri getUri() { + return dataSource.getLastOpenedUri(); } @Override @@ -133,13 +139,14 @@ public final class ParsingLoadable implements Loadable { @Override public final void load() throws IOException { + // We always load from the beginning, so reset bytesRead to 0. + dataSource.resetBytesRead(); DataSourceInputStream inputStream = new DataSourceInputStream(dataSource, dataSpec); try { inputStream.open(); Uri dataSourceUri = Assertions.checkNotNull(dataSource.getUri()); result = parser.parse(dataSourceUri, inputStream); } finally { - bytesLoaded = inputStream.bytesRead(); Util.closeQuietly(inputStream); } } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java b/library/core/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java index 71458b24a4..79868806d1 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/upstream/StatsDataSource.java @@ -47,6 +47,11 @@ public final class StatsDataSource implements DataSource { lastResponseHeaders = Collections.emptyMap(); } + /** Resets the number of bytes read as returned from {@link #getBytesRead()} to zero. */ + public void resetBytesRead() { + bytesRead = 0; + } + /** Returns the total number of bytes that have been read from the data source. */ public long getBytesRead() { return bytesRead; diff --git a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java index 530c41684d..d826e4165f 100644 --- a/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java +++ b/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashMediaSource.java @@ -638,6 +638,7 @@ public final class DashMediaSource extends BaseMediaSource { long elapsedRealtimeMs, long loadDurationMs) { manifestEventDispatcher.loadCompleted( loadable.dataSpec, + loadable.getUri(), loadable.type, elapsedRealtimeMs, loadDurationMs, @@ -699,7 +700,9 @@ public final class DashMediaSource extends BaseMediaSource { synchronized (manifestUriLock) { // This condition checks that replaceManifestUri wasn't called between the start and end of // this load. If it was, we ignore the manifest location and prefer the manual replacement. - if (loadable.dataSpec.uri == manifestUri) { + @SuppressWarnings("ReferenceEquality") + boolean isSameUriInstance = loadable.dataSpec.uri == manifestUri; + if (isSameUriInstance) { manifestUri = manifest.location; } } @@ -725,6 +728,7 @@ public final class DashMediaSource extends BaseMediaSource { boolean isFatal = error instanceof ParserException; manifestEventDispatcher.loadError( loadable.dataSpec, + loadable.getUri(), loadable.type, elapsedRealtimeMs, loadDurationMs, @@ -738,6 +742,7 @@ public final class DashMediaSource extends BaseMediaSource { long elapsedRealtimeMs, long loadDurationMs) { manifestEventDispatcher.loadCompleted( loadable.dataSpec, + loadable.getUri(), loadable.type, elapsedRealtimeMs, loadDurationMs, @@ -752,6 +757,7 @@ public final class DashMediaSource extends BaseMediaSource { IOException error) { manifestEventDispatcher.loadError( loadable.dataSpec, + loadable.getUri(), loadable.type, elapsedRealtimeMs, loadDurationMs, @@ -766,6 +772,7 @@ public final class DashMediaSource extends BaseMediaSource { long loadDurationMs) { manifestEventDispatcher.loadCanceled( loadable.dataSpec, + loadable.getUri(), loadable.type, elapsedRealtimeMs, loadDurationMs, @@ -953,7 +960,8 @@ public final class DashMediaSource extends BaseMediaSource { private void startLoading(ParsingLoadable loadable, Loader.Callback> callback, int minRetryCount) { long elapsedRealtimeMs = loader.startLoading(loadable, callback, minRetryCount); - manifestEventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs); + manifestEventDispatcher.loadStarted( + loadable.dataSpec, loadable.dataSpec.uri, loadable.type, elapsedRealtimeMs); } private long getNowUnixTimeUs() { diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java index f55fc78b60..13f44aa3dd 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java @@ -562,9 +562,17 @@ import java.util.Arrays; mediaChunks.add(mediaChunk); } long elapsedRealtimeMs = loader.startLoading(loadable, this, minLoadableRetryCount); - eventDispatcher.loadStarted(loadable.dataSpec, loadable.type, trackType, loadable.trackFormat, - loadable.trackSelectionReason, loadable.trackSelectionData, loadable.startTimeUs, - loadable.endTimeUs, elapsedRealtimeMs); + eventDispatcher.loadStarted( + loadable.dataSpec, + loadable.dataSpec.uri, + loadable.type, + trackType, + loadable.trackFormat, + loadable.trackSelectionReason, + loadable.trackSelectionData, + loadable.startTimeUs, + loadable.endTimeUs, + elapsedRealtimeMs); return true; } @@ -578,9 +586,19 @@ import java.util.Arrays; @Override public void onLoadCompleted(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs) { chunkSource.onChunkLoadCompleted(loadable); - eventDispatcher.loadCompleted(loadable.dataSpec, loadable.type, trackType, loadable.trackFormat, - loadable.trackSelectionReason, loadable.trackSelectionData, loadable.startTimeUs, - loadable.endTimeUs, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); + eventDispatcher.loadCompleted( + loadable.dataSpec, + loadable.getUri(), + loadable.type, + trackType, + loadable.trackFormat, + loadable.trackSelectionReason, + loadable.trackSelectionData, + loadable.startTimeUs, + loadable.endTimeUs, + elapsedRealtimeMs, + loadDurationMs, + loadable.bytesLoaded()); if (!prepared) { continueLoading(lastSeekPositionUs); } else { @@ -591,9 +609,19 @@ import java.util.Arrays; @Override public void onLoadCanceled(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs, boolean released) { - eventDispatcher.loadCanceled(loadable.dataSpec, loadable.type, trackType, loadable.trackFormat, - loadable.trackSelectionReason, loadable.trackSelectionData, loadable.startTimeUs, - loadable.endTimeUs, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded()); + eventDispatcher.loadCanceled( + loadable.dataSpec, + loadable.getUri(), + loadable.type, + trackType, + loadable.trackFormat, + loadable.trackSelectionReason, + loadable.trackSelectionData, + loadable.startTimeUs, + loadable.endTimeUs, + elapsedRealtimeMs, + loadDurationMs, + loadable.bytesLoaded()); if (!released) { resetSampleQueues(); if (enabledTrackGroupCount > 0) { @@ -623,9 +651,20 @@ import java.util.Arrays; } canceled = true; } - eventDispatcher.loadError(loadable.dataSpec, loadable.type, trackType, loadable.trackFormat, - loadable.trackSelectionReason, loadable.trackSelectionData, loadable.startTimeUs, - loadable.endTimeUs, elapsedRealtimeMs, loadDurationMs, loadable.bytesLoaded(), error, + eventDispatcher.loadError( + loadable.dataSpec, + loadable.getUri(), + loadable.type, + trackType, + loadable.trackFormat, + loadable.trackSelectionReason, + loadable.trackSelectionData, + loadable.startTimeUs, + loadable.endTimeUs, + elapsedRealtimeMs, + loadDurationMs, + loadable.bytesLoaded(), + error, canceled); if (canceled) { if (!prepared) { diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java index 15136236eb..97a4ecc181 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/playlist/DefaultHlsPlaylistTracker.java @@ -102,7 +102,10 @@ public final class DefaultHlsPlaylistTracker long elapsedRealtime = initialPlaylistLoader.startLoading(masterPlaylistLoadable, this, minRetryCount); eventDispatcher.loadStarted( - masterPlaylistLoadable.dataSpec, masterPlaylistLoadable.type, elapsedRealtime); + masterPlaylistLoadable.dataSpec, + masterPlaylistLoadable.dataSpec.uri, + masterPlaylistLoadable.type, + elapsedRealtime); } @Override @@ -209,6 +212,7 @@ public final class DefaultHlsPlaylistTracker } eventDispatcher.loadCompleted( loadable.dataSpec, + loadable.getUri(), C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, @@ -223,6 +227,7 @@ public final class DefaultHlsPlaylistTracker boolean released) { eventDispatcher.loadCanceled( loadable.dataSpec, + loadable.getUri(), C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, @@ -239,6 +244,7 @@ public final class DefaultHlsPlaylistTracker boolean isFatal = error instanceof ParserException; eventDispatcher.loadError( loadable.dataSpec, + loadable.getUri(), C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, @@ -463,6 +469,7 @@ public final class DefaultHlsPlaylistTracker processLoadedPlaylist((HlsMediaPlaylist) result); eventDispatcher.loadCompleted( loadable.dataSpec, + loadable.getUri(), C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, @@ -480,6 +487,7 @@ public final class DefaultHlsPlaylistTracker boolean released) { eventDispatcher.loadCanceled( loadable.dataSpec, + loadable.getUri(), C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, @@ -496,6 +504,7 @@ public final class DefaultHlsPlaylistTracker boolean isFatal = error instanceof ParserException; eventDispatcher.loadError( loadable.dataSpec, + loadable.getUri(), C.DATA_TYPE_MANIFEST, elapsedRealtimeMs, loadDurationMs, @@ -528,7 +537,10 @@ public final class DefaultHlsPlaylistTracker long elapsedRealtime = mediaPlaylistLoader.startLoading(mediaPlaylistLoadable, this, minRetryCount); eventDispatcher.loadStarted( - mediaPlaylistLoadable.dataSpec, mediaPlaylistLoadable.type, elapsedRealtime); + mediaPlaylistLoadable.dataSpec, + mediaPlaylistLoadable.dataSpec.uri, + mediaPlaylistLoadable.type, + elapsedRealtime); } private void processLoadedPlaylist(HlsMediaPlaylist loadedPlaylist) { diff --git a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java index 7da0e92739..19335a78fa 100644 --- a/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java +++ b/library/smoothstreaming/src/main/java/com/google/android/exoplayer2/source/smoothstreaming/SsMediaSource.java @@ -519,6 +519,7 @@ public final class SsMediaSource extends BaseMediaSource long loadDurationMs) { manifestEventDispatcher.loadCompleted( loadable.dataSpec, + loadable.getUri(), loadable.type, elapsedRealtimeMs, loadDurationMs, @@ -534,6 +535,7 @@ public final class SsMediaSource extends BaseMediaSource long loadDurationMs, boolean released) { manifestEventDispatcher.loadCanceled( loadable.dataSpec, + loadable.getUri(), loadable.type, elapsedRealtimeMs, loadDurationMs, @@ -550,6 +552,7 @@ public final class SsMediaSource extends BaseMediaSource boolean isFatal = error instanceof ParserException; manifestEventDispatcher.loadError( loadable.dataSpec, + loadable.getUri(), loadable.type, elapsedRealtimeMs, loadDurationMs, @@ -643,7 +646,8 @@ public final class SsMediaSource extends BaseMediaSource ParsingLoadable loadable = new ParsingLoadable<>(manifestDataSource, manifestUri, C.DATA_TYPE_MANIFEST, manifestParser); long elapsedRealtimeMs = manifestLoader.startLoading(loadable, this, minLoadableRetryCount); - manifestEventDispatcher.loadStarted(loadable.dataSpec, loadable.type, elapsedRealtimeMs); + manifestEventDispatcher.loadStarted( + loadable.dataSpec, loadable.dataSpec.uri, loadable.type, elapsedRealtimeMs); } } diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java index a251bd5ef0..8cef80766b 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaPeriod.java @@ -121,6 +121,7 @@ public class FakeMediaPeriod implements MediaPeriod { public synchronized void prepare(Callback callback, long positionUs) { eventDispatcher.loadStarted( FAKE_DATA_SPEC, + FAKE_DATA_SPEC.uri, C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, /* trackFormat= */ null, @@ -232,6 +233,7 @@ public class FakeMediaPeriod implements MediaPeriod { prepareCallback.onPrepared(this); eventDispatcher.loadCompleted( FAKE_DATA_SPEC, + FAKE_DATA_SPEC.uri, C.DATA_TYPE_MEDIA, C.TRACK_TYPE_UNKNOWN, /* trackFormat= */ null, diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaSource.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaSource.java index ec8bd6b75a..3b0823ad76 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaSource.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeMediaSource.java @@ -216,11 +216,16 @@ public class FakeMediaSource extends BaseMediaSource { EventDispatcher eventDispatcher = createEventDispatcher(/* mediaPeriodId= */ null); eventDispatcher.loadStarted( new LoadEventInfo( - FAKE_DATA_SPEC, elapsedRealTimeMs, /* loadDurationMs= */ 0, /* bytesLoaded= */ 0), + FAKE_DATA_SPEC, + FAKE_DATA_SPEC.uri, + elapsedRealTimeMs, + /* loadDurationMs= */ 0, + /* bytesLoaded= */ 0), mediaLoadData); eventDispatcher.loadCompleted( new LoadEventInfo( FAKE_DATA_SPEC, + FAKE_DATA_SPEC.uri, elapsedRealTimeMs, /* loadDurationMs= */ 0, /* bytesLoaded= */ MANIFEST_LOAD_BYTES),