summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--media/java/android/media/MediaCodecInfo.java64
1 files changed, 62 insertions, 2 deletions
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index f42fab74631f..76d36a09b592 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -16,6 +16,8 @@
package android.media;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.util.Log;
import android.util.Pair;
import android.util.Range;
@@ -1003,6 +1005,7 @@ public final class MediaCodecInfo {
private Range<Rational> mAspectRatioRange;
private Range<Rational> mBlockAspectRatioRange;
private Range<Long> mBlocksPerSecondRange;
+ private Map<Size, Range<Long>> mMeasuredFrameRates;
private Range<Integer> mFrameRateRange;
private int mBlockWidth;
@@ -1195,6 +1198,28 @@ public final class MediaCodecInfo {
(double) mFrameRateRange.getUpper()));
}
+ @NonNull
+ private Size findClosestSize(int width, int height) {
+ int targetPixels = width * height;
+ Size closestSize = null;
+ int mimPixelsDiff = Integer.MAX_VALUE;
+ for (Size size : mMeasuredFrameRates.keySet()) {
+ int pixelsDiff = Math.abs(targetPixels - size.getWidth() * size.getHeight());
+ if (pixelsDiff < mimPixelsDiff) {
+ mimPixelsDiff = pixelsDiff;
+ closestSize = size;
+ }
+ }
+ return closestSize;
+ }
+
+ private Range<Double> estimateFrameRatesFor(int width, int height) {
+ Size size = findClosestSize(width, height);
+ Range<Long> range = mMeasuredFrameRates.get(size);
+ Double ratio = (double)(width * height) / (size.getWidth() * size.getHeight());
+ return Range.create(range.getLower() * ratio, range.getUpper() * ratio);
+ }
+
/**
* Returns the range of achievable video frame rates for a video size.
* May return {@code null}, if the codec did not publish any measurement
@@ -1208,12 +1233,18 @@ public final class MediaCodecInfo {
*
* @throws IllegalArgumentException if the video size is not supported.
*/
+ @Nullable
public Range<Double> getAchievableFrameRatesFor(int width, int height) {
if (!supports(width, height, null)) {
throw new IllegalArgumentException("unsupported size");
}
- // TODO: get this data from the codec
- return null;
+
+ if (mMeasuredFrameRates == null || mMeasuredFrameRates.size() <= 0) {
+ Log.w(TAG, "Codec did not publish any measurement data.");
+ return null;
+ }
+
+ return estimateFrameRatesFor(width, height);
}
/**
@@ -1346,6 +1377,34 @@ public final class MediaCodecInfo {
mSmallerDimensionUpperLimit = SIZE_RANGE.getUpper();
}
+ private Map<Size, Range<Long>> getMeasuredFrameRates(Map<String, Object> map) {
+ Map<Size, Range<Long>> ret = new HashMap<Size, Range<Long>>();
+ final String prefix = "measured-frame-rate-";
+ Set<String> keys = map.keySet();
+ for (String key : keys) {
+ // looking for: measured-frame-rate-WIDTHxHEIGHT-range
+ if (!key.startsWith(prefix)) {
+ continue;
+ }
+ String subKey = key.substring(prefix.length());
+ String[] temp = key.split("-");
+ if (temp.length != 5) {
+ continue;
+ }
+ String sizeStr = temp[3];
+ Size size = Utils.parseSize(sizeStr, null);
+ if (size == null || size.getWidth() * size.getHeight() <= 0) {
+ continue;
+ }
+ Range<Long> range = Utils.parseLongRange(map.get(key), null);
+ if (range == null || range.getLower() < 0 || range.getUpper() < 0) {
+ continue;
+ }
+ ret.put(size, range);
+ }
+ return ret;
+ }
+
private void parseFromInfo(MediaFormat info) {
final Map<String, Object> map = info.getMap();
Size blockSize = new Size(mBlockWidth, mBlockHeight);
@@ -1360,6 +1419,7 @@ public final class MediaCodecInfo {
counts = Utils.parseIntRange(map.get("block-count-range"), null);
blockRates =
Utils.parseLongRange(map.get("blocks-per-second-range"), null);
+ mMeasuredFrameRates = getMeasuredFrameRates(map);
{
Object o = map.get("size-range");
Pair<Size, Size> sizeRange = Utils.parseSizeRange(o);