Skip to content

Commit

Permalink
Improve multi-window playback controls behavior.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
andrewlewis authored and ojw28 committed Apr 6, 2017
1 parent 6a7db4b commit 8208a75
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@

// Playback information when there is a pending seek/set source operation.
private int maskingWindowIndex;
private int maskingPeriodIndex;
private long maskingWindowPositionMs;

/**
Expand Down Expand Up @@ -187,6 +188,22 @@ public void seekTo(int windowIndex, long positionMs) {
}
pendingSeekAcks++;
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) {
maskingWindowPositionMs = 0;
internalPlayer.seekTo(timeline, windowIndex, C.TIME_UNSET);
Expand Down Expand Up @@ -235,7 +252,11 @@ public void blockingSendMessages(ExoPlayerMessage... messages) {

@Override
public int getCurrentPeriodIndex() {
return playbackInfo.periodIndex;
if (timeline.isEmpty() || pendingSeekAcks > 0) {
return maskingPeriodIndex;
} else {
return playbackInfo.periodIndex;
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import android.content.res.TypedArray;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
Expand All @@ -34,6 +33,7 @@
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import java.util.Arrays;
import java.util.Formatter;
Expand Down Expand Up @@ -345,8 +345,9 @@ public void setPlayer(ExoPlayer player) {

/**
* 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
* fall back to showing a single window.
* timeline has a period with unknown duration or more than
* {@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.
*/
Expand Down Expand Up @@ -523,14 +524,8 @@ private void updateTimeBarMode() {
if (player == null) {
return;
}
if (showMultiWindowTimeBar) {
if (player.getCurrentTimeline().getWindowCount() <= MAX_WINDOWS_FOR_MULTI_WINDOW_TIME_BAR) {
multiWindowTimeBar = true;
return;
}
Log.w(TAG, "Too many windows for multi-window time bar. Falling back to showing one window.");
}
multiWindowTimeBar = false;
multiWindowTimeBar = showMultiWindowTimeBar
&& canShowMultiWindowTimeBar(player.getCurrentTimeline(), period);
}

private void updateProgress() {
Expand Down Expand Up @@ -568,10 +563,7 @@ private void updateProgress() {
} else {
isInAdBreak = false;
long periodDurationUs = period.getDurationUs();
if (periodDurationUs == C.TIME_UNSET) {
durationUs = C.TIME_UNSET;
break;
}
Assertions.checkState(periodDurationUs != C.TIME_UNSET);
long periodDurationInWindowUs = periodDurationUs;
if (j == window.firstPeriodIndex) {
periodDurationInWindowUs -= window.positionInFirstPeriodUs;
Expand Down Expand Up @@ -797,6 +789,26 @@ private static boolean isHandledMediaKey(int keyCode) {
|| 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,
OnClickListener {

Expand Down

0 comments on commit 8208a75

Please sign in to comment.