summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--media/java/android/media/MediaCodecInfo.java98
-rw-r--r--media/java/android/media/MediaFormat.java10
2 files changed, 103 insertions, 5 deletions
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 87c6d88a0c11..349d67ec9145 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -567,6 +567,34 @@ public final class MediaCodecInfo {
return false;
}
}
+
+ Integer profile = (Integer)map.get(MediaFormat.KEY_PROFILE);
+ Integer level = (Integer)map.get(MediaFormat.KEY_LEVEL);
+
+ if (profile != null) {
+ if (!supportsProfileLevel(profile, level)) {
+ return false;
+ }
+
+ // If we recognize this profile, check that this format is supported by the
+ // highest level supported by the codec for that profile. (Ignore specified
+ // level beyond the above profile/level check as level is only used as a
+ // guidance. E.g. AVC Level 1 CIF format is supported if codec supports level 1.1
+ // even though max size for Level 1 is QCIF. However, MPEG2 Simple Profile
+ // 1080p format is not supported even if codec supports Main Profile Level High,
+ // as Simple Profile does not support 1080p.
+ CodecCapabilities levelCaps = null;
+ int maxLevel = 0;
+ for (CodecProfileLevel pl : profileLevels) {
+ if (pl.profile == profile && pl.level > maxLevel) {
+ maxLevel = pl.level;
+ }
+ }
+ levelCaps = createFromProfileLevel(mMime, profile, maxLevel);
+ if (levelCaps != null && !levelCaps.isFormatSupported(format)) {
+ return false;
+ }
+ }
if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) {
return false;
}
@@ -579,6 +607,57 @@ public final class MediaCodecInfo {
return true;
}
+ private static boolean supportsBitrate(
+ Range<Integer> bitrateRange, MediaFormat format) {
+ Map<String, Object> map = format.getMap();
+
+ // consider max bitrate over average bitrate for support
+ Integer maxBitrate = (Integer)map.get(MediaFormat.KEY_MAX_BIT_RATE);
+ Integer bitrate = (Integer)map.get(MediaFormat.KEY_BIT_RATE);
+ if (bitrate == null) {
+ bitrate = maxBitrate;
+ } else if (maxBitrate != null) {
+ bitrate = Math.max(bitrate, maxBitrate);
+ }
+
+ if (bitrate != null && bitrate > 0) {
+ return bitrateRange.contains(bitrate);
+ }
+
+ return true;
+ }
+
+ private boolean supportsProfileLevel(int profile, Integer level) {
+ for (CodecProfileLevel pl: profileLevels) {
+ if (pl.profile != profile) {
+ continue;
+ }
+
+ // AAC does not use levels
+ if (level == null || mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_AUDIO_AAC)) {
+ return true;
+ }
+
+ // H.263 levels are not completely ordered:
+ // Level45 support only implies Level10 support
+ if (mMime.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)) {
+ if (pl.level != level && pl.level == CodecProfileLevel.H263Level45
+ && level > CodecProfileLevel.H263Level10) {
+ continue;
+ }
+ }
+ if (pl.level >= level) {
+ // if we recognize the listed profile/level, we must also recognize the
+ // profile/level arguments.
+ if (createFromProfileLevel(mMime, profile, pl.level) != null) {
+ return createFromProfileLevel(mMime, profile, level) != null;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
// errors while reading profile levels - accessed from sister capabilities
int mError;
@@ -1004,10 +1083,15 @@ public final class MediaCodecInfo {
Map<String, Object> map = format.getMap();
Integer sampleRate = (Integer)map.get(MediaFormat.KEY_SAMPLE_RATE);
Integer channels = (Integer)map.get(MediaFormat.KEY_CHANNEL_COUNT);
+
if (!supports(sampleRate, channels)) {
return false;
}
+ if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) {
+ return false;
+ }
+
// nothing to do for:
// KEY_CHANNEL_MASK: codecs don't get this
// KEY_IS_ADTS: required feature for all AAC decoders
@@ -1310,8 +1394,7 @@ public final class MediaCodecInfo {
return supports(width, height, null);
}
- private boolean supports(
- Integer width, Integer height, Number rate) {
+ private boolean supports(Integer width, Integer height, Number rate) {
boolean ok = true;
if (ok && width != null) {
@@ -1353,9 +1436,16 @@ public final class MediaCodecInfo {
Integer height = (Integer)map.get(MediaFormat.KEY_HEIGHT);
Number rate = (Number)map.get(MediaFormat.KEY_FRAME_RATE);
- // we ignore color-format for now as it is not reliably reported by codec
+ if (!supports(width, height, rate)) {
+ return false;
+ }
- return supports(width, height, rate);
+ if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) {
+ return false;
+ }
+
+ // we ignore color-format for now as it is not reliably reported by codec
+ return true;
}
/* no public constructor */
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 93c595f1ca2b..33e39575fdac 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -185,12 +185,20 @@ public final class MediaFormat {
public static final String KEY_MAX_INPUT_SIZE = "max-input-size";
/**
- * A key describing the bitrate in bits/sec.
+ * A key describing the average bitrate in bits/sec.
* The associated value is an integer
*/
public static final String KEY_BIT_RATE = "bitrate";
/**
+ * A key describing the max bitrate in bits/sec.
+ * This is usually over a one-second sliding window (e.g. over any window of one second).
+ * The associated value is an integer
+ * @hide
+ */
+ public static final String KEY_MAX_BIT_RATE = "max-bitrate";
+
+ /**
* A key describing the color format of the content in a video format.
* Constants are declared in {@link android.media.MediaCodecInfo.CodecCapabilities}.
*/