Incorporate MediaSourceEventListener.onLoadStarted with retryCount parameter with backward compatibility

This commit is contained in:
Colin Kho 2024-09-27 00:02:11 -07:00 committed by Ian Baker
parent 45317394da
commit 8adcd35c75
19 changed files with 223 additions and 18 deletions

View File

@ -576,6 +576,25 @@ import java.util.Set;
} }
} }
@Override
public void onLoadStarted(
int windowIndex,
@Nullable MediaSource.MediaPeriodId mediaPeriodId,
LoadEventInfo loadEventData,
MediaLoadData mediaLoadData,
int retryCount) {
@Nullable
Pair<Integer, MediaSource.@NullableType MediaPeriodId> eventParameters =
getEventParameters(windowIndex, mediaPeriodId);
if (eventParameters != null) {
eventHandler.post(
() ->
eventListener.onLoadStarted(
eventParameters.first, eventParameters.second,
loadEventData, mediaLoadData, retryCount));
}
}
@Override @Override
public void onLoadCompleted( public void onLoadCompleted(
int windowIndex, int windowIndex,

View File

@ -851,9 +851,26 @@ public interface AnalyticsListener {
* @param mediaLoadData The {@link MediaLoadData} defining the data being loaded. * @param mediaLoadData The {@link MediaLoadData} defining the data being loaded.
*/ */
@UnstableApi @UnstableApi
@Deprecated
default void onLoadStarted( default void onLoadStarted(
EventTime eventTime, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) {} EventTime eventTime, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) {}
/**
* Called when a media source started loading data.
*
* @param eventTime The event time.
* @param loadEventInfo The {@link LoadEventInfo} defining the load event.
* @param mediaLoadData The {@link MediaLoadData} defining the data being loaded.
* @param retryCount The number of failed attempts since {@link #onLoadStarted} was called (this
* is zero for the first load attempt).
*/
@UnstableApi
default void onLoadStarted(
EventTime eventTime,
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData,
int retryCount) {}
/** /**
* Called when a media source completed loading data. * Called when a media source completed loading data.
* *

View File

@ -410,6 +410,20 @@ public class DefaultAnalyticsCollector implements AnalyticsCollector {
listener -> listener.onLoadStarted(eventTime, loadEventInfo, mediaLoadData)); listener -> listener.onLoadStarted(eventTime, loadEventInfo, mediaLoadData));
} }
@Override
public final void onLoadStarted(
int windowIndex,
@Nullable MediaPeriodId mediaPeriodId,
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData,
int retryCount) {
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
sendEvent(
eventTime,
AnalyticsListener.EVENT_LOAD_STARTED,
listener -> listener.onLoadStarted(eventTime, loadEventInfo, mediaLoadData, retryCount));
}
@Override @Override
public final void onLoadCompleted( public final void onLoadCompleted(
int windowIndex, int windowIndex,

View File

@ -246,6 +246,19 @@ public abstract class CompositeMediaSource<T> extends BaseMediaSource {
} }
} }
@Override
public void onLoadStarted(
int windowIndex,
@Nullable MediaPeriodId mediaPeriodId,
LoadEventInfo loadEventData,
MediaLoadData mediaLoadData,
int retryCount) {
if (maybeUpdateEventDispatcher(windowIndex, mediaPeriodId)) {
mediaSourceEventDispatcher.loadStarted(
loadEventData, maybeUpdateMediaLoadData(mediaLoadData, mediaPeriodId), retryCount);
}
}
@Override @Override
public void onLoadCompleted( public void onLoadCompleted(
int windowIndex, int windowIndex,

View File

@ -47,12 +47,37 @@ public interface MediaSourceEventListener {
* LoadEventInfo#responseHeaders} will be empty. * LoadEventInfo#responseHeaders} will be empty.
* @param mediaLoadData The {@link MediaLoadData} defining the data being loaded. * @param mediaLoadData The {@link MediaLoadData} defining the data being loaded.
*/ */
@Deprecated
default void onLoadStarted( default void onLoadStarted(
int windowIndex, int windowIndex,
@Nullable MediaPeriodId mediaPeriodId, @Nullable MediaPeriodId mediaPeriodId,
LoadEventInfo loadEventInfo, LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData) {} MediaLoadData mediaLoadData) {}
/**
* Called when a load begins.
*
* @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} corresponding to the event. The value of {@link
* LoadEventInfo#uri} won't reflect potential redirection yet and {@link
* LoadEventInfo#responseHeaders} will be empty.
* @param mediaLoadData The {@link MediaLoadData} defining the data being loaded.
* @param retryCount The number of failed attempts since {@link #onLoadStarted} was called (this
* is zero for the first load attempt).
*/
default void onLoadStarted(
int windowIndex,
@Nullable MediaPeriodId mediaPeriodId,
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData,
int retryCount) {
if (retryCount == 0) {
onLoadStarted(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData);
}
}
/** /**
* Called when a load ends. * Called when a load ends.
* *
@ -224,6 +249,7 @@ public interface MediaSourceEventListener {
} }
/** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ /** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */
@Deprecated
public void loadStarted(LoadEventInfo loadEventInfo, @DataType int dataType) { public void loadStarted(LoadEventInfo loadEventInfo, @DataType int dataType) {
loadStarted( loadStarted(
loadEventInfo, loadEventInfo,
@ -236,7 +262,22 @@ public interface MediaSourceEventListener {
/* mediaEndTimeUs= */ C.TIME_UNSET); /* mediaEndTimeUs= */ C.TIME_UNSET);
} }
/** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData, int)}. */
public void loadStarted(LoadEventInfo loadEventInfo, @DataType int dataType, int retryCount) {
loadStarted(
loadEventInfo,
dataType,
/* trackType= */ C.TRACK_TYPE_UNKNOWN,
/* trackFormat= */ null,
/* trackSelectionReason= */ C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null,
/* mediaStartTimeUs= */ C.TIME_UNSET,
/* mediaEndTimeUs= */ C.TIME_UNSET,
/* retryCount= */ retryCount);
}
/** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ /** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */
@Deprecated
public void loadStarted( public void loadStarted(
LoadEventInfo loadEventInfo, LoadEventInfo loadEventInfo,
@DataType int dataType, @DataType int dataType,
@ -258,11 +299,48 @@ public interface MediaSourceEventListener {
usToMs(mediaEndTimeUs))); usToMs(mediaEndTimeUs)));
} }
/** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData, int)}. */
public void loadStarted(
LoadEventInfo loadEventInfo,
@DataType int dataType,
@C.TrackType int trackType,
@Nullable Format trackFormat,
@C.SelectionReason int trackSelectionReason,
@Nullable Object trackSelectionData,
long mediaStartTimeUs,
long mediaEndTimeUs,
int retryCount) {
loadStarted(
loadEventInfo,
new MediaLoadData(
dataType,
trackType,
trackFormat,
trackSelectionReason,
trackSelectionData,
usToMs(mediaStartTimeUs),
usToMs(mediaEndTimeUs)),
retryCount);
}
/** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ /** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */
@Deprecated
public void loadStarted(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) { public void loadStarted(LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) {
dispatchEvent( dispatchEvent(
(listener) -> (listener) ->
listener.onLoadStarted(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData)); listener.onLoadStarted(
windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData));
}
/** Dispatches {@link #onLoadStarted(int, MediaPeriodId, LoadEventInfo, MediaLoadData, int)}. */
public void loadStarted(
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData,
int retryCount) {
dispatchEvent(
(listener) ->
listener.onLoadStarted(
windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData, retryCount));
} }
/** Dispatches {@link #onLoadCompleted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */ /** Dispatches {@link #onLoadCompleted(int, MediaPeriodId, LoadEventInfo, MediaLoadData)}. */

View File

@ -597,6 +597,33 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
// Loader.Callback implementation. // Loader.Callback implementation.
@Override
public void onLoadStarted(
ExtractingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs, int retryCount) {
if (retryCount > 0) {
StatsDataSource dataSource = loadable.dataSource;
LoadEventInfo loadEventInfo =
new LoadEventInfo(
loadable.loadTaskId,
loadable.dataSpec,
dataSource.getLastOpenedUri(),
dataSource.getLastResponseHeaders(),
elapsedRealtimeMs,
loadDurationMs,
dataSource.getBytesRead());
mediaSourceEventDispatcher.loadStarted(
loadEventInfo,
C.DATA_TYPE_MEDIA,
C.TRACK_TYPE_UNKNOWN,
/* trackFormat= */ null,
C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null,
/* mediaStartTimeUs= */ loadable.seekTimeUs,
durationUs,
retryCount);
}
}
@Override @Override
public void onLoadCompleted( public void onLoadCompleted(
ExtractingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) { ExtractingLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) {
@ -893,7 +920,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
C.SELECTION_REASON_UNKNOWN, C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null, /* trackSelectionData= */ null,
/* mediaStartTimeUs= */ loadable.seekTimeUs, /* mediaStartTimeUs= */ loadable.seekTimeUs,
durationUs); durationUs,
0);
} }
/** /**

View File

@ -168,7 +168,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
C.SELECTION_REASON_UNKNOWN, C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null, /* trackSelectionData= */ null,
/* mediaStartTimeUs= */ 0, /* mediaStartTimeUs= */ 0,
durationUs); durationUs,
/* retryCount= */ 0);
return true; return true;
} }

View File

@ -427,12 +427,13 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
int windowIndex, int windowIndex,
@Nullable MediaPeriodId mediaPeriodId, @Nullable MediaPeriodId mediaPeriodId,
LoadEventInfo loadEventInfo, LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData) { MediaLoadData mediaLoadData,
int retryCount) {
@Nullable @Nullable
MediaPeriodImpl mediaPeriod = MediaPeriodImpl mediaPeriod =
getMediaPeriodForEvent(mediaPeriodId, mediaLoadData, /* useLoadingPeriod= */ true); getMediaPeriodForEvent(mediaPeriodId, mediaLoadData, /* useLoadingPeriod= */ true);
if (mediaPeriod == null) { if (mediaPeriod == null) {
mediaSourceEventDispatcherWithoutId.loadStarted(loadEventInfo, mediaLoadData); mediaSourceEventDispatcherWithoutId.loadStarted(loadEventInfo, mediaLoadData, retryCount);
} else { } else {
mediaPeriod.sharedPeriod.onLoadStarted(loadEventInfo, mediaLoadData); mediaPeriod.sharedPeriod.onLoadStarted(loadEventInfo, mediaLoadData);
mediaPeriod.mediaSourceEventDispatcher.loadStarted( mediaPeriod.mediaSourceEventDispatcher.loadStarted(
@ -440,7 +441,8 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
correctMediaLoadData( correctMediaLoadData(
mediaPeriod, mediaPeriod,
mediaLoadData, mediaLoadData,
checkNotNull(adPlaybackStates.get(mediaPeriod.mediaPeriodId.periodUid)))); checkNotNull(adPlaybackStates.get(mediaPeriod.mediaPeriodId.periodUid))),
retryCount);
} }
} }
@ -750,7 +752,9 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
loadData.first, loadData.first,
correctMediaLoadData(loadingPeriod, loadData.second, adPlaybackState)); correctMediaLoadData(loadingPeriod, loadData.second, adPlaybackState));
mediaPeriod.mediaSourceEventDispatcher.loadStarted( mediaPeriod.mediaSourceEventDispatcher.loadStarted(
loadData.first, correctMediaLoadData(mediaPeriod, loadData.second, adPlaybackState)); loadData.first,
correctMediaLoadData(mediaPeriod, loadData.second, adPlaybackState),
0);
} }
} }
this.loadingPeriod = mediaPeriod; this.loadingPeriod = mediaPeriod;

View File

@ -647,7 +647,8 @@ public class ChunkSampleStream<T extends ChunkSource>
loadable.trackSelectionReason, loadable.trackSelectionReason,
loadable.trackSelectionData, loadable.trackSelectionData,
loadable.startTimeUs, loadable.startTimeUs,
loadable.endTimeUs); loadable.endTimeUs,
0);
return true; return true;
} }

View File

@ -132,6 +132,7 @@ import java.io.IOException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -1715,7 +1716,7 @@ public final class DefaultAnalyticsCollectorTest {
ArgumentCaptor<AnalyticsListener.EventTime> individualLoadStartedEventTimes = ArgumentCaptor<AnalyticsListener.EventTime> individualLoadStartedEventTimes =
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class); ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
verify(listener, atLeastOnce()) verify(listener, atLeastOnce())
.onLoadStarted(individualLoadStartedEventTimes.capture(), any(), any()); .onLoadStarted(individualLoadStartedEventTimes.capture(), any(), any(), anyInt());
ArgumentCaptor<AnalyticsListener.EventTime> individualLoadCompletedEventTimes = ArgumentCaptor<AnalyticsListener.EventTime> individualLoadCompletedEventTimes =
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class); ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
verify(listener, atLeastOnce()) verify(listener, atLeastOnce())
@ -2199,6 +2200,15 @@ public final class DefaultAnalyticsCollectorTest {
reportedEvents.add(new ReportedEvent(EVENT_LOAD_STARTED, eventTime)); reportedEvents.add(new ReportedEvent(EVENT_LOAD_STARTED, eventTime));
} }
@Override
public void onLoadStarted(
EventTime eventTime,
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData,
int retryCount) {
reportedEvents.add(new ReportedEvent(EVENT_LOAD_STARTED, eventTime));
}
@Override @Override
public void onLoadCompleted( public void onLoadCompleted(
EventTime eventTime, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) { EventTime eventTime, LoadEventInfo loadEventInfo, MediaLoadData mediaLoadData) {

View File

@ -20,6 +20,7 @@ import static androidx.media3.test.utils.robolectric.TestPlayerRunHelper.runUnti
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static java.lang.Math.max; import static java.lang.Math.max;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@ -625,7 +626,8 @@ public final class ConcatenatingMediaSource2Test {
/* windowIndex= */ eq(0), /* windowIndex= */ eq(0),
/* mediaPeriodId= */ eq(mediaPeriodId), /* mediaPeriodId= */ eq(mediaPeriodId),
/* loadEventInfo= */ any(), /* loadEventInfo= */ any(),
/* mediaLoadData= */ any()); /* mediaLoadData= */ any(),
/* retryCount */ anyInt());
verify(eventListener) verify(eventListener)
.onLoadCompleted( .onLoadCompleted(
/* windowIndex= */ eq(0), /* windowIndex= */ eq(0),

View File

@ -1097,7 +1097,8 @@ public final class DashMediaSource extends BaseMediaSource {
long elapsedRealtimeMs = loader.startLoading(loadable, callback, minRetryCount); long elapsedRealtimeMs = loader.startLoading(loadable, callback, minRetryCount);
manifestEventDispatcher.loadStarted( manifestEventDispatcher.loadStarted(
new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs), new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs),
loadable.type); loadable.type,
0);
} }
private static long getIntervalUntilNextManifestRefreshMs( private static long getIntervalUntilNextManifestRefreshMs(

View File

@ -819,7 +819,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
loadable.trackSelectionReason, loadable.trackSelectionReason,
loadable.trackSelectionData, loadable.trackSelectionData,
loadable.startTimeUs, loadable.startTimeUs,
loadable.endTimeUs); loadable.endTimeUs,
0);
return true; return true;
} }

View File

@ -152,7 +152,8 @@ public final class DefaultHlsPlaylistTracker
multivariantPlaylistLoadable.loadTaskId, multivariantPlaylistLoadable.loadTaskId,
multivariantPlaylistLoadable.dataSpec, multivariantPlaylistLoadable.dataSpec,
elapsedRealtime), elapsedRealtime),
multivariantPlaylistLoadable.type); multivariantPlaylistLoadable.type,
0);
} }
@Override @Override
@ -744,7 +745,8 @@ public final class DefaultHlsPlaylistTracker
eventDispatcher.loadStarted( eventDispatcher.loadStarted(
new LoadEventInfo( new LoadEventInfo(
mediaPlaylistLoadable.loadTaskId, mediaPlaylistLoadable.dataSpec, elapsedRealtime), mediaPlaylistLoadable.loadTaskId, mediaPlaylistLoadable.dataSpec, elapsedRealtime),
mediaPlaylistLoadable.type); mediaPlaylistLoadable.type,
0);
} }
private void processLoadedPlaylist( private void processLoadedPlaylist(

View File

@ -664,6 +664,7 @@ public final class SsMediaSource extends BaseMediaSource
loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(loadable.type)); loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(loadable.type));
manifestEventDispatcher.loadStarted( manifestEventDispatcher.loadStarted(
new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs), new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs),
loadable.type); loadable.type,
0);
} }
} }

View File

@ -116,7 +116,8 @@ public class FakeAdaptiveMediaPeriod
C.SELECTION_REASON_UNKNOWN, C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null, /* trackSelectionData= */ null,
/* mediaStartTimeUs= */ 0, /* mediaStartTimeUs= */ 0,
/* mediaEndTimeUs= */ C.TIME_UNSET); /* mediaEndTimeUs= */ C.TIME_UNSET,
/* retryCount= */ 0);
this.callback = callback; this.callback = callback;
prepared = true; prepared = true;
Util.castNonNull(this.callback).onPrepared(this); Util.castNonNull(this.callback).onPrepared(this);

View File

@ -235,7 +235,8 @@ public class FakeMediaPeriod implements MediaPeriod {
C.SELECTION_REASON_UNKNOWN, C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null, /* trackSelectionData= */ null,
/* mediaStartTimeUs= */ 0, /* mediaStartTimeUs= */ 0,
/* mediaEndTimeUs= */ C.TIME_UNSET); /* mediaEndTimeUs= */ C.TIME_UNSET,
0);
prepareCallback = callback; prepareCallback = callback;
if (deferOnPrepared) { if (deferOnPrepared) {
playerHandler = Util.createHandlerForCurrentLooper(); playerHandler = Util.createHandlerForCurrentLooper();

View File

@ -455,7 +455,8 @@ public class FakeMediaSource extends BaseMediaSource {
elapsedRealTimeMs, elapsedRealTimeMs,
/* loadDurationMs= */ 0, /* loadDurationMs= */ 0,
/* bytesLoaded= */ 0), /* bytesLoaded= */ 0),
mediaLoadData); mediaLoadData,
0);
eventDispatcher.loadCompleted( eventDispatcher.loadCompleted(
new LoadEventInfo( new LoadEventInfo(
loadTaskId, loadTaskId,

View File

@ -368,6 +368,16 @@ public class MediaSourceTestRunner {
Assertions.checkState(Looper.myLooper() == playbackThread.getLooper()); Assertions.checkState(Looper.myLooper() == playbackThread.getLooper());
} }
@Override
public void onLoadStarted(
int windowIndex,
@Nullable MediaPeriodId mediaPeriodId,
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData,
int retryCount) {
Assertions.checkState(Looper.myLooper() == playbackThread.getLooper());
}
@Override @Override
public void onLoadCompleted( public void onLoadCompleted(
int windowIndex, int windowIndex,