Commit f0e734d3 by olly Committed by Oliver Woodman

Workaround C2 AAC decoder flush problem on Android 10

Issue: #6671
PiperOrigin-RevId: 303364788
parent 69ca5349
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
* Allow missing hours and milliseconds in SubRip (.srt) timecodes * Allow missing hours and milliseconds in SubRip (.srt) timecodes
([#7122](https://github.com/google/ExoPlayer/issues/7122)). ([#7122](https://github.com/google/ExoPlayer/issues/7122)).
* Audio: * Audio:
* Workaround issue that could cause slower than realtime playback of AAC on
Android 10 ([#6671](https://github.com/google/ExoPlayer/issues/6671).
* Enable playback speed adjustment and silence skipping for floating point PCM * Enable playback speed adjustment and silence skipping for floating point PCM
audio, via resampling to 16-bit integer PCM. To output the original floating audio, via resampling to 16-bit integer PCM. To output the original floating
point audio without adjustment, pass `enableFloatOutput=true` to the point audio without adjustment, pass `enableFloatOutput=true` to the
......
...@@ -344,6 +344,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -344,6 +344,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
private boolean codecNeedsReconfigureWorkaround; private boolean codecNeedsReconfigureWorkaround;
private boolean codecNeedsDiscardToSpsWorkaround; private boolean codecNeedsDiscardToSpsWorkaround;
private boolean codecNeedsFlushWorkaround; private boolean codecNeedsFlushWorkaround;
private boolean codecNeedsSosFlushWorkaround;
private boolean codecNeedsEosFlushWorkaround; private boolean codecNeedsEosFlushWorkaround;
private boolean codecNeedsEosOutputExceptionWorkaround; private boolean codecNeedsEosOutputExceptionWorkaround;
private boolean codecNeedsMonoChannelCountWorkaround; private boolean codecNeedsMonoChannelCountWorkaround;
...@@ -364,6 +365,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -364,6 +365,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
@DrainAction private int codecDrainAction; @DrainAction private int codecDrainAction;
private boolean codecReceivedBuffers; private boolean codecReceivedBuffers;
private boolean codecReceivedEos; private boolean codecReceivedEos;
private boolean codecHasOutputMediaFormat;
private long largestQueuedPresentationTimeUs; private long largestQueuedPresentationTimeUs;
private long lastBufferInStreamPresentationTimeUs; private long lastBufferInStreamPresentationTimeUs;
private boolean inputStreamEnded; private boolean inputStreamEnded;
...@@ -652,6 +654,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -652,6 +654,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
availableCodecInfos = null; availableCodecInfos = null;
codecInfo = null; codecInfo = null;
codecFormat = null; codecFormat = null;
codecHasOutputMediaFormat = false;
resetInputBuffer(); resetInputBuffer();
resetOutputBuffer(); resetOutputBuffer();
resetCodecBuffers(); resetCodecBuffers();
...@@ -765,6 +768,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -765,6 +768,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
} }
if (codecDrainAction == DRAIN_ACTION_REINITIALIZE if (codecDrainAction == DRAIN_ACTION_REINITIALIZE
|| codecNeedsFlushWorkaround || codecNeedsFlushWorkaround
|| (codecNeedsSosFlushWorkaround && !codecHasOutputMediaFormat)
|| (codecNeedsEosFlushWorkaround && codecReceivedEos)) { || (codecNeedsEosFlushWorkaround && codecReceivedEos)) {
releaseCodec(); releaseCodec();
return true; return true;
...@@ -944,6 +948,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -944,6 +948,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
codecNeedsReconfigureWorkaround = codecNeedsReconfigureWorkaround(codecName); codecNeedsReconfigureWorkaround = codecNeedsReconfigureWorkaround(codecName);
codecNeedsDiscardToSpsWorkaround = codecNeedsDiscardToSpsWorkaround(codecName, codecFormat); codecNeedsDiscardToSpsWorkaround = codecNeedsDiscardToSpsWorkaround(codecName, codecFormat);
codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName); codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName);
codecNeedsSosFlushWorkaround = codecNeedsSosFlushWorkaround(codecName);
codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName); codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName);
codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName); codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName);
codecNeedsMonoChannelCountWorkaround = codecNeedsMonoChannelCountWorkaround =
...@@ -1610,6 +1615,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1610,6 +1615,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
/** Processes a new output {@link MediaFormat}. */ /** Processes a new output {@link MediaFormat}. */
private void processOutputFormat() throws ExoPlaybackException { private void processOutputFormat() throws ExoPlaybackException {
codecHasOutputMediaFormat = true;
MediaFormat mediaFormat = codec.getOutputFormat(); MediaFormat mediaFormat = codec.getOutputFormat();
if (codecAdaptationWorkaroundMode != ADAPTATION_WORKAROUND_MODE_NEVER if (codecAdaptationWorkaroundMode != ADAPTATION_WORKAROUND_MODE_NEVER
&& mediaFormat.getInteger(MediaFormat.KEY_WIDTH) == ADAPTATION_WORKAROUND_SLICE_WIDTH_HEIGHT && mediaFormat.getInteger(MediaFormat.KEY_WIDTH) == ADAPTATION_WORKAROUND_SLICE_WIDTH_HEIGHT
...@@ -1989,4 +1995,20 @@ public abstract class MediaCodecRenderer extends BaseRenderer { ...@@ -1989,4 +1995,20 @@ public abstract class MediaCodecRenderer extends BaseRenderer {
&& "OMX.MTK.AUDIO.DECODER.MP3".equals(name); && "OMX.MTK.AUDIO.DECODER.MP3".equals(name);
} }
/**
* Returns whether the decoder is known to behave incorrectly if flushed prior to having output a
* {@link MediaFormat}.
*
* <p>If true is returned, the renderer will work around the issue by instantiating a new decoder
* when this case occurs.
*
* <p>See [Internal: b/141097367].
*
* @param name The name of the decoder.
* @return True if the decoder is known to behave incorrectly if flushed prior to having output a
* {@link MediaFormat}. False otherwise.
*/
private static boolean codecNeedsSosFlushWorkaround(String name) {
return Util.SDK_INT == 29 && "c2.android.aac.decoder".equals(name);
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment