Merge "media: add macroblockrate to PerformancePoint"

This commit is contained in:
Lajos Molnar
2019-02-08 23:29:38 +00:00
committed by Android (Google) Code Review
2 changed files with 83 additions and 33 deletions

View File

@@ -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 {

View File

@@ -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.
*/
public final int height;
/**
* Frame rate in frames per second.
* (Maximum) frame rate in frames per second.
*/
public final int frameRate;
/**
* (Maximum) number of macroblocks processed per second.
*/
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;
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;
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);
}
/**
* 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;
}