summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt6
-rw-r--r--media/java/android/media/MediaCodecInfo.java104
2 files changed, 80 insertions, 30 deletions
diff --git a/api/current.txt b/api/current.txt
index 673d90fc236f..7e956264ab29 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24538,7 +24538,9 @@ package android.media {
}
public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint {
+ ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int);
method public boolean covers(@NonNull android.media.MediaFormat);
+ method public boolean covers(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint);
field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_100;
field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_120;
field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_200;
@@ -24573,8 +24575,8 @@ package android.media {
field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_50;
field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_60;
field public final int frameRate;
- field public final int height;
- field public final int width;
+ field public final long macroBlockRate;
+ field public final int macroBlocks;
}
public final class MediaCodecList {
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 572c5f4b3e67..4bc3897c4477 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1614,29 +1614,59 @@ public final class MediaCodecInfo {
}
/**
- * Video performance points are a set of standard performance points defined by pixel rate.
+ * Video performance points are a set of standard performance points defined by number of
+ * pixels, pixel rate and frame rate. Performance point represents an upper bound. This
+ * means that it covers all performance points with fewer pixels, pixel rate and frame
+ * rate.
*/
public static final class PerformancePoint {
/**
- * Frame width in pixels.
+ * (Maximum) number of macroblocks in the frame.
+ *
+ * Video frames are conceptually divided into 16-by-16 pixel blocks called macroblocks.
+ * Most coding standards operate on these 16-by-16 pixel blocks; thus, codec performance
+ * is characterized using such blocks.
*/
- public final int width;
+ public final int macroBlocks;
/**
- * Frame height in pixels.
+ * (Maximum) frame rate in frames per second.
*/
- public final int height;
+ public final int frameRate;
/**
- * Frame rate in frames per second.
+ * (Maximum) number of macroblocks processed per second.
*/
- public final int frameRate;
+ public final long macroBlockRate;
/* package private */
- PerformancePoint(int width_, int height_, int frameRate_) {
- width = width_;
- height = height_;
- frameRate = frameRate_;
+ PerformancePoint(int width_, int height_, int frameRate_, int maxFrameRate_) {
+ macroBlocks = saturateLongToInt(
+ ((Math.max(1, (long)width_) + 15) / 16)
+ * ((Math.max(1, (long)height_) + 15) / 16));
+ frameRate = Math.max(1, frameRate_);
+ macroBlockRate = Math.max(maxFrameRate_, frameRate) * macroBlocks;
+ }
+
+ /**
+ * Create a performance point for a given frame size and frame rate.
+ *
+ * @param width_ width of the frame in pixels
+ * @param height_ height of the frame in pixels
+ * @param frameRate_ frame rate in frames per second
+ */
+ public PerformancePoint(int width_, int height_, int frameRate_) {
+ this(width_, height_, frameRate_, frameRate_ /* maxFrameRate */);
+ }
+
+ private int saturateLongToInt(long value) {
+ if (value < Integer.MIN_VALUE) {
+ return Integer.MIN_VALUE;
+ } else if (value > Integer.MAX_VALUE) {
+ return Integer.MAX_VALUE;
+ } else {
+ return (int)value;
+ }
}
/**
@@ -1647,26 +1677,40 @@ public final class MediaCodecInfo {
* @return {@code true} if the performance point covers the format.
*/
public boolean covers(@NonNull MediaFormat format) {
- // for simplicity, this code assumes a 16x16 block size.
- long macroBlocks = ((width + 15) / 16) * (long)((height + 15) / 16);
- long mbps = macroBlocks * frameRate;
+ PerformancePoint other = new PerformancePoint(
+ format.getInteger(MediaFormat.KEY_WIDTH, 0),
+ format.getInteger(MediaFormat.KEY_HEIGHT, 0),
+ // safely convert ceil(double) to int through float case and Math.round
+ Math.round((float)(
+ Math.ceil(format.getNumber(MediaFormat.KEY_FRAME_RATE, 0)
+ .doubleValue()))));
+ return covers(other);
+ }
- long formatMacroBlocks =
- (long)((format.getInteger(MediaFormat.KEY_WIDTH, 0) + 15) / 16)
- * ((format.getInteger(MediaFormat.KEY_HEIGHT, 0) + 15) / 16);
- double formatMbps =
- Math.ceil(formatMacroBlocks
- * format.getNumber(MediaFormat.KEY_FRAME_RATE, 0).doubleValue());
- return formatMacroBlocks > 0 && formatMacroBlocks <= macroBlocks
- && formatMbps <= mbps;
+ /**
+ * Checks whether the performance point covers another performance point. Use this
+ * method to determine if a performance point advertised by a codec covers the
+ * performance point required. This method can also be used for lose ordering as this
+ * method is transitive.
+ *
+ * @param other other performance point considered
+ *
+ * @return {@code true} if the performance point covers the other.
+ */
+ public boolean covers(@NonNull PerformancePoint other) {
+ return (macroBlocks >= other.macroBlocks
+ && frameRate >= other.frameRate
+ && macroBlockRate >= other.macroBlockRate);
}
+
@Override
public boolean equals(Object o) {
if (o instanceof PerformancePoint) {
PerformancePoint other = (PerformancePoint)o;
- return ((long)width * height) == ((long)other.width * other.height)
- && frameRate == other.frameRate;
+ return (macroBlocks == other.macroBlocks
+ && frameRate == other.frameRate
+ && macroBlockRate == other.macroBlockRate);
}
return false;
}
@@ -1931,7 +1975,8 @@ public final class MediaCodecInfo {
continue;
}
ret.add(new PerformancePoint(
- size.getWidth(), size.getHeight(), range.getLower().intValue()));
+ size.getWidth(), size.getHeight(), range.getLower().intValue(),
+ range.getUpper().intValue()));
}
// check if the component specified no performance point indication
if (ret.size() == 0) {
@@ -1939,9 +1984,12 @@ public final class MediaCodecInfo {
}
// sort reversed by area first, then by frame rate
- ret.sort((a, b) -> (a.width * a.height != b.width * b.height ?
- (b.width * b.height - a.width * a.height) :
- (b.frameRate - a.frameRate)));
+ ret.sort((a, b) -> -((a.macroBlocks != b.macroBlocks) ?
+ (a.macroBlocks < b.macroBlocks ? -1 : 1) :
+ (a.macroBlockRate != b.macroBlockRate) ?
+ (a.macroBlockRate < b.macroBlockRate ? -1 : 1) :
+ (a.frameRate != b.frameRate) ?
+ (a.frameRate < b.frameRate ? -1 : 1) : 0));
return ret;
}