Treat onLoadStarted with retryCount to be a new method rather than redirect calls

This commit is contained in:
Colin Kho 2024-10-09 16:01:36 -07:00 committed by Ian Baker
parent 8adcd35c75
commit 5dbe1efa9e
15 changed files with 245 additions and 27 deletions

View File

@ -345,6 +345,10 @@ public interface AnalyticsListener {
/** {@link Player#getDeviceVolume()} changed. */
@UnstableApi int EVENT_DEVICE_VOLUME_CHANGED = Player.EVENT_DEVICE_VOLUME_CHANGED;
/** A source started loading data. */
@UnstableApi
int EVENT_ON_LOAD_STARTED = 999;
/** A source started loading data. */
@UnstableApi
int EVENT_LOAD_STARTED = 1000; // Intentional gap to leave space for new Player events

View File

@ -420,7 +420,7 @@ public class DefaultAnalyticsCollector implements AnalyticsCollector {
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
sendEvent(
eventTime,
AnalyticsListener.EVENT_LOAD_STARTED,
AnalyticsListener.EVENT_ON_LOAD_STARTED,
listener -> listener.onLoadStarted(eventTime, loadEventInfo, mediaLoadData, retryCount));
}

View File

@ -72,11 +72,7 @@ public interface MediaSourceEventListener {
@Nullable MediaPeriodId mediaPeriodId,
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData,
int retryCount) {
if (retryCount == 0) {
onLoadStarted(windowIndex, mediaPeriodId, loadEventInfo, mediaLoadData);
}
}
int retryCount) {}
/**
* Called when a load ends.

View File

@ -920,8 +920,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null,
/* mediaStartTimeUs= */ loadable.seekTimeUs,
durationUs,
0);
durationUs);
}
/**

View File

@ -168,8 +168,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null,
/* mediaStartTimeUs= */ 0,
durationUs,
/* retryCount= */ 0);
durationUs);
return true;
}
@ -208,6 +207,31 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
// Loader.Callback implementation.
@Override
public void onLoadStarted(SourceLoadable loadable, long elapsedRealtimeMs, long loadDurationMs,
int retryCount) {
StatsDataSource dataSource = loadable.dataSource;
LoadEventInfo loadEventInfo =
new LoadEventInfo(
loadable.loadTaskId,
loadable.dataSpec,
dataSource.getLastOpenedUri(),
dataSource.getLastResponseHeaders(),
elapsedRealtimeMs,
loadDurationMs,
sampleSize);
eventDispatcher.loadStarted(
loadEventInfo,
C.DATA_TYPE_MEDIA,
C.TRACK_TYPE_UNKNOWN,
format,
C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null,
/* mediaStartTimeUs= */ 0,
durationUs,
retryCount);
}
@Override
public void onLoadCompleted(
SourceLoadable loadable, long elapsedRealtimeMs, long loadDurationMs) {

View File

@ -422,6 +422,28 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
}
}
@Override
public void onLoadStarted(
int windowIndex,
@Nullable MediaPeriodId mediaPeriodId,
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData) {
@Nullable
MediaPeriodImpl mediaPeriod =
getMediaPeriodForEvent(mediaPeriodId, mediaLoadData, /* useLoadingPeriod= */ true);
if (mediaPeriod == null) {
mediaSourceEventDispatcherWithoutId.loadStarted(loadEventInfo, mediaLoadData);
} else {
mediaPeriod.sharedPeriod.onLoadStarted(loadEventInfo, mediaLoadData);
mediaPeriod.mediaSourceEventDispatcher.loadStarted(
loadEventInfo,
correctMediaLoadData(
mediaPeriod,
mediaLoadData,
checkNotNull(adPlaybackStates.get(mediaPeriod.mediaPeriodId.periodUid))));
}
}
@Override
public void onLoadStarted(
int windowIndex,
@ -751,10 +773,12 @@ public final class ServerSideAdInsertionMediaSource extends BaseMediaSource
loadingPeriod.mediaSourceEventDispatcher.loadCompleted(
loadData.first,
correctMediaLoadData(loadingPeriod, loadData.second, adPlaybackState));
mediaPeriod.mediaSourceEventDispatcher.loadStarted(
loadData.first, correctMediaLoadData(mediaPeriod, loadData.second, adPlaybackState));
mediaPeriod.mediaSourceEventDispatcher.loadStarted(
loadData.first,
correctMediaLoadData(mediaPeriod, loadData.second, adPlaybackState),
0);
/* retryCount= */ 0);
}
}
this.loadingPeriod = mediaPeriod;

View File

@ -429,6 +429,22 @@ public class ChunkSampleStream<T extends ChunkSource>
// Loader.Callback implementation.
@Override
public void onLoadStarted(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs,
int retryCount) {
mediaSourceEventDispatcher.loadStarted(
new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs),
loadable.type,
primaryTrackType,
loadable.trackFormat,
loadable.trackSelectionReason,
loadable.trackSelectionData,
loadable.startTimeUs,
loadable.endTimeUs,
retryCount);
}
@Override
public void onLoadCompleted(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs) {
loadingChunk = null;
@ -647,8 +663,7 @@ public class ChunkSampleStream<T extends ChunkSource>
loadable.trackSelectionReason,
loadable.trackSelectionData,
loadable.startTimeUs,
loadable.endTimeUs,
0);
loadable.endTimeUs);
return true;
}

View File

@ -32,6 +32,7 @@ import static androidx.media3.exoplayer.analytics.AnalyticsListener.EVENT_LOAD_C
import static androidx.media3.exoplayer.analytics.AnalyticsListener.EVENT_LOAD_ERROR;
import static androidx.media3.exoplayer.analytics.AnalyticsListener.EVENT_LOAD_STARTED;
import static androidx.media3.exoplayer.analytics.AnalyticsListener.EVENT_MEDIA_ITEM_TRANSITION;
import static androidx.media3.exoplayer.analytics.AnalyticsListener.EVENT_ON_LOAD_STARTED;
import static androidx.media3.exoplayer.analytics.AnalyticsListener.EVENT_PLAYBACK_PARAMETERS_CHANGED;
import static androidx.media3.exoplayer.analytics.AnalyticsListener.EVENT_PLAYBACK_STATE_CHANGED;
import static androidx.media3.exoplayer.analytics.AnalyticsListener.EVENT_PLAYER_ERROR;
@ -265,6 +266,9 @@ public final class DefaultAnalyticsCollectorTest {
assertThat(listener.getEvents(EVENT_LOAD_STARTED))
.containsExactly(WINDOW_0 /* manifest */, period0 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_ON_LOAD_STARTED))
.containsExactly(WINDOW_0 /* manifest */, period0 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_LOAD_COMPLETED))
.containsExactly(WINDOW_0 /* manifest */, period0 /* media */)
.inOrder();
@ -334,6 +338,13 @@ public final class DefaultAnalyticsCollectorTest {
period0 /* media */,
period1 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_ON_LOAD_STARTED))
.containsExactly(
WINDOW_0 /* manifest */,
WINDOW_1 /* manifest */,
period0 /* media */,
period1 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_LOAD_COMPLETED))
.containsExactly(
WINDOW_0 /* manifest */,
@ -412,6 +423,13 @@ public final class DefaultAnalyticsCollectorTest {
period0 /* media */,
period1 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_ON_LOAD_STARTED))
.containsExactly(
WINDOW_0 /* manifest */,
WINDOW_1 /* manifest */,
period0 /* media */,
period1 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_LOAD_COMPLETED))
.containsExactly(
WINDOW_0 /* manifest */,
@ -494,6 +512,13 @@ public final class DefaultAnalyticsCollectorTest {
period0 /* media */,
period1 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_ON_LOAD_STARTED))
.containsExactly(
WINDOW_0 /* manifest */,
WINDOW_1 /* manifest */,
period0 /* media */,
period1 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_LOAD_COMPLETED))
.containsExactly(
WINDOW_0 /* manifest */,
@ -591,6 +616,14 @@ public final class DefaultAnalyticsCollectorTest {
period1Seq1 /* media */,
period1Seq2 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_ON_LOAD_STARTED))
.containsExactly(
WINDOW_0 /* manifest */,
WINDOW_1 /* manifest */,
period0 /* media */,
period1Seq1 /* media */,
period1Seq2 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_LOAD_COMPLETED))
.containsExactly(
WINDOW_0 /* manifest */,
@ -710,6 +743,13 @@ public final class DefaultAnalyticsCollectorTest {
WINDOW_0 /* manifest */,
period0Seq1 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_ON_LOAD_STARTED))
.containsExactly(
WINDOW_0 /* manifest */,
period0Seq0 /* media */,
WINDOW_0 /* manifest */,
period0Seq1 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_LOAD_COMPLETED))
.containsExactly(
WINDOW_0 /* manifest */,
@ -804,6 +844,13 @@ public final class DefaultAnalyticsCollectorTest {
WINDOW_0 /* manifest */,
period0Seq0 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_ON_LOAD_STARTED))
.containsExactly(
WINDOW_0 /* manifest */,
period0Seq0 /* media */,
WINDOW_0 /* manifest */,
period0Seq0 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_LOAD_COMPLETED))
.containsExactly(
WINDOW_0 /* manifest */,
@ -876,6 +923,10 @@ public final class DefaultAnalyticsCollectorTest {
.containsExactly(
WINDOW_0 /* manifest */, window0Period1Seq0 /* media */, window1Period0Seq1 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_ON_LOAD_STARTED))
.containsExactly(
WINDOW_0 /* manifest */, window0Period1Seq0 /* media */, window1Period0Seq1 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_LOAD_COMPLETED))
.containsExactly(
WINDOW_0 /* manifest */, window0Period1Seq0 /* media */, window1Period0Seq1 /* media */)
@ -974,6 +1025,9 @@ public final class DefaultAnalyticsCollectorTest {
assertThat(listener.getEvents(EVENT_LOAD_STARTED))
.containsExactly(WINDOW_0 /* manifest */, period0Seq0 /* media */, period1Seq1 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_ON_LOAD_STARTED))
.containsExactly(WINDOW_0 /* manifest */, period0Seq0 /* media */, period1Seq1 /* media */)
.inOrder();
assertThat(listener.getEvents(EVENT_LOAD_COMPLETED))
.containsExactly(WINDOW_0 /* manifest */, period0Seq0 /* media */, period1Seq1 /* media */)
.inOrder();
@ -1179,6 +1233,16 @@ public final class DefaultAnalyticsCollectorTest {
postrollAd,
contentAfterPostroll)
.inOrder();
assertThat(listener.getEvents(EVENT_ON_LOAD_STARTED))
.containsExactly(
WINDOW_0 /* content manifest */,
prerollAd,
contentAfterPreroll,
midrollAd,
contentAfterMidroll,
postrollAd,
contentAfterPostroll)
.inOrder();
assertThat(listener.getEvents(EVENT_LOAD_COMPLETED))
.containsExactly(
WINDOW_0 /* content manifest */,
@ -1338,6 +1402,14 @@ public final class DefaultAnalyticsCollectorTest {
contentAfterMidroll,
contentAfterMidroll)
.inOrder();
assertThat(listener.getEvents(EVENT_ON_LOAD_STARTED))
.containsExactly(
WINDOW_0 /* content manifest */,
contentBeforeMidroll,
midrollAd,
contentAfterMidroll,
contentAfterMidroll)
.inOrder();
assertThat(listener.getEvents(EVENT_LOAD_COMPLETED))
.containsExactly(
WINDOW_0 /* content manifest */,
@ -1716,7 +1788,11 @@ public final class DefaultAnalyticsCollectorTest {
ArgumentCaptor<AnalyticsListener.EventTime> individualLoadStartedEventTimes =
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
verify(listener, atLeastOnce())
.onLoadStarted(individualLoadStartedEventTimes.capture(), any(), any(), anyInt());
.onLoadStarted(individualLoadStartedEventTimes.capture(), any(), any());
ArgumentCaptor<AnalyticsListener.EventTime> individualOnLoadStartedEventTimes =
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
verify(listener, atLeastOnce())
.onLoadStarted(individualOnLoadStartedEventTimes.capture(), any(), any(), anyInt());
ArgumentCaptor<AnalyticsListener.EventTime> individualLoadCompletedEventTimes =
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
verify(listener, atLeastOnce())
@ -1844,6 +1920,9 @@ public final class DefaultAnalyticsCollectorTest {
assertThat(individualLoadStartedEventTimes.getAllValues())
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_LOAD_STARTED))
.inOrder();
assertThat(individualOnLoadStartedEventTimes.getAllValues())
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_ON_LOAD_STARTED))
.inOrder();
assertThat(individualLoadCompletedEventTimes.getAllValues())
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_LOAD_COMPLETED))
.inOrder();
@ -2206,7 +2285,7 @@ public final class DefaultAnalyticsCollectorTest {
LoadEventInfo loadEventInfo,
MediaLoadData mediaLoadData,
int retryCount) {
reportedEvents.add(new ReportedEvent(EVENT_LOAD_STARTED, eventTime));
reportedEvents.add(new ReportedEvent(EVENT_ON_LOAD_STARTED, eventTime));
}
@Override

View File

@ -629,6 +629,15 @@ public final class DashMediaSource extends BaseMediaSource {
// Loadable callbacks.
/* package */ void onManifestLoadStarted(
ParsingLoadable<DashManifest> loadable, long elapsedRealtimeMs,
long loadDurationMs, int retryCount) {
manifestEventDispatcher.loadStarted(
new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs),
loadable.type,
retryCount);
}
/* package */ void onManifestLoadCompleted(
ParsingLoadable<DashManifest> loadable, long elapsedRealtimeMs, long loadDurationMs) {
LoadEventInfo loadEventInfo =
@ -1097,8 +1106,7 @@ public final class DashMediaSource extends BaseMediaSource {
long elapsedRealtimeMs = loader.startLoading(loadable, callback, minRetryCount);
manifestEventDispatcher.loadStarted(
new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs),
loadable.type,
0);
loadable.type);
}
private static long getIntervalUntilNextManifestRefreshMs(
@ -1390,6 +1398,12 @@ public final class DashMediaSource extends BaseMediaSource {
private final class ManifestCallback implements Loader.Callback<ParsingLoadable<DashManifest>> {
@Override
public void onLoadStarted(ParsingLoadable<DashManifest> loadable, long elapsedRealtimeMs,
long loadDurationMs, int retryCount) {
onManifestLoadStarted(loadable, elapsedRealtimeMs, loadDurationMs, retryCount);
}
@Override
public void onLoadCompleted(
ParsingLoadable<DashManifest> loadable, long elapsedRealtimeMs, long loadDurationMs) {

View File

@ -819,8 +819,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
loadable.trackSelectionReason,
loadable.trackSelectionData,
loadable.startTimeUs,
loadable.endTimeUs,
0);
loadable.endTimeUs);
return true;
}
@ -861,6 +860,21 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
// Loader.Callback implementation.
@Override
public void onLoadStarted(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs,
int retryCount) {
mediaSourceEventDispatcher.loadStarted(
new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs),
loadable.type,
trackType,
loadable.trackFormat,
loadable.trackSelectionReason,
loadable.trackSelectionData,
loadable.startTimeUs,
loadable.endTimeUs);
}
@Override
public void onLoadCompleted(Chunk loadable, long elapsedRealtimeMs, long loadDurationMs) {
loadingChunk = null;

View File

@ -152,8 +152,7 @@ public final class DefaultHlsPlaylistTracker
multivariantPlaylistLoadable.loadTaskId,
multivariantPlaylistLoadable.dataSpec,
elapsedRealtime),
multivariantPlaylistLoadable.type,
0);
multivariantPlaylistLoadable.type);
}
@Override
@ -255,6 +254,21 @@ public final class DefaultHlsPlaylistTracker
// Loader.Callback implementation.
@Override
public void onLoadStarted(
ParsingLoadable<HlsPlaylist> loadable,
long elapsedRealtimeMs,
long loadDurationMs,
int retryCount) {
eventDispatcher.loadStarted(
new LoadEventInfo(
loadable.loadTaskId,
loadable.dataSpec,
elapsedRealtimeMs),
loadable.type,
retryCount);
}
@Override
public void onLoadCompleted(
ParsingLoadable<HlsPlaylist> loadable, long elapsedRealtimeMs, long loadDurationMs) {
@ -745,8 +759,7 @@ public final class DefaultHlsPlaylistTracker
eventDispatcher.loadStarted(
new LoadEventInfo(
mediaPlaylistLoadable.loadTaskId, mediaPlaylistLoadable.dataSpec, elapsedRealtime),
mediaPlaylistLoadable.type,
0);
mediaPlaylistLoadable.type);
}
private void processLoadedPlaylist(

View File

@ -497,6 +497,15 @@ public final class SsMediaSource extends BaseMediaSource
// Loader.Callback implementation
@Override
public void onLoadStarted(ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs,
long loadDurationMs, int retryCount) {
manifestEventDispatcher.loadStarted(
new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs),
loadable.type,
/* retryCount= */ 0);
}
@Override
public void onLoadCompleted(
ParsingLoadable<SsManifest> loadable, long elapsedRealtimeMs, long loadDurationMs) {
@ -664,7 +673,6 @@ public final class SsMediaSource extends BaseMediaSource
loadable, this, loadErrorHandlingPolicy.getMinimumLoadableRetryCount(loadable.type));
manifestEventDispatcher.loadStarted(
new LoadEventInfo(loadable.loadTaskId, loadable.dataSpec, elapsedRealtimeMs),
loadable.type,
0);
loadable.type);
}
}

View File

@ -108,6 +108,15 @@ public class FakeAdaptiveMediaPeriod
@Override
public void prepare(Callback callback, long positionUs) {
mediaSourceEventDispatcher.loadStarted(
new LoadEventInfo(fakePreparationLoadTaskId, FAKE_DATA_SPEC, SystemClock.elapsedRealtime()),
C.DATA_TYPE_MEDIA,
C.TRACK_TYPE_UNKNOWN,
/* trackFormat= */ null,
C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null,
/* mediaStartTimeUs= */ 0,
/* mediaEndTimeUs= */ C.TIME_UNSET);
mediaSourceEventDispatcher.loadStarted(
new LoadEventInfo(fakePreparationLoadTaskId, FAKE_DATA_SPEC, SystemClock.elapsedRealtime()),
C.DATA_TYPE_MEDIA,

View File

@ -227,6 +227,15 @@ public class FakeMediaPeriod implements MediaPeriod {
@Override
public synchronized void prepare(Callback callback, long positionUs) {
mediaSourceEventDispatcher.loadStarted(
new LoadEventInfo(fakePreparationLoadTaskId, FAKE_DATA_SPEC, SystemClock.elapsedRealtime()),
C.DATA_TYPE_MEDIA,
C.TRACK_TYPE_UNKNOWN,
/* trackFormat= */ null,
C.SELECTION_REASON_UNKNOWN,
/* trackSelectionData= */ null,
/* mediaStartTimeUs= */ 0,
/* mediaEndTimeUs= */ C.TIME_UNSET);
mediaSourceEventDispatcher.loadStarted(
new LoadEventInfo(fakePreparationLoadTaskId, FAKE_DATA_SPEC, SystemClock.elapsedRealtime()),
C.DATA_TYPE_MEDIA,
@ -236,7 +245,7 @@ public class FakeMediaPeriod implements MediaPeriod {
/* trackSelectionData= */ null,
/* mediaStartTimeUs= */ 0,
/* mediaEndTimeUs= */ C.TIME_UNSET,
0);
/* retryCount= */ 0);
prepareCallback = callback;
if (deferOnPrepared) {
playerHandler = Util.createHandlerForCurrentLooper();

View File

@ -446,6 +446,16 @@ public class FakeMediaSource extends BaseMediaSource {
MediaSourceEventListener.EventDispatcher eventDispatcher =
createEventDispatcher(/* mediaPeriodId= */ null);
long loadTaskId = LoadEventInfo.getNewId();
eventDispatcher.loadStarted(
new LoadEventInfo(
loadTaskId,
FAKE_DATA_SPEC,
FAKE_DATA_SPEC.uri,
/* responseHeaders= */ ImmutableMap.of(),
elapsedRealTimeMs,
/* loadDurationMs= */ 0,
/* bytesLoaded= */ 0),
mediaLoadData);
eventDispatcher.loadStarted(
new LoadEventInfo(
loadTaskId,
@ -456,7 +466,7 @@ public class FakeMediaSource extends BaseMediaSource {
/* loadDurationMs= */ 0,
/* bytesLoaded= */ 0),
mediaLoadData,
0);
/* retryCount= */ 0);
eventDispatcher.loadCompleted(
new LoadEventInfo(
loadTaskId,