diff options
| -rw-r--r-- | api/current.txt | 6 | ||||
| -rw-r--r-- | media/java/android/media/MediaCodecInfo.java | 104 |
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; } |