diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecInfo.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecInfo.java index 6dfda947802..00fd12eeeff 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecInfo.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/mediacodec/MediaCodecInfo.java @@ -494,6 +494,17 @@ public DecoderReuseEvaluation canReuseCodec(Format oldFormat, Format newFormat) } } + // For eac3 and eac3-joc formats, adaptation is possible without reconfiguration or flushing. + if (discardReasons == 0 && (MimeTypes.AUDIO_E_AC3_JOC.equals(mimeType) + || MimeTypes.AUDIO_E_AC3.equals(mimeType))) { + return new DecoderReuseEvaluation( + name, + oldFormat, + newFormat, + REUSE_RESULT_YES_WITHOUT_RECONFIGURATION, + /* discardReasons= */ 0); + } + if (!oldFormat.initializationDataEquals(newFormat)) { discardReasons |= DISCARD_REASON_INITIALIZATION_DATA_CHANGED; } diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/mediacodec/MediaCodecInfoTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/mediacodec/MediaCodecInfoTest.java index 5be91270249..8ba0257c46b 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/mediacodec/MediaCodecInfoTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/mediacodec/MediaCodecInfoTest.java @@ -16,6 +16,8 @@ package androidx.media3.exoplayer.mediacodec; import static androidx.media3.common.MimeTypes.AUDIO_AAC; +import static androidx.media3.common.MimeTypes.AUDIO_E_AC3; +import static androidx.media3.common.MimeTypes.AUDIO_E_AC3_JOC; import static androidx.media3.common.MimeTypes.VIDEO_AV1; import static androidx.media3.common.MimeTypes.VIDEO_H264; import static androidx.media3.exoplayer.DecoderReuseEvaluation.DISCARD_REASON_AUDIO_CHANNEL_COUNT_CHANGED; @@ -73,6 +75,24 @@ public final class MediaCodecInfoTest { .setInitializationData(ImmutableList.of(new byte[] {4, 4, 1, 0, 0})) .build(); + private static final Format FORMAT_EAC3 = + new Format.Builder() + .setSampleMimeType(AUDIO_E_AC3) + .setChannelCount(6) + .setSampleRate(48000) + .setAverageBitrate(5000) + .setInitializationData(ImmutableList.of(new byte[] {4, 4, 1, 0, 0})) + .build(); + + private static final Format FORMAT_EAC3JOC = + new Format.Builder() + .setSampleMimeType(AUDIO_E_AC3_JOC) + .setChannelCount(12) + .setSampleRate(48000) + .setAverageBitrate(5000) + .setInitializationData(ImmutableList.of(new byte[] {4, 4, 1, 0, 0})) + .build(); + @Test public void canReuseCodec_withDifferentMimeType_returnsNo() { MediaCodecInfo codecInfo = buildH264CodecInfo(/* adaptive= */ true); @@ -299,6 +319,43 @@ public void canReuseCodec_audioWithDifferentInitializationData_returnsNo() { DISCARD_REASON_INITIALIZATION_DATA_CHANGED)); } + @Test + public void canReuseCodec_eac3_returnsYesWithoutReconfiguration() { + MediaCodecInfo codecInfo = buildEac3CodecInfo(); + + Format variantFormat = + FORMAT_EAC3 + .buildUpon() + .setInitializationData(ImmutableList.of(new byte[] {0})) + .build(); + assertThat(codecInfo.canReuseCodec(FORMAT_EAC3, variantFormat)) + .isEqualTo( + new DecoderReuseEvaluation( + codecInfo.name, + FORMAT_EAC3, + variantFormat, + DecoderReuseEvaluation.REUSE_RESULT_YES_WITHOUT_RECONFIGURATION, + /* discardReasons= */ 0)); + } + @Test + public void canReuseCodec_eac3joc_returnsYesWithoutReconfiguration() { + MediaCodecInfo codecInfo = buildEac3JocCodecInfo(); + + Format variantFormat = + FORMAT_EAC3JOC + .buildUpon() + .setInitializationData(ImmutableList.of(new byte[] {0})) + .build(); + assertThat(codecInfo.canReuseCodec(FORMAT_EAC3JOC, variantFormat)) + .isEqualTo( + new DecoderReuseEvaluation( + codecInfo.name, + FORMAT_EAC3JOC, + variantFormat, + DecoderReuseEvaluation.REUSE_RESULT_YES_WITHOUT_RECONFIGURATION, + /* discardReasons= */ 0)); + } + private static MediaCodecInfo buildH264CodecInfo(boolean adaptive) { return new MediaCodecInfo( "h264", @@ -329,6 +386,36 @@ private static MediaCodecInfo buildAacCodecInfo() { /* detachedSurfaceSupported= */ false); } + private static MediaCodecInfo buildEac3CodecInfo() { + return new MediaCodecInfo( + "eac3joc", + AUDIO_E_AC3, + AUDIO_E_AC3, + /* capabilities= */ null, + /* hardwareAccelerated= */ false, + /* softwareOnly= */ true, + /* vendor= */ true, + /* adaptive= */ false, + /* tunneling= */ false, + /* secure= */ false, + /* detachedSurfaceSupported= */ false); + } + + private static MediaCodecInfo buildEac3JocCodecInfo() { + return new MediaCodecInfo( + "eac3joc", + AUDIO_E_AC3_JOC, + AUDIO_E_AC3_JOC, + /* capabilities= */ null, + /* hardwareAccelerated= */ false, + /* softwareOnly= */ true, + /* vendor= */ true, + /* adaptive= */ false, + /* tunneling= */ false, + /* secure= */ false, + /* detachedSurfaceSupported= */ false); + } + private static ColorInfo buildHdrColorInfo(@C.ColorSpace int colorSpace) { return new ColorInfo.Builder() .setColorSpace(colorSpace)