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 abab90182b01..a86001e3eab3 100644 --- a/api/current.txt +++ b/api/current.txt @@ -24535,7 +24535,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; @@ -24570,8 +24572,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 751d57bbdc81..7ade0c4bc586 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;          }  |