diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java index 4bca4024901..8eeffdcef9c 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/audio/DefaultAudioSink.java @@ -495,7 +495,8 @@ public DefaultAudioSink build() { private AudioAttributes audioAttributes; @Nullable private MediaPositionParameters afterDrainParameters; private MediaPositionParameters mediaPositionParameters; - private PlaybackParameters audioTrackPlaybackParameters; + private PlaybackParameters playbackParameters; + private boolean skipSilenceEnabled; @Nullable private ByteBuffer avSyncHeader; private int bytesUntilNextAvSync; @@ -552,11 +553,9 @@ private DefaultAudioSink(Builder builder) { auxEffectInfo = new AuxEffectInfo(AuxEffectInfo.NO_AUX_EFFECT_ID, 0f); mediaPositionParameters = new MediaPositionParameters( - PlaybackParameters.DEFAULT, - DEFAULT_SKIP_SILENCE, - /* mediaTimeUs= */ 0, - /* audioTrackPositionUs= */ 0); - audioTrackPlaybackParameters = PlaybackParameters.DEFAULT; + PlaybackParameters.DEFAULT, /* mediaTimeUs= */ 0, /* audioTrackPositionUs= */ 0); + playbackParameters = PlaybackParameters.DEFAULT; + skipSilenceEnabled = DEFAULT_SKIP_SILENCE; mediaPositionParametersCheckpoints = new ArrayDeque<>(); initializationExceptionPendingExceptionHolder = new PendingExceptionHolder<>(AUDIO_TRACK_RETRY_DURATION_MS); @@ -859,8 +858,8 @@ public boolean handleBuffer( startMediaTimeUsNeedsSync = false; startMediaTimeUsNeedsInit = false; - if (enableAudioTrackPlaybackParams && Util.SDK_INT >= 23) { - setAudioTrackPlaybackParametersV23(audioTrackPlaybackParameters); + if (useAudioTrackPlaybackParams()) { + setAudioTrackPlaybackParametersV23(); } applyAudioProcessorPlaybackParametersAndSkipSilence(presentationTimeUs); @@ -1213,34 +1212,34 @@ public boolean hasPendingData() { @Override public void setPlaybackParameters(PlaybackParameters playbackParameters) { - playbackParameters = + this.playbackParameters = new PlaybackParameters( constrainValue(playbackParameters.speed, MIN_PLAYBACK_SPEED, MAX_PLAYBACK_SPEED), constrainValue(playbackParameters.pitch, MIN_PITCH, MAX_PITCH)); - if (enableAudioTrackPlaybackParams && Util.SDK_INT >= 23) { - setAudioTrackPlaybackParametersV23(playbackParameters); + if (useAudioTrackPlaybackParams()) { + setAudioTrackPlaybackParametersV23(); } else { - setAudioProcessorPlaybackParametersAndSkipSilence( - playbackParameters, getSkipSilenceEnabled()); + setAudioProcessorPlaybackParameters(playbackParameters); } } @Override public PlaybackParameters getPlaybackParameters() { - return enableAudioTrackPlaybackParams - ? audioTrackPlaybackParameters - : getAudioProcessorPlaybackParameters(); + return playbackParameters; } @Override public void setSkipSilenceEnabled(boolean skipSilenceEnabled) { - setAudioProcessorPlaybackParametersAndSkipSilence( - getAudioProcessorPlaybackParameters(), skipSilenceEnabled); + this.skipSilenceEnabled = skipSilenceEnabled; + // Skip silence is applied together with the AudioProcessor playback parameters after draining + // the pipeline. Force a drain by re-applying the current playback parameters. + setAudioProcessorPlaybackParameters( + useAudioTrackPlaybackParams() ? PlaybackParameters.DEFAULT : playbackParameters); } @Override public boolean getSkipSilenceEnabled() { - return getMediaPositionParameters().skipSilence; + return skipSilenceEnabled; } @Override @@ -1433,10 +1432,7 @@ private void resetSinkStateForFlush() { framesPerEncodedSample = 0; mediaPositionParameters = new MediaPositionParameters( - getAudioProcessorPlaybackParameters(), - getSkipSilenceEnabled(), - /* mediaTimeUs= */ 0, - /* audioTrackPositionUs= */ 0); + playbackParameters, /* mediaTimeUs= */ 0, /* audioTrackPositionUs= */ 0); startMediaTimeUs = 0; afterDrainParameters = null; mediaPositionParametersCheckpoints.clear(); @@ -1452,13 +1448,13 @@ private void resetSinkStateForFlush() { } @RequiresApi(23) - private void setAudioTrackPlaybackParametersV23(PlaybackParameters audioTrackPlaybackParameters) { + private void setAudioTrackPlaybackParametersV23() { if (isAudioTrackInitialized()) { PlaybackParams playbackParams = new PlaybackParams() .allowDefaults() - .setSpeed(audioTrackPlaybackParameters.speed) - .setPitch(audioTrackPlaybackParameters.pitch) + .setSpeed(playbackParameters.speed) + .setPitch(playbackParameters.pitch) .setAudioFallbackMode(PlaybackParams.AUDIO_FALLBACK_MODE_FAIL); try { audioTrack.setPlaybackParams(playbackParams); @@ -1466,63 +1462,48 @@ private void setAudioTrackPlaybackParametersV23(PlaybackParameters audioTrackPla Log.w(TAG, "Failed to set playback params", e); } // Update the speed using the actual effective speed from the audio track. - audioTrackPlaybackParameters = + playbackParameters = new PlaybackParameters( audioTrack.getPlaybackParams().getSpeed(), audioTrack.getPlaybackParams().getPitch()); - audioTrackPositionTracker.setAudioTrackPlaybackSpeed(audioTrackPlaybackParameters.speed); - } - this.audioTrackPlaybackParameters = audioTrackPlaybackParameters; - } - - private void setAudioProcessorPlaybackParametersAndSkipSilence( - PlaybackParameters playbackParameters, boolean skipSilence) { - MediaPositionParameters currentMediaPositionParameters = getMediaPositionParameters(); - if (!playbackParameters.equals(currentMediaPositionParameters.playbackParameters) - || skipSilence != currentMediaPositionParameters.skipSilence) { - MediaPositionParameters mediaPositionParameters = - new MediaPositionParameters( - playbackParameters, - skipSilence, - /* mediaTimeUs= */ C.TIME_UNSET, - /* audioTrackPositionUs= */ C.TIME_UNSET); - if (isAudioTrackInitialized()) { - // Drain the audio processors so we can determine the frame position at which the new - // parameters apply. - this.afterDrainParameters = mediaPositionParameters; - } else { - // Update the audio processor chain parameters now. They will be applied to the audio - // processors during initialization. - this.mediaPositionParameters = mediaPositionParameters; - } + audioTrackPositionTracker.setAudioTrackPlaybackSpeed(playbackParameters.speed); } } - private PlaybackParameters getAudioProcessorPlaybackParameters() { - return getMediaPositionParameters().playbackParameters; - } - - private MediaPositionParameters getMediaPositionParameters() { - // Mask the already set parameters. - return afterDrainParameters != null - ? afterDrainParameters - : !mediaPositionParametersCheckpoints.isEmpty() - ? mediaPositionParametersCheckpoints.getLast() - : mediaPositionParameters; + private void setAudioProcessorPlaybackParameters(PlaybackParameters playbackParameters) { + MediaPositionParameters mediaPositionParameters = + new MediaPositionParameters( + playbackParameters, + /* mediaTimeUs= */ C.TIME_UNSET, + /* audioTrackPositionUs= */ C.TIME_UNSET); + if (isAudioTrackInitialized()) { + // Drain the audio processors so we can determine the frame position at which the new + // parameters apply. + this.afterDrainParameters = mediaPositionParameters; + } else { + // Update the audio processor chain parameters now. They will be applied to the audio + // processors during initialization. + this.mediaPositionParameters = mediaPositionParameters; + } } private void applyAudioProcessorPlaybackParametersAndSkipSilence(long presentationTimeUs) { - PlaybackParameters playbackParameters = - shouldApplyAudioProcessorPlaybackParameters() - ? audioProcessorChain.applyPlaybackParameters(getAudioProcessorPlaybackParameters()) - : PlaybackParameters.DEFAULT; - boolean skipSilenceEnabled = + PlaybackParameters audioProcessorPlaybackParameters; + if (!useAudioTrackPlaybackParams()) { + playbackParameters = + shouldApplyAudioProcessorPlaybackParameters() + ? audioProcessorChain.applyPlaybackParameters(playbackParameters) + : PlaybackParameters.DEFAULT; + audioProcessorPlaybackParameters = playbackParameters; + } else { + audioProcessorPlaybackParameters = PlaybackParameters.DEFAULT; + } + skipSilenceEnabled = shouldApplyAudioProcessorPlaybackParameters() - ? audioProcessorChain.applySkipSilenceEnabled(getSkipSilenceEnabled()) + ? audioProcessorChain.applySkipSilenceEnabled(skipSilenceEnabled) : DEFAULT_SKIP_SILENCE; mediaPositionParametersCheckpoints.add( new MediaPositionParameters( - playbackParameters, - skipSilenceEnabled, + audioProcessorPlaybackParameters, /* mediaTimeUs= */ max(0, presentationTimeUs), /* audioTrackPositionUs= */ configuration.framesToDurationUs(getWrittenFrames()))); setupAudioProcessors(); @@ -1548,6 +1529,10 @@ private boolean shouldApplyAudioProcessorPlaybackParameters() { && !shouldUseFloatOutput(configuration.inputFormat.pcmEncoding); } + private boolean useAudioTrackPlaybackParams() { + return configuration != null && enableAudioTrackPlaybackParams && Util.SDK_INT >= 23; + } + /** * Returns whether audio in the specified PCM encoding should be written to the audio track as * float PCM. @@ -1869,20 +1854,14 @@ private static final class MediaPositionParameters { /** The playback parameters. */ public final PlaybackParameters playbackParameters; - /** Whether to skip silences. */ - public final boolean skipSilence; /** The media time from which the playback parameters apply, in microseconds. */ public final long mediaTimeUs; /** The audio track position from which the playback parameters apply, in microseconds. */ public final long audioTrackPositionUs; private MediaPositionParameters( - PlaybackParameters playbackParameters, - boolean skipSilence, - long mediaTimeUs, - long audioTrackPositionUs) { + PlaybackParameters playbackParameters, long mediaTimeUs, long audioTrackPositionUs) { this.playbackParameters = playbackParameters; - this.skipSilence = skipSilence; this.mediaTimeUs = mediaTimeUs; this.audioTrackPositionUs = audioTrackPositionUs; }