summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Lajos Molnar <lajos@google.com> 2023-04-24 16:38:20 -0700
committer Lajos Molnar <lajos@google.com> 2023-06-05 16:30:45 +0000
commite422c9959aa14a23eeb2624217765e964064fc7f (patch)
treee3dc1aa6391253c05cef14c3c16f7295b9e760d8
parentb36fa7723ab2f105b532be74cbfa5cdb902a4b79 (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.java45
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 */