Skip to content

Commit

Permalink
Always drain/flush AudioProcessors after configuration
Browse files Browse the repository at this point in the history
This simplifies the contract of configure and is in preparation for
fixing a bug where more input can't be queued when draining audio
processors for a configuration change.

Issue: #6601
PiperOrigin-RevId: 282514367
  • Loading branch information
andrewlewis authored and ojw28 committed Nov 27, 2019
1 parent 64569a3 commit b7000e6
Show file tree
Hide file tree
Showing 12 changed files with 38 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,12 @@ public synchronized void updateOrientation(float w, float x, float y, float z) {

@SuppressWarnings("ReferenceEquality")
@Override
public synchronized boolean configure(
int sampleRateHz, int channelCount, @C.Encoding int encoding)
public synchronized void configure(int sampleRateHz, int channelCount, @C.Encoding int encoding)
throws UnhandledFormatException {
if (encoding != C.ENCODING_PCM_16BIT) {
maybeReleaseGvrAudioSurround();
throw new UnhandledFormatException(sampleRateHz, channelCount, encoding);
}
if (this.sampleRateHz == sampleRateHz && this.channelCount == channelCount) {
return false;
}
this.sampleRateHz = sampleRateHz;
this.channelCount = channelCount;
switch (channelCount) {
Expand Down Expand Up @@ -125,7 +121,6 @@ public synchronized boolean configure(
buffer = ByteBuffer.allocateDirect(FRAMES_PER_OUTPUT_BUFFER * OUTPUT_FRAME_SIZE)
.order(ByteOrder.nativeOrder());
}
return true;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,16 @@ public UnhandledFormatException(
* <p>If the audio processor is active after configuration, call {@link #getOutputSampleRateHz()},
* {@link #getOutputChannelCount()} and {@link #getOutputEncoding()} to get its new output format.
*
* <p>If this method returns {@code true}, it is necessary to {@link #flush()} the processor
* before queueing more data, but you can (optionally) first drain output in the previous
* configuration by calling {@link #queueEndOfStream()} and {@link #getOutput()}. If this method
* returns {@code false}, it is safe to queue new input immediately.
* <p>After calling this method, it is necessary to {@link #flush()} the processor to apply the
* new configuration before queueing more data. You can (optionally) first drain output in the
* previous configuration by calling {@link #queueEndOfStream()} and {@link #getOutput()}.
*
* @param sampleRateHz The sample rate of input audio in Hz.
* @param channelCount The number of interleaved channels in input audio.
* @param encoding The encoding of input audio.
* @return Whether the processor must be {@link #flush() flushed} before queueing more input.
* @throws UnhandledFormatException Thrown if the specified format can't be handled as input.
*/
boolean configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding)
void configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding)
throws UnhandledFormatException;

/** Returns whether the processor is configured and will process input buffers. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,18 +104,12 @@ public final void reset() {
onReset();
}

/** Sets the input format of this processor, returning whether the input format has changed. */
protected final boolean setInputFormat(
/** Sets the input format of this processor. */
protected final void setInputFormat(
int sampleRateHz, int channelCount, @C.PcmEncoding int encoding) {
if (sampleRateHz == this.sampleRateHz
&& channelCount == this.channelCount
&& encoding == this.encoding) {
return false;
}
this.sampleRateHz = sampleRateHz;
this.channelCount = channelCount;
this.encoding = encoding;
return true;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.Assertions;
import java.nio.ByteBuffer;
import java.util.Arrays;

/**
* An {@link AudioProcessor} that applies a mapping from input channels onto specified output
Expand Down Expand Up @@ -48,23 +47,20 @@ public void setChannelMap(@Nullable int[] outputChannels) {
}

@Override
public boolean configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding)
public void configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding)
throws UnhandledFormatException {
boolean outputChannelsChanged = !Arrays.equals(pendingOutputChannels, outputChannels);
outputChannels = pendingOutputChannels;

int[] outputChannels = this.outputChannels;
if (outputChannels == null) {
active = false;
return outputChannelsChanged;
return;
}
if (encoding != C.ENCODING_PCM_16BIT) {
throw new UnhandledFormatException(sampleRateHz, channelCount, encoding);
}
if (!outputChannelsChanged && !setInputFormat(sampleRateHz, channelCount, encoding)) {
return false;
}

setInputFormat(sampleRateHz, channelCount, encoding);
active = channelCount != outputChannels.length;
for (int i = 0; i < outputChannels.length; i++) {
int channelIndex = outputChannels[i];
Expand All @@ -73,7 +69,6 @@ public boolean configure(int sampleRateHz, int channelCount, @C.PcmEncoding int
}
active |= (channelIndex != i);
}
return true;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ public long getSkippedOutputFrameCount() {
private final ArrayDeque<PlaybackParametersCheckpoint> playbackParametersCheckpoints;

@Nullable private Listener listener;
/** Used to keep the audio session active on pre-V21 builds (see {@link #initialize()}). */
/** Used to keep the audio session active on pre-V21 builds (see {@link #initialize(long)}). */
@Nullable private AudioTrack keepSessionIdAudioTrack;

@Nullable private Configuration pendingConfiguration;
Expand Down Expand Up @@ -432,13 +432,12 @@ && supportsOutput(inputChannelCount, C.ENCODING_PCM_FLOAT)
shouldConvertHighResIntPcmToFloat
? toFloatPcmAvailableAudioProcessors
: toIntPcmAvailableAudioProcessors;
boolean flushAudioProcessors = false;
if (processingEnabled) {
trimmingAudioProcessor.setTrimFrameCount(trimStartFrames, trimEndFrames);
channelMappingAudioProcessor.setChannelMap(outputChannels);
for (AudioProcessor audioProcessor : availableAudioProcessors) {
try {
flushAudioProcessors |= audioProcessor.configure(sampleRate, channelCount, encoding);
audioProcessor.configure(sampleRate, channelCount, encoding);
} catch (AudioProcessor.UnhandledFormatException e) {
throw new ConfigurationException(e);
}
Expand Down Expand Up @@ -473,11 +472,7 @@ && supportsOutput(inputChannelCount, C.ENCODING_PCM_FLOAT)
processingEnabled,
canApplyPlaybackParameters,
availableAudioProcessors);
// If we have a pending configuration already, we always drain audio processors as the preceding
// configuration may have required it (even if this one doesn't).
boolean drainAudioProcessors = flushAudioProcessors || this.pendingConfiguration != null;
if (isInitialized()
&& (!pendingConfiguration.canReuseAudioTrack(configuration) || drainAudioProcessors)) {
if (isInitialized()) {
this.pendingConfiguration = pendingConfiguration;
} else {
configuration = pendingConfiguration;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@
private static final double PCM_32_BIT_INT_TO_PCM_32_BIT_FLOAT_FACTOR = 1.0 / 0x7FFFFFFF;

@Override
public boolean configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding)
public void configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding)
throws UnhandledFormatException {
if (!Util.isEncodingHighResolutionIntegerPcm(encoding)) {
throw new UnhandledFormatException(sampleRateHz, channelCount, encoding);
}
return setInputFormat(sampleRateHz, channelCount, encoding);
setInputFormat(sampleRateHz, channelCount, encoding);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@
/* package */ final class ResamplingAudioProcessor extends BaseAudioProcessor {

@Override
public boolean configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding)
public void configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding)
throws UnhandledFormatException {
if (encoding != C.ENCODING_PCM_8BIT && encoding != C.ENCODING_PCM_16BIT
&& encoding != C.ENCODING_PCM_24BIT && encoding != C.ENCODING_PCM_32BIT) {
throw new UnhandledFormatException(sampleRateHz, channelCount, encoding);
}
return setInputFormat(sampleRateHz, channelCount, encoding);
setInputFormat(sampleRateHz, channelCount, encoding);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,13 @@ public long getSkippedFrames() {
// AudioProcessor implementation.

@Override
public boolean configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding)
public void configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding)
throws UnhandledFormatException {
if (encoding != C.ENCODING_PCM_16BIT) {
throw new UnhandledFormatException(sampleRateHz, channelCount, encoding);
}
bytesPerFrame = channelCount * 2;
return setInputFormat(sampleRateHz, channelCount, encoding);
setInputFormat(sampleRateHz, channelCount, encoding);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,22 +159,17 @@ public long scaleDurationForSpeedup(long duration) {
}

@Override
public boolean configure(int sampleRateHz, int channelCount, @Encoding int encoding)
public void configure(int sampleRateHz, int channelCount, @Encoding int encoding)
throws UnhandledFormatException {
if (encoding != C.ENCODING_PCM_16BIT) {
throw new UnhandledFormatException(sampleRateHz, channelCount, encoding);
}
int outputSampleRateHz = pendingOutputSampleRateHz == SAMPLE_RATE_NO_CHANGE
? sampleRateHz : pendingOutputSampleRateHz;
if (this.sampleRateHz == sampleRateHz && this.channelCount == channelCount
&& this.outputSampleRateHz == outputSampleRateHz) {
return false;
}
this.sampleRateHz = sampleRateHz;
this.channelCount = channelCount;
this.outputSampleRateHz = outputSampleRateHz;
pendingSonicRecreation = true;
return true;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ public TeeAudioProcessor(AudioBufferSink audioBufferSink) {
}

@Override
public boolean configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding) {
return setInputFormat(sampleRateHz, channelCount, encoding);
public void configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding) {
setInputFormat(sampleRateHz, channelCount, encoding);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public long getTrimmedFrameCount() {
}

@Override
public boolean configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding)
public void configure(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding)
throws UnhandledFormatException {
if (encoding != OUTPUT_ENCODING) {
throw new UnhandledFormatException(sampleRateHz, channelCount, encoding);
Expand All @@ -80,11 +80,9 @@ public boolean configure(int sampleRateHz, int channelCount, @C.PcmEncoding int
endBuffer = new byte[trimEndFrames * bytesPerFrame];
endBufferSize = 0;
pendingTrimStartBytes = trimStartFrames * bytesPerFrame;
boolean wasActive = isActive;
isActive = trimStartFrames != 0 || trimEndFrames != 0;
receivedInputSinceConfigure = false;
setInputFormat(sampleRateHz, channelCount, encoding);
return wasActive != isActive;
}

@Override
Expand Down
Loading

0 comments on commit b7000e6

Please sign in to comment.