mirror of
https://github.com/androidx/media.git
synced 2025-05-09 16:40:55 +08:00
Forward live playback speed changes to track selections and renderers.
This allows the respective components to adapt to the speed changes if desired. To avoid frequent updates to the media codec operating rate, we also forward the target speed to the renderers so that this value can be set based on the target speed and not the current speed. PiperOrigin-RevId: 351336401
This commit is contained in:
parent
c63f3d92ba
commit
d640cedab8
@ -447,7 +447,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@Override
|
||||
public void onPlaybackParametersChanged(PlaybackParameters newPlaybackParameters) {
|
||||
sendPlaybackParametersChangedInternal(newPlaybackParameters, /* acknowledgeCommand= */ false);
|
||||
handler
|
||||
.obtainMessage(MSG_PLAYBACK_PARAMETERS_CHANGED_INTERNAL, newPlaybackParameters)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
// Handler.Callback implementation.
|
||||
@ -501,8 +503,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
reselectTracksInternal();
|
||||
break;
|
||||
case MSG_PLAYBACK_PARAMETERS_CHANGED_INTERNAL:
|
||||
handlePlaybackParameters(
|
||||
(PlaybackParameters) msg.obj, /* acknowledgeCommand= */ msg.arg1 != 0);
|
||||
handlePlaybackParameters((PlaybackParameters) msg.obj, /* acknowledgeCommand= */ false);
|
||||
break;
|
||||
case MSG_SEND_MESSAGE:
|
||||
sendMessageInternal((PlayerMessage) msg.obj);
|
||||
@ -888,6 +889,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
getCurrentLiveOffsetUs(), getTotalBufferedDurationUs());
|
||||
if (mediaClock.getPlaybackParameters().speed != adjustedSpeed) {
|
||||
mediaClock.setPlaybackParameters(playbackInfo.playbackParameters.withSpeed(adjustedSpeed));
|
||||
handlePlaybackParameters(
|
||||
playbackInfo.playbackParameters,
|
||||
/* currentPlaybackSpeed= */ mediaClock.getPlaybackParameters().speed,
|
||||
/* updatePlaybackInfo= */ false,
|
||||
/* acknowledgeCommand= */ false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1279,10 +1285,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
notifyTrackSelectionDiscontinuity();
|
||||
}
|
||||
|
||||
private void setPlaybackParametersInternal(PlaybackParameters playbackParameters) {
|
||||
private void setPlaybackParametersInternal(PlaybackParameters playbackParameters)
|
||||
throws ExoPlaybackException {
|
||||
mediaClock.setPlaybackParameters(playbackParameters);
|
||||
sendPlaybackParametersChangedInternal(
|
||||
mediaClock.getPlaybackParameters(), /* acknowledgeCommand= */ true);
|
||||
handlePlaybackParameters(mediaClock.getPlaybackParameters(), /* acknowledgeCommand= */ true);
|
||||
}
|
||||
|
||||
private void setSeekParametersInternal(SeekParameters seekParameters) {
|
||||
@ -2141,12 +2147,30 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
private void handlePlaybackParameters(
|
||||
PlaybackParameters playbackParameters, boolean acknowledgeCommand)
|
||||
throws ExoPlaybackException {
|
||||
playbackInfoUpdate.incrementPendingOperationAcks(acknowledgeCommand ? 1 : 0);
|
||||
playbackInfo = playbackInfo.copyWithPlaybackParameters(playbackParameters);
|
||||
handlePlaybackParameters(
|
||||
playbackParameters,
|
||||
playbackParameters.speed,
|
||||
/* updatePlaybackInfo= */ true,
|
||||
acknowledgeCommand);
|
||||
}
|
||||
|
||||
private void handlePlaybackParameters(
|
||||
PlaybackParameters playbackParameters,
|
||||
float currentPlaybackSpeed,
|
||||
boolean updatePlaybackInfo,
|
||||
boolean acknowledgeCommand)
|
||||
throws ExoPlaybackException {
|
||||
if (updatePlaybackInfo) {
|
||||
if (acknowledgeCommand) {
|
||||
playbackInfoUpdate.incrementPendingOperationAcks(1);
|
||||
}
|
||||
playbackInfo = playbackInfo.copyWithPlaybackParameters(playbackParameters);
|
||||
}
|
||||
updateTrackSelectionPlaybackSpeed(playbackParameters.speed);
|
||||
for (Renderer renderer : renderers) {
|
||||
if (renderer != null) {
|
||||
renderer.setPlaybackSpeed(playbackParameters.speed);
|
||||
renderer.setPlaybackSpeed(
|
||||
currentPlaybackSpeed, /* targetPlaybackSpeed= */ playbackParameters.speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2372,17 +2396,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
loadControl.onTracksSelected(renderers, trackGroups, trackSelectorResult.selections);
|
||||
}
|
||||
|
||||
private void sendPlaybackParametersChangedInternal(
|
||||
PlaybackParameters playbackParameters, boolean acknowledgeCommand) {
|
||||
handler
|
||||
.obtainMessage(
|
||||
MSG_PLAYBACK_PARAMETERS_CHANGED_INTERNAL,
|
||||
acknowledgeCommand ? 1 : 0,
|
||||
0,
|
||||
playbackParameters)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
private boolean shouldPlayWhenReady() {
|
||||
return playbackInfo.playWhenReady
|
||||
&& playbackInfo.playbackSuppressionReason == Player.PLAYBACK_SUPPRESSION_REASON_NONE;
|
||||
|
@ -403,10 +403,14 @@ public interface Renderer extends PlayerMessage.Target {
|
||||
*
|
||||
* <p>The default implementation is a no-op.
|
||||
*
|
||||
* @param playbackSpeed The factor by which playback is sped up.
|
||||
* @param currentPlaybackSpeed The factor by which playback is currently sped up.
|
||||
* @param targetPlaybackSpeed The target factor by which playback should be sped up. This may be
|
||||
* different from {@code currentPlaybackSpeed}, for example, if the speed is temporarily
|
||||
* adjusted for live playback.
|
||||
* @throws ExoPlaybackException If an error occurs handling the playback speed.
|
||||
*/
|
||||
default void setPlaybackSpeed(float playbackSpeed) throws ExoPlaybackException {}
|
||||
default void setPlaybackSpeed(float currentPlaybackSpeed, float targetPlaybackSpeed)
|
||||
throws ExoPlaybackException {}
|
||||
|
||||
/**
|
||||
* Incrementally renders the {@link SampleStream}.
|
||||
|
@ -390,7 +390,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||
|
||||
@Override
|
||||
protected float getCodecOperatingRateV23(
|
||||
float playbackSpeed, Format format, Format[] streamFormats) {
|
||||
float targetPlaybackSpeed, Format format, Format[] streamFormats) {
|
||||
// Use the highest known stream sample-rate up front, to avoid having to reconfigure the codec
|
||||
// should an adaptive switch to that stream occur.
|
||||
int maxSampleRate = -1;
|
||||
@ -400,7 +400,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
|
||||
maxSampleRate = max(maxSampleRate, streamSampleRate);
|
||||
}
|
||||
}
|
||||
return maxSampleRate == -1 ? CODEC_OPERATING_RATE_UNSET : (maxSampleRate * playbackSpeed);
|
||||
return maxSampleRate == -1 ? CODEC_OPERATING_RATE_UNSET : (maxSampleRate * targetPlaybackSpeed);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -312,7 +312,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
@Nullable private MediaCrypto mediaCrypto;
|
||||
private boolean mediaCryptoRequiresSecureDecoder;
|
||||
private long renderTimeLimitMs;
|
||||
private float playbackSpeed;
|
||||
private float currentPlaybackSpeed;
|
||||
private float targetPlaybackSpeed;
|
||||
@Nullable private MediaCodecAdapter codec;
|
||||
@Nullable private Format codecInputFormat;
|
||||
@Nullable private MediaFormat codecOutputMediaFormat;
|
||||
@ -393,7 +394,8 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
formatQueue = new TimedValueQueue<>();
|
||||
decodeOnlyPresentationTimestamps = new ArrayList<>();
|
||||
outputBufferInfo = new MediaCodec.BufferInfo();
|
||||
playbackSpeed = 1f;
|
||||
currentPlaybackSpeed = 1f;
|
||||
targetPlaybackSpeed = 1f;
|
||||
renderTimeLimitMs = C.TIME_UNSET;
|
||||
pendingOutputStreamStartPositionsUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT];
|
||||
pendingOutputStreamOffsetsUs = new long[MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT];
|
||||
@ -715,8 +717,10 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlaybackSpeed(float playbackSpeed) throws ExoPlaybackException {
|
||||
this.playbackSpeed = playbackSpeed;
|
||||
public void setPlaybackSpeed(float currentPlaybackSpeed, float targetPlaybackSpeed)
|
||||
throws ExoPlaybackException {
|
||||
this.currentPlaybackSpeed = currentPlaybackSpeed;
|
||||
this.targetPlaybackSpeed = targetPlaybackSpeed;
|
||||
if (codec != null
|
||||
&& codecDrainAction != DRAIN_ACTION_REINITIALIZE
|
||||
&& getState() != STATE_DISABLED) {
|
||||
@ -1082,7 +1086,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
float codecOperatingRate =
|
||||
Util.SDK_INT < 23
|
||||
? CODEC_OPERATING_RATE_UNSET
|
||||
: getCodecOperatingRateV23(playbackSpeed, inputFormat, getStreamFormats());
|
||||
: getCodecOperatingRateV23(targetPlaybackSpeed, inputFormat, getStreamFormats());
|
||||
if (codecOperatingRate <= assumedMinimumCodecOperatingRate) {
|
||||
codecOperatingRate = CODEC_OPERATING_RATE_UNSET;
|
||||
}
|
||||
@ -1624,9 +1628,9 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
&& SystemClock.elapsedRealtime() < codecHotswapDeadlineMs));
|
||||
}
|
||||
|
||||
/** Returns the playback speed, as set by {@link #setPlaybackSpeed}. */
|
||||
/** Returns the current playback speed, as set by {@link #setPlaybackSpeed}. */
|
||||
protected float getPlaybackSpeed() {
|
||||
return playbackSpeed;
|
||||
return currentPlaybackSpeed;
|
||||
}
|
||||
|
||||
/** Returns the operating rate used by the current codec */
|
||||
@ -1640,14 +1644,16 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
*
|
||||
* <p>The default implementation returns {@link #CODEC_OPERATING_RATE_UNSET}.
|
||||
*
|
||||
* @param playbackSpeed The factor by which playback is sped up.
|
||||
* @param targetPlaybackSpeed The target factor by which playback should be sped up. This may be
|
||||
* different from the current playback speed, for example, if the speed is temporarily
|
||||
* adjusted for live playback.
|
||||
* @param format The {@link Format} for which the codec is being configured.
|
||||
* @param streamFormats The possible stream formats.
|
||||
* @return The codec operating rate, or {@link #CODEC_OPERATING_RATE_UNSET} if no codec operating
|
||||
* rate should be set.
|
||||
*/
|
||||
protected float getCodecOperatingRateV23(
|
||||
float playbackSpeed, Format format, Format[] streamFormats) {
|
||||
float targetPlaybackSpeed, Format format, Format[] streamFormats) {
|
||||
return CODEC_OPERATING_RATE_UNSET;
|
||||
}
|
||||
|
||||
@ -1665,7 +1671,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
|
||||
}
|
||||
|
||||
float newCodecOperatingRate =
|
||||
getCodecOperatingRateV23(playbackSpeed, format, getStreamFormats());
|
||||
getCodecOperatingRateV23(targetPlaybackSpeed, format, getStreamFormats());
|
||||
if (codecOperatingRate == newCodecOperatingRate) {
|
||||
// No change.
|
||||
return true;
|
||||
|
@ -645,14 +645,15 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlaybackSpeed(float playbackSpeed) throws ExoPlaybackException {
|
||||
super.setPlaybackSpeed(playbackSpeed);
|
||||
frameReleaseHelper.onPlaybackSpeed(playbackSpeed);
|
||||
public void setPlaybackSpeed(float currentPlaybackSpeed, float targetPlaybackSpeed)
|
||||
throws ExoPlaybackException {
|
||||
super.setPlaybackSpeed(currentPlaybackSpeed, targetPlaybackSpeed);
|
||||
frameReleaseHelper.onPlaybackSpeed(currentPlaybackSpeed);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getCodecOperatingRateV23(
|
||||
float playbackSpeed, Format format, Format[] streamFormats) {
|
||||
float targetPlaybackSpeed, Format format, Format[] streamFormats) {
|
||||
// Use the highest known stream frame-rate up front, to avoid having to reconfigure the codec
|
||||
// should an adaptive switch to that stream occur.
|
||||
float maxFrameRate = -1;
|
||||
@ -662,7 +663,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
|
||||
maxFrameRate = max(maxFrameRate, streamFrameRate);
|
||||
}
|
||||
}
|
||||
return maxFrameRate == -1 ? CODEC_OPERATING_RATE_UNSET : (maxFrameRate * playbackSpeed);
|
||||
return maxFrameRate == -1 ? CODEC_OPERATING_RATE_UNSET : (maxFrameRate * targetPlaybackSpeed);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -190,10 +190,9 @@ public final class VideoFrameReleaseHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the renderer's playback speed changes, where 1 is the default rate, 2 is twice the
|
||||
* default rate, 0.5 is half the default rate and so on.
|
||||
* Called when the renderer's playback speed changes.
|
||||
*
|
||||
* @param playbackSpeed The player's speed.
|
||||
* @param playbackSpeed The factor by which playback is sped up.
|
||||
*/
|
||||
public void onPlaybackSpeed(float playbackSpeed) {
|
||||
this.playbackSpeed = playbackSpeed;
|
||||
|
Loading…
x
Reference in New Issue
Block a user