mirror of
https://github.com/samsonjs/media.git
synced 2026-03-30 10:15:48 +00:00
Add getNextWindowIndex to Timeline
(Preparation for Repeat Toggle Function - GitHub Issue #2577) In addition, Timeline now also got a getPreviousWindowIndex and a getNextPeriodIndex method with default implementations. Changed ExoPlayerImplInternal and PlaybackControlView to use these methods at all occurances of period and window index operations. Note: Does not include repeat mode yet and no timelines are actually using it so far. Please wait for the next CLs for this. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=154520664
This commit is contained in:
parent
5c723f4d3d
commit
6d2fa12e16
4 changed files with 130 additions and 18 deletions
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package com.google.android.exoplayer2;
|
||||
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer;
|
||||
import com.google.android.exoplayer2.metadata.MetadataRenderer;
|
||||
|
|
@ -30,6 +31,8 @@ import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
|||
import com.google.android.exoplayer2.trackselection.TrackSelector;
|
||||
import com.google.android.exoplayer2.upstream.DataSource;
|
||||
import com.google.android.exoplayer2.video.MediaCodecVideoRenderer;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* An extensible media player exposing traditional high-level media player functionality, such as
|
||||
|
|
@ -251,6 +254,17 @@ public interface ExoPlayer {
|
|||
*/
|
||||
int STATE_ENDED = 4;
|
||||
|
||||
/**
|
||||
* Repeat modes for playback.
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({REPEAT_MODE_OFF})
|
||||
@interface RepeatMode {}
|
||||
/**
|
||||
* Normal playback without repetition.
|
||||
*/
|
||||
int REPEAT_MODE_OFF = 0;
|
||||
|
||||
/**
|
||||
* Register a listener to receive events from the player. The listener's methods will be called on
|
||||
* the thread that was used to construct the player.
|
||||
|
|
|
|||
|
|
@ -948,10 +948,7 @@ import java.io.IOException;
|
|||
}
|
||||
|
||||
// The current period is in the new timeline. Update the holder and playbackInfo.
|
||||
timeline.getPeriod(periodIndex, period);
|
||||
boolean isLastPeriod = periodIndex == timeline.getPeriodCount() - 1
|
||||
&& !timeline.getWindow(period.windowIndex, window).isDynamic;
|
||||
periodHolder.setIndex(periodIndex, isLastPeriod);
|
||||
periodHolder.setIndex(periodIndex, isLastPeriod(periodIndex));
|
||||
boolean seenReadingPeriod = periodHolder == readingPeriodHolder;
|
||||
if (periodIndex != playbackInfo.periodIndex) {
|
||||
playbackInfo = playbackInfo.copyWithPeriodIndex(periodIndex);
|
||||
|
|
@ -962,10 +959,10 @@ import java.io.IOException;
|
|||
while (periodHolder.next != null) {
|
||||
MediaPeriodHolder previousPeriodHolder = periodHolder;
|
||||
periodHolder = periodHolder.next;
|
||||
periodIndex++;
|
||||
periodIndex = timeline.getNextPeriodIndex(periodIndex, period, window,
|
||||
ExoPlayer.REPEAT_MODE_OFF);
|
||||
boolean isLastPeriod = isLastPeriod(periodIndex);
|
||||
timeline.getPeriod(periodIndex, period, true);
|
||||
isLastPeriod = periodIndex == timeline.getPeriodCount() - 1
|
||||
&& !timeline.getWindow(period.windowIndex, window).isDynamic;
|
||||
if (periodHolder.uid.equals(period.uid)) {
|
||||
// The holder is consistent with the new timeline. Update its index and continue.
|
||||
periodHolder.setIndex(periodIndex, isLastPeriod);
|
||||
|
|
@ -1023,13 +1020,22 @@ import java.io.IOException;
|
|||
private int resolveSubsequentPeriod(int oldPeriodIndex, Timeline oldTimeline,
|
||||
Timeline newTimeline) {
|
||||
int newPeriodIndex = C.INDEX_UNSET;
|
||||
while (newPeriodIndex == C.INDEX_UNSET && oldPeriodIndex < oldTimeline.getPeriodCount() - 1) {
|
||||
int maxIterations = oldTimeline.getPeriodCount();
|
||||
for (int i = 0; i < maxIterations && newPeriodIndex == C.INDEX_UNSET; i++) {
|
||||
oldPeriodIndex = oldTimeline.getNextPeriodIndex(oldPeriodIndex, period, window,
|
||||
ExoPlayer.REPEAT_MODE_OFF);
|
||||
newPeriodIndex = newTimeline.getIndexOfPeriod(
|
||||
oldTimeline.getPeriod(++oldPeriodIndex, period, true).uid);
|
||||
oldTimeline.getPeriod(oldPeriodIndex, period, true).uid);
|
||||
}
|
||||
return newPeriodIndex;
|
||||
}
|
||||
|
||||
private boolean isLastPeriod(int periodIndex) {
|
||||
int windowIndex = timeline.getPeriod(periodIndex, period).windowIndex;
|
||||
return !timeline.getWindow(windowIndex, window).isDynamic
|
||||
&& timeline.isLastPeriod(periodIndex, period, window, ExoPlayer.REPEAT_MODE_OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link SeekPosition} into the corresponding (periodIndex, periodPositionUs) for the
|
||||
* internal timeline.
|
||||
|
|
@ -1240,7 +1246,8 @@ import java.io.IOException;
|
|||
// We are already buffering the maximum number of periods ahead.
|
||||
return;
|
||||
}
|
||||
newLoadingPeriodIndex = loadingPeriodHolder.index + 1;
|
||||
newLoadingPeriodIndex = timeline.getNextPeriodIndex(loadingPeriodHolder.index, period, window,
|
||||
ExoPlayer.REPEAT_MODE_OFF);
|
||||
}
|
||||
|
||||
if (newLoadingPeriodIndex >= timeline.getPeriodCount()) {
|
||||
|
|
@ -1283,9 +1290,8 @@ import java.io.IOException;
|
|||
? newLoadingPeriodStartPositionUs + RENDERER_TIMESTAMP_OFFSET_US
|
||||
: (loadingPeriodHolder.getRendererOffset()
|
||||
+ timeline.getPeriod(loadingPeriodHolder.index, period).getDurationUs());
|
||||
boolean isLastPeriod = isLastPeriod(newLoadingPeriodIndex);
|
||||
timeline.getPeriod(newLoadingPeriodIndex, period, true);
|
||||
boolean isLastPeriod = newLoadingPeriodIndex == timeline.getPeriodCount() - 1
|
||||
&& !timeline.getWindow(period.windowIndex, window).isDynamic;
|
||||
MediaPeriodHolder newPeriodHolder = new MediaPeriodHolder(renderers, rendererCapabilities,
|
||||
rendererPositionOffsetUs, trackSelector, loadControl, mediaSource, period.uid,
|
||||
newLoadingPeriodIndex, isLastPeriod, newLoadingPeriodStartPositionUs);
|
||||
|
|
|
|||
|
|
@ -136,6 +136,54 @@ public abstract class Timeline {
|
|||
*/
|
||||
public abstract int getWindowCount();
|
||||
|
||||
/**
|
||||
* Returns the index of the window after the window at index {@code windowIndex} depending on the
|
||||
* {@code repeatMode}.
|
||||
*
|
||||
* @param windowIndex Index of a window in the timeline.
|
||||
* @param repeatMode A repeat mode.
|
||||
* @return The index of the next window, or {@link C#INDEX_UNSET} if this is the last window.
|
||||
*/
|
||||
public int getNextWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
return windowIndex == getWindowCount() - 1 ? C.INDEX_UNSET : windowIndex + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the window before the window at index {@code windowIndex} depending on the
|
||||
* {@code repeatMode}.
|
||||
*
|
||||
* @param windowIndex Index of a window in the timeline.
|
||||
* @param repeatMode A repeat mode.
|
||||
* @return The index of the previous window, or {@link C#INDEX_UNSET} if this is the first window.
|
||||
*/
|
||||
public int getPreviousWindowIndex(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
return windowIndex == 0 ? C.INDEX_UNSET : windowIndex - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given window is the last window of the timeline depending on the
|
||||
* {@code repeatMode}.
|
||||
*
|
||||
* @param windowIndex A window index.
|
||||
* @param repeatMode A repeat mode.
|
||||
* @return Whether the window of the given index is the last window of the timeline.
|
||||
*/
|
||||
public final boolean isLastWindow(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
return getNextWindowIndex(windowIndex, repeatMode) == C.INDEX_UNSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given window is the first window of the timeline depending on the
|
||||
* {@code repeatMode}.
|
||||
*
|
||||
* @param windowIndex A window index.
|
||||
* @param repeatMode A repeat mode.
|
||||
* @return Whether the window of the given index is the first window of the timeline.
|
||||
*/
|
||||
public final boolean isFirstWindow(int windowIndex, @ExoPlayer.RepeatMode int repeatMode) {
|
||||
return getPreviousWindowIndex(windowIndex, repeatMode) == C.INDEX_UNSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates a {@link Window} with data for the window at the specified index. Does not populate
|
||||
* {@link Window#id}.
|
||||
|
|
@ -180,6 +228,44 @@ public abstract class Timeline {
|
|||
*/
|
||||
public abstract int getPeriodCount();
|
||||
|
||||
/**
|
||||
* Returns the index of the period after the period at index {@code periodIndex} depending on the
|
||||
* {@code repeatMode}.
|
||||
*
|
||||
* @param periodIndex Index of a period in the timeline.
|
||||
* @param period A {@link Period} to be used internally. Must not be null.
|
||||
* @param window A {@link Window} to be used internally. Must not be null.
|
||||
* @param repeatMode A repeat mode.
|
||||
* @return The index of the next period, or {@link C#INDEX_UNSET} if this is the last period.
|
||||
*/
|
||||
public final int getNextPeriodIndex(int periodIndex, Period period, Window window,
|
||||
@ExoPlayer.RepeatMode int repeatMode) {
|
||||
int windowIndex = getPeriod(periodIndex, period).windowIndex;
|
||||
if (getWindow(windowIndex, window).lastPeriodIndex == periodIndex) {
|
||||
int nextWindowIndex = getNextWindowIndex(windowIndex, repeatMode);
|
||||
if (nextWindowIndex == C.INDEX_UNSET) {
|
||||
return C.INDEX_UNSET;
|
||||
}
|
||||
return getWindow(nextWindowIndex, window).firstPeriodIndex;
|
||||
}
|
||||
return periodIndex + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given period is the last period of the timeline depending on the
|
||||
* {@code repeatMode}.
|
||||
*
|
||||
* @param periodIndex A period index.
|
||||
* @param period A {@link Period} to be used internally. Must not be null.
|
||||
* @param window A {@link Window} to be used internally. Must not be null.
|
||||
* @param repeatMode A repeat mode.
|
||||
* @return Whether the period of the given index is the last period of the timeline.
|
||||
*/
|
||||
public final boolean isLastPeriod(int periodIndex, Period period, Window window,
|
||||
@ExoPlayer.RepeatMode int repeatMode) {
|
||||
return getNextPeriodIndex(periodIndex, period, window, repeatMode) == C.INDEX_UNSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates a {@link Period} with data for the period at the specified index. Does not populate
|
||||
* {@link Period#id} and {@link Period#uid}.
|
||||
|
|
|
|||
|
|
@ -529,8 +529,10 @@ public class PlaybackControlView extends FrameLayout {
|
|||
int windowIndex = player.getCurrentWindowIndex();
|
||||
timeline.getWindow(windowIndex, window);
|
||||
isSeekable = window.isSeekable;
|
||||
enablePrevious = windowIndex > 0 || isSeekable || !window.isDynamic;
|
||||
enableNext = (windowIndex < timeline.getWindowCount() - 1) || window.isDynamic;
|
||||
enablePrevious = !timeline.isFirstWindow(windowIndex, ExoPlayer.REPEAT_MODE_OFF)
|
||||
|| isSeekable || !window.isDynamic;
|
||||
enableNext = !timeline.isLastWindow(windowIndex, ExoPlayer.REPEAT_MODE_OFF)
|
||||
|| window.isDynamic;
|
||||
if (timeline.getPeriod(player.getCurrentPeriodIndex(), period).isAd) {
|
||||
// Always hide player controls during ads.
|
||||
hide();
|
||||
|
|
@ -680,9 +682,12 @@ public class PlaybackControlView extends FrameLayout {
|
|||
}
|
||||
int windowIndex = player.getCurrentWindowIndex();
|
||||
timeline.getWindow(windowIndex, window);
|
||||
if (windowIndex > 0 && (player.getCurrentPosition() <= MAX_POSITION_FOR_SEEK_TO_PREVIOUS
|
||||
int previousWindowIndex = timeline.getPreviousWindowIndex(windowIndex,
|
||||
ExoPlayer.REPEAT_MODE_OFF);
|
||||
if (previousWindowIndex != C.INDEX_UNSET
|
||||
&& (player.getCurrentPosition() <= MAX_POSITION_FOR_SEEK_TO_PREVIOUS
|
||||
|| (window.isDynamic && !window.isSeekable))) {
|
||||
seekTo(windowIndex - 1, C.TIME_UNSET);
|
||||
seekTo(previousWindowIndex, C.TIME_UNSET);
|
||||
} else {
|
||||
seekTo(0);
|
||||
}
|
||||
|
|
@ -694,8 +699,9 @@ public class PlaybackControlView extends FrameLayout {
|
|||
return;
|
||||
}
|
||||
int windowIndex = player.getCurrentWindowIndex();
|
||||
if (windowIndex < timeline.getWindowCount() - 1) {
|
||||
seekTo(windowIndex + 1, C.TIME_UNSET);
|
||||
int nextWindowIndex = timeline.getNextWindowIndex(windowIndex, ExoPlayer.REPEAT_MODE_OFF);
|
||||
if (nextWindowIndex != C.INDEX_UNSET) {
|
||||
seekTo(nextWindowIndex, C.TIME_UNSET);
|
||||
} else if (timeline.getWindow(windowIndex, window, false).isDynamic) {
|
||||
seekTo(windowIndex, C.TIME_UNSET);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue