Simplify playback parameter state tracking in DefaultAudioSink
This makes it easier to reason about some parts of the code and will eventually allow to easily switch between AudioProcessor- based on AudioSink-based speed adjustment. The current state saves the applicable playback parameters in separate variables depending on which speed adjustment path is used. Moreover, the AudioProcessor-based logic keeps a chain of pending parameter changes and we derive the last applicable one everytime we need the current parameters. After this change, this is simplified by - keeping a common value for playback parameters independent of the actual path we use for adjustment. - keeping the final ("current") parameters directly, instead of deriving it from a chain of yet to be applied parameters. PiperOrigin-RevId: 505097294
This commit is contained in:
parent
5e44af0ad9
commit
3d82846074
@ -495,7 +495,8 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
private AudioAttributes audioAttributes;
|
private AudioAttributes audioAttributes;
|
||||||
@Nullable private MediaPositionParameters afterDrainParameters;
|
@Nullable private MediaPositionParameters afterDrainParameters;
|
||||||
private MediaPositionParameters mediaPositionParameters;
|
private MediaPositionParameters mediaPositionParameters;
|
||||||
private PlaybackParameters audioTrackPlaybackParameters;
|
private PlaybackParameters playbackParameters;
|
||||||
|
private boolean skipSilenceEnabled;
|
||||||
|
|
||||||
@Nullable private ByteBuffer avSyncHeader;
|
@Nullable private ByteBuffer avSyncHeader;
|
||||||
private int bytesUntilNextAvSync;
|
private int bytesUntilNextAvSync;
|
||||||
@ -552,11 +553,9 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
auxEffectInfo = new AuxEffectInfo(AuxEffectInfo.NO_AUX_EFFECT_ID, 0f);
|
auxEffectInfo = new AuxEffectInfo(AuxEffectInfo.NO_AUX_EFFECT_ID, 0f);
|
||||||
mediaPositionParameters =
|
mediaPositionParameters =
|
||||||
new MediaPositionParameters(
|
new MediaPositionParameters(
|
||||||
PlaybackParameters.DEFAULT,
|
PlaybackParameters.DEFAULT, /* mediaTimeUs= */ 0, /* audioTrackPositionUs= */ 0);
|
||||||
DEFAULT_SKIP_SILENCE,
|
playbackParameters = PlaybackParameters.DEFAULT;
|
||||||
/* mediaTimeUs= */ 0,
|
skipSilenceEnabled = DEFAULT_SKIP_SILENCE;
|
||||||
/* audioTrackPositionUs= */ 0);
|
|
||||||
audioTrackPlaybackParameters = PlaybackParameters.DEFAULT;
|
|
||||||
mediaPositionParametersCheckpoints = new ArrayDeque<>();
|
mediaPositionParametersCheckpoints = new ArrayDeque<>();
|
||||||
initializationExceptionPendingExceptionHolder =
|
initializationExceptionPendingExceptionHolder =
|
||||||
new PendingExceptionHolder<>(AUDIO_TRACK_RETRY_DURATION_MS);
|
new PendingExceptionHolder<>(AUDIO_TRACK_RETRY_DURATION_MS);
|
||||||
@ -859,8 +858,8 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
startMediaTimeUsNeedsSync = false;
|
startMediaTimeUsNeedsSync = false;
|
||||||
startMediaTimeUsNeedsInit = false;
|
startMediaTimeUsNeedsInit = false;
|
||||||
|
|
||||||
if (enableAudioTrackPlaybackParams && Util.SDK_INT >= 23) {
|
if (useAudioTrackPlaybackParams()) {
|
||||||
setAudioTrackPlaybackParametersV23(audioTrackPlaybackParameters);
|
setAudioTrackPlaybackParametersV23();
|
||||||
}
|
}
|
||||||
applyAudioProcessorPlaybackParametersAndSkipSilence(presentationTimeUs);
|
applyAudioProcessorPlaybackParametersAndSkipSilence(presentationTimeUs);
|
||||||
|
|
||||||
@ -1213,34 +1212,34 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPlaybackParameters(PlaybackParameters playbackParameters) {
|
public void setPlaybackParameters(PlaybackParameters playbackParameters) {
|
||||||
playbackParameters =
|
this.playbackParameters =
|
||||||
new PlaybackParameters(
|
new PlaybackParameters(
|
||||||
constrainValue(playbackParameters.speed, MIN_PLAYBACK_SPEED, MAX_PLAYBACK_SPEED),
|
constrainValue(playbackParameters.speed, MIN_PLAYBACK_SPEED, MAX_PLAYBACK_SPEED),
|
||||||
constrainValue(playbackParameters.pitch, MIN_PITCH, MAX_PITCH));
|
constrainValue(playbackParameters.pitch, MIN_PITCH, MAX_PITCH));
|
||||||
if (enableAudioTrackPlaybackParams && Util.SDK_INT >= 23) {
|
if (useAudioTrackPlaybackParams()) {
|
||||||
setAudioTrackPlaybackParametersV23(playbackParameters);
|
setAudioTrackPlaybackParametersV23();
|
||||||
} else {
|
} else {
|
||||||
setAudioProcessorPlaybackParametersAndSkipSilence(
|
setAudioProcessorPlaybackParameters(playbackParameters);
|
||||||
playbackParameters, getSkipSilenceEnabled());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlaybackParameters getPlaybackParameters() {
|
public PlaybackParameters getPlaybackParameters() {
|
||||||
return enableAudioTrackPlaybackParams
|
return playbackParameters;
|
||||||
? audioTrackPlaybackParameters
|
|
||||||
: getAudioProcessorPlaybackParameters();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSkipSilenceEnabled(boolean skipSilenceEnabled) {
|
public void setSkipSilenceEnabled(boolean skipSilenceEnabled) {
|
||||||
setAudioProcessorPlaybackParametersAndSkipSilence(
|
this.skipSilenceEnabled = skipSilenceEnabled;
|
||||||
getAudioProcessorPlaybackParameters(), 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
|
@Override
|
||||||
public boolean getSkipSilenceEnabled() {
|
public boolean getSkipSilenceEnabled() {
|
||||||
return getMediaPositionParameters().skipSilence;
|
return skipSilenceEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1433,10 +1432,7 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
framesPerEncodedSample = 0;
|
framesPerEncodedSample = 0;
|
||||||
mediaPositionParameters =
|
mediaPositionParameters =
|
||||||
new MediaPositionParameters(
|
new MediaPositionParameters(
|
||||||
getAudioProcessorPlaybackParameters(),
|
playbackParameters, /* mediaTimeUs= */ 0, /* audioTrackPositionUs= */ 0);
|
||||||
getSkipSilenceEnabled(),
|
|
||||||
/* mediaTimeUs= */ 0,
|
|
||||||
/* audioTrackPositionUs= */ 0);
|
|
||||||
startMediaTimeUs = 0;
|
startMediaTimeUs = 0;
|
||||||
afterDrainParameters = null;
|
afterDrainParameters = null;
|
||||||
mediaPositionParametersCheckpoints.clear();
|
mediaPositionParametersCheckpoints.clear();
|
||||||
@ -1452,13 +1448,13 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(23)
|
@RequiresApi(23)
|
||||||
private void setAudioTrackPlaybackParametersV23(PlaybackParameters audioTrackPlaybackParameters) {
|
private void setAudioTrackPlaybackParametersV23() {
|
||||||
if (isAudioTrackInitialized()) {
|
if (isAudioTrackInitialized()) {
|
||||||
PlaybackParams playbackParams =
|
PlaybackParams playbackParams =
|
||||||
new PlaybackParams()
|
new PlaybackParams()
|
||||||
.allowDefaults()
|
.allowDefaults()
|
||||||
.setSpeed(audioTrackPlaybackParameters.speed)
|
.setSpeed(playbackParameters.speed)
|
||||||
.setPitch(audioTrackPlaybackParameters.pitch)
|
.setPitch(playbackParameters.pitch)
|
||||||
.setAudioFallbackMode(PlaybackParams.AUDIO_FALLBACK_MODE_FAIL);
|
.setAudioFallbackMode(PlaybackParams.AUDIO_FALLBACK_MODE_FAIL);
|
||||||
try {
|
try {
|
||||||
audioTrack.setPlaybackParams(playbackParams);
|
audioTrack.setPlaybackParams(playbackParams);
|
||||||
@ -1466,63 +1462,48 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
Log.w(TAG, "Failed to set playback params", e);
|
Log.w(TAG, "Failed to set playback params", e);
|
||||||
}
|
}
|
||||||
// Update the speed using the actual effective speed from the audio track.
|
// Update the speed using the actual effective speed from the audio track.
|
||||||
audioTrackPlaybackParameters =
|
playbackParameters =
|
||||||
new PlaybackParameters(
|
new PlaybackParameters(
|
||||||
audioTrack.getPlaybackParams().getSpeed(), audioTrack.getPlaybackParams().getPitch());
|
audioTrack.getPlaybackParams().getSpeed(), audioTrack.getPlaybackParams().getPitch());
|
||||||
audioTrackPositionTracker.setAudioTrackPlaybackSpeed(audioTrackPlaybackParameters.speed);
|
audioTrackPositionTracker.setAudioTrackPlaybackSpeed(playbackParameters.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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PlaybackParameters getAudioProcessorPlaybackParameters() {
|
private void setAudioProcessorPlaybackParameters(PlaybackParameters playbackParameters) {
|
||||||
return getMediaPositionParameters().playbackParameters;
|
MediaPositionParameters mediaPositionParameters =
|
||||||
}
|
new MediaPositionParameters(
|
||||||
|
playbackParameters,
|
||||||
private MediaPositionParameters getMediaPositionParameters() {
|
/* mediaTimeUs= */ C.TIME_UNSET,
|
||||||
// Mask the already set parameters.
|
/* audioTrackPositionUs= */ C.TIME_UNSET);
|
||||||
return afterDrainParameters != null
|
if (isAudioTrackInitialized()) {
|
||||||
? afterDrainParameters
|
// Drain the audio processors so we can determine the frame position at which the new
|
||||||
: !mediaPositionParametersCheckpoints.isEmpty()
|
// parameters apply.
|
||||||
? mediaPositionParametersCheckpoints.getLast()
|
this.afterDrainParameters = mediaPositionParameters;
|
||||||
: 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) {
|
private void applyAudioProcessorPlaybackParametersAndSkipSilence(long presentationTimeUs) {
|
||||||
PlaybackParameters playbackParameters =
|
PlaybackParameters audioProcessorPlaybackParameters;
|
||||||
|
if (!useAudioTrackPlaybackParams()) {
|
||||||
|
playbackParameters =
|
||||||
|
shouldApplyAudioProcessorPlaybackParameters()
|
||||||
|
? audioProcessorChain.applyPlaybackParameters(playbackParameters)
|
||||||
|
: PlaybackParameters.DEFAULT;
|
||||||
|
audioProcessorPlaybackParameters = playbackParameters;
|
||||||
|
} else {
|
||||||
|
audioProcessorPlaybackParameters = PlaybackParameters.DEFAULT;
|
||||||
|
}
|
||||||
|
skipSilenceEnabled =
|
||||||
shouldApplyAudioProcessorPlaybackParameters()
|
shouldApplyAudioProcessorPlaybackParameters()
|
||||||
? audioProcessorChain.applyPlaybackParameters(getAudioProcessorPlaybackParameters())
|
? audioProcessorChain.applySkipSilenceEnabled(skipSilenceEnabled)
|
||||||
: PlaybackParameters.DEFAULT;
|
|
||||||
boolean skipSilenceEnabled =
|
|
||||||
shouldApplyAudioProcessorPlaybackParameters()
|
|
||||||
? audioProcessorChain.applySkipSilenceEnabled(getSkipSilenceEnabled())
|
|
||||||
: DEFAULT_SKIP_SILENCE;
|
: DEFAULT_SKIP_SILENCE;
|
||||||
mediaPositionParametersCheckpoints.add(
|
mediaPositionParametersCheckpoints.add(
|
||||||
new MediaPositionParameters(
|
new MediaPositionParameters(
|
||||||
playbackParameters,
|
audioProcessorPlaybackParameters,
|
||||||
skipSilenceEnabled,
|
|
||||||
/* mediaTimeUs= */ max(0, presentationTimeUs),
|
/* mediaTimeUs= */ max(0, presentationTimeUs),
|
||||||
/* audioTrackPositionUs= */ configuration.framesToDurationUs(getWrittenFrames())));
|
/* audioTrackPositionUs= */ configuration.framesToDurationUs(getWrittenFrames())));
|
||||||
setupAudioProcessors();
|
setupAudioProcessors();
|
||||||
@ -1548,6 +1529,10 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
&& !shouldUseFloatOutput(configuration.inputFormat.pcmEncoding);
|
&& !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
|
* Returns whether audio in the specified PCM encoding should be written to the audio track as
|
||||||
* float PCM.
|
* float PCM.
|
||||||
@ -1869,20 +1854,14 @@ public final class DefaultAudioSink implements AudioSink {
|
|||||||
|
|
||||||
/** The playback parameters. */
|
/** The playback parameters. */
|
||||||
public final PlaybackParameters playbackParameters;
|
public final PlaybackParameters playbackParameters;
|
||||||
/** Whether to skip silences. */
|
|
||||||
public final boolean skipSilence;
|
|
||||||
/** The media time from which the playback parameters apply, in microseconds. */
|
/** The media time from which the playback parameters apply, in microseconds. */
|
||||||
public final long mediaTimeUs;
|
public final long mediaTimeUs;
|
||||||
/** The audio track position from which the playback parameters apply, in microseconds. */
|
/** The audio track position from which the playback parameters apply, in microseconds. */
|
||||||
public final long audioTrackPositionUs;
|
public final long audioTrackPositionUs;
|
||||||
|
|
||||||
private MediaPositionParameters(
|
private MediaPositionParameters(
|
||||||
PlaybackParameters playbackParameters,
|
PlaybackParameters playbackParameters, long mediaTimeUs, long audioTrackPositionUs) {
|
||||||
boolean skipSilence,
|
|
||||||
long mediaTimeUs,
|
|
||||||
long audioTrackPositionUs) {
|
|
||||||
this.playbackParameters = playbackParameters;
|
this.playbackParameters = playbackParameters;
|
||||||
this.skipSilence = skipSilence;
|
|
||||||
this.mediaTimeUs = mediaTimeUs;
|
this.mediaTimeUs = mediaTimeUs;
|
||||||
this.audioTrackPositionUs = audioTrackPositionUs;
|
this.audioTrackPositionUs = audioTrackPositionUs;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user