Skip to content

Commit

Permalink
'locakl_high_reverse_playback'
Browse files Browse the repository at this point in the history
  • Loading branch information
WeiChungChang committed Feb 21, 2017
1 parent 5f44118 commit 922529f
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,9 @@ public ExoPlayerMessage(ExoPlayerComponent target, int messageType, Object messa
*/
void seekTo(int windowIndex, long positionMs);

/*TODO: add commmets later*/
void seekWithDelay(long positionMs, long delayMs);

/**
* Stops playback. Use {@code setPlayWhenReady(false)} rather than this method if the intention
* is to pause playback.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,28 @@ public void seekTo(int windowIndex, long positionMs) {
}
}
}
@Override
public void seekWithDelay(long positionMs, long delayMs) {
seekToWithDelay(getCurrentWindowIndex(), positionMs, delayMs);
}

public void seekToWithDelay(int windowIndex, long positionMs, long delayMs) {
if (windowIndex < 0 || (!timeline.isEmpty() && windowIndex >= timeline.getWindowCount())) {
throw new IllegalSeekPositionException(timeline, windowIndex, positionMs);
}
pendingSeekAcks++;
maskingWindowIndex = windowIndex;
if (positionMs == C.TIME_UNSET) {
maskingWindowPositionMs = 0;
internalPlayer.seekToWithDelay(timeline, windowIndex, C.TIME_UNSET, delayMs);
} else {
maskingWindowPositionMs = positionMs;
internalPlayer.seekToWithDelay(timeline, windowIndex, C.msToUs(positionMs), delayMs);
for (EventListener listener : listeners) {
listener.onPositionDiscontinuity();
}
}
}

@Override
public void stop() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

import android.os.Build;
import android.media.PlaybackParams;

import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.source.TrackGroup;

Expand Down Expand Up @@ -218,10 +218,23 @@ public void setPlayWhenReady(boolean playWhenReady) {
}

public void seekTo(Timeline timeline, int windowIndex, long positionUs) {
if (Util.isHighSpeed(speed)) {
handler.removeMessages(MSG_SEEK_TO);
}
handler.obtainMessage(MSG_SEEK_TO, new SeekPosition(timeline, windowIndex, positionUs))
.sendToTarget();
}

public void seekToWithDelay(Timeline timeline, int windowIndex, long positionUs, long delay) {
if (delay == 0) {
handler.obtainMessage(MSG_SEEK_TO, new SeekPosition(timeline, windowIndex, positionUs))
.sendToTarget();
return;
}
Message message = handler.obtainMessage(MSG_SEEK_TO, new SeekPosition(timeline, windowIndex, positionUs));
handler.sendMessageDelayed(message, (delay));
}

public void stop() {
handler.sendEmptyMessage(MSG_STOP);
}
Expand Down Expand Up @@ -1420,30 +1433,33 @@ public float getPlaybackSpeed() {

public void setPlaybackSpeed(float speed) {
this.speed = speed;

if ((Build.VERSION.SDK_INT >= 23) && (rendererMediaClockSource != null)) {
PlaybackParams params = new PlaybackParams();
params.setSpeed(speed);
ExoPlayerMessage[] messages = new ExoPlayerMessage[renderers.length];
for (int i = 0; i < renderers.length; i++) {
messages[i] = new ExoPlayerMessage(renderers[i], C.MSG_SET_PLAYBACK_PARAMS, params);
}
try {
sendMessagesInternal(messages);
} catch (ExoPlaybackException e) {
e.printStackTrace();
}
if (Util.isHighSpeed(speed)/*in this mode, we operate by seek*/) {
return;
} else {
this.speed = speed;
standaloneMediaClock.setPlaybackSpeed(speed);
if (rendererMediaClock != null) {
rendererMediaClock.setPlaybackSpeed(speed);
if ((Build.VERSION.SDK_INT >= 23) && (rendererMediaClockSource != null)) {
PlaybackParams params = new PlaybackParams();
params.setSpeed(speed);
ExoPlayerMessage[] messages = new ExoPlayerMessage[renderers.length];
for (int i = 0; i < renderers.length; i++) {
messages[i] = new ExoPlayerMessage(renderers[i], C.MSG_SET_PLAYBACK_PARAMS, params);
}
try {
sendMessagesInternal(messages);
} catch (ExoPlaybackException e) {
e.printStackTrace();
}
} else {
this.speed = speed;
standaloneMediaClock.setPlaybackSpeed(speed);
if (rendererMediaClock != null) {
rendererMediaClock.setPlaybackSpeed(speed);
}
}
if (playingPeriodHolder != null) {
setFormatSpeed(speed);
} else {
pendingFormatSpeed = true;
}
}
if (playingPeriodHolder != null) {
setFormatSpeed(speed);
} else {
pendingFormatSpeed = true;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@
import java.util.ArrayList;
import java.util.List;

import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.util.StandaloneMediaClock;

/**
* An {@link ExoPlayer} implementation that uses default {@link Renderer} components. Instances can
* be obtained from {@link ExoPlayerFactory}.
Expand Down Expand Up @@ -147,6 +150,9 @@ void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees,
private float audioVolume;
private PlaybackParamsHolder playbackParamsHolder;

boolean trickPlayBySeek;
private final StandaloneMediaClock standaloneMediaClock;
private float speed;
protected SimpleExoPlayer(Context context, TrackSelector trackSelector, LoadControl loadControl,
DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
@ExtensionRendererMode int extensionRendererMode, long allowedVideoJoiningTimeMs) {
Expand Down Expand Up @@ -183,6 +189,9 @@ protected SimpleExoPlayer(Context context, TrackSelector trackSelector, LoadCont

// Build the player and associated objects.
player = new ExoPlayerImpl(renderers, trackSelector, loadControl);
standaloneMediaClock = new StandaloneMediaClock();
this.speed = 1;
trickPlayBySeek = false;
}

/**
Expand Down Expand Up @@ -486,6 +495,9 @@ public void prepare(MediaSource mediaSource, boolean resetPosition, boolean rese

@Override
public void setPlayWhenReady(boolean playWhenReady) {
if (!getPlayWhenReady() && speed != 1 && playWhenReady) {
setPlaybackSpeed(1);
}
player.setPlayWhenReady(playWhenReady);
}

Expand All @@ -499,6 +511,12 @@ public boolean isLoading() {
return player.isLoading();
}

@Override
public void seekWithDelay(long positionMs, long delayMs) {

player.seekWithDelay(positionMs, delayMs);
}

@Override
public void seekToDefaultPosition() {
player.seekToDefaultPosition();
Expand All @@ -511,11 +529,21 @@ public void seekToDefaultPosition(int windowIndex) {

@Override
public void seekTo(long positionMs) {

if (Util.isHighSpeed(speed)) {
standaloneMediaClock.setPositionUs(positionMs * 1000);
}
player.seekTo(positionMs);
}

@Override
public void seekTo(int windowIndex, long positionMs) {

if (Util.isHighSpeed(speed)) {
standaloneMediaClock.stop();
standaloneMediaClock.setPositionUs(positionMs * 1000);
standaloneMediaClock.start();
}
player.seekTo(windowIndex, positionMs);
}

Expand Down Expand Up @@ -893,6 +921,25 @@ public void onVideoSizeChanged(int width, int height, int unappliedRotationDegre
}
}

private long getNextPositionMs() {
long currentPositionUs = standaloneMediaClock.getPositionUs();
long nextPositionUs = ((currentPositionUs / 1000) + ((long)speed * Util.TRICK_PLAY_DISPLAY_TIME_MS)); /*in ms*/
if (speed > 0) {
if (nextPositionUs > (getDuration())) {
trickPlayBySeek = false;
seekWithDelay(getDuration()/*in ms*/, 0);
return C.TIME_END_OF_SOURCE;
}
} else {
if (nextPositionUs < 0) {
trickPlayBySeek = false;
seekWithDelay(0, 0);
return C.TIME_END_OF_SOURCE;
}
}
return nextPositionUs; /*in ms*/
}

@Override
public void onRenderedFirstFrame(Surface surface) {
if (videoListener != null && SimpleExoPlayer.this.surface == surface) {
Expand All @@ -901,6 +948,13 @@ public void onRenderedFirstFrame(Surface surface) {
if (videoDebugListener != null) {
videoDebugListener.onRenderedFirstFrame(surface);
}
if (trickPlayBySeek) {
/*issue next seek*/
long nextPosition = getNextPositionMs();
if (nextPosition != C.TIME_END_OF_SOURCE) {
seekWithDelay(nextPosition, Util.TRICK_PLAY_DISPLAY_TIME_MS);
}
}
}

@Override
Expand Down Expand Up @@ -1043,6 +1097,21 @@ public float getPlaybackSpeed() {

@Override
public void setPlaybackSpeed(float speed) {
this.speed = speed;

if (videoDecoderCounters != null && Util.isHighSpeed(speed)) {
standaloneMediaClock.start();
long currentPositionMs = getCurrentPosition();
standaloneMediaClock.setPositionUs(currentPositionMs * 1000);
standaloneMediaClock.setPlaybackSpeed(speed);

setPlayWhenReady(false);
seekWithDelay(currentPositionMs, 0);
trickPlayBySeek = true;
} else {
trickPlayBySeek = false;
setPlayWhenReady(true);
}
player.setPlaybackSpeed(speed);
}

Expand Down
11 changes: 11 additions & 0 deletions library/src/main/java/com/google/android/exoplayer2/util/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
*/
public final class Util {

public static final boolean TRICK_PLAY_TEST_HACK = false;
public static final boolean TRICK_PLAY_HIGH_SPEED = true;
public static final long TRICK_PLAY_DISPLAY_TIME_MS = 500; /*ms*/
public static final long MAX_NATIVE_SUPPORT_SPEED = 4;
/**
* Like {@link android.os.Build.VERSION#SDK_INT}, but in a place where it can be conveniently
* overridden for local testing.
Expand Down Expand Up @@ -103,6 +107,13 @@ public final class Util {

private Util() {}

public static boolean isHighSpeed(float speed) {
if (((speed > MAX_NATIVE_SUPPORT_SPEED) || (speed < 0))) {
return true;
}
return false;
}

/**
* Converts the entirety of an {@link InputStream} to a byte array.
*
Expand Down

0 comments on commit 922529f

Please sign in to comment.