Change areSizeAndRateSupported to use PerfomancePoint.covers

PiperOrigin-RevId: 482461219
(cherry picked from commit b9c945459820ae264670aa2548fc747bb9402e97)
This commit is contained in:
michaelkatz 2022-10-20 12:20:14 +00:00 committed by microkatz
parent f10021ff7f
commit f56193bcd7

View File

@ -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.
*
* <p>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<PerformancePoint> performancePointList =
videoCapabilities.getSupportedPerformancePoints();
if (performancePointList == null || performancePointList.isEmpty()) {
return COVERAGE_RESULT_NO_EMPTY_LIST;
}
// Round frame rate down to to avoid situations where a range check in
// covers fails due to slightly exceeding the limits for a standard format
// (e.g., 1080p at 30 fps). [Internal ref: b/134706676]
PerformancePoint targetPerformancePoint =
new PerformancePoint(width, height, (int) frameRate);
for (int i = 0; i < performancePointList.size(); i++) {
if (performancePointList.get(i).covers(targetPerformancePoint)) {
return COVERAGE_RESULT_YES;
}
}
return COVERAGE_RESULT_NO;
}
}
}