Loading media/java/android/media/MediaCodecInfo.java +62 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading @@ -1208,14 +1233,20 @@ 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 if (mMeasuredFrameRates == null || mMeasuredFrameRates.size() <= 0) { Log.w(TAG, "Codec did not publish any measurement data."); return null; } return estimateFrameRatesFor(width, height); } /** * Returns whether a given video size ({@code width} and * {@code height}) and {@code frameRate} combination is supported. Loading Loading @@ -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); Loading @@ -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); Loading Loading
media/java/android/media/MediaCodecInfo.java +62 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading @@ -1208,14 +1233,20 @@ 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 if (mMeasuredFrameRates == null || mMeasuredFrameRates.size() <= 0) { Log.w(TAG, "Codec did not publish any measurement data."); return null; } return estimateFrameRatesFor(width, height); } /** * Returns whether a given video size ({@code width} and * {@code height}) and {@code frameRate} combination is supported. Loading Loading @@ -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); Loading @@ -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); Loading