diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index c2168f12a3514..e7e83ebb001fd 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -25,6 +25,7 @@ import android.annotation.SuppressLint; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; +import android.os.Process; import android.os.SystemProperties; import android.util.Log; import android.util.Pair; @@ -188,13 +189,14 @@ public final class MediaCodecInfo { // COMMON CONSTANTS private static final Range POSITIVE_INTEGERS = - Range.create(1, Integer.MAX_VALUE); + Range.create(1, Integer.MAX_VALUE); private static final Range POSITIVE_LONGS = - Range.create(1l, Long.MAX_VALUE); + Range.create(1L, Long.MAX_VALUE); private static final Range POSITIVE_RATIONALS = - Range.create(new Rational(1, Integer.MAX_VALUE), - new Rational(Integer.MAX_VALUE, 1)); - private static final Range SIZE_RANGE = Range.create(1, 32768); + Range.create(new Rational(1, Integer.MAX_VALUE), + new Rational(Integer.MAX_VALUE, 1)); + private static final Range SIZE_RANGE = + Process.is64Bit() ? Range.create(1, 32768) : Range.create(1, 4096); private static final Range FRAME_RATE_RANGE = Range.create(0, 960); private static final Range BITRATE_RANGE = Range.create(0, 500000000); private static final int DEFAULT_MAX_SUPPORTED_INSTANCES = 32; @@ -1399,6 +1401,9 @@ public final class MediaCodecInfo { /** * Returns the range of supported video widths. + *

+ * 32-bit processes will not support resolutions larger than 4096x4096 due to + * the limited address space. */ public Range getSupportedWidths() { return mWidthRange; @@ -1406,6 +1411,9 @@ public final class MediaCodecInfo { /** * Returns the range of supported video heights. + *

+ * 32-bit processes will not support resolutions larger than 4096x4096 due to + * the limited address space. */ public Range getSupportedHeights() { return mHeightRange; @@ -1857,6 +1865,10 @@ public final class MediaCodecInfo { && aligned.mMaxMacroBlockRate >= otherAligned.mMaxMacroBlockRate); } + /* package private */ boolean isEqualDimension(@NonNull PerformancePoint other) { + return mWidth == other.mWidth && mHeight == other.mHeight; + } + private @NonNull Size getCommonBlockSize(@NonNull PerformancePoint other) { return new Size( Math.max(mBlockSize.getWidth(), other.mBlockSize.getWidth()) * 16, @@ -1997,6 +2009,9 @@ public final class MediaCodecInfo { * Performance points assume a single active codec. For use cases where multiple * codecs are active, should use that highest pixel count, and add the frame rates of * each individual codec. + *

+ * Supported resolution could be further restricted for 32-bit processes due to + * the limited virtual memory space. */ @Nullable public List getSupportedPerformancePoints() { @@ -2164,6 +2179,12 @@ public final class MediaCodecInfo { if (size == null || size.getWidth() * size.getHeight() <= 0) { continue; } + if (size.getWidth() > SIZE_RANGE.getUpper() + || size.getHeight() > SIZE_RANGE.getUpper()) { + size = new Size( + Math.min(size.getWidth(), SIZE_RANGE.getUpper()), + Math.min(size.getHeight(), SIZE_RANGE.getUpper())); + } Range range = Utils.parseLongRange(map.get(key), null); if (range == null || range.getLower() < 0 || range.getUpper() < 0) { continue; @@ -2193,6 +2214,29 @@ public final class MediaCodecInfo { (a.getMaxMacroBlockRate() < b.getMaxMacroBlockRate() ? -1 : 1) : (a.getMaxFrameRate() != b.getMaxFrameRate()) ? (a.getMaxFrameRate() < b.getMaxFrameRate() ? -1 : 1) : 0)); + + // remove redundant points + for (int i = 1; i < ret.size(); ++i) { + PerformancePoint a = ret.get(i); + for (int j = 0; j < i; ++j) { + PerformancePoint b = ret.get(j); + if (b.isEqualDimension(a) && b.covers(a)) { + ret.set(i, null); + break; + } + } + } + int newSize = 0; + for (int i = 0; i < ret.size(); ++i) { + PerformancePoint a = ret.get(i); + if (a == null) { + continue; + } + ret.set(newSize, a); + ++newSize; + } + ret.setSize(newSize); + return Collections.unmodifiableList(ret); }