diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 84c933c52c..6af3381a34 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -16,6 +16,8 @@ ([#5784](https://github.com/google/ExoPlayer/issues/5784)). * Add a workaround for a decoder failure on ZTE Axon7 mini devices when playing 48kHz audio ([#5821](https://github.com/google/ExoPlayer/issues/5821)). +* Add a workaround for broken raw audio decoding on Oppo R9 + ([#5782](https://github.com/google/ExoPlayer/issues/5782)). ### 2.10.0 ### 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 08ba94f257..e79c776f88 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 @@ -51,13 +51,13 @@ public final class MediaCodecInfo { public final String name; /** The MIME type handled by the codec, or {@code null} if this is a passthrough codec. */ - public final @Nullable String mimeType; + @Nullable public final String mimeType; /** - * The capabilities of the decoder, like the profiles/levels it supports, or {@code null} if this - * is a passthrough codec. + * The capabilities of the decoder, like the profiles/levels it supports, or {@code null} if not + * known. */ - public final @Nullable CodecCapabilities capabilities; + @Nullable public final CodecCapabilities capabilities; /** * Whether the decoder supports seamless resolution switches. @@ -109,11 +109,12 @@ public final class MediaCodecInfo { * * @param name The name of the {@link MediaCodec}. * @param mimeType A mime type supported by the {@link MediaCodec}. - * @param capabilities The capabilities of the {@link MediaCodec} for the specified mime type. + * @param capabilities The capabilities of the {@link MediaCodec} for the specified mime type, or + * {@code null} if not known. * @return The created instance. */ - public static MediaCodecInfo newInstance(String name, String mimeType, - CodecCapabilities capabilities) { + public static MediaCodecInfo newInstance( + String name, String mimeType, @Nullable CodecCapabilities capabilities) { return new MediaCodecInfo( name, mimeType, @@ -128,7 +129,8 @@ public final class MediaCodecInfo { * * @param name The name of the {@link MediaCodec}. * @param mimeType A mime type supported by the {@link MediaCodec}. - * @param capabilities The capabilities of the {@link MediaCodec} for the specified mime type. + * @param capabilities The capabilities of the {@link MediaCodec} for the specified mime type, or + * {@code null} if not known. * @param forceDisableAdaptive Whether {@link #adaptive} should be forced to {@code false}. * @param forceSecure Whether {@link #secure} should be forced to {@code true}. * @return The created instance. @@ -136,7 +138,7 @@ public final class MediaCodecInfo { public static MediaCodecInfo newInstance( String name, String mimeType, - CodecCapabilities capabilities, + @Nullable CodecCapabilities capabilities, boolean forceDisableAdaptive, boolean forceSecure) { return new MediaCodecInfo( diff --git a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java index f275dfe7d7..f3936e5dc2 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/mediacodec/MediaCodecUtil.java @@ -504,6 +504,16 @@ public final class MediaCodecUtil { */ private static void applyWorkarounds(String mimeType, List decoderInfos) { if (MimeTypes.AUDIO_RAW.equals(mimeType)) { + if (Util.SDK_INT < 26 + && Util.DEVICE.equals("R9") + && decoderInfos.size() == 1 + && decoderInfos.get(0).name.equals("OMX.MTK.AUDIO.DECODER.RAW")) { + // This device does not list a generic raw audio decoder, yet it can be instantiated by + // name. See Issue #5782. + decoderInfos.add( + MediaCodecInfo.newInstance( + "OMX.google.raw.decoder", MimeTypes.AUDIO_RAW, /* capabilities= */ null)); + } // Work around inconsistent raw audio decoding behavior across different devices. sortByScore( decoderInfos, diff --git a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/EnumerateDecodersTest.java b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/EnumerateDecodersTest.java index d256db8c30..e9d856015e 100644 --- a/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/EnumerateDecodersTest.java +++ b/playbacktests/src/androidTest/java/com/google/android/exoplayer2/playbacktests/gts/EnumerateDecodersTest.java @@ -20,12 +20,12 @@ import android.media.MediaCodecInfo.AudioCapabilities; import android.media.MediaCodecInfo.CodecCapabilities; import android.media.MediaCodecInfo.CodecProfileLevel; import android.media.MediaCodecInfo.VideoCapabilities; +import androidx.annotation.Nullable; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.mediacodec.MediaCodecInfo; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil; import com.google.android.exoplayer2.mediacodec.MediaCodecUtil.DecoderQueryException; import com.google.android.exoplayer2.testutil.MetricsLogger; -import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.Util; import java.util.Arrays; @@ -93,14 +93,17 @@ public class EnumerateDecodersTest { List mediaCodecInfos = MediaCodecUtil.getDecoderInfos(mimeType, secure, tunneling); for (MediaCodecInfo mediaCodecInfo : mediaCodecInfos) { - CodecCapabilities capabilities = Assertions.checkNotNull(mediaCodecInfo.capabilities); + CodecCapabilities capabilities = mediaCodecInfo.capabilities; metricsLogger.logMetric( "capabilities_" + mediaCodecInfo.name, codecCapabilitiesToString(mimeType, capabilities)); } } private static String codecCapabilitiesToString( - String requestedMimeType, CodecCapabilities codecCapabilities) { + String requestedMimeType, @Nullable CodecCapabilities codecCapabilities) { + if (codecCapabilities == null) { + return "[null]"; + } boolean isVideo = MimeTypes.isVideo(requestedMimeType); boolean isAudio = MimeTypes.isAudio(requestedMimeType); StringBuilder result = new StringBuilder();