diff options
| author | 2023-04-24 16:38:20 -0700 | |
|---|---|---|
| committer | 2023-06-05 16:30:45 +0000 | |
| commit | e422c9959aa14a23eeb2624217765e964064fc7f (patch) | |
| tree | e3dc1aa6391253c05cef14c3c16f7295b9e760d8 | |
| parent | b36fa7723ab2f105b532be74cbfa5cdb902a4b79 (diff) | |
MediaCodecInfo: consider only critical flags for level support check
isFormatSupported() checks that the format confirms to the highest
level advertised by the codec for the desired profile if the format
contains a profile.
This additional check uses a capabilities object synthesized from
only the profile/level, so consider only the format keys that
are relevant for a level check for this.
Bug: 278575882
Change-Id: Ide3782882216135e5fac4f53bab21123a73f87b3
Merged-in: Ide3782882216135e5fac4f53bab21123a73f87b3
| -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 */ |