Loading media/java/android/media/MediaCodecInfo.java +94 −4 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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) { Loading Loading @@ -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; } if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) { return false; } return supports(width, height, rate); // we ignore color-format for now as it is not reliably reported by codec return true; } /* no public constructor */ Loading media/java/android/media/MediaFormat.java +9 −1 Original line number Diff line number Diff line Loading @@ -185,11 +185,19 @@ 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}. Loading Loading
media/java/android/media/MediaCodecInfo.java +94 −4 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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) { Loading Loading @@ -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; } if (!CodecCapabilities.supportsBitrate(mBitrateRange, format)) { return false; } return supports(width, height, rate); // we ignore color-format for now as it is not reliably reported by codec return true; } /* no public constructor */ Loading
media/java/android/media/MediaFormat.java +9 −1 Original line number Diff line number Diff line Loading @@ -185,11 +185,19 @@ 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}. Loading