From 85076ec095e35bda8a8eb7dd3ce99e3832aaa3bc Mon Sep 17 00:00:00 2001 From: Brian Wernick Date: Tue, 29 May 2018 10:16:17 -0600 Subject: [PATCH] Fixed the `seekTo` and `getCurrentPosition` functionality to pay attention to multi-window media sources. Updated ExoPlayer to `2.8.1` (from `2.8.0`) --- README.md | 2 +- build.gradle | 2 +- library/build.gradle | 2 +- .../core/exoplayer/ExoMediaPlayer.java | 77 ++++++++++++++++++- 4 files changed, 78 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0e718076..2a732f1e 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ repositories { } dependencies { - implementation 'com.devbrackets.android:exomedia:4.2.0' + implementation 'com.devbrackets.android:exomedia:4.2.1' } ``` diff --git a/build.gradle b/build.gradle index 344bc463..f0b4cbe7 100644 --- a/build.gradle +++ b/build.gradle @@ -17,6 +17,6 @@ allprojects { } ext { - exoPlayerVersion = "2.8.0" + exoPlayerVersion = "2.8.1" supportLibVersion = "27.1.1" } \ No newline at end of file diff --git a/library/build.gradle b/library/build.gradle index 81ca5d67..d850b99e 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -4,7 +4,7 @@ apply plugin: 'com.novoda.bintray-release' def versionMajor = 4 def versionMinor = 2 -def versionPatch = 0 +def versionPatch = 1 def libraryGroupId = 'com.devbrackets.android' def libraryBaseName = 'exomedia' diff --git a/library/src/main/java/com/devbrackets/android/exomedia/core/exoplayer/ExoMediaPlayer.java b/library/src/main/java/com/devbrackets/android/exomedia/core/exoplayer/ExoMediaPlayer.java index 29c266af..c261836b 100644 --- a/library/src/main/java/com/devbrackets/android/exomedia/core/exoplayer/ExoMediaPlayer.java +++ b/library/src/main/java/com/devbrackets/android/exomedia/core/exoplayer/ExoMediaPlayer.java @@ -377,6 +377,47 @@ public void setPlayWhenReady(boolean playWhenReady) { } public void seekTo(long positionMs) { + seekTo(positionMs, false); + } + + /** + * TODO: Expose this + * Seeks to the specified position in the media currently loaded specified by positionMs. + * If limitToCurrentWindow is true then a seek won't be allowed to span across windows. + * This should only be different if the media in playback has multiple windows (e.g. in the case of using a + * ConcatenatingMediaSource with more than 1 source) + * + * @param positionMs The position to seek to in the media + * @param limitToCurrentWindow true to only seek in the current window + */ + public void seekTo(long positionMs, boolean limitToCurrentWindow) { + if (limitToCurrentWindow) { + player.seekTo(positionMs); + stateStore.setMostRecentState(stateStore.isLastReportedPlayWhenReady(), StateStore.STATE_SEEKING); + return; + } + + // We seek to the position in the timeline (may be across windows) + Timeline timeline = player.getCurrentTimeline(); + int windowCount = timeline.getWindowCount(); + + long cumulativePositionMs = 0; + Timeline.Window window = new Timeline.Window(); + + for (int index = 0; index < windowCount; index++) { + timeline.getWindow(index, window); + + long windowDurationMs = window.getDurationMs(); + if (cumulativePositionMs < positionMs && positionMs <= (cumulativePositionMs + windowDurationMs)) { + player.seekTo(index, positionMs - cumulativePositionMs); + stateStore.setMostRecentState(stateStore.isLastReportedPlayWhenReady(), StateStore.STATE_SEEKING); + return; + } + + cumulativePositionMs += windowDurationMs; + } + + Log.e(TAG, "Unable to seek across windows, falling back to in-window seeking"); player.seekTo(positionMs); stateStore.setMostRecentState(stateStore.isLastReportedPlayWhenReady(), StateStore.STATE_SEEKING); } @@ -431,7 +472,39 @@ public float getPlaybackSpeed() { } public long getCurrentPosition() { - return player.getCurrentPosition(); + return getCurrentPosition(false); + } + + /** + * TODO: Expose this + * Returns the position in the media. If limitToCurrentWindow is true then the position + * in the current window will be returned, otherwise the total position across all windows will be returned. + * These should only be different if the media in playback has multiple windows (e.g. in the case of using a + * ConcatenatingMediaSource with more than 1 source) + * + * @param limitToCurrentWindow If true the position within the current window will be returned + * @return The current position in the media + */ + public long getCurrentPosition(boolean limitToCurrentWindow) { + long positionInCurrentWindow = player.getCurrentPosition(); + if (limitToCurrentWindow) { + return positionInCurrentWindow; + } + + // TODO cache the total time at the start of each window (e.g. Map) + // Adds the preceding window durations + Timeline timeline = player.getCurrentTimeline(); + int maxWindowIndex = Math.min(timeline.getWindowCount() -1, player.getCurrentWindowIndex()); + + long cumulativePositionMs = 0; + Timeline.Window window = new Timeline.Window(); + + for (int index = 0; index < maxWindowIndex; index++) { + timeline.getWindow(index, window); + cumulativePositionMs += window.getDurationMs(); + } + + return cumulativePositionMs + positionInCurrentWindow; } public long getDuration() { @@ -450,7 +523,7 @@ public WindowInfo getWindowInfo() { } int currentWindowIndex = player.getCurrentWindowIndex(); - Timeline.Window currentWindow = timeline.getWindow(currentWindowIndex, new Timeline.Window()); + Timeline.Window currentWindow = timeline.getWindow(currentWindowIndex, new Timeline.Window(), true); return new WindowInfo( player.getPreviousWindowIndex(),