diff options
| -rw-r--r-- | media/java/android/media/MediaCodecInfo.java | 45 |
1 files changed, 38 insertions, 7 deletions
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index 193544edbf99..88b9643c12c1 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -934,13 +934,25 @@ public final class MediaCodecInfo { } } levelCaps = createFromProfileLevel(mMime, profile, maxLevel); - // remove profile from this format otherwise levelCaps.isFormatSupported will - // get into this same conditon and loop forever. - Map<String, Object> mapWithoutProfile = new HashMap<>(map); - mapWithoutProfile.remove(MediaFormat.KEY_PROFILE); - MediaFormat formatWithoutProfile = new MediaFormat(mapWithoutProfile); - if (levelCaps != null && !levelCaps.isFormatSupported(formatWithoutProfile)) { - return false; + // We must remove the profile from this format otherwise levelCaps.isFormatSupported + // will get into this same condition and loop forever. Furthermore, since levelCaps + // does not contain features and bitrate specific keys, keep only keys relevant for + // a level check. + Map<String, Object> levelCriticalFormatMap = new HashMap<>(map); + final Set<String> criticalKeys = + isVideo() ? VideoCapabilities.VIDEO_LEVEL_CRITICAL_FORMAT_KEYS : + isAudio() ? AudioCapabilities.AUDIO_LEVEL_CRITICAL_FORMAT_KEYS : + null; + + // critical keys will always contain KEY_MIME, but should also contain others to be + // meaningful + if (criticalKeys != null && criticalKeys.size() > 1 && levelCaps != null) { + levelCriticalFormatMap.keySet().retainAll(criticalKeys); + + MediaFormat levelCriticalFormat = new MediaFormat(levelCriticalFormatMap); + if (!levelCaps.isFormatSupported(levelCriticalFormat)) { + return false; + } } } if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) { @@ -1633,6 +1645,16 @@ public final class MediaCodecInfo { } } + /* package private */ + // must not contain KEY_PROFILE + static final Set<String> AUDIO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of( + // We don't set level-specific limits for audio codecs today. Key candidates would + // be sample rate, bit rate or channel count. + // MediaFormat.KEY_SAMPLE_RATE, + // MediaFormat.KEY_CHANNEL_COUNT, + // MediaFormat.KEY_BIT_RATE, + MediaFormat.KEY_MIME); + /** @hide */ public boolean supportsFormat(MediaFormat format) { Map<String, Object> map = format.getMap(); @@ -2357,6 +2379,15 @@ public final class MediaCodecInfo { return ok; } + /* package private */ + // must not contain KEY_PROFILE + static final Set<String> VIDEO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of( + MediaFormat.KEY_WIDTH, + MediaFormat.KEY_HEIGHT, + MediaFormat.KEY_FRAME_RATE, + MediaFormat.KEY_BIT_RATE, + MediaFormat.KEY_MIME); + /** * @hide * @throws java.lang.ClassCastException */ |