From 1c11febf3fa92ff6df7196510b19c7f6d717f062 Mon Sep 17 00:00:00 2001 From: olly Date: Fri, 27 Mar 2020 18:01:16 +0000 Subject: [PATCH] Workaround C2 AAC decoder flush problem on Android 10 Issue: #6671 PiperOrigin-RevId: 303364788 --- RELEASENOTES.md | 2 ++ .../mediacodec/MediaCodecRenderer.java | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 212f02f6fe6..b2ce5a4e883 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -67,6 +67,8 @@ to the `DefaultAudioSink` constructor ([#7134](https://github.com/google/ExoPlayer/issues/7134)). * Add media item based playlist API to Player. + * Workaround issue that could cause slower than realtime playback of AAC + on Android 10 ([#6671](https://github.com/google/ExoPlayer/issues/6671). * Text: * Parse `` and `` tags in WebVTT subtitles (rendering is coming later). 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 b5fe6de11a9..bb772a70255 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 @@ -386,6 +386,7 @@ private static String buildCustomDiagnosticInfo(int errorCode) { private boolean codecNeedsReconfigureWorkaround; private boolean codecNeedsDiscardToSpsWorkaround; private boolean codecNeedsFlushWorkaround; + private boolean codecNeedsSosFlushWorkaround; private boolean codecNeedsEosFlushWorkaround; private boolean codecNeedsEosOutputExceptionWorkaround; private boolean codecNeedsMonoChannelCountWorkaround; @@ -406,6 +407,7 @@ private static String buildCustomDiagnosticInfo(int errorCode) { @DrainAction private int codecDrainAction; private boolean codecReceivedBuffers; private boolean codecReceivedEos; + private boolean codecHasOutputMediaFormat; private long largestQueuedPresentationTimeUs; private long lastBufferInStreamPresentationTimeUs; private boolean inputStreamEnded; @@ -838,6 +840,7 @@ protected boolean flushOrReleaseCodec() { } if (codecDrainAction == DRAIN_ACTION_REINITIALIZE || codecNeedsFlushWorkaround + || (codecNeedsSosFlushWorkaround && !codecHasOutputMediaFormat) || (codecNeedsEosFlushWorkaround && codecReceivedEos)) { releaseCodec(); return true; @@ -889,11 +892,13 @@ protected void resetCodecStateForRelease() { availableCodecInfos = null; codecInfo = null; codecFormat = null; + codecHasOutputMediaFormat = false; codecOperatingRate = CODEC_OPERATING_RATE_UNSET; codecAdaptationWorkaroundMode = ADAPTATION_WORKAROUND_MODE_NEVER; codecNeedsReconfigureWorkaround = false; codecNeedsDiscardToSpsWorkaround = false; codecNeedsFlushWorkaround = false; + codecNeedsSosFlushWorkaround = false; codecNeedsEosFlushWorkaround = false; codecNeedsEosOutputExceptionWorkaround = false; codecNeedsMonoChannelCountWorkaround = false; @@ -1084,6 +1089,7 @@ private void initCodec(MediaCodecInfo codecInfo, MediaCrypto crypto) throws Exce codecNeedsReconfigureWorkaround = codecNeedsReconfigureWorkaround(codecName); codecNeedsDiscardToSpsWorkaround = codecNeedsDiscardToSpsWorkaround(codecName, codecFormat); codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName); + codecNeedsSosFlushWorkaround = codecNeedsSosFlushWorkaround(codecName); codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName); codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName); codecNeedsMonoChannelCountWorkaround = @@ -1738,6 +1744,7 @@ private boolean drainOutputBuffer(long positionUs, long elapsedRealtimeUs) /** Processes a new output {@link MediaFormat}. */ private void processOutputMediaFormat() throws ExoPlaybackException { + codecHasOutputMediaFormat = true; MediaFormat mediaFormat = codecAdapter.getOutputFormat(); if (codecAdaptationWorkaroundMode != ADAPTATION_WORKAROUND_MODE_NEVER && mediaFormat.getInteger(MediaFormat.KEY_WIDTH) == ADAPTATION_WORKAROUND_SLICE_WIDTH_HEIGHT @@ -2139,4 +2146,21 @@ private static boolean codecNeedsMonoChannelCountWorkaround(String name, Format return Util.SDK_INT <= 18 && format.channelCount == 1 && "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); + } }