-Modified adaptive track selection to upgrade with 1 second of buffer.
-Modified dynamic track updates to seek to default time instead of clamping to 0 time when negative progress is reached.
This commit is contained in:
parent
de534b58c5
commit
238bff1fee
|
@ -46,7 +46,7 @@ import com.google.android.exoplayer2.Timeline;
|
||||||
import com.google.android.exoplayer2.source.BehindLiveWindowException;
|
import com.google.android.exoplayer2.source.BehindLiveWindowException;
|
||||||
import com.google.android.exoplayer2.source.MediaSource;
|
import com.google.android.exoplayer2.source.MediaSource;
|
||||||
import com.google.android.exoplayer2.source.TrackGroupArray;
|
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.trackselection.TrackSelectionArray;
|
||||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
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_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 PlayQueue playQueue;
|
||||||
protected PlayQueueAdapter playQueueAdapter;
|
protected PlayQueueAdapter playQueueAdapter;
|
||||||
|
@ -141,10 +140,11 @@ public abstract class BasePlayer implements
|
||||||
// Player
|
// Player
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
protected final static int FAST_FORWARD_REWIND_AMOUNT = 10000; // 10 Seconds
|
protected final static int FAST_FORWARD_REWIND_AMOUNT_MILLIS = 10000; // 10 Seconds
|
||||||
protected final static int PLAY_PREV_ACTIVATION_LIMIT = 5000; // 5 seconds
|
protected final static int PLAY_PREV_ACTIVATION_LIMIT_MILLIS = 5000; // 5 seconds
|
||||||
protected final static int PROGRESS_LOOP_INTERVAL = 500;
|
protected final static int PROGRESS_LOOP_INTERVAL_MILLIS = 500;
|
||||||
protected final static int RECOVERY_SKIP_THRESHOLD = 3000; // 3 seconds
|
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 CustomTrackSelector trackSelector;
|
||||||
protected PlayerDataSource dataSource;
|
protected PlayerDataSource dataSource;
|
||||||
|
@ -192,8 +192,8 @@ public abstract class BasePlayer implements
|
||||||
final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
|
final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
|
||||||
dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter);
|
dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter);
|
||||||
|
|
||||||
final AdaptiveTrackSelection.Factory trackSelectionFactory =
|
final TrackSelection.Factory trackSelectionFactory =
|
||||||
new AdaptiveTrackSelection.Factory(bandwidthMeter);
|
PlayerHelper.getQualitySelector(context, bandwidthMeter);
|
||||||
trackSelector = new CustomTrackSelector(trackSelectionFactory);
|
trackSelector = new CustomTrackSelector(trackSelectionFactory);
|
||||||
|
|
||||||
final LoadControl loadControl = new LoadController(context);
|
final LoadControl loadControl = new LoadController(context);
|
||||||
|
@ -519,15 +519,16 @@ public abstract class BasePlayer implements
|
||||||
}
|
}
|
||||||
|
|
||||||
public void triggerProgressUpdate() {
|
public void triggerProgressUpdate() {
|
||||||
|
if (simpleExoPlayer == null) return;
|
||||||
onUpdateProgress(
|
onUpdateProgress(
|
||||||
(int) simpleExoPlayer.getCurrentPosition(),
|
Math.max((int) simpleExoPlayer.getCurrentPosition(), 0),
|
||||||
(int) simpleExoPlayer.getDuration(),
|
(int) simpleExoPlayer.getDuration(),
|
||||||
simpleExoPlayer.getBufferedPercentage()
|
simpleExoPlayer.getBufferedPercentage()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Disposable getProgressReactor() {
|
private Disposable getProgressReactor() {
|
||||||
return Observable.interval(PROGRESS_LOOP_INTERVAL, TimeUnit.MILLISECONDS)
|
return Observable.interval(PROGRESS_LOOP_INTERVAL_MILLIS, TimeUnit.MILLISECONDS)
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(ignored -> triggerProgressUpdate());
|
.subscribe(ignored -> triggerProgressUpdate());
|
||||||
}
|
}
|
||||||
|
@ -554,8 +555,8 @@ public abstract class BasePlayer implements
|
||||||
// Ensure dynamic/livestream timeline changes does not cause negative position
|
// Ensure dynamic/livestream timeline changes does not cause negative position
|
||||||
if (isPlaylistStable && !isCurrentWindowValid() && !isSynchronizing) {
|
if (isPlaylistStable && !isCurrentWindowValid() && !isSynchronizing) {
|
||||||
if (DEBUG) Log.d(TAG, "Playback - negative time position reached, " +
|
if (DEBUG) Log.d(TAG, "Playback - negative time position reached, " +
|
||||||
"clamping position to 0ms.");
|
"clamping to default position.");
|
||||||
seekTo(/*clampToTime=*/0);
|
seekToDefault();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -703,11 +704,7 @@ public abstract class BasePlayer implements
|
||||||
|
|
||||||
private void processSourceError(final IOException error) {
|
private void processSourceError(final IOException error) {
|
||||||
if (simpleExoPlayer == null || playQueue == null) return;
|
if (simpleExoPlayer == null || playQueue == null) return;
|
||||||
|
setRecovery();
|
||||||
if (simpleExoPlayer.getCurrentPosition() <
|
|
||||||
simpleExoPlayer.getDuration() - RECOVERY_SKIP_THRESHOLD) {
|
|
||||||
setRecovery();
|
|
||||||
}
|
|
||||||
|
|
||||||
final Throwable cause = error.getCause();
|
final Throwable cause = error.getCause();
|
||||||
if (cause instanceof BehindLiveWindowException) {
|
if (cause instanceof BehindLiveWindowException) {
|
||||||
|
@ -972,22 +969,22 @@ public abstract class BasePlayer implements
|
||||||
|
|
||||||
public void onFastRewind() {
|
public void onFastRewind() {
|
||||||
if (DEBUG) Log.d(TAG, "onFastRewind() called");
|
if (DEBUG) Log.d(TAG, "onFastRewind() called");
|
||||||
seekBy(-FAST_FORWARD_REWIND_AMOUNT);
|
seekBy(-FAST_FORWARD_REWIND_AMOUNT_MILLIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onFastForward() {
|
public void onFastForward() {
|
||||||
if (DEBUG) Log.d(TAG, "onFastForward() called");
|
if (DEBUG) Log.d(TAG, "onFastForward() called");
|
||||||
seekBy(FAST_FORWARD_REWIND_AMOUNT);
|
seekBy(FAST_FORWARD_REWIND_AMOUNT_MILLIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPlayPrevious() {
|
public void onPlayPrevious() {
|
||||||
if (simpleExoPlayer == null || playQueue == null) return;
|
if (simpleExoPlayer == null || playQueue == null) return;
|
||||||
if (DEBUG) Log.d(TAG, "onPlayPrevious() called");
|
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
|
* restart current track. Also restart the track if the current track
|
||||||
* is the first in a queue.*/
|
* is the first in a queue.*/
|
||||||
if (simpleExoPlayer.getCurrentPosition() > PLAY_PREV_ACTIVATION_LIMIT ||
|
if (simpleExoPlayer.getCurrentPosition() > PLAY_PREV_ACTIVATION_LIMIT_MILLIS ||
|
||||||
playQueue.getIndex() == 0) {
|
playQueue.getIndex() == 0) {
|
||||||
seekToDefault();
|
seekToDefault();
|
||||||
playQueue.offsetIndex(0);
|
playQueue.offsetIndex(0);
|
||||||
|
@ -1036,8 +1033,27 @@ public abstract class BasePlayer implements
|
||||||
&& simpleExoPlayer.getCurrentPosition() >= 0;
|
&& 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.
|
||||||
|
* <br><br>
|
||||||
|
* 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() {
|
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() {
|
private void savePlaybackState() {
|
||||||
if (simpleExoPlayer == null || currentInfo == null) return;
|
if (simpleExoPlayer == null || currentInfo == null) return;
|
||||||
|
|
||||||
if (simpleExoPlayer.getCurrentPosition() > RECOVERY_SKIP_THRESHOLD &&
|
if (simpleExoPlayer.getCurrentPosition() > RECOVERY_SKIP_THRESHOLD_MILLIS &&
|
||||||
simpleExoPlayer.getCurrentPosition() <
|
simpleExoPlayer.getCurrentPosition() <
|
||||||
simpleExoPlayer.getDuration() - RECOVERY_SKIP_THRESHOLD) {
|
simpleExoPlayer.getDuration() - RECOVERY_SKIP_THRESHOLD_MILLIS) {
|
||||||
savePlaybackState(currentInfo, simpleExoPlayer.getCurrentPosition());
|
savePlaybackState(currentInfo, simpleExoPlayer.getCurrentPosition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1165,10 +1181,6 @@ public abstract class BasePlayer implements
|
||||||
setPlaybackParameters(speed, getPlaybackPitch());
|
setPlaybackParameters(speed, getPlaybackPitch());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPlaybackPitch(float pitch) {
|
|
||||||
setPlaybackParameters(getPlaybackSpeed(), pitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlaybackParameters getPlaybackParameters() {
|
public PlaybackParameters getPlaybackParameters() {
|
||||||
final PlaybackParameters defaultParameters = new PlaybackParameters(1f, 1f);
|
final PlaybackParameters defaultParameters = new PlaybackParameters(1f, 1f);
|
||||||
if (simpleExoPlayer == null) return defaultParameters;
|
if (simpleExoPlayer == null) return defaultParameters;
|
||||||
|
|
|
@ -7,7 +7,11 @@ import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.android.exoplayer2.SeekParameters;
|
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.ui.AspectRatioFrameLayout;
|
||||||
|
import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||||
|
import com.google.android.exoplayer2.util.Clock;
|
||||||
import com.google.android.exoplayer2.util.MimeTypes;
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
@ -203,6 +207,16 @@ public class PlayerHelper {
|
||||||
return 60000;
|
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) {
|
public static boolean isUsingDSP(@NonNull final Context context) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue