Commit 8208a75f by andrewlewis Committed by Oliver Woodman

Improve multi-window playback controls behavior.

Only enable multi-window mode when the duration of every period in the timeline
is known. Also, remove the warning logged when there are too many windows as it
doesn't add much.

The player's current period index was not masked while there were
unacknowledged seeks. This led to the displayed position jumping, between when
seekTo was called (after which the position would be masked but not the period
index) and the seek being acknowledged (at which point the time bar's position
would jump back to the seek position, due to the period index being resolved).
Mask the period index, like the window index, to fix this behavior.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=152116040
parent 6a7db4b1
...@@ -65,6 +65,7 @@ import java.util.concurrent.CopyOnWriteArraySet; ...@@ -65,6 +65,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
// Playback information when there is a pending seek/set source operation. // Playback information when there is a pending seek/set source operation.
private int maskingWindowIndex; private int maskingWindowIndex;
private int maskingPeriodIndex;
private long maskingWindowPositionMs; private long maskingWindowPositionMs;
/** /**
...@@ -187,6 +188,22 @@ import java.util.concurrent.CopyOnWriteArraySet; ...@@ -187,6 +188,22 @@ import java.util.concurrent.CopyOnWriteArraySet;
} }
pendingSeekAcks++; pendingSeekAcks++;
maskingWindowIndex = windowIndex; maskingWindowIndex = windowIndex;
if (timeline.isEmpty()) {
maskingPeriodIndex = 0;
} else {
timeline.getWindow(windowIndex, window);
long resolvedPositionMs =
positionMs == C.TIME_UNSET ? window.getDefaultPositionUs() : positionMs;
int periodIndex = window.firstPeriodIndex;
long periodPositionUs = window.getPositionInFirstPeriodUs() + C.msToUs(resolvedPositionMs);
long periodDurationUs = timeline.getPeriod(periodIndex, period).getDurationUs();
while (periodDurationUs != C.TIME_UNSET && periodPositionUs >= periodDurationUs
&& periodIndex < window.lastPeriodIndex) {
periodPositionUs -= periodDurationUs;
periodDurationUs = timeline.getPeriod(++periodIndex, period).getDurationUs();
}
maskingPeriodIndex = periodIndex;
}
if (positionMs == C.TIME_UNSET) { if (positionMs == C.TIME_UNSET) {
maskingWindowPositionMs = 0; maskingWindowPositionMs = 0;
internalPlayer.seekTo(timeline, windowIndex, C.TIME_UNSET); internalPlayer.seekTo(timeline, windowIndex, C.TIME_UNSET);
...@@ -235,7 +252,11 @@ import java.util.concurrent.CopyOnWriteArraySet; ...@@ -235,7 +252,11 @@ import java.util.concurrent.CopyOnWriteArraySet;
@Override @Override
public int getCurrentPeriodIndex() { public int getCurrentPeriodIndex() {
return playbackInfo.periodIndex; if (timeline.isEmpty() || pendingSeekAcks > 0) {
return maskingPeriodIndex;
} else {
return playbackInfo.periodIndex;
}
} }
@Override @Override
......
...@@ -21,7 +21,6 @@ import android.content.Context; ...@@ -21,7 +21,6 @@ import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
...@@ -34,6 +33,7 @@ import com.google.android.exoplayer2.PlaybackParameters; ...@@ -34,6 +33,7 @@ import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import java.util.Arrays; import java.util.Arrays;
import java.util.Formatter; import java.util.Formatter;
...@@ -345,8 +345,9 @@ public class PlaybackControlView extends FrameLayout { ...@@ -345,8 +345,9 @@ public class PlaybackControlView extends FrameLayout {
/** /**
* Sets whether the time bar should show all windows, as opposed to just the current one. If the * Sets whether the time bar should show all windows, as opposed to just the current one. If the
* timeline has more than {@link #MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR} windows the time bar will * timeline has a period with unknown duration or more than
* fall back to showing a single window. * {@link #MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR} windows the time bar will fall back to showing a
* single window.
* *
* @param showMultiWindowTimeBar Whether the time bar should show all windows. * @param showMultiWindowTimeBar Whether the time bar should show all windows.
*/ */
...@@ -523,14 +524,8 @@ public class PlaybackControlView extends FrameLayout { ...@@ -523,14 +524,8 @@ public class PlaybackControlView extends FrameLayout {
if (player == null) { if (player == null) {
return; return;
} }
if (showMultiWindowTimeBar) { multiWindowTimeBar = showMultiWindowTimeBar
if (player.getCurrentTimeline().getWindowCount() <= MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR) { && canShowMultiWindowTimeBar(player.getCurrentTimeline(), period);
multiWindowTimeBar = true;
return;
}
Log.w(TAG, "Too many windows for multi-window time bar. Falling back to showing one window.");
}
multiWindowTimeBar = false;
} }
private void updateProgress() { private void updateProgress() {
...@@ -568,10 +563,7 @@ public class PlaybackControlView extends FrameLayout { ...@@ -568,10 +563,7 @@ public class PlaybackControlView extends FrameLayout {
} else { } else {
isInAdBreak = false; isInAdBreak = false;
long periodDurationUs = period.getDurationUs(); long periodDurationUs = period.getDurationUs();
if (periodDurationUs == C.TIME_UNSET) { Assertions.checkState(periodDurationUs != C.TIME_UNSET);
durationUs = C.TIME_UNSET;
break;
}
long periodDurationInWindowUs = periodDurationUs; long periodDurationInWindowUs = periodDurationUs;
if (j == window.firstPeriodIndex) { if (j == window.firstPeriodIndex) {
periodDurationInWindowUs -= window.positionInFirstPeriodUs; periodDurationInWindowUs -= window.positionInFirstPeriodUs;
...@@ -797,6 +789,26 @@ public class PlaybackControlView extends FrameLayout { ...@@ -797,6 +789,26 @@ public class PlaybackControlView extends FrameLayout {
|| keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS; || keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS;
} }
/**
* Returns whether the specified {@code timeline} can be shown on a multi-window time bar.
*
* @param timeline The {@link Timeline} to check.
* @param period A scratch {@link Timeline.Period} instance.
* @return Whether the specified timeline can be shown on a multi-window time bar.
*/
private static boolean canShowMultiWindowTimeBar(Timeline timeline, Timeline.Period period) {
if (timeline.getWindowCount() > MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR) {
return false;
}
int periodCount = timeline.getPeriodCount();
for (int i = 0; i < periodCount; i++) {
if (timeline.getPeriod(i, period).durationUs == C.TIME_UNSET) {
return false;
}
}
return true;
}
private final class ComponentListener implements ExoPlayer.EventListener, TimeBar.OnScrubListener, private final class ComponentListener implements ExoPlayer.EventListener, TimeBar.OnScrubListener,
OnClickListener { OnClickListener {
......
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