diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1bc43e60fc..9a45664a14 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -9,6 +9,8 @@ * Allow missing hours and milliseconds in SubRip (.srt) timecodes ([#7122](https://github.com/google/ExoPlayer/issues/7122)). * 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 audio, via resampling to 16-bit integer PCM. To output the original floating point audio without adjustment, pass `enableFloatOutput=true` to the diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java index 4830b78760..e1026ed196 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecRenderer.java @@ -344,6 +344,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { private boolean codecNeedsReconfigureWorkaround; private boolean codecNeedsDiscardToSpsWorkaround; private boolean codecNeedsFlushWorkaround; + private boolean codecNeedsSosFlushWorkaround; private boolean codecNeedsEosFlushWorkaround; private boolean codecNeedsEosOutputExceptionWorkaround; private boolean codecNeedsMonoChannelCountWorkaround; @@ -364,6 +365,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { @DrainAction private int codecDrainAction; private boolean codecReceivedBuffers; private boolean codecReceivedEos; + private boolean codecHasOutputMediaFormat; private long largestQueuedPresentationTimeUs; private long lastBufferInStreamPresentationTimeUs; private boolean inputStreamEnded; @@ -652,6 +654,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { availableCodecInfos = null; codecInfo = null; codecFormat = null; + codecHasOutputMediaFormat = false; resetInputBuffer(); resetOutputBuffer(); resetCodecBuffers(); @@ -765,6 +768,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } if (codecDrainAction == DRAIN_ACTION_REINITIALIZE || codecNeedsFlushWorkaround + || (codecNeedsSosFlushWorkaround && !codecHasOutputMediaFormat) || (codecNeedsEosFlushWorkaround && codecReceivedEos)) { releaseCodec(); return true; @@ -944,6 +948,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { codecNeedsReconfigureWorkaround = codecNeedsReconfigureWorkaround(codecName); codecNeedsDiscardToSpsWorkaround = codecNeedsDiscardToSpsWorkaround(codecName, codecFormat); codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName); + codecNeedsSosFlushWorkaround = codecNeedsSosFlushWorkaround(codecName); codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName); codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName); codecNeedsMonoChannelCountWorkaround = @@ -1610,6 +1615,7 @@ public abstract class MediaCodecRenderer extends BaseRenderer { /** Processes a new output {@link MediaFormat}. */ private void processOutputFormat() throws ExoPlaybackException { + codecHasOutputMediaFormat = true; MediaFormat mediaFormat = codec.getOutputFormat(); if (codecAdaptationWorkaroundMode != ADAPTATION_WORKAROUND_MODE_NEVER && mediaFormat.getInteger(MediaFormat.KEY_WIDTH) == ADAPTATION_WORKAROUND_SLICE_WIDTH_HEIGHT @@ -1989,4 +1995,20 @@ public abstract class MediaCodecRenderer extends BaseRenderer { && "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}. + * + *
If true is returned, the renderer will work around the issue by instantiating a new decoder + * when this case occurs. + * + *
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); + } }