media: update MediaCodecList test to use new API
Bug: 15141324
Change-Id: I66fc118ed396ca5920a0fc7df9c0bf11e61a9e67
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
index d8a20e9..865780e 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
@@ -16,24 +16,38 @@
package android.media.cts;
-
+import android.content.pm.PackageManager;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecProfileLevel;
import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecInfo.AudioCapabilities;
+import android.media.MediaCodecInfo.VideoCapabilities;
+import android.media.MediaCodecInfo.EncoderCapabilities;
import android.media.MediaCodecList;
+import android.media.MediaFormat;
import android.test.AndroidTestCase;
import android.util.Log;
import java.io.File;
import java.io.IOException;
-import java.util.List;
import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
public class MediaCodecListTest extends AndroidTestCase {
private static final String TAG = "MediaCodecListTest";
private static final String MEDIA_CODEC_XML_FILE = "/etc/media_codecs.xml";
+ private final MediaCodecList mRegularCodecs =
+ new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ private final MediaCodecList mAllCodecs =
+ new MediaCodecList(MediaCodecList.ALL_CODECS);
+ private final MediaCodecInfo[] mRegularInfos =
+ mRegularCodecs.getCodecInfos();
+ private final MediaCodecInfo[] mAllInfos =
+ mAllCodecs.getCodecInfos();
class CodecType {
CodecType(String type, boolean isEncoder) {
@@ -55,55 +69,120 @@
assertTrue("/etc/media_codecs.xml does not exist", file.exists());
}
- // Each component advertised by MediaCodecList should at least be
- // instantiate-able.
- public void testComponentInstantiation() throws IOException {
- Log.d(TAG, "testComponentInstantiation");
+ private MediaCodecInfo[] getLegacyInfos() {
+ Log.d(TAG, "getLegacyInfos");
int codecCount = MediaCodecList.getCodecCount();
- for (int i = 0; i < codecCount; ++i) {
- MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+ MediaCodecInfo[] res = new MediaCodecInfo[codecCount];
- Log.d(TAG, (i + 1) + ": " + info.getName());
+ for (int i = 0; i < codecCount; ++i) {
+ res[i] = MediaCodecList.getCodecInfoAt(i);
+ }
+ return res;
+ }
+
+ public void assertEqualsOrSuperset(Set big, Set tiny, boolean superset) {
+ if (!superset) {
+ assertEquals(big, tiny);
+ } else {
+ assertTrue(big.containsAll(tiny));
+ }
+ }
+
+ private static <T> Set<T> asSet(T[] array) {
+ Set<T> s = new HashSet<T>();
+ for (T el : array) {
+ s.add(el);
+ }
+ return s;
+ }
+
+ private static Set<Integer> asSet(int[] array) {
+ Set<Integer> s = new HashSet<Integer>();
+ for (int el : array) {
+ s.add(el);
+ }
+ return s;
+ }
+
+ public void assertEqualsOrSuperset(
+ CodecCapabilities big, CodecCapabilities tiny, boolean superset) {
+ // ordering of enumerations may differ
+ assertEqualsOrSuperset(asSet(big.colorFormats), asSet(tiny.colorFormats), superset);
+ assertEqualsOrSuperset(asSet(big.profileLevels), asSet(tiny.profileLevels), superset);
+ AudioCapabilities bigAudCaps = big.getAudioCapabilities();
+ VideoCapabilities bigVidCaps = big.getVideoCapabilities();
+ EncoderCapabilities bigEncCaps = big.getEncoderCapabilities();
+ AudioCapabilities tinyAudCaps = tiny.getAudioCapabilities();
+ VideoCapabilities tinyVidCaps = tiny.getVideoCapabilities();
+ EncoderCapabilities tinyEncCaps = tiny.getEncoderCapabilities();
+ assertEquals(bigAudCaps != null, tinyAudCaps != null);
+ assertEquals(bigAudCaps != null, tinyAudCaps != null);
+ assertEquals(bigAudCaps != null, tinyAudCaps != null);
+ }
+
+ public void assertEqualsOrSuperset(
+ MediaCodecInfo big, MediaCodecInfo tiny, boolean superset) {
+ assertEquals(big.getName(), tiny.getName());
+ assertEquals(big.isEncoder(), tiny.isEncoder());
+ assertEqualsOrSuperset(
+ asSet(big.getSupportedTypes()), asSet(tiny.getSupportedTypes()), superset);
+ for (String type : big.getSupportedTypes()) {
+ assertEqualsOrSuperset(
+ big.getCapabilitiesForType(type),
+ tiny.getCapabilitiesForType(type),
+ superset);
+ }
+ }
+
+ public void assertSuperset(MediaCodecInfo big, MediaCodecInfo tiny) {
+ assertEqualsOrSuperset(big, tiny, true /* superset */);
+ }
+
+ public void assertEquals(MediaCodecInfo big, MediaCodecInfo tiny) {
+ assertEqualsOrSuperset(big, tiny, false /* superset */);
+ }
+
+ // Each component advertised by MediaCodecList should at least be
+ // instantiable.
+ private void testComponentInstantiation(MediaCodecInfo[] infos) throws IOException {
+ for (MediaCodecInfo info : infos) {
+ Log.d(TAG, "codec: " + info.getName());
Log.d(TAG, " isEncoder = " + info.isEncoder());
- if (!info.getName().startsWith("OMX.")) {
- // Unfortunately for legacy reasons, "AACEncoder", a
- // non OMX component had to be in this list for the video
- // editor code to work... but it cannot actually be instantiated
- // using MediaCodec.
- Log.d(TAG, " skipping...");
- continue;
- }
-
MediaCodec codec = MediaCodec.createByCodecName(info.getName());
+ assertEquals(codec.getName(), info.getName());
+
+ assertEquals(codec.getCodecInfo(), info);
+
codec.release();
codec = null;
}
}
+ public void testRegularComponentInstantiation() throws IOException {
+ Log.d(TAG, "testRegularComponentInstantiation");
+ testComponentInstantiation(mRegularInfos);
+ }
+
+ public void testAllComponentInstantiation() throws IOException {
+ Log.d(TAG, "testAllComponentInstantiation");
+ testComponentInstantiation(mAllInfos);
+ }
+
+ public void testLegacyComponentInstantiation() throws IOException {
+ Log.d(TAG, "testLegacyComponentInstantiation");
+ testComponentInstantiation(getLegacyInfos());
+ }
+
// For each type advertised by any of the components we should be able
// to get capabilities.
- public void testGetCapabilities() {
- Log.d(TAG, "testGetCapabilities");
-
- int codecCount = MediaCodecList.getCodecCount();
- for (int i = 0; i < codecCount; ++i) {
- MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
-
- Log.d(TAG, (i + 1) + ": " + info.getName());
+ private void testGetCapabilities(MediaCodecInfo[] infos) {
+ for (MediaCodecInfo info : infos) {
+ Log.d(TAG, "codec: " + info.getName());
Log.d(TAG, " isEncoder = " + info.isEncoder());
- if (!info.getName().startsWith("OMX.")) {
- // Unfortunately for legacy reasons, "AACEncoder", a
- // non OMX component had to be in this list for the video
- // editor code to work... but it cannot actually be instantiated
- // using MediaCodec.
- Log.d(TAG, " skipping...");
- continue;
- }
-
String[] types = info.getSupportedTypes();
for (int j = 0; j < types.length; ++j) {
Log.d(TAG, "calling getCapabilitiesForType " + types[j]);
@@ -112,14 +191,71 @@
}
}
+ public void testGetRegularCapabilities() {
+ Log.d(TAG, "testGetRegularCapabilities");
+ testGetCapabilities(mRegularInfos);
+ }
+
+ public void testGetAllCapabilities() {
+ Log.d(TAG, "testGetAllCapabilities");
+ testGetCapabilities(mAllInfos);
+ }
+
+ public void testGetLegacyCapabilities() {
+ Log.d(TAG, "testGetLegacyCapabilities");
+ testGetCapabilities(getLegacyInfos());
+ }
+
+ public void testLegacyMediaCodecListIsSameAsRegular() {
+ // regular codecs should be equivalent to legacy codecs, including
+ // codec ordering
+ MediaCodecInfo[] legacyInfos = getLegacyInfos();
+ assertEquals(legacyInfos.length, mRegularInfos.length);
+ for (int i = 0; i < legacyInfos.length; ++i) {
+ assertEquals(legacyInfos[i], mRegularInfos[i]);
+ }
+ }
+
+ public void testRegularMediaCodecListIsASubsetOfAll() {
+ Log.d(TAG, "testRegularMediaCodecListIsASubsetOfAll");
+ // regular codecs should be a subsequence of all codecs, including
+ // codec ordering
+ int ix = 0;
+ for (MediaCodecInfo info : mAllInfos) {
+ if (ix == mRegularInfos.length) {
+ break;
+ }
+ if (!mRegularInfos[ix].getName().equals(info.getName())) {
+ Log.d(TAG, "skipping non-regular codec " + info.getName());
+ continue;
+ }
+ Log.d(TAG, "checking codec " + info.getName());
+ assertSuperset(info, mRegularInfos[ix]);
+ ++ix;
+ }
+ assertEquals(
+ "some regular codecs are not listed in all codecs", ix, mRegularInfos.length);
+ }
+
public void testRequiredMediaCodecList() {
List<CodecType> requiredList = getRequiredCodecTypes();
List<CodecType> supportedList = getSupportedCodecTypes();
assertTrue(areRequiredCodecTypesSupported(requiredList, supportedList));
}
+ private boolean hasCamera() {
+ PackageManager pm = getContext().getPackageManager();
+ return pm.hasSystemFeature(pm.FEATURE_CAMERA_FRONT) ||
+ pm.hasSystemFeature(pm.FEATURE_CAMERA);
+ }
+
// H263 baseline profile must be supported
public void testIsH263BaselineProfileSupported() {
+ if (!hasCamera()) {
+ Log.d(TAG, "not required without camera");
+ return;
+ }
+
int profile = CodecProfileLevel.H263ProfileBaseline;
assertTrue(checkProfileSupported("video/3gpp", false, profile));
assertTrue(checkProfileSupported("video/3gpp", true, profile));
@@ -140,6 +276,11 @@
// MPEG4 simple profile must be supported
public void testIsM4VSimpleProfileSupported() {
+ if (!hasCamera()) {
+ Log.d(TAG, "not required without camera");
+ return;
+ }
+
int profile = CodecProfileLevel.MPEG4ProfileSimple;
assertTrue(checkProfileSupported("video/mp4v-es", false, profile));
@@ -151,26 +292,24 @@
* Find whether the given codec is supported
*/
private boolean checkProfileSupported(
- String codecName, boolean isEncoder, int profile) {
+ String mime, boolean isEncoder, int profile) {
+ return profileIsListed(mime, isEncoder, profile) &&
+ codecCanBeFound(mime, isEncoder);
+ }
- boolean isSupported = false;
+ private boolean profileIsListed(
+ String mime, boolean isEncoder, int profile) {
- int codecCount = MediaCodecList.getCodecCount();
- for (int i = 0; i < codecCount; ++i) {
-
- MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
- String[] types = info.getSupportedTypes();
-
+ for (MediaCodecInfo info : mRegularInfos) {
if (isEncoder != info.isEncoder()) {
continue;
}
- for (int j = 0; j < types.length; ++j) {
- if (types[j].compareTo(codecName) == 0) {
- CodecCapabilities cap = info.getCapabilitiesForType(types[j]);
- CodecProfileLevel[] profileLevels = cap.profileLevels;
- for (int k = 0; k < profileLevels.length; ++k) {
- if (profileLevels[k].profile == profile) {
+ for (String type : info.getSupportedTypes()) {
+ if (type.equalsIgnoreCase(mime)) {
+ CodecCapabilities cap = info.getCapabilitiesForType(type);
+ for (CodecProfileLevel pl : cap.profileLevels) {
+ if (pl.profile == profile) {
return true;
}
}
@@ -180,6 +319,16 @@
return false;
}
+ // Find whether the given codec can be found using MediaCodecList.find methods.
+ private boolean codecCanBeFound(String mime, boolean isEncoder) {
+ // implicit assumption that QVGA video is always valid.
+ MediaFormat format = MediaFormat.createVideoFormat(mime, 176, 144);
+ String codecName = isEncoder
+ ? mRegularCodecs.findEncoderForFormat(format)
+ : mRegularCodecs.findDecoderForFormat(format);
+ return codecName != null;
+ }
+
/*
* Find whether all required media codec types are supported
*/
@@ -206,11 +355,8 @@
* Find all the media codec types are supported.
*/
private List<CodecType> getSupportedCodecTypes() {
- int codecCount = MediaCodecList.getCodecCount();
- assertTrue("Unexpected media codec count", codecCount > 0);
- List<CodecType> supportedList = new ArrayList<CodecType>(codecCount);
- for (int i = 0; i < codecCount; ++i) {
- MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
+ List<CodecType> supportedList = new ArrayList<CodecType>();
+ for (MediaCodecInfo info : mRegularInfos) {
String[] types = info.getSupportedTypes();
assertTrue("Unexpected number of supported types", types.length > 0);
boolean isEncoder = info.isEncoder();