Reorder renderer changes at period transitions
Currently the following sequence of events happens at automatic period transitions: 1. Update queue (=release old playing period) 2. Disable unused renderers 3. Enable newly needed renderers This order requires difficult to follow workarounds in AnalyticsCollector for all events related to step 2 (disable renderers). The current media period has already been advanced so can't be used. The current workaround saves the last known playing media period that was published as part of a PlaybackInfo update in ExoPlayerImpl. This works in most cases, but is inherently wrong because the published state in ExoPlayerImpl may be completely unrelated to the updates happening on the playback thread (e.g. if many other operations are pending). Simplify and fix this problem by changing the order of the events above: 1. Disable unused renderers. 2. Update queue 3. Enable newly needed renderers. This way the current playing media period can be used for both renderer disable and renderer enable events, thus it's correct in all cases and the workaround in AnalyticsCollector can be removed. PiperOrigin-RevId: 290037225
This commit is contained in:
parent
8d2fd383f9
commit
2e7978a0e2
@ -950,15 +950,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
setState(Player.STATE_BUFFERING);
|
setState(Player.STATE_BUFFERING);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the timeline, but keep the requested period if it is already prepared.
|
// Find the requested period if it's already prepared.
|
||||||
MediaPeriodHolder oldPlayingPeriodHolder = queue.getPlayingPeriod();
|
@Nullable MediaPeriodHolder oldPlayingPeriodHolder = queue.getPlayingPeriod();
|
||||||
MediaPeriodHolder newPlayingPeriodHolder = oldPlayingPeriodHolder;
|
@Nullable MediaPeriodHolder newPlayingPeriodHolder = oldPlayingPeriodHolder;
|
||||||
while (newPlayingPeriodHolder != null) {
|
while (newPlayingPeriodHolder != null) {
|
||||||
if (periodId.equals(newPlayingPeriodHolder.info.id) && newPlayingPeriodHolder.prepared) {
|
if (periodId.equals(newPlayingPeriodHolder.info.id) && newPlayingPeriodHolder.prepared) {
|
||||||
queue.removeAfter(newPlayingPeriodHolder);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
newPlayingPeriodHolder = queue.advancePlayingPeriod();
|
newPlayingPeriodHolder = newPlayingPeriodHolder.getNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable all renderers if the period being played is changing, if the seek results in negative
|
// Disable all renderers if the period being played is changing, if the seek results in negative
|
||||||
@ -971,15 +970,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
disableRenderer(renderer);
|
disableRenderer(renderer);
|
||||||
}
|
}
|
||||||
enabledRenderers = new Renderer[0];
|
enabledRenderers = new Renderer[0];
|
||||||
oldPlayingPeriodHolder = null;
|
|
||||||
if (newPlayingPeriodHolder != null) {
|
if (newPlayingPeriodHolder != null) {
|
||||||
|
// Update the queue and reenable renderers if the requested media period already exists.
|
||||||
|
while (queue.getPlayingPeriod() != newPlayingPeriodHolder) {
|
||||||
|
queue.advancePlayingPeriod();
|
||||||
|
}
|
||||||
newPlayingPeriodHolder.setRendererOffset(/* rendererPositionOffsetUs= */ 0);
|
newPlayingPeriodHolder.setRendererOffset(/* rendererPositionOffsetUs= */ 0);
|
||||||
|
enablePlayingPeriodRenderers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the holders.
|
// Do the actual seeking.
|
||||||
if (newPlayingPeriodHolder != null) {
|
if (newPlayingPeriodHolder != null) {
|
||||||
updatePlayingPeriodRenderers(oldPlayingPeriodHolder);
|
queue.removeAfter(newPlayingPeriodHolder);
|
||||||
if (newPlayingPeriodHolder.hasEnabledTracks) {
|
if (newPlayingPeriodHolder.hasEnabledTracks) {
|
||||||
periodPositionUs = newPlayingPeriodHolder.mediaPeriod.seekToUs(periodPositionUs);
|
periodPositionUs = newPlayingPeriodHolder.mediaPeriod.seekToUs(periodPositionUs);
|
||||||
newPlayingPeriodHolder.mediaPeriod.discardBuffer(
|
newPlayingPeriodHolder.mediaPeriod.discardBuffer(
|
||||||
@ -1694,7 +1697,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
// The window index of the seek position was outside the bounds of the timeline.
|
// The window index of the seek position was outside the bounds of the timeline.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (timeline == seekTimeline) {
|
if (timeline.equals(seekTimeline)) {
|
||||||
// Our internal timeline is the seek timeline, so the mapped position is correct.
|
// Our internal timeline is the seek timeline, so the mapped position is correct.
|
||||||
return periodPosition;
|
return periodPosition;
|
||||||
}
|
}
|
||||||
@ -1869,8 +1872,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
// anymore and need to re-enable the renderers. Set all current streams final to do that.
|
// anymore and need to re-enable the renderers. Set all current streams final to do that.
|
||||||
setAllRendererStreamsFinal();
|
setAllRendererStreamsFinal();
|
||||||
}
|
}
|
||||||
|
boolean[] rendererWasEnabledFlags = new boolean[renderers.length];
|
||||||
|
disablePlayingPeriodRenderersForTransition(rendererWasEnabledFlags);
|
||||||
MediaPeriodHolder newPlayingPeriodHolder = queue.advancePlayingPeriod();
|
MediaPeriodHolder newPlayingPeriodHolder = queue.advancePlayingPeriod();
|
||||||
updatePlayingPeriodRenderers(oldPlayingPeriodHolder);
|
enablePlayingPeriodRenderers(rendererWasEnabledFlags);
|
||||||
playbackInfo =
|
playbackInfo =
|
||||||
copyWithNewPosition(
|
copyWithNewPosition(
|
||||||
newPlayingPeriodHolder.info.id,
|
newPlayingPeriodHolder.info.id,
|
||||||
@ -1943,7 +1948,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
if (loadingPeriodHolder == queue.getPlayingPeriod()) {
|
if (loadingPeriodHolder == queue.getPlayingPeriod()) {
|
||||||
// This is the first prepared period, so update the position and the renderers.
|
// This is the first prepared period, so update the position and the renderers.
|
||||||
resetRendererPosition(loadingPeriodHolder.info.startPositionUs);
|
resetRendererPosition(loadingPeriodHolder.info.startPositionUs);
|
||||||
updatePlayingPeriodRenderers(/* oldPlayingPeriodHolder= */ null);
|
enablePlayingPeriodRenderers();
|
||||||
}
|
}
|
||||||
maybeContinueLoading();
|
maybeContinueLoading();
|
||||||
}
|
}
|
||||||
@ -2025,22 +2030,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
mediaPeriodId, positionUs, contentPositionUs, getTotalBufferedDurationUs());
|
mediaPeriodId, positionUs, contentPositionUs, getTotalBufferedDurationUs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("ParameterNotNullable")
|
private void disablePlayingPeriodRenderersForTransition(boolean[] outRendererWasEnabledFlags)
|
||||||
private void updatePlayingPeriodRenderers(@Nullable MediaPeriodHolder oldPlayingPeriodHolder)
|
|
||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
MediaPeriodHolder newPlayingPeriodHolder = queue.getPlayingPeriod();
|
MediaPeriodHolder oldPlayingPeriodHolder = Assertions.checkNotNull(queue.getPlayingPeriod());
|
||||||
if (newPlayingPeriodHolder == null || oldPlayingPeriodHolder == newPlayingPeriodHolder) {
|
MediaPeriodHolder newPlayingPeriodHolder =
|
||||||
return;
|
Assertions.checkNotNull(oldPlayingPeriodHolder.getNext());
|
||||||
}
|
|
||||||
int enabledRendererCount = 0;
|
|
||||||
boolean[] rendererWasEnabledFlags = new boolean[renderers.length];
|
|
||||||
for (int i = 0; i < renderers.length; i++) {
|
for (int i = 0; i < renderers.length; i++) {
|
||||||
Renderer renderer = renderers[i];
|
Renderer renderer = renderers[i];
|
||||||
rendererWasEnabledFlags[i] = renderer.getState() != Renderer.STATE_DISABLED;
|
outRendererWasEnabledFlags[i] = renderer.getState() != Renderer.STATE_DISABLED;
|
||||||
if (newPlayingPeriodHolder.getTrackSelectorResult().isRendererEnabled(i)) {
|
if (outRendererWasEnabledFlags[i]
|
||||||
enabledRendererCount++;
|
|
||||||
}
|
|
||||||
if (rendererWasEnabledFlags[i]
|
|
||||||
&& (!newPlayingPeriodHolder.getTrackSelectorResult().isRendererEnabled(i)
|
&& (!newPlayingPeriodHolder.getTrackSelectorResult().isRendererEnabled(i)
|
||||||
|| (renderer.isCurrentStreamFinal()
|
|| (renderer.isCurrentStreamFinal()
|
||||||
&& renderer.getStream() == oldPlayingPeriodHolder.sampleStreams[i]))) {
|
&& renderer.getStream() == oldPlayingPeriodHolder.sampleStreams[i]))) {
|
||||||
@ -2050,10 +2048,24 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
disableRenderer(renderer);
|
disableRenderer(renderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enablePlayingPeriodRenderers() throws ExoPlaybackException {
|
||||||
|
enablePlayingPeriodRenderers(/* rendererWasEnabledFlags= */ new boolean[renderers.length]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enablePlayingPeriodRenderers(boolean[] rendererWasEnabledFlags)
|
||||||
|
throws ExoPlaybackException {
|
||||||
|
MediaPeriodHolder playingPeriodHolder = Assertions.checkNotNull(queue.getPlayingPeriod());
|
||||||
playbackInfo =
|
playbackInfo =
|
||||||
playbackInfo.copyWithTrackInfo(
|
playbackInfo.copyWithTrackInfo(
|
||||||
newPlayingPeriodHolder.getTrackGroups(),
|
playingPeriodHolder.getTrackGroups(), playingPeriodHolder.getTrackSelectorResult());
|
||||||
newPlayingPeriodHolder.getTrackSelectorResult());
|
int enabledRendererCount = 0;
|
||||||
|
for (int i = 0; i < renderers.length; i++) {
|
||||||
|
if (playingPeriodHolder.getTrackSelectorResult().isRendererEnabled(i)) {
|
||||||
|
enabledRendererCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
enableRenderers(rendererWasEnabledFlags, enabledRendererCount);
|
enableRenderers(rendererWasEnabledFlags, enabledRendererCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ public class AnalyticsCollector
|
|||||||
*/
|
*/
|
||||||
public final void notifySeekStarted() {
|
public final void notifySeekStarted() {
|
||||||
if (!mediaPeriodQueueTracker.isSeeking()) {
|
if (!mediaPeriodQueueTracker.isSeeking()) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
mediaPeriodQueueTracker.onSeekStarted();
|
mediaPeriodQueueTracker.onSeekStarted();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onSeekStarted(eventTime);
|
listener.onSeekStarted(eventTime);
|
||||||
@ -149,7 +149,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onMetadata(Metadata metadata) {
|
public final void onMetadata(Metadata metadata) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onMetadata(eventTime, metadata);
|
listener.onMetadata(eventTime, metadata);
|
||||||
}
|
}
|
||||||
@ -195,9 +195,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onAudioDisabled(DecoderCounters counters) {
|
public final void onAudioDisabled(DecoderCounters counters) {
|
||||||
// The renderers are disabled after we changed the playing media period on the playback thread
|
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
||||||
// but before this change is reported to the app thread.
|
|
||||||
EventTime eventTime = generateLastReportedPlayingMediaPeriodEventTime();
|
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onDecoderDisabled(eventTime, C.TRACK_TYPE_AUDIO, counters);
|
listener.onDecoderDisabled(eventTime, C.TRACK_TYPE_AUDIO, counters);
|
||||||
}
|
}
|
||||||
@ -260,7 +258,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onDroppedFrames(int count, long elapsedMs) {
|
public final void onDroppedFrames(int count, long elapsedMs) {
|
||||||
EventTime eventTime = generateLastReportedPlayingMediaPeriodEventTime();
|
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onDroppedVideoFrames(eventTime, count, elapsedMs);
|
listener.onDroppedVideoFrames(eventTime, count, elapsedMs);
|
||||||
}
|
}
|
||||||
@ -268,9 +266,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onVideoDisabled(DecoderCounters counters) {
|
public final void onVideoDisabled(DecoderCounters counters) {
|
||||||
// The renderers are disabled after we changed the playing media period on the playback thread
|
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
||||||
// but before this change is reported to the app thread.
|
|
||||||
EventTime eventTime = generateLastReportedPlayingMediaPeriodEventTime();
|
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onDecoderDisabled(eventTime, C.TRACK_TYPE_VIDEO, counters);
|
listener.onDecoderDisabled(eventTime, C.TRACK_TYPE_VIDEO, counters);
|
||||||
}
|
}
|
||||||
@ -416,7 +412,7 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) {
|
public final void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) {
|
||||||
mediaPeriodQueueTracker.onTimelineChanged(timeline);
|
mediaPeriodQueueTracker.onTimelineChanged(timeline);
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onTimelineChanged(eventTime, reason);
|
listener.onTimelineChanged(eventTime, reason);
|
||||||
}
|
}
|
||||||
@ -425,7 +421,7 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onTracksChanged(
|
public final void onTracksChanged(
|
||||||
TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
|
TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onTracksChanged(eventTime, trackGroups, trackSelections);
|
listener.onTracksChanged(eventTime, trackGroups, trackSelections);
|
||||||
}
|
}
|
||||||
@ -433,7 +429,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onLoadingChanged(boolean isLoading) {
|
public final void onLoadingChanged(boolean isLoading) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onLoadingChanged(eventTime, isLoading);
|
listener.onLoadingChanged(eventTime, isLoading);
|
||||||
}
|
}
|
||||||
@ -441,7 +437,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onPlayerStateChanged(boolean playWhenReady, @Player.State int playbackState) {
|
public final void onPlayerStateChanged(boolean playWhenReady, @Player.State int playbackState) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onPlayerStateChanged(eventTime, playWhenReady, playbackState);
|
listener.onPlayerStateChanged(eventTime, playWhenReady, playbackState);
|
||||||
}
|
}
|
||||||
@ -450,7 +446,7 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public void onPlaybackSuppressionReasonChanged(
|
public void onPlaybackSuppressionReasonChanged(
|
||||||
@PlaybackSuppressionReason int playbackSuppressionReason) {
|
@PlaybackSuppressionReason int playbackSuppressionReason) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onPlaybackSuppressionReasonChanged(eventTime, playbackSuppressionReason);
|
listener.onPlaybackSuppressionReasonChanged(eventTime, playbackSuppressionReason);
|
||||||
}
|
}
|
||||||
@ -458,7 +454,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onIsPlayingChanged(boolean isPlaying) {
|
public void onIsPlayingChanged(boolean isPlaying) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onIsPlayingChanged(eventTime, isPlaying);
|
listener.onIsPlayingChanged(eventTime, isPlaying);
|
||||||
}
|
}
|
||||||
@ -466,7 +462,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {
|
public final void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onRepeatModeChanged(eventTime, repeatMode);
|
listener.onRepeatModeChanged(eventTime, repeatMode);
|
||||||
}
|
}
|
||||||
@ -474,7 +470,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
|
public final void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onShuffleModeChanged(eventTime, shuffleModeEnabled);
|
listener.onShuffleModeChanged(eventTime, shuffleModeEnabled);
|
||||||
}
|
}
|
||||||
@ -482,7 +478,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onPlayerError(ExoPlaybackException error) {
|
public final void onPlayerError(ExoPlaybackException error) {
|
||||||
EventTime eventTime = generateLastReportedPlayingMediaPeriodEventTime();
|
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onPlayerError(eventTime, error);
|
listener.onPlayerError(eventTime, error);
|
||||||
}
|
}
|
||||||
@ -490,8 +486,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) {
|
public final void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) {
|
||||||
mediaPeriodQueueTracker.onPositionDiscontinuity(reason);
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onPositionDiscontinuity(eventTime, reason);
|
listener.onPositionDiscontinuity(eventTime, reason);
|
||||||
}
|
}
|
||||||
@ -499,7 +494,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
|
public final void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onPlaybackParametersChanged(eventTime, playbackParameters);
|
listener.onPlaybackParametersChanged(eventTime, playbackParameters);
|
||||||
}
|
}
|
||||||
@ -509,7 +504,7 @@ public class AnalyticsCollector
|
|||||||
public final void onSeekProcessed() {
|
public final void onSeekProcessed() {
|
||||||
if (mediaPeriodQueueTracker.isSeeking()) {
|
if (mediaPeriodQueueTracker.isSeeking()) {
|
||||||
mediaPeriodQueueTracker.onSeekProcessed();
|
mediaPeriodQueueTracker.onSeekProcessed();
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onSeekProcessed(eventTime);
|
listener.onSeekProcessed(eventTime);
|
||||||
}
|
}
|
||||||
@ -570,7 +565,7 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onDrmSessionReleased() {
|
public final void onDrmSessionReleased() {
|
||||||
EventTime eventTime = generateLastReportedPlayingMediaPeriodEventTime();
|
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
||||||
for (AnalyticsListener listener : listeners) {
|
for (AnalyticsListener listener : listeners) {
|
||||||
listener.onDrmSessionReleased(eventTime);
|
listener.onDrmSessionReleased(eventTime);
|
||||||
}
|
}
|
||||||
@ -594,7 +589,8 @@ public class AnalyticsCollector
|
|||||||
long realtimeMs = clock.elapsedRealtime();
|
long realtimeMs = clock.elapsedRealtime();
|
||||||
long eventPositionMs;
|
long eventPositionMs;
|
||||||
boolean isInCurrentWindow =
|
boolean isInCurrentWindow =
|
||||||
timeline == player.getCurrentTimeline() && windowIndex == player.getCurrentWindowIndex();
|
timeline.equals(player.getCurrentTimeline())
|
||||||
|
&& windowIndex == player.getCurrentWindowIndex();
|
||||||
if (mediaPeriodId != null && mediaPeriodId.isAd()) {
|
if (mediaPeriodId != null && mediaPeriodId.isAd()) {
|
||||||
boolean isCurrentAd =
|
boolean isCurrentAd =
|
||||||
isInCurrentWindow
|
isInCurrentWindow
|
||||||
@ -636,8 +632,8 @@ public class AnalyticsCollector
|
|||||||
mediaPeriodInfo.timeline, mediaPeriodInfo.windowIndex, mediaPeriodInfo.mediaPeriodId);
|
mediaPeriodInfo.timeline, mediaPeriodInfo.windowIndex, mediaPeriodInfo.mediaPeriodId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private EventTime generateLastReportedPlayingMediaPeriodEventTime() {
|
private EventTime generateCurrentPlayerMediaPeriodEventTime() {
|
||||||
return generateEventTime(mediaPeriodQueueTracker.getLastReportedPlayingMediaPeriod());
|
return generateEventTime(mediaPeriodQueueTracker.getCurrentPlayerMediaPeriod());
|
||||||
}
|
}
|
||||||
|
|
||||||
private EventTime generatePlayingMediaPeriodEventTime() {
|
private EventTime generatePlayingMediaPeriodEventTime() {
|
||||||
@ -677,8 +673,7 @@ public class AnalyticsCollector
|
|||||||
private final HashMap<MediaPeriodId, MediaPeriodInfo> mediaPeriodIdToInfo;
|
private final HashMap<MediaPeriodId, MediaPeriodInfo> mediaPeriodIdToInfo;
|
||||||
private final Period period;
|
private final Period period;
|
||||||
|
|
||||||
@Nullable private MediaPeriodInfo lastPlayingMediaPeriod;
|
@Nullable private MediaPeriodInfo playingMediaPeriod;
|
||||||
@Nullable private MediaPeriodInfo lastReportedPlayingMediaPeriod;
|
|
||||||
@Nullable private MediaPeriodInfo readingMediaPeriod;
|
@Nullable private MediaPeriodInfo readingMediaPeriod;
|
||||||
private Timeline timeline;
|
private Timeline timeline;
|
||||||
private boolean isSeeking;
|
private boolean isSeeking;
|
||||||
@ -691,34 +686,34 @@ public class AnalyticsCollector
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link MediaPeriodInfo} of the media period in the front of the queue. This is
|
* Returns the {@link MediaPeriodInfo} of the media period corresponding the current position of
|
||||||
* the playing media period unless the player hasn't started playing yet (in which case it is
|
* the player.
|
||||||
* the loading media period or null). While the player is seeking or preparing, this method will
|
*
|
||||||
* always return null to reflect the uncertainty about the current playing period. May also be
|
* <p>May be null if no matching media period has been created yet or the player is currently
|
||||||
* null, if the timeline is empty or no media period is active yet.
|
* masking its state.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public MediaPeriodInfo getPlayingMediaPeriod() {
|
public MediaPeriodInfo getCurrentPlayerMediaPeriod() {
|
||||||
return mediaPeriodInfoQueue.isEmpty() || timeline.isEmpty() || isSeeking
|
return mediaPeriodInfoQueue.isEmpty() || timeline.isEmpty() || isSeeking
|
||||||
? null
|
? null
|
||||||
: mediaPeriodInfoQueue.get(0);
|
: mediaPeriodInfoQueue.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link MediaPeriodInfo} of the currently playing media period. This is the
|
* Returns the {@link MediaPeriodInfo} of the media period at the front of the queue. If the
|
||||||
* publicly reported period which should always match {@link Player#getCurrentPeriodIndex()}
|
* queue is empty, this is the last media period which was at the front of the queue.
|
||||||
* unless the player is currently seeking or being prepared in which case the previous period is
|
*
|
||||||
* reported until the seek or preparation is processed. May be null, if no media period is
|
* <p>May be null, if no media period has been created yet.
|
||||||
* active yet.
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public MediaPeriodInfo getLastReportedPlayingMediaPeriod() {
|
public MediaPeriodInfo getPlayingMediaPeriod() {
|
||||||
return lastReportedPlayingMediaPeriod;
|
return playingMediaPeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link MediaPeriodInfo} of the media period currently being read by the player.
|
* Returns the {@link MediaPeriodInfo} of the media period currently being read by the player.
|
||||||
* May be null, if the player is not reading a media period.
|
*
|
||||||
|
* <p>May be null, if the player is not reading a media period.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public MediaPeriodInfo getReadingMediaPeriod() {
|
public MediaPeriodInfo getReadingMediaPeriod() {
|
||||||
@ -727,8 +722,9 @@ public class AnalyticsCollector
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link MediaPeriodInfo} of the media period at the end of the queue which is
|
* Returns the {@link MediaPeriodInfo} of the media period at the end of the queue which is
|
||||||
* currently loading or will be the next one loading. May be null, if no media period is active
|
* currently loading or will be the next one loading.
|
||||||
* yet.
|
*
|
||||||
|
* <p>May be null, if no media period is active yet.
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public MediaPeriodInfo getLoadingMediaPeriod() {
|
public MediaPeriodInfo getLoadingMediaPeriod() {
|
||||||
@ -770,11 +766,6 @@ public class AnalyticsCollector
|
|||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Updates the queue with a reported position discontinuity . */
|
|
||||||
public void onPositionDiscontinuity(@Player.DiscontinuityReason int reason) {
|
|
||||||
lastReportedPlayingMediaPeriod = lastPlayingMediaPeriod;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Updates the queue with a reported timeline change. */
|
/** Updates the queue with a reported timeline change. */
|
||||||
public void onTimelineChanged(Timeline timeline) {
|
public void onTimelineChanged(Timeline timeline) {
|
||||||
for (int i = 0; i < mediaPeriodInfoQueue.size(); i++) {
|
for (int i = 0; i < mediaPeriodInfoQueue.size(); i++) {
|
||||||
@ -786,8 +777,10 @@ public class AnalyticsCollector
|
|||||||
if (readingMediaPeriod != null) {
|
if (readingMediaPeriod != null) {
|
||||||
readingMediaPeriod = updateMediaPeriodInfoToNewTimeline(readingMediaPeriod, timeline);
|
readingMediaPeriod = updateMediaPeriodInfoToNewTimeline(readingMediaPeriod, timeline);
|
||||||
}
|
}
|
||||||
|
if (!mediaPeriodInfoQueue.isEmpty()) {
|
||||||
|
playingMediaPeriod = mediaPeriodInfoQueue.get(0);
|
||||||
|
}
|
||||||
this.timeline = timeline;
|
this.timeline = timeline;
|
||||||
lastReportedPlayingMediaPeriod = lastPlayingMediaPeriod;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Updates the queue with a reported start of seek. */
|
/** Updates the queue with a reported start of seek. */
|
||||||
@ -798,7 +791,6 @@ public class AnalyticsCollector
|
|||||||
/** Updates the queue with a reported processed seek. */
|
/** Updates the queue with a reported processed seek. */
|
||||||
public void onSeekProcessed() {
|
public void onSeekProcessed() {
|
||||||
isSeeking = false;
|
isSeeking = false;
|
||||||
lastReportedPlayingMediaPeriod = lastPlayingMediaPeriod;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Updates the queue with a newly created media period. */
|
/** Updates the queue with a newly created media period. */
|
||||||
@ -812,10 +804,7 @@ public class AnalyticsCollector
|
|||||||
isInTimeline ? timeline.getPeriod(periodIndex, period).windowIndex : windowIndex);
|
isInTimeline ? timeline.getPeriod(periodIndex, period).windowIndex : windowIndex);
|
||||||
mediaPeriodInfoQueue.add(mediaPeriodInfo);
|
mediaPeriodInfoQueue.add(mediaPeriodInfo);
|
||||||
mediaPeriodIdToInfo.put(mediaPeriodId, mediaPeriodInfo);
|
mediaPeriodIdToInfo.put(mediaPeriodId, mediaPeriodInfo);
|
||||||
lastPlayingMediaPeriod = mediaPeriodInfoQueue.get(0);
|
playingMediaPeriod = mediaPeriodInfoQueue.get(0);
|
||||||
if (mediaPeriodInfoQueue.size() == 1 && !timeline.isEmpty()) {
|
|
||||||
lastReportedPlayingMediaPeriod = lastPlayingMediaPeriod;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -833,7 +822,7 @@ public class AnalyticsCollector
|
|||||||
readingMediaPeriod = mediaPeriodInfoQueue.isEmpty() ? null : mediaPeriodInfoQueue.get(0);
|
readingMediaPeriod = mediaPeriodInfoQueue.isEmpty() ? null : mediaPeriodInfoQueue.get(0);
|
||||||
}
|
}
|
||||||
if (!mediaPeriodInfoQueue.isEmpty()) {
|
if (!mediaPeriodInfoQueue.isEmpty()) {
|
||||||
lastPlayingMediaPeriod = mediaPeriodInfoQueue.get(0);
|
playingMediaPeriod = mediaPeriodInfoQueue.get(0);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ public final class AnalyticsCollectorTest {
|
|||||||
assertThat(listener.getEvents(EVENT_DECODER_DISABLED)).containsExactly(period0);
|
assertThat(listener.getEvents(EVENT_DECODER_DISABLED)).containsExactly(period0);
|
||||||
assertThat(listener.getEvents(EVENT_AUDIO_SESSION_ID)).containsExactly(period1Seq2);
|
assertThat(listener.getEvents(EVENT_AUDIO_SESSION_ID)).containsExactly(period1Seq2);
|
||||||
assertThat(listener.getEvents(EVENT_DROPPED_VIDEO_FRAMES))
|
assertThat(listener.getEvents(EVENT_DROPPED_VIDEO_FRAMES))
|
||||||
.containsExactly(period0, period0, period1Seq2);
|
.containsExactly(period0, period1Seq2, period1Seq2);
|
||||||
assertThat(listener.getEvents(EVENT_VIDEO_SIZE_CHANGED)).containsExactly(period0, period1Seq2);
|
assertThat(listener.getEvents(EVENT_VIDEO_SIZE_CHANGED)).containsExactly(period0, period1Seq2);
|
||||||
assertThat(listener.getEvents(EVENT_RENDERED_FIRST_FRAME))
|
assertThat(listener.getEvents(EVENT_RENDERED_FIRST_FRAME))
|
||||||
.containsExactly(period0, period1Seq2);
|
.containsExactly(period0, period1Seq2);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user