Automated g4 rollback of changelist 217356705.
*** Reason for rollback *** Photos regression is resolved by [] *** Original change description *** Automated g4 rollback of changelist 217189082. *** Reason for rollback *** Broke photos (b/117818304) *** Original change description *** Add ExoPlayer.setForegroundMode Issue: #2826 *** *** ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=217773278
This commit is contained in:
parent
3805717026
commit
1ef3efaa90
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
### dev-v2 (not yet released) ###
|
### dev-v2 (not yet released) ###
|
||||||
|
|
||||||
|
* Improve decoder re-use between playbacks. TODO: Write and link a blog post
|
||||||
|
here ([#2826](https://github.com/google/ExoPlayer/issues/2826)).
|
||||||
* Improve initial bandwidth meter estimates using the current country and
|
* Improve initial bandwidth meter estimates using the current country and
|
||||||
network type.
|
network type.
|
||||||
* Do not retry failed loads whose error is `FileNotFoundException`.
|
* Do not retry failed loads whose error is `FileNotFoundException`.
|
||||||
|
@ -209,4 +209,34 @@ public interface ExoPlayer extends Player {
|
|||||||
|
|
||||||
/** Returns the currently active {@link SeekParameters} of the player. */
|
/** Returns the currently active {@link SeekParameters} of the player. */
|
||||||
SeekParameters getSeekParameters();
|
SeekParameters getSeekParameters();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the player is allowed to keep holding limited resources such as video decoders,
|
||||||
|
* even when in the idle state. By doing so, the player may be able to reduce latency when
|
||||||
|
* starting to play another piece of content for which the same resources are required.
|
||||||
|
*
|
||||||
|
* <p>This mode should be used with caution, since holding limited resources may prevent other
|
||||||
|
* players of media components from acquiring them. It should only be enabled when <em>both</em>
|
||||||
|
* of the following conditions are true:
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>The application that owns the player is in the foreground.
|
||||||
|
* <li>The player is used in a way that may benefit from foreground mode. For this to be true,
|
||||||
|
* the same player instance must be used to play multiple pieces of content, and there must
|
||||||
|
* be gaps between the playbacks (i.e. {@link #stop} is called to halt one playback, and
|
||||||
|
* {@link #prepare} is called some time later to start a new one).
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>Note that foreground mode is <em>not</em> useful for switching between content without gaps
|
||||||
|
* between the playbacks. For this use case {@link #stop} does not need to be called, and simply
|
||||||
|
* calling {@link #prepare} for the new media will cause limited resources to be retained even if
|
||||||
|
* foreground mode is not enabled.
|
||||||
|
*
|
||||||
|
* <p>If foreground mode is enabled, it's the application's responsibility to disable it when the
|
||||||
|
* conditions described above no longer hold.
|
||||||
|
*
|
||||||
|
* @param foregroundMode Whether the player is allowed to keep limited resources even when in the
|
||||||
|
* idle state.
|
||||||
|
*/
|
||||||
|
void setForegroundMode(boolean foregroundMode);
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
private int pendingOperationAcks;
|
private int pendingOperationAcks;
|
||||||
private boolean hasPendingPrepare;
|
private boolean hasPendingPrepare;
|
||||||
private boolean hasPendingSeek;
|
private boolean hasPendingSeek;
|
||||||
|
private boolean foregroundMode;
|
||||||
private PlaybackParameters playbackParameters;
|
private PlaybackParameters playbackParameters;
|
||||||
private SeekParameters seekParameters;
|
private SeekParameters seekParameters;
|
||||||
private @Nullable ExoPlaybackException playbackError;
|
private @Nullable ExoPlaybackException playbackError;
|
||||||
@ -359,6 +360,14 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||||||
return seekParameters;
|
return seekParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setForegroundMode(boolean foregroundMode) {
|
||||||
|
if (this.foregroundMode != foregroundMode) {
|
||||||
|
this.foregroundMode = foregroundMode;
|
||||||
|
internalPlayer.setForegroundMode(foregroundMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop(boolean reset) {
|
public void stop(boolean reset) {
|
||||||
if (reset) {
|
if (reset) {
|
||||||
|
@ -44,6 +44,7 @@ import com.google.android.exoplayer2.util.Util;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
/** Implements the internal behavior of {@link ExoPlayerImpl}. */
|
/** Implements the internal behavior of {@link ExoPlayerImpl}. */
|
||||||
/* package */ final class ExoPlayerImplInternal
|
/* package */ final class ExoPlayerImplInternal
|
||||||
@ -76,9 +77,10 @@ import java.util.Collections;
|
|||||||
private static final int MSG_TRACK_SELECTION_INVALIDATED = 11;
|
private static final int MSG_TRACK_SELECTION_INVALIDATED = 11;
|
||||||
private static final int MSG_SET_REPEAT_MODE = 12;
|
private static final int MSG_SET_REPEAT_MODE = 12;
|
||||||
private static final int MSG_SET_SHUFFLE_ENABLED = 13;
|
private static final int MSG_SET_SHUFFLE_ENABLED = 13;
|
||||||
private static final int MSG_SEND_MESSAGE = 14;
|
private static final int MSG_SET_FOREGROUND_MODE = 14;
|
||||||
private static final int MSG_SEND_MESSAGE_TO_TARGET_THREAD = 15;
|
private static final int MSG_SEND_MESSAGE = 15;
|
||||||
private static final int MSG_PLAYBACK_PARAMETERS_CHANGED_INTERNAL = 16;
|
private static final int MSG_SEND_MESSAGE_TO_TARGET_THREAD = 16;
|
||||||
|
private static final int MSG_PLAYBACK_PARAMETERS_CHANGED_INTERNAL = 17;
|
||||||
|
|
||||||
private static final int PREPARING_SOURCE_INTERVAL_MS = 10;
|
private static final int PREPARING_SOURCE_INTERVAL_MS = 10;
|
||||||
private static final int RENDERING_INTERVAL_MS = 10;
|
private static final int RENDERING_INTERVAL_MS = 10;
|
||||||
@ -115,6 +117,7 @@ import java.util.Collections;
|
|||||||
private boolean rebuffering;
|
private boolean rebuffering;
|
||||||
@Player.RepeatMode private int repeatMode;
|
@Player.RepeatMode private int repeatMode;
|
||||||
private boolean shuffleModeEnabled;
|
private boolean shuffleModeEnabled;
|
||||||
|
private boolean foregroundMode;
|
||||||
|
|
||||||
private int pendingPrepareCount;
|
private int pendingPrepareCount;
|
||||||
private SeekPosition pendingInitialSeekPosition;
|
private SeekPosition pendingInitialSeekPosition;
|
||||||
@ -218,6 +221,29 @@ import java.util.Collections;
|
|||||||
handler.obtainMessage(MSG_SEND_MESSAGE, message).sendToTarget();
|
handler.obtainMessage(MSG_SEND_MESSAGE, message).sendToTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized void setForegroundMode(boolean foregroundMode) {
|
||||||
|
if (foregroundMode) {
|
||||||
|
handler.obtainMessage(MSG_SET_FOREGROUND_MODE, /* foregroundMode */ 1, 0).sendToTarget();
|
||||||
|
} else {
|
||||||
|
AtomicBoolean processedFlag = new AtomicBoolean();
|
||||||
|
handler
|
||||||
|
.obtainMessage(MSG_SET_FOREGROUND_MODE, /* foregroundMode */ 0, 0, processedFlag)
|
||||||
|
.sendToTarget();
|
||||||
|
boolean wasInterrupted = false;
|
||||||
|
while (!processedFlag.get() && !released) {
|
||||||
|
try {
|
||||||
|
wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
wasInterrupted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wasInterrupted) {
|
||||||
|
// Restore the interrupted status.
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized void release() {
|
public synchronized void release() {
|
||||||
if (released) {
|
if (released) {
|
||||||
return;
|
return;
|
||||||
@ -311,8 +337,15 @@ import java.util.Collections;
|
|||||||
case MSG_SET_SEEK_PARAMETERS:
|
case MSG_SET_SEEK_PARAMETERS:
|
||||||
setSeekParametersInternal((SeekParameters) msg.obj);
|
setSeekParametersInternal((SeekParameters) msg.obj);
|
||||||
break;
|
break;
|
||||||
|
case MSG_SET_FOREGROUND_MODE:
|
||||||
|
setForegroundModeInternal(
|
||||||
|
/* foregroundMode= */ msg.arg1 != 0, /* processedFlag= */ (AtomicBoolean) msg.obj);
|
||||||
|
break;
|
||||||
case MSG_STOP:
|
case MSG_STOP:
|
||||||
stopInternal(/* reset= */ msg.arg1 != 0, /* acknowledgeStop= */ true);
|
stopInternal(
|
||||||
|
/* forceResetRenderers= */ false,
|
||||||
|
/* resetPositionAndState= */ msg.arg1 != 0,
|
||||||
|
/* acknowledgeStop= */ true);
|
||||||
break;
|
break;
|
||||||
case MSG_PERIOD_PREPARED:
|
case MSG_PERIOD_PREPARED:
|
||||||
handlePeriodPrepared((MediaPeriod) msg.obj);
|
handlePeriodPrepared((MediaPeriod) msg.obj);
|
||||||
@ -345,17 +378,26 @@ import java.util.Collections;
|
|||||||
maybeNotifyPlaybackInfoChanged();
|
maybeNotifyPlaybackInfoChanged();
|
||||||
} catch (ExoPlaybackException e) {
|
} catch (ExoPlaybackException e) {
|
||||||
Log.e(TAG, "Playback error.", e);
|
Log.e(TAG, "Playback error.", e);
|
||||||
stopInternal(/* reset= */ false, /* acknowledgeStop= */ false);
|
stopInternal(
|
||||||
|
/* forceResetRenderers= */ true,
|
||||||
|
/* resetPositionAndState= */ false,
|
||||||
|
/* acknowledgeStop= */ false);
|
||||||
eventHandler.obtainMessage(MSG_ERROR, e).sendToTarget();
|
eventHandler.obtainMessage(MSG_ERROR, e).sendToTarget();
|
||||||
maybeNotifyPlaybackInfoChanged();
|
maybeNotifyPlaybackInfoChanged();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Source error.", e);
|
Log.e(TAG, "Source error.", e);
|
||||||
stopInternal(/* reset= */ false, /* acknowledgeStop= */ false);
|
stopInternal(
|
||||||
|
/* forceResetRenderers= */ false,
|
||||||
|
/* resetPositionAndState= */ false,
|
||||||
|
/* acknowledgeStop= */ false);
|
||||||
eventHandler.obtainMessage(MSG_ERROR, ExoPlaybackException.createForSource(e)).sendToTarget();
|
eventHandler.obtainMessage(MSG_ERROR, ExoPlaybackException.createForSource(e)).sendToTarget();
|
||||||
maybeNotifyPlaybackInfoChanged();
|
maybeNotifyPlaybackInfoChanged();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
Log.e(TAG, "Internal runtime error.", e);
|
Log.e(TAG, "Internal runtime error.", e);
|
||||||
stopInternal(/* reset= */ false, /* acknowledgeStop= */ false);
|
stopInternal(
|
||||||
|
/* forceResetRenderers= */ true,
|
||||||
|
/* resetPositionAndState= */ false,
|
||||||
|
/* acknowledgeStop= */ false);
|
||||||
eventHandler.obtainMessage(MSG_ERROR, ExoPlaybackException.createForUnexpected(e))
|
eventHandler.obtainMessage(MSG_ERROR, ExoPlaybackException.createForUnexpected(e))
|
||||||
.sendToTarget();
|
.sendToTarget();
|
||||||
maybeNotifyPlaybackInfoChanged();
|
maybeNotifyPlaybackInfoChanged();
|
||||||
@ -394,7 +436,8 @@ import java.util.Collections;
|
|||||||
|
|
||||||
private void prepareInternal(MediaSource mediaSource, boolean resetPosition, boolean resetState) {
|
private void prepareInternal(MediaSource mediaSource, boolean resetPosition, boolean resetState) {
|
||||||
pendingPrepareCount++;
|
pendingPrepareCount++;
|
||||||
resetInternal(/* releaseMediaSource= */ true, resetPosition, resetState);
|
resetInternal(
|
||||||
|
/* resetRenderers= */ false, /* releaseMediaSource= */ true, resetPosition, resetState);
|
||||||
loadControl.onPrepared();
|
loadControl.onPrepared();
|
||||||
this.mediaSource = mediaSource;
|
this.mediaSource = mediaSource;
|
||||||
setState(Player.STATE_BUFFERING);
|
setState(Player.STATE_BUFFERING);
|
||||||
@ -631,7 +674,10 @@ import java.util.Collections;
|
|||||||
// End playback, as we didn't manage to find a valid seek position.
|
// End playback, as we didn't manage to find a valid seek position.
|
||||||
setState(Player.STATE_ENDED);
|
setState(Player.STATE_ENDED);
|
||||||
resetInternal(
|
resetInternal(
|
||||||
/* releaseMediaSource= */ false, /* resetPosition= */ true, /* resetState= */ false);
|
/* resetRenderers= */ false,
|
||||||
|
/* releaseMediaSource= */ false,
|
||||||
|
/* resetPosition= */ true,
|
||||||
|
/* resetState= */ false);
|
||||||
} else {
|
} else {
|
||||||
// Execute the seek in the current media periods.
|
// Execute the seek in the current media periods.
|
||||||
long newPeriodPositionUs = periodPositionUs;
|
long newPeriodPositionUs = periodPositionUs;
|
||||||
@ -738,9 +784,33 @@ import java.util.Collections;
|
|||||||
this.seekParameters = seekParameters;
|
this.seekParameters = seekParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopInternal(boolean reset, boolean acknowledgeStop) {
|
private void setForegroundModeInternal(
|
||||||
|
boolean foregroundMode, @Nullable AtomicBoolean processedFlag) {
|
||||||
|
if (this.foregroundMode != foregroundMode) {
|
||||||
|
this.foregroundMode = foregroundMode;
|
||||||
|
if (!foregroundMode) {
|
||||||
|
for (Renderer renderer : renderers) {
|
||||||
|
if (renderer.getState() == Renderer.STATE_DISABLED) {
|
||||||
|
renderer.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (processedFlag != null) {
|
||||||
|
synchronized (this) {
|
||||||
|
processedFlag.set(true);
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopInternal(
|
||||||
|
boolean forceResetRenderers, boolean resetPositionAndState, boolean acknowledgeStop) {
|
||||||
resetInternal(
|
resetInternal(
|
||||||
/* releaseMediaSource= */ true, /* resetPosition= */ reset, /* resetState= */ reset);
|
/* resetRenderers= */ forceResetRenderers || !foregroundMode,
|
||||||
|
/* releaseMediaSource= */ true,
|
||||||
|
/* resetPosition= */ resetPositionAndState,
|
||||||
|
/* resetState= */ resetPositionAndState);
|
||||||
playbackInfoUpdate.incrementPendingOperationAcks(
|
playbackInfoUpdate.incrementPendingOperationAcks(
|
||||||
pendingPrepareCount + (acknowledgeStop ? 1 : 0));
|
pendingPrepareCount + (acknowledgeStop ? 1 : 0));
|
||||||
pendingPrepareCount = 0;
|
pendingPrepareCount = 0;
|
||||||
@ -750,7 +820,10 @@ import java.util.Collections;
|
|||||||
|
|
||||||
private void releaseInternal() {
|
private void releaseInternal() {
|
||||||
resetInternal(
|
resetInternal(
|
||||||
/* releaseMediaSource= */ true, /* resetPosition= */ true, /* resetState= */ true);
|
/* resetRenderers= */ true,
|
||||||
|
/* releaseMediaSource= */ true,
|
||||||
|
/* resetPosition= */ true,
|
||||||
|
/* resetState= */ true);
|
||||||
loadControl.onReleased();
|
loadControl.onReleased();
|
||||||
setState(Player.STATE_IDLE);
|
setState(Player.STATE_IDLE);
|
||||||
internalPlaybackThread.quit();
|
internalPlaybackThread.quit();
|
||||||
@ -772,7 +845,10 @@ import java.util.Collections;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void resetInternal(
|
private void resetInternal(
|
||||||
boolean releaseMediaSource, boolean resetPosition, boolean resetState) {
|
boolean resetRenderers,
|
||||||
|
boolean releaseMediaSource,
|
||||||
|
boolean resetPosition,
|
||||||
|
boolean resetState) {
|
||||||
handler.removeMessages(MSG_DO_SOME_WORK);
|
handler.removeMessages(MSG_DO_SOME_WORK);
|
||||||
rebuffering = false;
|
rebuffering = false;
|
||||||
mediaClock.stop();
|
mediaClock.stop();
|
||||||
@ -782,7 +858,17 @@ import java.util.Collections;
|
|||||||
disableRenderer(renderer);
|
disableRenderer(renderer);
|
||||||
} catch (ExoPlaybackException | RuntimeException e) {
|
} catch (ExoPlaybackException | RuntimeException e) {
|
||||||
// There's nothing we can do.
|
// There's nothing we can do.
|
||||||
Log.e(TAG, "Stop failed.", e);
|
Log.e(TAG, "Disable failed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resetRenderers) {
|
||||||
|
for (Renderer renderer : renderers) {
|
||||||
|
try {
|
||||||
|
renderer.reset();
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// There's nothing we can do.
|
||||||
|
Log.e(TAG, "Reset failed.", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
enabledRenderers = new Renderer[0];
|
enabledRenderers = new Renderer[0];
|
||||||
@ -989,7 +1075,6 @@ import java.util.Collections;
|
|||||||
mediaClock.onRendererDisabled(renderer);
|
mediaClock.onRendererDisabled(renderer);
|
||||||
ensureStopped(renderer);
|
ensureStopped(renderer);
|
||||||
renderer.disable();
|
renderer.disable();
|
||||||
renderer.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void reselectTracksInternal() throws ExoPlaybackException {
|
private void reselectTracksInternal() throws ExoPlaybackException {
|
||||||
@ -1294,7 +1379,10 @@ import java.util.Collections;
|
|||||||
setState(Player.STATE_ENDED);
|
setState(Player.STATE_ENDED);
|
||||||
// Reset, but retain the source so that it can still be used should a seek occur.
|
// Reset, but retain the source so that it can still be used should a seek occur.
|
||||||
resetInternal(
|
resetInternal(
|
||||||
/* releaseMediaSource= */ false, /* resetPosition= */ true, /* resetState= */ false);
|
/* resetRenderers= */ false,
|
||||||
|
/* releaseMediaSource= */ false,
|
||||||
|
/* resetPosition= */ true,
|
||||||
|
/* resetState= */ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1639,9 +1727,17 @@ import java.util.Collections;
|
|||||||
throws ExoPlaybackException {
|
throws ExoPlaybackException {
|
||||||
enabledRenderers = new Renderer[totalEnabledRendererCount];
|
enabledRenderers = new Renderer[totalEnabledRendererCount];
|
||||||
int enabledRendererCount = 0;
|
int enabledRendererCount = 0;
|
||||||
MediaPeriodHolder playingPeriodHolder = queue.getPlayingPeriod();
|
TrackSelectorResult trackSelectorResult = queue.getPlayingPeriod().getTrackSelectorResult();
|
||||||
|
// Reset all disabled renderers before enabling any new ones. This makes sure resources released
|
||||||
|
// by the disabled renderers will be available to renderers that are being enabled.
|
||||||
for (int i = 0; i < renderers.length; i++) {
|
for (int i = 0; i < renderers.length; i++) {
|
||||||
if (playingPeriodHolder.getTrackSelectorResult().isRendererEnabled(i)) {
|
if (!trackSelectorResult.isRendererEnabled(i)) {
|
||||||
|
renderers[i].reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Enable the renderers.
|
||||||
|
for (int i = 0; i < renderers.length; i++) {
|
||||||
|
if (trackSelectorResult.isRendererEnabled(i)) {
|
||||||
enableRenderer(i, rendererWasEnabledFlags[i], enabledRendererCount++);
|
enableRenderer(i, rendererWasEnabledFlags[i], enabledRendererCount++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -958,6 +958,11 @@ public class SimpleExoPlayer extends BasePlayer
|
|||||||
return player.getSeekParameters();
|
return player.getSeekParameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setForegroundMode(boolean foregroundMode) {
|
||||||
|
player.setForegroundMode(foregroundMode);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop(boolean reset) {
|
public void stop(boolean reset) {
|
||||||
verifyApplicationThread();
|
verifyApplicationThread();
|
||||||
|
@ -267,4 +267,9 @@ public abstract class StubExoPlayer extends BasePlayer implements ExoPlayer {
|
|||||||
public long getContentBufferedPosition() {
|
public long getContentBufferedPosition() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setForegroundMode(boolean foregroundMode) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user