diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java index ced56b53f3..90f9517a8d 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecInfo.java @@ -393,9 +393,11 @@ public final class MediaCodecInfo { && (adaptive || (oldFormat.width == newFormat.width && oldFormat.height == newFormat.height)) && Util.areEqual(oldFormat.colorInfo, newFormat.colorInfo)) { - return oldFormat.initializationDataEquals(newFormat) - ? KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION - : KEEP_CODEC_RESULT_YES_WITH_RECONFIGURATION; + if (oldFormat.initializationDataEquals(newFormat)) { + return KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION; + } else if (!needsAdaptationReconfigureWorkaround(name)) { + return KEEP_CODEC_RESULT_YES_WITH_RECONFIGURATION; + } } } else { if (oldFormat.channelCount != newFormat.channelCount @@ -423,11 +425,8 @@ public final class MediaCodecInfo { } } - // For Opus, we don't flush and reuse the codec because the decoder may discard samples after - // flushing, which would result in audio being dropped just after a stream change (see - // [Internal: b/143450854]). For other formats, we allow reuse after flushing if the codec - // initialization data is unchanged. - if (!MimeTypes.AUDIO_OPUS.equals(mimeType) && oldFormat.initializationDataEquals(newFormat)) { + if (oldFormat.initializationDataEquals(newFormat) + && !needsAdaptationFlushWorkaround(mimeType)) { return KEEP_CODEC_RESULT_YES_WITH_FLUSH; } } @@ -459,7 +458,7 @@ public final class MediaCodecInfo { } if (!areSizeAndRateSupportedV21(videoCapabilities, width, height, frameRate)) { if (width >= height - || !enableRotatedVerticalResolutionWorkaround(name) + || !needsRotatedVerticalResolutionWorkaround(name) || !areSizeAndRateSupportedV21(videoCapabilities, height, width, frameRate)) { logNoSupport("sizeAndRate.support, " + width + "x" + height + "x" + frameRate); return false; @@ -654,6 +653,33 @@ public final class MediaCodecInfo { return capabilities.getMaxSupportedInstances(); } + /** + * Returns whether the decoder is known to fail when an attempt is made to reconfigure it with a + * new format's configuration data. + * + * @param name The name of the decoder. + * @return Whether the decoder is known to fail when an attempt is made to reconfigure it with a + * new format's configuration data. + */ + private static boolean needsAdaptationReconfigureWorkaround(String name) { + return Util.MODEL.startsWith("SM-T230") && "OMX.MARVELL.VIDEO.HW.CODA7542DECODER".equals(name); + } + + /** + * Returns whether the decoder is known to behave incorrectly if flushed to adapt to a new format. + * + * @param mimeType The name of the MIME type. + * @return Whether the decoder is known to to behave incorrectly if flushed to adapt to a new + * format. + */ + private static boolean needsAdaptationFlushWorkaround(String mimeType) { + // For Opus, we don't flush and reuse the codec because the decoder may discard samples after + // flushing, which would result in audio being dropped just after a stream change (see + // [Internal: b/143450854]). For other formats, we allow reuse after flushing if the codec + // initialization data is unchanged. + return MimeTypes.AUDIO_OPUS.equals(mimeType); + } + /** * Capabilities are known to be inaccurately reported for vertical resolutions on some devices. * [Internal ref: b/31387661]. When this workaround is enabled, we also check whether the @@ -663,7 +689,7 @@ public final class MediaCodecInfo { * @param name The name of the codec. * @return Whether to enable the workaround. */ - private static final boolean enableRotatedVerticalResolutionWorkaround(String name) { + private static final boolean needsRotatedVerticalResolutionWorkaround(String name) { if ("OMX.MTK.VIDEO.DECODER.HEVC".equals(name) && "mcv5a".equals(Util.DEVICE)) { // See https://github.com/google/ExoPlayer/issues/6612. return false; 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 a29de96ceb..987a556345 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 @@ -316,7 +316,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { @Nullable private DecoderInitializationException preferredDecoderInitializationException; @Nullable private MediaCodecInfo codecInfo; @AdaptationWorkaroundMode private int codecAdaptationWorkaroundMode; - private boolean codecNeedsReconfigureWorkaround; private boolean codecNeedsDiscardToSpsWorkaround; private boolean codecNeedsFlushWorkaround; private boolean codecNeedsSosFlushWorkaround; @@ -894,7 +893,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { codecHasOutputMediaFormat = false; codecOperatingRate = CODEC_OPERATING_RATE_UNSET; codecAdaptationWorkaroundMode = ADAPTATION_WORKAROUND_MODE_NEVER; - codecNeedsReconfigureWorkaround = false; codecNeedsDiscardToSpsWorkaround = false; codecNeedsFlushWorkaround = false; codecNeedsSosFlushWorkaround = false; @@ -1085,7 +1083,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { this.codecOperatingRate = codecOperatingRate; codecInputFormat = inputFormat; codecAdaptationWorkaroundMode = codecAdaptationWorkaroundMode(codecName); - codecNeedsReconfigureWorkaround = codecNeedsReconfigureWorkaround(codecName); codecNeedsDiscardToSpsWorkaround = codecNeedsDiscardToSpsWorkaround(codecName, codecInputFormat); codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName); @@ -1428,21 +1425,17 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } break; case KEEP_CODEC_RESULT_YES_WITH_RECONFIGURATION: - if (codecNeedsReconfigureWorkaround) { - drainAndReinitializeCodec(); - } else { - codecReconfigured = true; - codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING; - codecNeedsAdaptationWorkaroundBuffer = - codecAdaptationWorkaroundMode == ADAPTATION_WORKAROUND_MODE_ALWAYS - || (codecAdaptationWorkaroundMode == ADAPTATION_WORKAROUND_MODE_SAME_RESOLUTION - && newFormat.width == codecInputFormat.width - && newFormat.height == codecInputFormat.height); - codecInputFormat = newFormat; - updateCodecOperatingRate(); - if (drainAndUpdateCodecDrmSession) { - drainAndUpdateCodecDrmSessionV23(); - } + codecReconfigured = true; + codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING; + codecNeedsAdaptationWorkaroundBuffer = + codecAdaptationWorkaroundMode == ADAPTATION_WORKAROUND_MODE_ALWAYS + || (codecAdaptationWorkaroundMode == ADAPTATION_WORKAROUND_MODE_SAME_RESOLUTION + && newFormat.width == codecInputFormat.width + && newFormat.height == codecInputFormat.height); + codecInputFormat = newFormat; + updateCodecOperatingRate(); + if (drainAndUpdateCodecDrmSession) { + drainAndUpdateCodecDrmSessionV23(); } break; case KEEP_CODEC_RESULT_YES_WITHOUT_RECONFIGURATION: @@ -2244,21 +2237,6 @@ public abstract class MediaCodecRenderer extends BaseRenderer { } } - /** - * Returns whether the decoder is known to fail when an attempt is made to reconfigure it with a - * new format's configuration data. - * - *

When enabled, the workaround will always release and recreate the decoder, rather than - * attempting to reconfigure the existing instance. - * - * @param name The name of the decoder. - * @return True if the decoder is known to fail when an attempt is made to reconfigure it with a - * new format's configuration data. - */ - private static boolean codecNeedsReconfigureWorkaround(String name) { - return Util.MODEL.startsWith("SM-T230") && "OMX.MARVELL.VIDEO.HW.CODA7542DECODER".equals(name); - } - /** * Returns whether the decoder is an H.264/AVC decoder known to fail if NAL units are queued * before the codec specific data.