Skip to content

Commit

Permalink
Add convenience methods to query current window
Browse files Browse the repository at this point in the history
- Support querying whether the current window is dynamic
  and seekable. The new methods are similar to getDuration,
  which is also a convenience method for the current window.
- Improve demo app to restore positions in VOD items within
  playlists where the last item is live. Also restore the
  position within the window for live items unless the player
  failed with BehindLiveWindowException.

Issue: #2320

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=144443898
  • Loading branch information
ojw28 committed Jan 13, 2017
1 parent ca7febe commit 270f68a
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.DecoderInitializationException;
import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException;
import com.google.android.exoplayer2.source.BehindLiveWindowException;
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
Expand Down Expand Up @@ -100,7 +101,6 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
}

private Handler mainHandler;
private Timeline.Window window;
private EventLogger eventLogger;
private SimpleExoPlayerView simpleExoPlayerView;
private LinearLayout debugRootView;
Expand All @@ -115,19 +115,18 @@ public class PlayerActivity extends Activity implements OnClickListener, ExoPlay
private boolean playerNeedsSource;

private boolean shouldAutoPlay;
private boolean isTimelineStatic;
private int playerWindow;
private long playerPosition;
private int resumeWindow;
private long resumePosition;

// Activity lifecycle

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
shouldAutoPlay = true;
clearResumePosition();
mediaDataSourceFactory = buildDataSourceFactory(true);
mainHandler = new Handler();
window = new Timeline.Window();
if (CookieHandler.getDefault() != DEFAULT_COOKIE_MANAGER) {
CookieHandler.setDefault(DEFAULT_COOKIE_MANAGER);
}
Expand All @@ -148,7 +147,8 @@ public void onCreate(Bundle savedInstanceState) {
@Override
public void onNewIntent(Intent intent) {
releasePlayer();
isTimelineStatic = false;
shouldAutoPlay = true;
clearResumePosition();
setIntent(intent);
}

Expand Down Expand Up @@ -264,7 +264,7 @@ private void initializePlayer() {
@SimpleExoPlayer.ExtensionRendererMode int extensionRendererMode =
((DemoApplication) getApplication()).useExtensionRenderers()
? (preferExtensionDecoders ? SimpleExoPlayer.EXTENSION_RENDERER_MODE_PREFER
: SimpleExoPlayer.EXTENSION_RENDERER_MODE_ON)
: SimpleExoPlayer.EXTENSION_RENDERER_MODE_ON)
: SimpleExoPlayer.EXTENSION_RENDERER_MODE_OFF;
TrackSelection.Factory videoTrackSelectionFactory =
new AdaptiveVideoTrackSelection.Factory(BANDWIDTH_METER);
Expand All @@ -281,13 +281,6 @@ private void initializePlayer() {
player.setMetadataOutput(eventLogger);

simpleExoPlayerView.setPlayer(player);
if (isTimelineStatic) {
if (playerPosition == C.TIME_UNSET) {
player.seekToDefaultPosition(playerWindow);
} else {
player.seekTo(playerWindow, playerPosition);
}
}
player.setPlayWhenReady(shouldAutoPlay);
debugViewHelper = new DebugTextViewHelper(player, debugTextView);
debugViewHelper.start();
Expand Down Expand Up @@ -324,7 +317,8 @@ private void initializePlayer() {
}
MediaSource mediaSource = mediaSources.length == 1 ? mediaSources[0]
: new ConcatenatingMediaSource(mediaSources);
player.prepare(mediaSource, !isTimelineStatic, !isTimelineStatic);
player.seekTo(resumeWindow, resumePosition);
player.prepare(mediaSource, false, false);
playerNeedsSource = false;
updateButtonVisibilities();
}
Expand Down Expand Up @@ -367,12 +361,7 @@ private void releasePlayer() {
debugViewHelper.stop();
debugViewHelper = null;
shouldAutoPlay = player.getPlayWhenReady();
playerWindow = player.getCurrentWindowIndex();
playerPosition = C.TIME_UNSET;
Timeline timeline = player.getCurrentTimeline();
if (!timeline.isEmpty() && timeline.getWindow(playerWindow, window).isSeekable) {
playerPosition = player.getCurrentPosition();
}
updateResumePosition();
player.release();
player = null;
trackSelector = null;
Expand All @@ -381,6 +370,17 @@ private void releasePlayer() {
}
}

private void updateResumePosition() {
resumeWindow = player.getCurrentWindowIndex();
resumePosition = player.isCurrentWindowSeekable() ? Math.max(0, player.getCurrentPosition())
: C.TIME_UNSET;
}

private void clearResumePosition() {
resumeWindow = 0;
resumePosition = C.TIME_UNSET;
}

/**
* Returns a new DataSource factory.
*
Expand Down Expand Up @@ -427,8 +427,7 @@ public void onPositionDiscontinuity() {

@Override
public void onTimelineChanged(Timeline timeline, Object manifest) {
isTimelineStatic = !timeline.isEmpty()
&& !timeline.getWindow(timeline.getWindowCount() - 1, window).isDynamic;
// Do nothing.
}

@Override
Expand Down Expand Up @@ -460,6 +459,11 @@ public void onPlayerError(ExoPlaybackException e) {
showToast(errorString);
}
playerNeedsSource = true;
if (isBehindLiveWindow(e)) {
clearResumePosition();
} else {
updateResumePosition();
}
updateButtonVisibilities();
showControls();
}
Expand Down Expand Up @@ -535,4 +539,18 @@ private void showToast(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}

private static boolean isBehindLiveWindow(ExoPlaybackException e) {
if (e.type != ExoPlaybackException.TYPE_SOURCE) {
return false;
}
Throwable cause = e.getSourceException();
while (cause != null) {
if (cause instanceof BehindLiveWindowException) {
return true;
}
cause = cause.getCause();
}
return false;
}

}
16 changes: 16 additions & 0 deletions library/src/main/java/com/google/android/exoplayer2/ExoPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -447,4 +447,20 @@ public ExoPlayerMessage(ExoPlayerComponent target, int messageType, Object messa
*/
int getBufferedPercentage();

/**
* Returns whether the current window is dynamic, or {@code false} if the {@link Timeline} is
* empty.
*
* @see Timeline.Window#isDynamic
*/
boolean isCurrentWindowDynamic();

/**
* Returns whether the current window is seekable, or {@code false} if the {@link Timeline} is
* empty.
*
* @see Timeline.Window#isSeekable
*/
boolean isCurrentWindowSeekable();

}
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,22 @@ public int getBufferedPercentage() {
: (int) (duration == 0 ? 100 : (bufferedPosition * 100) / duration);
}

@Override
public boolean isCurrentWindowDynamic() {
if (timeline.isEmpty()) {
return false;
}
return timeline.getWindow(getCurrentWindowIndex(), window).isDynamic;
}

@Override
public boolean isCurrentWindowSeekable() {
if (timeline.isEmpty()) {
return false;
}
return timeline.getWindow(getCurrentWindowIndex(), window).isSeekable;
}

@Override
public int getRendererCount() {
return renderers.length;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -546,63 +546,73 @@ public void blockingSendMessages(ExoPlayerMessage... messages) {
}

@Override
public int getCurrentPeriodIndex() {
return player.getCurrentPeriodIndex();
public int getRendererCount() {
return player.getRendererCount();
}

@Override
public int getCurrentWindowIndex() {
return player.getCurrentWindowIndex();
public int getRendererType(int index) {
return player.getRendererType(index);
}

@Override
public long getDuration() {
return player.getDuration();
public TrackGroupArray getCurrentTrackGroups() {
return player.getCurrentTrackGroups();
}

@Override
public long getCurrentPosition() {
return player.getCurrentPosition();
public TrackSelectionArray getCurrentTrackSelections() {
return player.getCurrentTrackSelections();
}

@Override
public long getBufferedPosition() {
return player.getBufferedPosition();
public Timeline getCurrentTimeline() {
return player.getCurrentTimeline();
}

@Override
public int getBufferedPercentage() {
return player.getBufferedPercentage();
public Object getCurrentManifest() {
return player.getCurrentManifest();
}

@Override
public int getRendererCount() {
return player.getRendererCount();
public int getCurrentPeriodIndex() {
return player.getCurrentPeriodIndex();
}

@Override
public int getRendererType(int index) {
return player.getRendererType(index);
public int getCurrentWindowIndex() {
return player.getCurrentWindowIndex();
}

@Override
public TrackGroupArray getCurrentTrackGroups() {
return player.getCurrentTrackGroups();
public long getDuration() {
return player.getDuration();
}

@Override
public TrackSelectionArray getCurrentTrackSelections() {
return player.getCurrentTrackSelections();
public long getCurrentPosition() {
return player.getCurrentPosition();
}

@Override
public Timeline getCurrentTimeline() {
return player.getCurrentTimeline();
public long getBufferedPosition() {
return player.getBufferedPosition();
}

@Override
public Object getCurrentManifest() {
return player.getCurrentManifest();
public int getBufferedPercentage() {
return player.getBufferedPercentage();
}

@Override
public boolean isCurrentWindowDynamic() {
return player.isCurrentWindowDynamic();
}

@Override
public boolean isCurrentWindowSeekable() {
return player.isCurrentWindowSeekable();
}

// Renderer building.
Expand Down

0 comments on commit 270f68a

Please sign in to comment.