From 2b0b39ca3898ec71a8aa7b29386f789b3fff26fb Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 8 Dec 2017 06:14:14 -0800 Subject: [PATCH] Public API for setting seek parameters Issue: #2882 ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=178370038 --- .../google/android/exoplayer2/ExoPlayer.java | 7 ++ .../android/exoplayer2/ExoPlayerImpl.java | 8 ++ .../exoplayer2/ExoPlayerImplInternal.java | 76 ++++++++++--------- .../android/exoplayer2/SeekParameters.java | 72 ++++++++++++++++++ .../android/exoplayer2/SimpleExoPlayer.java | 5 ++ .../exoplayer2/testutil/StubExoPlayer.java | 6 ++ 6 files changed, 137 insertions(+), 37 deletions(-) create mode 100644 library/core/src/main/java/com/google/android/exoplayer2/SeekParameters.java diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java index 915a083657d..cc767752bec 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayer.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2; import android.os.Looper; +import android.support.annotation.Nullable; import com.google.android.exoplayer2.audio.MediaCodecAudioRenderer; import com.google.android.exoplayer2.metadata.MetadataRenderer; import com.google.android.exoplayer2.source.ClippingMediaSource; @@ -251,4 +252,10 @@ public ExoPlayerMessage(ExoPlayerComponent target, int messageType, Object messa */ void blockingSendMessages(ExoPlayerMessage... messages); + /** + * Sets the parameters that control how seek operations are performed. + * + * @param seekParameters The seek parameters, or {@code null} to use the defaults. + */ + void setSeekParameters(@Nullable SeekParameters seekParameters); } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java index ee96cb0c476..3fe6cc6eedc 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java @@ -258,6 +258,14 @@ public PlaybackParameters getPlaybackParameters() { return playbackParameters; } + @Override + public void setSeekParameters(@Nullable SeekParameters seekParameters) { + if (seekParameters == null) { + seekParameters = SeekParameters.DEFAULT; + } + internalPlayer.setSeekParameters(seekParameters); + } + @Override public void stop() { stop(/* reset= */ false); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java index dd3ce136d68..8f59451c485 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImplInternal.java @@ -66,15 +66,16 @@ private static final int MSG_DO_SOME_WORK = 2; private static final int MSG_SEEK_TO = 3; private static final int MSG_SET_PLAYBACK_PARAMETERS = 4; - private static final int MSG_STOP = 5; - private static final int MSG_RELEASE = 6; - private static final int MSG_REFRESH_SOURCE_INFO = 7; - private static final int MSG_PERIOD_PREPARED = 8; - private static final int MSG_SOURCE_CONTINUE_LOADING_REQUESTED = 9; - private static final int MSG_TRACK_SELECTION_INVALIDATED = 10; - private static final int MSG_CUSTOM = 11; - private static final int MSG_SET_REPEAT_MODE = 12; - private static final int MSG_SET_SHUFFLE_ENABLED = 13; + private static final int MSG_SET_SEEK_PARAMETERS = 5; + private static final int MSG_STOP = 6; + private static final int MSG_RELEASE = 7; + private static final int MSG_REFRESH_SOURCE_INFO = 8; + private static final int MSG_PERIOD_PREPARED = 9; + private static final int MSG_SOURCE_CONTINUE_LOADING_REQUESTED = 10; + private static final int MSG_TRACK_SELECTION_INVALIDATED = 11; + private static final int MSG_CUSTOM = 12; + private static final int MSG_SET_REPEAT_MODE = 13; + private static final int MSG_SET_SHUFFLE_ENABLED = 14; private static final int PREPARING_SOURCE_INTERVAL_MS = 10; private static final int RENDERING_INTERVAL_MS = 10; @@ -110,6 +111,9 @@ private final boolean retainBackBufferFromKeyframe; private final DefaultMediaClock mediaClock; + @SuppressWarnings("unused") + private SeekParameters seekParameters; + private PlaybackInfo playbackInfo; private MediaSource mediaSource; private Renderer[] enabledRenderers; @@ -148,6 +152,7 @@ public ExoPlayerImplInternal(Renderer[] renderers, TrackSelector trackSelector, backBufferDurationUs = loadControl.getBackBufferDurationUs(); retainBackBufferFromKeyframe = loadControl.retainBackBufferFromKeyframe(); + seekParameters = SeekParameters.DEFAULT; playbackInfo = new PlaybackInfo(null, null, 0, C.TIME_UNSET); rendererCapabilities = new RendererCapabilities[renderers.length]; for (int i = 0; i < renderers.length; i++) { @@ -195,6 +200,10 @@ public void setPlaybackParameters(PlaybackParameters playbackParameters) { handler.obtainMessage(MSG_SET_PLAYBACK_PARAMETERS, playbackParameters).sendToTarget(); } + public void setSeekParameters(SeekParameters seekParameters) { + handler.obtainMessage(MSG_SET_SEEK_PARAMETERS, seekParameters).sendToTarget(); + } + public void stop(boolean reset) { handler.obtainMessage(MSG_STOP, reset ? 1 : 0, 0).sendToTarget(); } @@ -294,62 +303,51 @@ public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { public boolean handleMessage(Message msg) { try { switch (msg.what) { - case MSG_PREPARE: { + case MSG_PREPARE: prepareInternal((MediaSource) msg.obj, msg.arg1 != 0); return true; - } - case MSG_SET_PLAY_WHEN_READY: { + case MSG_SET_PLAY_WHEN_READY: setPlayWhenReadyInternal(msg.arg1 != 0); return true; - } - case MSG_SET_REPEAT_MODE: { + case MSG_SET_REPEAT_MODE: setRepeatModeInternal(msg.arg1); return true; - } - case MSG_SET_SHUFFLE_ENABLED: { + case MSG_SET_SHUFFLE_ENABLED: setShuffleModeEnabledInternal(msg.arg1 != 0); return true; - } - case MSG_DO_SOME_WORK: { + case MSG_DO_SOME_WORK: doSomeWork(); return true; - } - case MSG_SEEK_TO: { + case MSG_SEEK_TO: seekToInternal((SeekPosition) msg.obj); return true; - } - case MSG_SET_PLAYBACK_PARAMETERS: { + case MSG_SET_PLAYBACK_PARAMETERS: setPlaybackParametersInternal((PlaybackParameters) msg.obj); return true; - } - case MSG_STOP: { + case MSG_SET_SEEK_PARAMETERS: + setSeekParametersInternal((SeekParameters) msg.obj); + return true; + case MSG_STOP: stopInternal(/* reset= */ msg.arg1 != 0); return true; - } - case MSG_RELEASE: { + case MSG_RELEASE: releaseInternal(); return true; - } - case MSG_PERIOD_PREPARED: { + case MSG_PERIOD_PREPARED: handlePeriodPrepared((MediaPeriod) msg.obj); return true; - } - case MSG_REFRESH_SOURCE_INFO: { + case MSG_REFRESH_SOURCE_INFO: handleSourceInfoRefreshed((MediaSourceRefreshInfo) msg.obj); return true; - } - case MSG_SOURCE_CONTINUE_LOADING_REQUESTED: { + case MSG_SOURCE_CONTINUE_LOADING_REQUESTED: handleContinueLoadingRequested((MediaPeriod) msg.obj); return true; - } - case MSG_TRACK_SELECTION_INVALIDATED: { + case MSG_TRACK_SELECTION_INVALIDATED: reselectTracksInternal(); return true; - } - case MSG_CUSTOM: { + case MSG_CUSTOM: sendMessagesInternal((ExoPlayerMessage[]) msg.obj); return true; - } default: return false; } @@ -765,6 +763,10 @@ private void setPlaybackParametersInternal(PlaybackParameters playbackParameters mediaClock.setPlaybackParameters(playbackParameters); } + private void setSeekParametersInternal(SeekParameters seekParameters) { + this.seekParameters = seekParameters; + } + private void stopInternal(boolean reset) { resetInternal( /* releaseMediaSource= */ true, /* resetPosition= */ reset, /* resetState= */ reset); diff --git a/library/core/src/main/java/com/google/android/exoplayer2/SeekParameters.java b/library/core/src/main/java/com/google/android/exoplayer2/SeekParameters.java new file mode 100644 index 00000000000..8643b3999e2 --- /dev/null +++ b/library/core/src/main/java/com/google/android/exoplayer2/SeekParameters.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2; + +import com.google.android.exoplayer2.util.Assertions; + +/** + * Parameters that apply to seeking. + * + *

The predefined {@link #EXACT}, {@link #CLOSEST_SYNC}, {@link #PREVIOUS_SYNC} and {@link + * #NEXT_SYNC} parameters are suitable for most use cases. Seeking to sync points is typically + * faster but less accurate than exact seeking. + * + *

In the general case, an instance specifies a maximum tolerance before ({@link + * #toleranceBeforeUs}) and after ({@link #toleranceAfterUs}) a requested seek position ({@code x}). + * If one or more sync points falls within the window {@code [x - toleranceBeforeUs, x + + * toleranceAfterUs]} then the seek will be performed to the sync point within the window that's + * closest to {@code x}. If no sync point falls within the window then the seek will be performed to + * {@code x - toleranceBeforeUs}. Internally the player may need to seek to an earlier sync point + * and discard media until this position is reached. + */ +public final class SeekParameters { + + /** Parameters for exact seeking. */ + public static final SeekParameters EXACT = new SeekParameters(0, 0); + /** Parameters for seeking to the closest sync point. */ + public static final SeekParameters CLOSEST_SYNC = + new SeekParameters(Long.MAX_VALUE, Long.MAX_VALUE); + /** Parameters for seeking to the sync point immediately before a requested seek position. */ + public static final SeekParameters PREVIOUS_SYNC = new SeekParameters(Long.MAX_VALUE, 0); + /** Parameters for seeking to the sync point immediately after a requested seek position. */ + public static final SeekParameters NEXT_SYNC = new SeekParameters(0, Long.MAX_VALUE); + /** Default parameters. */ + public static final SeekParameters DEFAULT = EXACT; + + /** + * The maximum time that the actual position seeked to may precede the requested seek position, in + * microseconds. + */ + public final long toleranceBeforeUs; + /** + * The maximum time that the actual position seeked to may exceed the requested seek position, in + * microseconds. + */ + public final long toleranceAfterUs; + + /** + * @param toleranceBeforeUs The maximum time that the actual position seeked to may precede the + * requested seek position, in microseconds. Must be non-negative. + * @param toleranceAfterUs The maximum time that the actual position seeked to may exceed the + * requested seek position, in microseconds. Must be non-negative. + */ + public SeekParameters(long toleranceBeforeUs, long toleranceAfterUs) { + Assertions.checkArgument(toleranceBeforeUs >= 0); + Assertions.checkArgument(toleranceAfterUs >= 0); + this.toleranceBeforeUs = toleranceBeforeUs; + this.toleranceAfterUs = toleranceAfterUs; + } +} diff --git a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java index 338c708864c..69369d4229e 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/SimpleExoPlayer.java @@ -738,6 +738,11 @@ public PlaybackParameters getPlaybackParameters() { return player.getPlaybackParameters(); } + @Override + public void setSeekParameters(@Nullable SeekParameters seekParameters) { + player.setSeekParameters(seekParameters); + } + @Override public void stop() { player.stop(); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java index 0d94b8fa03d..1ea83bf1ecd 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/StubExoPlayer.java @@ -19,6 +19,7 @@ import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SeekParameters; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.source.MediaSource; import com.google.android.exoplayer2.source.TrackGroupArray; @@ -125,6 +126,11 @@ public PlaybackParameters getPlaybackParameters() { throw new UnsupportedOperationException(); } + @Override + public void setSeekParameters(SeekParameters seekParameters) { + throw new UnsupportedOperationException(); + } + @Override public void stop() { throw new UnsupportedOperationException();