diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java
index bb1851efa..e3d351671 100644
--- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java
+++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java
@@ -46,7 +46,7 @@ import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.BehindLiveWindowException;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
-import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
+import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.util.Util;
@@ -125,7 +125,6 @@ public abstract class BasePlayer implements
//////////////////////////////////////////////////////////////////////////*/
protected static final float[] PLAYBACK_SPEEDS = {0.5f, 0.75f, 1f, 1.25f, 1.5f, 1.75f, 2f};
- protected static final float[] PLAYBACK_PITCHES = {0.8f, 0.9f, 0.95f, 1f, 1.05f, 1.1f, 1.2f};
protected PlayQueue playQueue;
protected PlayQueueAdapter playQueueAdapter;
@@ -141,10 +140,11 @@ public abstract class BasePlayer implements
// Player
//////////////////////////////////////////////////////////////////////////*/
- protected final static int FAST_FORWARD_REWIND_AMOUNT = 10000; // 10 Seconds
- protected final static int PLAY_PREV_ACTIVATION_LIMIT = 5000; // 5 seconds
- protected final static int PROGRESS_LOOP_INTERVAL = 500;
- protected final static int RECOVERY_SKIP_THRESHOLD = 3000; // 3 seconds
+ protected final static int FAST_FORWARD_REWIND_AMOUNT_MILLIS = 10000; // 10 Seconds
+ protected final static int PLAY_PREV_ACTIVATION_LIMIT_MILLIS = 5000; // 5 seconds
+ protected final static int PROGRESS_LOOP_INTERVAL_MILLIS = 500;
+ protected final static int RECOVERY_SKIP_THRESHOLD_MILLIS = 3000; // 3 seconds
+ protected final static int SHORT_LIVESTREAM_CHUNK_LENGTH_MILLIS = 60000; // 1 minute
protected CustomTrackSelector trackSelector;
protected PlayerDataSource dataSource;
@@ -192,8 +192,8 @@ public abstract class BasePlayer implements
final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter);
- final AdaptiveTrackSelection.Factory trackSelectionFactory =
- new AdaptiveTrackSelection.Factory(bandwidthMeter);
+ final TrackSelection.Factory trackSelectionFactory =
+ PlayerHelper.getQualitySelector(context, bandwidthMeter);
trackSelector = new CustomTrackSelector(trackSelectionFactory);
final LoadControl loadControl = new LoadController(context);
@@ -519,15 +519,16 @@ public abstract class BasePlayer implements
}
public void triggerProgressUpdate() {
+ if (simpleExoPlayer == null) return;
onUpdateProgress(
- (int) simpleExoPlayer.getCurrentPosition(),
+ Math.max((int) simpleExoPlayer.getCurrentPosition(), 0),
(int) simpleExoPlayer.getDuration(),
simpleExoPlayer.getBufferedPercentage()
);
}
private Disposable getProgressReactor() {
- return Observable.interval(PROGRESS_LOOP_INTERVAL, TimeUnit.MILLISECONDS)
+ return Observable.interval(PROGRESS_LOOP_INTERVAL_MILLIS, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(ignored -> triggerProgressUpdate());
}
@@ -554,8 +555,8 @@ public abstract class BasePlayer implements
// Ensure dynamic/livestream timeline changes does not cause negative position
if (isPlaylistStable && !isCurrentWindowValid() && !isSynchronizing) {
if (DEBUG) Log.d(TAG, "Playback - negative time position reached, " +
- "clamping position to 0ms.");
- seekTo(/*clampToTime=*/0);
+ "clamping to default position.");
+ seekToDefault();
}
break;
}
@@ -703,11 +704,7 @@ public abstract class BasePlayer implements
private void processSourceError(final IOException error) {
if (simpleExoPlayer == null || playQueue == null) return;
-
- if (simpleExoPlayer.getCurrentPosition() <
- simpleExoPlayer.getDuration() - RECOVERY_SKIP_THRESHOLD) {
- setRecovery();
- }
+ setRecovery();
final Throwable cause = error.getCause();
if (cause instanceof BehindLiveWindowException) {
@@ -972,22 +969,22 @@ public abstract class BasePlayer implements
public void onFastRewind() {
if (DEBUG) Log.d(TAG, "onFastRewind() called");
- seekBy(-FAST_FORWARD_REWIND_AMOUNT);
+ seekBy(-FAST_FORWARD_REWIND_AMOUNT_MILLIS);
}
public void onFastForward() {
if (DEBUG) Log.d(TAG, "onFastForward() called");
- seekBy(FAST_FORWARD_REWIND_AMOUNT);
+ seekBy(FAST_FORWARD_REWIND_AMOUNT_MILLIS);
}
public void onPlayPrevious() {
if (simpleExoPlayer == null || playQueue == null) return;
if (DEBUG) Log.d(TAG, "onPlayPrevious() called");
- /* If current playback has run for PLAY_PREV_ACTIVATION_LIMIT milliseconds,
+ /* If current playback has run for PLAY_PREV_ACTIVATION_LIMIT_MILLIS milliseconds,
* restart current track. Also restart the track if the current track
* is the first in a queue.*/
- if (simpleExoPlayer.getCurrentPosition() > PLAY_PREV_ACTIVATION_LIMIT ||
+ if (simpleExoPlayer.getCurrentPosition() > PLAY_PREV_ACTIVATION_LIMIT_MILLIS ||
playQueue.getIndex() == 0) {
seekToDefault();
playQueue.offsetIndex(0);
@@ -1036,8 +1033,27 @@ public abstract class BasePlayer implements
&& simpleExoPlayer.getCurrentPosition() >= 0;
}
+ /**
+ * Seeks to the default position of the currently playing
+ * {@link com.google.android.exoplayer2.Timeline.Window}. Does nothing if the
+ * {@link #simpleExoPlayer} is not initialized.
+ *
+ * If the current window is non-live, then this will seek to the start of the window.
+ * If the window is live but has a buffer length greater than
+ * {@link #SHORT_LIVESTREAM_CHUNK_LENGTH_MILLIS}, then this will seek to the default
+ * live edge position through {@link SimpleExoPlayer#seekToDefaultPosition}.
+ * Otherwise, this will seek to the maximum position possible for the current buffer
+ * given by {@link SimpleExoPlayer#getDuration}.
+ *
+ * @see SimpleExoPlayer#seekToDefaultPosition
+ * */
public void seekToDefault() {
- if (simpleExoPlayer != null) simpleExoPlayer.seekToDefaultPosition();
+ if (simpleExoPlayer == null) return;
+ if (isLive() && simpleExoPlayer.getDuration() < SHORT_LIVESTREAM_CHUNK_LENGTH_MILLIS) {
+ simpleExoPlayer.seekTo(simpleExoPlayer.getDuration());
+ } else {
+ simpleExoPlayer.seekToDefaultPosition();
+ }
}
/*//////////////////////////////////////////////////////////////////////////
@@ -1078,9 +1094,9 @@ public abstract class BasePlayer implements
private void savePlaybackState() {
if (simpleExoPlayer == null || currentInfo == null) return;
- if (simpleExoPlayer.getCurrentPosition() > RECOVERY_SKIP_THRESHOLD &&
+ if (simpleExoPlayer.getCurrentPosition() > RECOVERY_SKIP_THRESHOLD_MILLIS &&
simpleExoPlayer.getCurrentPosition() <
- simpleExoPlayer.getDuration() - RECOVERY_SKIP_THRESHOLD) {
+ simpleExoPlayer.getDuration() - RECOVERY_SKIP_THRESHOLD_MILLIS) {
savePlaybackState(currentInfo, simpleExoPlayer.getCurrentPosition());
}
}
@@ -1165,10 +1181,6 @@ public abstract class BasePlayer implements
setPlaybackParameters(speed, getPlaybackPitch());
}
- public void setPlaybackPitch(float pitch) {
- setPlaybackParameters(getPlaybackSpeed(), pitch);
- }
-
public PlaybackParameters getPlaybackParameters() {
final PlaybackParameters defaultParameters = new PlaybackParameters(1f, 1f);
if (simpleExoPlayer == null) return defaultParameters;
diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java
index 63ac7e8a1..84c7a619b 100644
--- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java
@@ -7,7 +7,11 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.SeekParameters;
+import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
+import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
+import com.google.android.exoplayer2.upstream.BandwidthMeter;
+import com.google.android.exoplayer2.util.Clock;
import com.google.android.exoplayer2.util.MimeTypes;
import org.schabi.newpipe.R;
@@ -203,6 +207,16 @@ public class PlayerHelper {
return 60000;
}
+ public static TrackSelection.Factory getQualitySelector(@NonNull final Context context,
+ @NonNull final BandwidthMeter meter) {
+ return new AdaptiveTrackSelection.Factory(meter,
+ AdaptiveTrackSelection.DEFAULT_MAX_INITIAL_BITRATE,
+ /*bufferDurationRequiredForQualityIncrease=*/1000,
+ AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS,
+ AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS,
+ AdaptiveTrackSelection.DEFAULT_BANDWIDTH_FRACTION);
+ }
+
public static boolean isUsingDSP(@NonNull final Context context) {
return true;
}