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 745cdc5474..72733a90e9 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 @@ -28,6 +28,7 @@ import static androidx.media3.exoplayer.DecoderReuseEvaluation.REUSE_RESULT_NO; import static androidx.media3.exoplayer.DecoderReuseEvaluation.REUSE_RESULT_YES_WITHOUT_RECONFIGURATION; import static androidx.media3.exoplayer.DecoderReuseEvaluation.REUSE_RESULT_YES_WITH_FLUSH; import static androidx.media3.exoplayer.DecoderReuseEvaluation.REUSE_RESULT_YES_WITH_RECONFIGURATION; +import static java.lang.annotation.ElementType.TYPE_USE; import android.graphics.Point; import android.media.MediaCodec; @@ -35,7 +36,10 @@ import android.media.MediaCodecInfo.AudioCapabilities; import android.media.MediaCodecInfo.CodecCapabilities; import android.media.MediaCodecInfo.CodecProfileLevel; import android.media.MediaCodecInfo.VideoCapabilities; +import android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint; import android.util.Pair; +import androidx.annotation.DoNotInline; +import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.annotation.VisibleForTesting; @@ -48,6 +52,11 @@ import androidx.media3.common.util.Util; import androidx.media3.exoplayer.DecoderReuseEvaluation; import androidx.media3.exoplayer.DecoderReuseEvaluation.DecoderDiscardReasons; import androidx.media3.exoplayer.DecoderReuseEvaluation.DecoderReuseResult; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.List; /** Information about a {@link MediaCodec} for a given mime type. */ @SuppressWarnings("InlinedApi") @@ -482,8 +491,6 @@ public final class MediaCodecInfo { /** * Whether the decoder supports video with a given width, height and frame rate. * - *
Must not be called if the device SDK version is less than 21.
- *
* @param width Width in pixels.
* @param height Height in pixels.
* @param frameRate Optional frame rate in frames per second. Ignored if set to {@link
@@ -501,14 +508,28 @@ public final class MediaCodecInfo {
logNoSupport("sizeAndRate.vCaps");
return false;
}
+
+ if (Util.SDK_INT >= 29) {
+ @PerformancePointCoverageResult
+ int evaluation =
+ Api29.areResolutionAndFrameRateCovered(videoCapabilities, width, height, frameRate);
+ if (evaluation == COVERAGE_RESULT_YES) {
+ return true;
+ } else if (evaluation == COVERAGE_RESULT_NO) {
+ logNoSupport("sizeAndRate.cover, " + width + "x" + height + "@" + frameRate);
+ return false;
+ }
+ // COVERAGE_RESULT_NO_EMPTY_LIST falls through to API 21+ code below
+ }
+
if (!areSizeAndRateSupportedV21(videoCapabilities, width, height, frameRate)) {
if (width >= height
|| !needsRotatedVerticalResolutionWorkaround(name)
|| !areSizeAndRateSupportedV21(videoCapabilities, height, width, frameRate)) {
- logNoSupport("sizeAndRate.support, " + width + "x" + height + "x" + frameRate);
+ logNoSupport("sizeAndRate.support, " + width + "x" + height + "@" + frameRate);
return false;
}
- logAssumedSupport("sizeAndRate.rotated, " + width + "x" + height + "x" + frameRate);
+ logAssumedSupport("sizeAndRate.rotated, " + width + "x" + height + "@" + frameRate);
}
return true;
}
@@ -844,4 +865,47 @@ public final class MediaCodecInfo {
&& CodecProfileLevel.HEVCProfileMain10 == profile
&& ("sailfish".equals(Util.DEVICE) || "marlin".equals(Util.DEVICE));
}
+
+ /** Possible outcomes of evaluating PerformancePoint coverage */
+ @Documented
+ @Retention(RetentionPolicy.SOURCE)
+ @Target(TYPE_USE)
+ @IntDef({COVERAGE_RESULT_YES, COVERAGE_RESULT_NO, COVERAGE_RESULT_NO_EMPTY_LIST})
+ private @interface PerformancePointCoverageResult {}
+
+ /** The decoder has a PerformancePoint that covers the resolution and frame rate */
+ private static final int COVERAGE_RESULT_YES = 2;
+ /**
+ * The decoder has at least one PerformancePoint, but none of them cover the resolution and frame
+ * rate
+ */
+ private static final int COVERAGE_RESULT_NO = 1;
+ /** The VideoCapabilities does not contain any PerformancePoints */
+ private static final int COVERAGE_RESULT_NO_EMPTY_LIST = 0;
+
+ @RequiresApi(29)
+ private static final class Api29 {
+ @DoNotInline
+ public static @PerformancePointCoverageResult int areResolutionAndFrameRateCovered(
+ VideoCapabilities videoCapabilities, int width, int height, double frameRate) {
+ List