Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 338ca88c authored by Lajos Molnar's avatar Lajos Molnar
Browse files

media: add macroblockrate to PerformancePoint

- also add a constructor so apps can create their performance points
- remove width and height as they are not by themselves meaningful
  (only their product)
- document that we are using macroblocks

Bug: 124061036
Change-Id: I70ff9f059859b83397ba484b9ea9215d1d2751ef
parent 40bfe83c
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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 {
+76 −28
Original line number Diff line number Diff line
@@ -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;
        }