Commit f3d331c9 by tonihei Committed by Andrew Lewis

Extend EventTime with full current position info.

EventTime contains information about when an event happened and where
it belongs to. Both places can be fully described using timeline, window
index, media period id and position.

Right now, only the information for where the event belongs to is fully
contained in EventTime, whereas the time when the event happened only has
the position, and none of the other information (timeline, window, period).

This change adds the missing information, so that the EventTime can easily
be used without having access to the Player. This also ensures Event
metadata is self-contained and can be stored and reused later.

issue:#7332
PiperOrigin-RevId: 311727004
parent 78c850a8
...@@ -88,6 +88,9 @@ ...@@ -88,6 +88,9 @@
`CacheDataSink.Factory` and `CacheDataSource.Factory` respectively. `CacheDataSink.Factory` and `CacheDataSource.Factory` respectively.
* Enable the configuration of `SilenceSkippingAudioProcessor` * Enable the configuration of `SilenceSkippingAudioProcessor`
([#6705](https://github.com/google/ExoPlayer/issues/6705)). ([#6705](https://github.com/google/ExoPlayer/issues/6705)).
* Extend `EventTime` with more details about the current player state for
easier access
([#7332](https://github.com/google/ExoPlayer/issues/7332)).
* Video: Pass frame rate hint to `Surface.setFrameRate` on Android R devices. * Video: Pass frame rate hint to `Surface.setFrameRate` on Android R devices.
* Text: * Text:
* Parse `<ruby>` and `<rt>` tags in WebVTT subtitles (rendering is coming * Parse `<ruby>` and `<rt>` tags in WebVTT subtitles (rendering is coming
......
...@@ -659,12 +659,16 @@ public class AnalyticsCollector ...@@ -659,12 +659,16 @@ public class AnalyticsCollector
eventPositionMs = eventPositionMs =
timeline.isEmpty() ? 0 : timeline.getWindow(windowIndex, window).getDefaultPositionMs(); timeline.isEmpty() ? 0 : timeline.getWindow(windowIndex, window).getDefaultPositionMs();
} }
@Nullable MediaPeriodInfo currentInfo = mediaPeriodQueueTracker.getCurrentPlayerMediaPeriod();
return new EventTime( return new EventTime(
realtimeMs, realtimeMs,
timeline, timeline,
windowIndex, windowIndex,
mediaPeriodId, mediaPeriodId,
eventPositionMs, eventPositionMs,
player.getCurrentTimeline(),
player.getCurrentWindowIndex(),
currentInfo == null ? null : currentInfo.mediaPeriodId,
player.getCurrentPosition(), player.getCurrentPosition(),
player.getTotalBufferedDuration()); player.getTotalBufferedDuration());
} }
......
...@@ -56,7 +56,7 @@ public interface AnalyticsListener { ...@@ -56,7 +56,7 @@ public interface AnalyticsListener {
*/ */
public final long realtimeMs; public final long realtimeMs;
/** Timeline at the time of the event. */ /** Most recent {@link Timeline} that contains the event position. */
public final Timeline timeline; public final Timeline timeline;
/** /**
...@@ -66,8 +66,8 @@ public interface AnalyticsListener { ...@@ -66,8 +66,8 @@ public interface AnalyticsListener {
public final int windowIndex; public final int windowIndex;
/** /**
* Media period identifier for the media period this event belongs to, or {@code null} if the * {@link MediaPeriodId Media period identifier} for the media period this event belongs to, or
* event is not associated with a specific media period. * {@code null} if the event is not associated with a specific media period.
*/ */
@Nullable public final MediaPeriodId mediaPeriodId; @Nullable public final MediaPeriodId mediaPeriodId;
...@@ -77,8 +77,27 @@ public interface AnalyticsListener { ...@@ -77,8 +77,27 @@ public interface AnalyticsListener {
public final long eventPlaybackPositionMs; public final long eventPlaybackPositionMs;
/** /**
* Position in the current timeline window ({@link Player#getCurrentWindowIndex()}) or the * The current {@link Timeline} at the time of the event (equivalent to {@link
* currently playing ad at the time of the event, in milliseconds. * Player#getCurrentTimeline()}).
*/
public final Timeline currentTimeline;
/**
* The current window index in {@link #currentTimeline} at the time of the event, or the
* prospective window index if the timeline is not yet known and empty (equivalent to {@link
* Player#getCurrentWindowIndex()}).
*/
public final int currentWindowIndex;
/**
* {@link MediaPeriodId Media period identifier} for the currently playing media period at the
* time of the event, or {@code null} if no current media period identifier is available.
*/
@Nullable public final MediaPeriodId currentMediaPeriodId;
/**
* Position in the {@link #currentWindowIndex current timeline window} or the currently playing
* ad at the time of the event, in milliseconds.
*/ */
public final long currentPlaybackPositionMs; public final long currentPlaybackPositionMs;
...@@ -91,19 +110,27 @@ public interface AnalyticsListener { ...@@ -91,19 +110,27 @@ public interface AnalyticsListener {
/** /**
* @param realtimeMs Elapsed real-time as returned by {@code SystemClock.elapsedRealtime()} at * @param realtimeMs Elapsed real-time as returned by {@code SystemClock.elapsedRealtime()} at
* the time of the event, in milliseconds. * the time of the event, in milliseconds.
* @param timeline Timeline at the time of the event. * @param timeline Most recent {@link Timeline} that contains the event position.
* @param windowIndex Window index in the {@link #timeline} this event belongs to, or the * @param windowIndex Window index in the {@code timeline} this event belongs to, or the
* prospective window index if the timeline is not yet known and empty. * prospective window index if the timeline is not yet known and empty.
* @param mediaPeriodId Media period identifier for the media period this event belongs to, or * @param mediaPeriodId {@link MediaPeriodId Media period identifier} for the media period this
* {@code null} if the event is not associated with a specific media period. * event belongs to, or {@code null} if the event is not associated with a specific media
* period.
* @param eventPlaybackPositionMs Position in the window or ad this event belongs to at the time * @param eventPlaybackPositionMs Position in the window or ad this event belongs to at the time
* of the event, in milliseconds. * of the event, in milliseconds.
* @param currentPlaybackPositionMs Position in the current timeline window ({@link * @param currentTimeline The current {@link Timeline} at the time of the event (equivalent to
* Player#getCurrentWindowIndex()}) or the currently playing ad at the time of the event, in * {@link Player#getCurrentTimeline()}).
* milliseconds. * @param currentWindowIndex The current window index in {@code currentTimeline} at the time of
* @param totalBufferedDurationMs Total buffered duration from {@link * the event, or the prospective window index if the timeline is not yet known and empty
* #currentPlaybackPositionMs} at the time of the event, in milliseconds. This includes * (equivalent to {@link Player#getCurrentWindowIndex()}).
* pre-buffered data for subsequent ads and windows. * @param currentMediaPeriodId {@link MediaPeriodId Media period identifier} for the currently
* playing media period at the time of the event, or {@code null} if no current media period
* identifier is available.
* @param currentPlaybackPositionMs Position in the current timeline window or the currently
* playing ad at the time of the event, in milliseconds.
* @param totalBufferedDurationMs Total buffered duration from {@code currentPlaybackPositionMs}
* at the time of the event, in milliseconds. This includes pre-buffered data for subsequent
* ads and windows.
*/ */
public EventTime( public EventTime(
long realtimeMs, long realtimeMs,
...@@ -111,6 +138,9 @@ public interface AnalyticsListener { ...@@ -111,6 +138,9 @@ public interface AnalyticsListener {
int windowIndex, int windowIndex,
@Nullable MediaPeriodId mediaPeriodId, @Nullable MediaPeriodId mediaPeriodId,
long eventPlaybackPositionMs, long eventPlaybackPositionMs,
Timeline currentTimeline,
int currentWindowIndex,
@Nullable MediaPeriodId currentMediaPeriodId,
long currentPlaybackPositionMs, long currentPlaybackPositionMs,
long totalBufferedDurationMs) { long totalBufferedDurationMs) {
this.realtimeMs = realtimeMs; this.realtimeMs = realtimeMs;
...@@ -118,6 +148,9 @@ public interface AnalyticsListener { ...@@ -118,6 +148,9 @@ public interface AnalyticsListener {
this.windowIndex = windowIndex; this.windowIndex = windowIndex;
this.mediaPeriodId = mediaPeriodId; this.mediaPeriodId = mediaPeriodId;
this.eventPlaybackPositionMs = eventPlaybackPositionMs; this.eventPlaybackPositionMs = eventPlaybackPositionMs;
this.currentTimeline = currentTimeline;
this.currentWindowIndex = currentWindowIndex;
this.currentMediaPeriodId = currentMediaPeriodId;
this.currentPlaybackPositionMs = currentPlaybackPositionMs; this.currentPlaybackPositionMs = currentPlaybackPositionMs;
this.totalBufferedDurationMs = totalBufferedDurationMs; this.totalBufferedDurationMs = totalBufferedDurationMs;
} }
......
...@@ -157,6 +157,9 @@ public final class PlaybackStatsListener ...@@ -157,6 +157,9 @@ public final class PlaybackStatsListener
/* windowIndex= */ 0, /* windowIndex= */ 0,
/* mediaPeriodId= */ null, /* mediaPeriodId= */ null,
/* eventPlaybackPositionMs= */ 0, /* eventPlaybackPositionMs= */ 0,
Timeline.EMPTY,
/* currentWindowIndex= */ 0,
/* currentMediaPeriodId= */ null,
/* currentPlaybackPositionMs= */ 0, /* currentPlaybackPositionMs= */ 0,
/* totalBufferedDurationMs= */ 0); /* totalBufferedDurationMs= */ 0);
sessionManager.finishAllSessions(dummyEventTime); sessionManager.finishAllSessions(dummyEventTime);
...@@ -210,6 +213,9 @@ public final class PlaybackStatsListener ...@@ -210,6 +213,9 @@ public final class PlaybackStatsListener
eventTime.mediaPeriodId.windowSequenceNumber, eventTime.mediaPeriodId.windowSequenceNumber,
eventTime.mediaPeriodId.adGroupIndex), eventTime.mediaPeriodId.adGroupIndex),
/* eventPlaybackPositionMs= */ C.usToMs(contentWindowPositionUs), /* eventPlaybackPositionMs= */ C.usToMs(contentWindowPositionUs),
eventTime.timeline,
eventTime.currentWindowIndex,
eventTime.currentMediaPeriodId,
eventTime.currentPlaybackPositionMs, eventTime.currentPlaybackPositionMs,
eventTime.totalBufferedDurationMs); eventTime.totalBufferedDurationMs);
Assertions.checkNotNull(playbackStatsTrackers.get(contentSession)) Assertions.checkNotNull(playbackStatsTrackers.get(contentSession))
......
...@@ -1092,6 +1092,9 @@ public final class DefaultPlaybackSessionManagerTest { ...@@ -1092,6 +1092,9 @@ public final class DefaultPlaybackSessionManagerTest {
windowIndex, windowIndex,
mediaPeriodId, mediaPeriodId,
/* eventPlaybackPositionMs= */ 0, /* eventPlaybackPositionMs= */ 0,
timeline,
windowIndex,
mediaPeriodId,
/* currentPlaybackPositionMs= */ 0, /* currentPlaybackPositionMs= */ 0,
/* totalBufferedDurationMs= */ 0); /* totalBufferedDurationMs= */ 0);
} }
......
...@@ -44,20 +44,27 @@ public final class PlaybackStatsListenerTest { ...@@ -44,20 +44,27 @@ public final class PlaybackStatsListenerTest {
/* windowIndex= */ 0, /* windowIndex= */ 0,
/* mediaPeriodId= */ null, /* mediaPeriodId= */ null,
/* eventPlaybackPositionMs= */ 0, /* eventPlaybackPositionMs= */ 0,
/* currentTimeline= */ Timeline.EMPTY,
/* currentWindowIndex= */ 0,
/* currentMediaPeriodId= */ null,
/* currentPlaybackPositionMs= */ 0, /* currentPlaybackPositionMs= */ 0,
/* totalBufferedDurationMs= */ 0); /* totalBufferedDurationMs= */ 0);
private static final Timeline TEST_TIMELINE = new FakeTimeline(/* windowCount= */ 1); private static final Timeline TEST_TIMELINE = new FakeTimeline(/* windowCount= */ 1);
private static final MediaSource.MediaPeriodId TEST_MEDIA_PERIOD_ID =
new MediaSource.MediaPeriodId(
TEST_TIMELINE.getPeriod(/* periodIndex= */ 0, new Timeline.Period(), /* setIds= */ true)
.uid,
/* windowSequenceNumber= */ 42);
private static final AnalyticsListener.EventTime TEST_EVENT_TIME = private static final AnalyticsListener.EventTime TEST_EVENT_TIME =
new AnalyticsListener.EventTime( new AnalyticsListener.EventTime(
/* realtimeMs= */ 500, /* realtimeMs= */ 500,
TEST_TIMELINE, TEST_TIMELINE,
/* windowIndex= */ 0, /* windowIndex= */ 0,
new MediaSource.MediaPeriodId( TEST_MEDIA_PERIOD_ID,
TEST_TIMELINE.getPeriod(
/* periodIndex= */ 0, new Timeline.Period(), /* setIds= */ true)
.uid,
/* windowSequenceNumber= */ 42),
/* eventPlaybackPositionMs= */ 123, /* eventPlaybackPositionMs= */ 123,
TEST_TIMELINE,
/* currentWindowIndex= */ 0,
TEST_MEDIA_PERIOD_ID,
/* currentPlaybackPositionMs= */ 123, /* currentPlaybackPositionMs= */ 123,
/* totalBufferedDurationMs= */ 456); /* totalBufferedDurationMs= */ 456);
...@@ -151,6 +158,9 @@ public final class PlaybackStatsListenerTest { ...@@ -151,6 +158,9 @@ public final class PlaybackStatsListenerTest {
/* windowIndex= */ 0, /* windowIndex= */ 0,
/* mediaPeriodId= */ null, /* mediaPeriodId= */ null,
/* eventPlaybackPositionMs= */ 0, /* eventPlaybackPositionMs= */ 0,
Timeline.EMPTY,
/* currentWindowIndex= */ 0,
/* currentMediaPeriodId= */ null,
/* currentPlaybackPositionMs= */ 0, /* currentPlaybackPositionMs= */ 0,
/* totalBufferedDurationMs= */ 0); /* totalBufferedDurationMs= */ 0);
AnalyticsListener.EventTime eventTimeWindow1 = AnalyticsListener.EventTime eventTimeWindow1 =
...@@ -160,6 +170,9 @@ public final class PlaybackStatsListenerTest { ...@@ -160,6 +170,9 @@ public final class PlaybackStatsListenerTest {
/* windowIndex= */ 1, /* windowIndex= */ 1,
/* mediaPeriodId= */ null, /* mediaPeriodId= */ null,
/* eventPlaybackPositionMs= */ 0, /* eventPlaybackPositionMs= */ 0,
Timeline.EMPTY,
/* currentWindowIndex= */ 1,
/* currentMediaPeriodId= */ null,
/* currentPlaybackPositionMs= */ 0, /* currentPlaybackPositionMs= */ 0,
/* totalBufferedDurationMs= */ 0); /* totalBufferedDurationMs= */ 0);
PlaybackStatsListener.Callback callback = mock(PlaybackStatsListener.Callback.class); PlaybackStatsListener.Callback callback = mock(PlaybackStatsListener.Callback.class);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment