Skip to content

Commit

Permalink
Apply playback parameters in a consistent way.
Browse files Browse the repository at this point in the history
Currently, we sometimes apply new playback parameters directly and sometimes
through the list of playbackParameterCheckpoints. Only when using the checkpoints,
we also reset the offset and corresponding position for speedup position
calculation. However, these offsets need to be changed in all cases to prevent
calculation errors during speedup calculation[1].

This change channels all playback parameters changes through the checkpoints to
ensure the offsets get updated accordingly. This fixes an issue introduced in
31911ca.

[1] - The speed up is calculated using the ratio of input and output bytes in
SonicAudioProcessor.scaleDurationForSpeedUp. Whenever we set new playback
parameters to the audio processor these two counts are reset. If we don't reset
the offsets too, the scaled timestamp can be a large value compared to the input
and output bytes causing massive inaccuracies (like the +20 seconds in the
linked issue).

Issue:#6117
PiperOrigin-RevId: 256533780
  • Loading branch information
tonihei committed Jul 5, 2019
1 parent 0f364df commit 81e7b31
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 25 deletions.
7 changes: 5 additions & 2 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
checks ([#5568](https:/google/ExoPlayer/issues/5568)).
* Decoders: Prefer decoders that advertise format support over ones that do not,
even if they are listed lower in the `MediaCodecList`.
* Audio: Fix an issue where not all audio was played out when the configuration
for the underlying track was changing (e.g., at some period transitions).
* Audio:
* Fix an issue where not all audio was played out when the configuration
for the underlying track was changing (e.g., at some period transitions).
* Fix an issue where playback speed was applied inaccurately in playlists
([#6117](https:/google/ExoPlayer/issues/6117)).
* Add a workaround for broken raw audio decoding on Oppo R9
([#5782](https:/google/ExoPlayer/issues/5782)).
* Add VR player demo.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ private void flushAudioProcessors() {
}
}

private void initialize() throws InitializationException {
private void initialize(long presentationTimeUs) throws InitializationException {
// If we're asynchronously releasing a previous audio track then we block until it has been
// released. This guarantees that we cannot end up in a state where we have multiple audio
// track instances. Without this guarantee it would be possible, in extreme cases, to exhaust
Expand Down Expand Up @@ -533,11 +533,7 @@ private void initialize() throws InitializationException {
}
}

playbackParameters =
configuration.canApplyPlaybackParameters
? audioProcessorChain.applyPlaybackParameters(playbackParameters)
: PlaybackParameters.DEFAULT;
setupAudioProcessors();
applyPlaybackParameters(playbackParameters, presentationTimeUs);

audioTrackPositionTracker.setAudioTrack(
audioTrack,
Expand Down Expand Up @@ -591,15 +587,12 @@ public boolean handleBuffer(ByteBuffer buffer, long presentationTimeUs)
configuration = pendingConfiguration;
pendingConfiguration = null;
}
playbackParameters =
configuration.canApplyPlaybackParameters
? audioProcessorChain.applyPlaybackParameters(playbackParameters)
: PlaybackParameters.DEFAULT;
setupAudioProcessors();
// Re-apply playback parameters.
applyPlaybackParameters(playbackParameters, presentationTimeUs);
}

if (!isInitialized()) {
initialize();
initialize(presentationTimeUs);
if (playing) {
play();
}
Expand Down Expand Up @@ -635,15 +628,7 @@ public boolean handleBuffer(ByteBuffer buffer, long presentationTimeUs)
}
PlaybackParameters newPlaybackParameters = afterDrainPlaybackParameters;
afterDrainPlaybackParameters = null;
newPlaybackParameters = audioProcessorChain.applyPlaybackParameters(newPlaybackParameters);
// Store the position and corresponding media time from which the parameters will apply.
playbackParametersCheckpoints.add(
new PlaybackParametersCheckpoint(
newPlaybackParameters,
Math.max(0, presentationTimeUs),
configuration.framesToDurationUs(getWrittenFrames())));
// Update the set of active audio processors to take into account the new parameters.
setupAudioProcessors();
applyPlaybackParameters(newPlaybackParameters, presentationTimeUs);
}

if (startMediaTimeState == START_NOT_SET) {
Expand Down Expand Up @@ -857,8 +842,9 @@ public PlaybackParameters setPlaybackParameters(PlaybackParameters playbackParam
// parameters apply.
afterDrainPlaybackParameters = playbackParameters;
} else {
// Update the playback parameters now.
this.playbackParameters = audioProcessorChain.applyPlaybackParameters(playbackParameters);
// Update the playback parameters now. They will be applied to the audio processors during
// initialization.
this.playbackParameters = playbackParameters;
}
}
return this.playbackParameters;
Expand Down Expand Up @@ -1040,6 +1026,21 @@ public void run() {
}.start();
}

private void applyPlaybackParameters(
PlaybackParameters playbackParameters, long presentationTimeUs) {
PlaybackParameters newPlaybackParameters =
configuration.canApplyPlaybackParameters
? audioProcessorChain.applyPlaybackParameters(playbackParameters)
: PlaybackParameters.DEFAULT;
// Store the position and corresponding media time from which the parameters will apply.
playbackParametersCheckpoints.add(
new PlaybackParametersCheckpoint(
newPlaybackParameters,
/* mediaTimeUs= */ Math.max(0, presentationTimeUs),
/* positionUs= */ configuration.framesToDurationUs(getWrittenFrames())));
setupAudioProcessors();
}

private long applySpeedup(long positionUs) {
@Nullable PlaybackParametersCheckpoint checkpoint = null;
while (!playbackParametersCheckpoints.isEmpty()
Expand Down

0 comments on commit 81e7b31

Please sign in to comment.