Merge "Add TV app tests to CtsVerifier DO NOT MERGE" into lmp-sprout-dev
diff --git a/libs/deviceutil/src/android/cts/util/MediaUtils.java b/libs/deviceutil/src/android/cts/util/MediaUtils.java
new file mode 100644
index 0000000..eab4808
--- /dev/null
+++ b/libs/deviceutil/src/android/cts/util/MediaUtils.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.cts.util;
+
+import android.content.Context;
+import android.content.res.AssetFileDescriptor;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaExtractor;
+import android.media.MediaFormat;
+import android.net.Uri;
+import java.lang.reflect.Method;
+import static java.lang.reflect.Modifier.isPublic;
+import static java.lang.reflect.Modifier.isStatic;
+import java.util.Map;
+import android.util.Log;
+
+import java.io.IOException;
+
+public class MediaUtils {
+ private static final String TAG = "MediaUtils";
+
+ private static final int ALL_AV_TRACKS = -1;
+
+ private static final MediaCodecList sMCL = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+
+
+ /**
+ * Finds test name (heuristically) and prints out standard skip message.
+ *
+ * Since it uses heuristics, this method has only been verified for media
+ * tests. This centralizes the way to signal a skipped test.
+ */
+ public static void skipTest(String tag, String reason) {
+ int bestScore = -1;
+ String testName = "test???";
+ Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces();
+ for (Map.Entry<Thread, StackTraceElement[]> entry : traces.entrySet()) {
+ StackTraceElement[] stack = entry.getValue();
+ for (int index = 0; index < stack.length; ++index) {
+ // method name must start with "test"
+ String methodName = stack[index].getMethodName();
+ if (!methodName.startsWith("test")) {
+ continue;
+ }
+
+ int score = 0;
+ // see if there is a public non-static void method that takes no argument
+ Class<?> clazz;
+ try {
+ clazz = Class.forName(stack[index].getClassName());
+ ++score;
+ for (final Method method : clazz.getDeclaredMethods()) {
+ if (method.getName().equals(methodName)
+ && isPublic(method.getModifiers())
+ && !isStatic(method.getModifiers())
+ && method.getParameterTypes().length == 0
+ && method.getReturnType().equals(Void.TYPE)) {
+ ++score;
+ break;
+ }
+ }
+ if (score == 1) {
+ // if we could read the class, but method is not public void, it is
+ // not a candidate
+ continue;
+ }
+ } catch (ClassNotFoundException e) {
+ }
+
+ // even if we cannot verify the method signature, there are signals in the stack
+
+ // usually test method is invoked by reflection
+ int depth = 1;
+ while (index + depth < stack.length
+ && stack[index + depth].getMethodName().equals("invoke")
+ && stack[index + depth].getClassName().equals(
+ "java.lang.reflect.Method")) {
+ ++depth;
+ }
+ if (depth > 1) {
+ ++score;
+ // and usually test method is run by runMethod method in android.test package
+ if (index + depth < stack.length) {
+ if (stack[index + depth].getClassName().startsWith("android.test.")) {
+ ++score;
+ }
+ if (stack[index + depth].getMethodName().equals("runMethod")) {
+ ++score;
+ }
+ }
+ }
+
+ if (score > bestScore) {
+ bestScore = score;
+ testName = methodName;
+ }
+ }
+ }
+
+ Log.i(tag, "SKIPPING " + testName + "(): " + reason);
+ }
+
+ /**
+ * Finds test name (heuristically) and prints out standard skip message.
+ *
+ * Since it uses heuristics, this method has only been verified for media
+ * tests. This centralizes the way to signal a skipped test.
+ */
+ public static void skipTest(String reason) {
+ skipTest(TAG, reason);
+ }
+
+ public static boolean check(boolean result, String message) {
+ if (!result) {
+ skipTest(message);
+ }
+ return result;
+ }
+
+ public static boolean canDecode(MediaFormat format) {
+ if (sMCL.findDecoderForFormat(format) == null) {
+ Log.i(TAG, "no decoder for " + format);
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean hasCodecForTrack(MediaExtractor ex, int track) {
+ int count = ex.getTrackCount();
+ if (track < 0 || track >= count) {
+ throw new IndexOutOfBoundsException(track + " not in [0.." + (count - 1) + "]");
+ }
+ return canDecode(ex.getTrackFormat(track));
+ }
+
+ /**
+ * return true iff all audio and video tracks are supported
+ */
+ public static boolean hasCodecsForMedia(MediaExtractor ex) {
+ for (int i = 0; i < ex.getTrackCount(); ++i) {
+ MediaFormat format = ex.getTrackFormat(i);
+ // only check for audio and video codecs
+ String mime = format.getString(MediaFormat.KEY_MIME).toLowerCase();
+ if (!mime.startsWith("audio/") && !mime.startsWith("video/")) {
+ continue;
+ }
+ if (!canDecode(format)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * return true iff any track starting with mimePrefix is supported
+ */
+ public static boolean hasCodecForMediaAndDomain(MediaExtractor ex, String mimePrefix) {
+ mimePrefix = mimePrefix.toLowerCase();
+ for (int i = 0; i < ex.getTrackCount(); ++i) {
+ MediaFormat format = ex.getTrackFormat(i);
+ String mime = format.getString(MediaFormat.KEY_MIME);
+ if (mime.toLowerCase().startsWith(mimePrefix)) {
+ if (canDecode(format)) {
+ return true;
+ }
+ Log.i(TAG, "no decoder for " + format);
+ }
+ }
+ return false;
+ }
+
+ private static boolean hasCodecsForResourceCombo(
+ Context context, int resourceId, int track, String mimePrefix) {
+ try {
+ AssetFileDescriptor afd = null;
+ MediaExtractor ex = null;
+ try {
+ afd = context.getResources().openRawResourceFd(resourceId);
+ ex = new MediaExtractor();
+ ex.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
+ if (mimePrefix != null) {
+ return hasCodecForMediaAndDomain(ex, mimePrefix);
+ } else if (track == ALL_AV_TRACKS) {
+ return hasCodecsForMedia(ex);
+ } else {
+ return hasCodecForTrack(ex, track);
+ }
+ } finally {
+ if (ex != null) {
+ ex.release();
+ }
+ if (afd != null) {
+ afd.close();
+ }
+ }
+ } catch (IOException e) {
+ Log.i(TAG, "could not open resource");
+ }
+ return false;
+ }
+
+ /**
+ * return true iff all audio and video tracks are supported
+ */
+ public static boolean hasCodecsForResource(Context context, int resourceId) {
+ return hasCodecsForResourceCombo(context, resourceId, ALL_AV_TRACKS, null /* mimePrefix */);
+ }
+
+ public static boolean checkCodecsForResource(Context context, int resourceId) {
+ return check(hasCodecsForResource(context, resourceId), "no decoder found");
+ }
+
+ /**
+ * return true iff track is supported.
+ */
+ public static boolean hasCodecForResource(Context context, int resourceId, int track) {
+ return hasCodecsForResourceCombo(context, resourceId, track, null /* mimePrefix */);
+ }
+
+ public static boolean checkCodecForResource(Context context, int resourceId, int track) {
+ return check(hasCodecForResource(context, resourceId, track), "no decoder found");
+ }
+
+ /**
+ * return true iff any track starting with mimePrefix is supported
+ */
+ public static boolean hasCodecForResourceAndDomain(
+ Context context, int resourceId, String mimePrefix) {
+ return hasCodecsForResourceCombo(context, resourceId, ALL_AV_TRACKS, mimePrefix);
+ }
+
+ /**
+ * return true iff all audio and video tracks are supported
+ */
+ public static boolean hasCodecsForPath(Context context, String path) {
+ MediaExtractor ex = null;
+ try {
+ ex = new MediaExtractor();
+ Uri uri = Uri.parse(path);
+ String scheme = uri.getScheme();
+ if (scheme == null) { // file
+ ex.setDataSource(path);
+ } else if (scheme.equalsIgnoreCase("file")) {
+ ex.setDataSource(uri.getPath());
+ } else {
+ ex.setDataSource(context, uri, null);
+ }
+ return hasCodecsForMedia(ex);
+ } catch (IOException e) {
+ Log.i(TAG, "could not open path " + path);
+ } finally {
+ if (ex != null) {
+ ex.release();
+ }
+ }
+ return false;
+ }
+
+ public static boolean checkCodecsForPath(Context context, String path) {
+ return check(hasCodecsForPath(context, path), "no decoder found");
+ }
+
+ private static boolean hasCodecForMime(boolean encoder, String mime) {
+ for (MediaCodecInfo info : sMCL.getCodecInfos()) {
+ if (encoder != info.isEncoder()) {
+ continue;
+ }
+
+ for (String type : info.getSupportedTypes()) {
+ if (type.equalsIgnoreCase(mime)) {
+ Log.i(TAG, "found codec " + info.getName() + " for mime " + mime);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static boolean hasCodecForMimes(boolean encoder, String[] mimes) {
+ for (String mime : mimes) {
+ if (!hasCodecForMime(encoder, mime)) {
+ Log.i(TAG, "no " + (encoder ? "encoder" : "decoder") + " for mime " + mime);
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ public static boolean hasEncoder(String... mimes) {
+ return hasCodecForMimes(true /* encoder */, mimes);
+ }
+
+ public static boolean hasDecoder(String... mimes) {
+ return hasCodecForMimes(false /* encoder */, mimes);
+ }
+
+ public static boolean checkDecoder(String... mimes) {
+ return check(hasCodecForMimes(false /* encoder */, mimes), "no decoder found");
+ }
+
+ public static boolean checkEncoder(String... mimes) {
+ return check(hasCodecForMimes(true /* encoder */, mimes), "no encoder found");
+ }
+
+ public static boolean canDecodeVideo(String mime, int width, int height, float rate) {
+ MediaFormat format = MediaFormat.createVideoFormat(mime, width, height);
+ format.setFloat(MediaFormat.KEY_FRAME_RATE, rate);
+ return canDecode(format);
+ }
+
+ public static boolean checkDecoderForFormat(MediaFormat format) {
+ return check(canDecode(format), "no decoder for " + format);
+ }
+}
diff --git a/suite/cts/deviceTests/videoperf/Android.mk b/suite/cts/deviceTests/videoperf/Android.mk
index cb398a9..cd82dde 100644
--- a/suite/cts/deviceTests/videoperf/Android.mk
+++ b/suite/cts/deviceTests/videoperf/Android.mk
@@ -24,7 +24,7 @@
LOCAL_PACKAGE_NAME := CtsDeviceVideoPerf
-LOCAL_SDK_VERSION := 16
+LOCAL_SDK_VERSION := current
include $(BUILD_CTS_PACKAGE)
diff --git a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/CodecInfo.java b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/CodecInfo.java
index b9edfa4..b7d1d27 100644
--- a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/CodecInfo.java
+++ b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/CodecInfo.java
@@ -19,7 +19,9 @@
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.CodecProfileLevel;
+import android.media.MediaCodecInfo.VideoCapabilities;
import android.media.MediaCodecList;
+import android.media.MediaFormat;
import android.util.Log;
@@ -38,21 +40,33 @@
public boolean mSupportPlanar = false;
private static final String TAG = "CodecInfo";
- private static final String VIDEO_AVC = "video/avc";
+ private static final String VIDEO_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
/**
* Check if given codec with given (w,h) is supported.
- * @param mimeType codec type in mime format like "video/avc"
+ * @param mimeType codec type in mime format like MediaFormat.MIMETYPE_VIDEO_AVC
* @param w video width
* @param h video height
* @param isEncoder whether the codec is encoder or decoder
* @return null if the configuration is not supported.
*/
- public static CodecInfo getSupportedFormatInfo(String mimeType, int w, int h,
- boolean isEncoder) {
- CodecCapabilities cap = getCodecCapability(mimeType, isEncoder);
- if (cap == null) { // not supported
+ public static CodecInfo getSupportedFormatInfo(
+ String mimeType, int w, int h, boolean isEncoder) {
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ MediaFormat format = MediaFormat.createVideoFormat(mimeType, w, h);
+ String codec = isEncoder
+ ? mcl.findEncoderForFormat(format)
+ : mcl.findDecoderForFormat(format);
+ if (codec == null) { // not supported
return null;
}
+ CodecCapabilities cap = null;
+ for (MediaCodecInfo info : mcl.getCodecInfos()) {
+ if (info.getName().equals(codec)) {
+ cap = info.getCapabilitiesForType(mimeType);
+ break;
+ }
+ }
+ VideoCapabilities vidCap = cap.getVideoCapabilities();
CodecInfo info = new CodecInfo();
for (int color : cap.colorFormats) {
if (color == CodecCapabilities.COLOR_FormatYUV420SemiPlanar) {
@@ -70,129 +84,13 @@
}
if (mimeType.equals(VIDEO_AVC)) {
- int highestLevel = 0;
- for (CodecProfileLevel lvl : cap.profileLevels) {
- if (lvl.level > highestLevel) {
- highestLevel = lvl.level;
- }
- }
- Log.i(TAG, "Avc highest level " + Integer.toHexString(highestLevel));
- int maxW = 0;
- int maxH = 0;
- int bitRate = 0;
- int mbW = (w + 15) / 16; // size in macroblocks
- int mbH = (h + 15) / 16;
- int maxMacroblocksPerSecond = 0; // max decoding speed
- switch(highestLevel) {
- // Do not support Level 1 to 2.
- case CodecProfileLevel.AVCLevel1:
- case CodecProfileLevel.AVCLevel11:
- case CodecProfileLevel.AVCLevel12:
- case CodecProfileLevel.AVCLevel13:
- case CodecProfileLevel.AVCLevel1b:
- case CodecProfileLevel.AVCLevel2:
- return null;
- case CodecProfileLevel.AVCLevel21:
- maxW = 352;
- maxH = 576;
- bitRate = 4000000;
- maxMacroblocksPerSecond = 19800;
- break;
- case CodecProfileLevel.AVCLevel22:
- maxW = 720;
- maxH = 480;
- bitRate = 4000000;
- maxMacroblocksPerSecond = 20250;
- break;
- case CodecProfileLevel.AVCLevel3:
- maxW = 720;
- maxH = 480;
- bitRate = 10000000;
- maxMacroblocksPerSecond = 40500;
- break;
- case CodecProfileLevel.AVCLevel31:
- maxW = 1280;
- maxH = 720;
- bitRate = 14000000;
- maxMacroblocksPerSecond = 108000;
- break;
- case CodecProfileLevel.AVCLevel32:
- maxW = 1280;
- maxH = 720;
- bitRate = 20000000;
- maxMacroblocksPerSecond = 216000;
- break;
- case CodecProfileLevel.AVCLevel4:
- maxW = 1920;
- maxH = 1080;
- bitRate = 20000000;
- maxMacroblocksPerSecond = 245760;
- break;
- case CodecProfileLevel.AVCLevel41:
- maxW = 1920;
- maxH = 1080;
- bitRate = 50000000;
- maxMacroblocksPerSecond = 245760;
- break;
- case CodecProfileLevel.AVCLevel42:
- maxW = 2048;
- maxH = 1080;
- bitRate = 50000000;
- maxMacroblocksPerSecond = 522240;
- break;
- case CodecProfileLevel.AVCLevel5:
- maxW = 3672;
- maxH = 1536;
- bitRate = 135000000;
- maxMacroblocksPerSecond = 589824;
- break;
- case CodecProfileLevel.AVCLevel51:
- default:
- maxW = 4096;
- maxH = 2304;
- bitRate = 240000000;
- maxMacroblocksPerSecond = 983040;
- break;
- }
- if ((w > maxW) || (h > maxH)) {
- Log.i(TAG, "Requested resolution (" + w + "," + h + ") exceeds (" +
- maxW + "," + maxH + ")");
- return null;
- }
- info.mFps = maxMacroblocksPerSecond / mbH / mbW;
- info.mBitRate = bitRate;
- Log.i(TAG, "AVC Level " + Integer.toHexString(highestLevel) + " bit rate " + bitRate +
- " fps " + info.mFps);
+ info.mFps = vidCap.getSupportedFrameRatesFor(w, h).getUpper().intValue();
+ info.mBitRate = vidCap.getBitrateRange().getUpper();
+ Log.i(TAG, "AVC bit rate " + info.mBitRate + " fps " + info.mFps);
}
return info;
}
- /**
- * Search for given codecName and returns CodecCapabilities if found
- * @param codecName
- * @param isEncoder true for encoder, false for decoder
- * @return null if the codec is not supported
- */
- private static CodecCapabilities getCodecCapability(
- String codecName, boolean isEncoder) {
- int codecCount = MediaCodecList.getCodecCount();
- for (int i = 0; i < codecCount; ++i) {
- MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
- String[] types = info.getSupportedTypes();
- 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]);
- Log.i(TAG, "Use codec " + info.getName());
- return cap;
- }
- }
- }
- return null;
- }
-
// for debugging
private static void printIntArray(String msg, int[] data) {
StringBuilder builder = new StringBuilder();
diff --git a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
index a009ce2..aacb7a5 100644
--- a/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
+++ b/suite/cts/deviceTests/videoperf/src/com/android/cts/videoperf/VideoEncoderDecoderTest.java
@@ -18,6 +18,7 @@
import android.graphics.Point;
import android.media.MediaCodec;
+import android.media.MediaCodecList;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaFormat;
import android.util.Log;
@@ -27,6 +28,7 @@
import com.android.cts.util.ResultUnit;
import com.android.cts.util.Stat;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.lang.System;
import java.util.Random;
@@ -49,7 +51,7 @@
// is not very high.
private static final long VIDEO_CODEC_WAIT_TIME_US = 5000;
private static final boolean VERBOSE = false;
- private static final String VIDEO_AVC = "video/avc";
+ private static final String VIDEO_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
private static final int TOTAL_FRAMES = 300;
private static final int NUMBER_OF_REPEAT = 10;
// i frame interval for encoder
@@ -130,12 +132,12 @@
* @param numberRepeat how many times to repeat the encoding / decoding process
*/
private void doTest(String mimeType, int w, int h, int numberRepeat) throws Exception {
- CodecInfo infoEnc = CodecInfo.getSupportedFormatInfo(mimeType, w, h, true);
+ CodecInfo infoEnc = CodecInfo.getSupportedFormatInfo(mimeType, w, h, true /* encoder */);
if (infoEnc == null) {
- Log.i(TAG, "Codec " + mimeType + "with " + w + "," + h + " not supported");
+ Log.i(TAG, "Encoder " + mimeType + " with " + w + "," + h + " not supported");
return;
}
- CodecInfo infoDec = CodecInfo.getSupportedFormatInfo(mimeType, w, h, false);
+ CodecInfo infoDec = CodecInfo.getSupportedFormatInfo(mimeType, w, h, false /* encoder */);
assertNotNull(infoDec);
mVideoWidth = w;
mVideoHeight = h;
@@ -207,8 +209,11 @@
* @return time taken in ms to encode the frames. This does not include initialization time.
*/
private double runEncoder(String mimeType, MediaFormat format, int totalFrames) {
- MediaCodec codec = MediaCodec.createEncoderByType(mimeType);
+ MediaCodec codec = null;
try {
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ String encoderName = mcl.findEncoderForFormat(format);
+ codec = MediaCodec.createByCodecName(encoderName);
codec.configure(
format,
null /* surface */,
@@ -216,7 +221,11 @@
MediaCodec.CONFIGURE_FLAG_ENCODE);
} catch (IllegalStateException e) {
Log.e(TAG, "codec '" + mimeType + "' failed configuration.");
+ codec.release();
assertTrue("codec '" + mimeType + "' failed configuration.", false);
+ } catch (IOException | NullPointerException e) {
+ Log.i(TAG, "could not find codec for " + format);
+ return Double.NaN;
}
codec.start();
ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
@@ -347,7 +356,15 @@
* @return returns length-2 array with 0: time for decoding, 1 : rms error of pixels
*/
private double[] runDecoder(String mimeType, MediaFormat format) {
- MediaCodec codec = MediaCodec.createDecoderByType(mimeType);
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ String decoderName = mcl.findDecoderForFormat(format);
+ MediaCodec codec = null;
+ try {
+ codec = MediaCodec.createByCodecName(decoderName);
+ } catch (IOException | NullPointerException e) {
+ Log.i(TAG, "could not find codec for " + format);
+ return null;
+ }
codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
codec.start();
ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
index 669de2d..52f6075 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/RecordingTest.java
@@ -30,6 +30,7 @@
import android.media.Image;
import android.media.ImageReader;
import android.media.MediaCodecList;
+import android.media.MediaFormat;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Environment;
@@ -1050,133 +1051,10 @@
* by AVC specification for certain level.
*/
private static boolean isSupportedByAVCEncoder(Size sz, int frameRate) {
- String mimeType = "video/avc";
- MediaCodecInfo codecInfo = getEncoderInfo(mimeType);
- if (codecInfo == null) {
- return false;
- }
- CodecCapabilities cap = codecInfo.getCapabilitiesForType(mimeType);
- if (cap == null) {
- return false;
- }
-
- int highestLevel = 0;
- for (CodecProfileLevel lvl : cap.profileLevels) {
- if (lvl.level > highestLevel) {
- highestLevel = lvl.level;
- }
- }
- // Don't support anything meaningful for level 1 or 2.
- if (highestLevel <= CodecProfileLevel.AVCLevel2) {
- return false;
- }
-
- if(VERBOSE) {
- Log.v(TAG, "The highest level supported by encoder is: " + highestLevel);
- }
-
- // Put bitRate here for future use.
- int maxW, maxH, bitRate;
- // Max encoding speed.
- int maxMacroblocksPerSecond = 0;
- switch(highestLevel) {
- case CodecProfileLevel.AVCLevel21:
- maxW = 352;
- maxH = 576;
- bitRate = 4000000;
- maxMacroblocksPerSecond = 19800;
- break;
- case CodecProfileLevel.AVCLevel22:
- maxW = 720;
- maxH = 480;
- bitRate = 4000000;
- maxMacroblocksPerSecond = 20250;
- break;
- case CodecProfileLevel.AVCLevel3:
- maxW = 720;
- maxH = 480;
- bitRate = 10000000;
- maxMacroblocksPerSecond = 40500;
- break;
- case CodecProfileLevel.AVCLevel31:
- maxW = 1280;
- maxH = 720;
- bitRate = 14000000;
- maxMacroblocksPerSecond = 108000;
- break;
- case CodecProfileLevel.AVCLevel32:
- maxW = 1280;
- maxH = 720;
- bitRate = 20000000;
- maxMacroblocksPerSecond = 216000;
- break;
- case CodecProfileLevel.AVCLevel4:
- maxW = 1920;
- maxH = 1088; // It should be 1088 in terms of AVC capability.
- bitRate = 20000000;
- maxMacroblocksPerSecond = 245760;
- break;
- case CodecProfileLevel.AVCLevel41:
- maxW = 1920;
- maxH = 1088; // It should be 1088 in terms of AVC capability.
- bitRate = 50000000;
- maxMacroblocksPerSecond = 245760;
- break;
- case CodecProfileLevel.AVCLevel42:
- maxW = 2048;
- maxH = 1088; // It should be 1088 in terms of AVC capability.
- bitRate = 50000000;
- maxMacroblocksPerSecond = 522240;
- break;
- case CodecProfileLevel.AVCLevel5:
- maxW = 3672;
- maxH = 1536;
- bitRate = 135000000;
- maxMacroblocksPerSecond = 589824;
- break;
- case CodecProfileLevel.AVCLevel51:
- default:
- maxW = 4096;
- maxH = 2304;
- bitRate = 240000000;
- maxMacroblocksPerSecond = 983040;
- break;
- }
-
- // Check size limit.
- if (sz.getWidth() > maxW || sz.getHeight() > maxH) {
- Log.i(TAG, "Requested resolution " + sz.toString() + " exceeds (" +
- maxW + "," + maxH + ")");
- return false;
- }
-
- // Check frame rate limit.
- Size sizeInMb = new Size((sz.getWidth() + 15) / 16, (sz.getHeight() + 15) / 16);
- int maxFps = maxMacroblocksPerSecond / (sizeInMb.getWidth() * sizeInMb.getHeight());
- if (frameRate > maxFps) {
- Log.i(TAG, "Requested frame rate " + frameRate + " exceeds " + maxFps);
- return false;
- }
-
- return true;
- }
-
- private static MediaCodecInfo getEncoderInfo(String mimeType) {
- int numCodecs = MediaCodecList.getCodecCount();
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-
- if (!codecInfo.isEncoder()) {
- continue;
- }
-
- String[] types = codecInfo.getSupportedTypes();
- for (int j = 0; j < types.length; j++) {
- if (types[j].equalsIgnoreCase(mimeType)) {
- return codecInfo;
- }
- }
- }
- return null;
+ MediaFormat format = MediaFormat.createVideoFormat(
+ MediaFormat.MIMETYPE_VIDEO_AVC, sz.getWidth(), sz.getHeight());
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ return mcl.findEncoderForFormat(format) != null;
}
}
diff --git a/tests/tests/media/assets/noiseandchirps.ogg b/tests/tests/media/assets/noiseandchirps.ogg
index 1acb643..5c67a88 100644
--- a/tests/tests/media/assets/noiseandchirps.ogg
+++ b/tests/tests/media/assets/noiseandchirps.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_mp4_h264_8192kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_1280x720_mp4_h264_8192kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..2c9c3d3
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_mp4_h264_8192kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_mp4_h264_8192kbps_60fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_1280x720_mp4_h264_8192kbps_60fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..71150af
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_mp4_h264_8192kbps_60fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_mp4_hevc_4096kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_1280x720_mp4_hevc_4096kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..18d53e6
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_mp4_hevc_4096kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz.webm b/tests/tests/media/res/raw/video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz.webm
deleted file mode 100644
index c8b9512..0000000
--- a/tests/tests/media/res/raw/video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz.webm
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..b0cd94d
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_webm_vp8_8192kbps_30fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_1280x720_webm_vp8_8192kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..bf93ab4
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_webm_vp8_8192kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_webm_vp8_8192kbps_60fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_1280x720_webm_vp8_8192kbps_60fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..ae0e0e3
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_webm_vp8_8192kbps_60fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_44100hz.webm b/tests/tests/media/res/raw/video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_44100hz.webm
deleted file mode 100644
index 65b436a..0000000
--- a/tests/tests/media/res/raw/video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_44100hz.webm
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..b79e3f6
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_webm_vp9_4096kbps_30fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_1280x720_webm_vp9_4096kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..2e769e6
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_webm_vp9_4096kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..35ab7a0
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..b837dc2
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1920x1080_mp4_hevc_10240kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_1920x1080_mp4_hevc_10240kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..631ea04
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1920x1080_mp4_hevc_10240kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1920x1080_webm_vp8_20480kbps_30fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_1920x1080_webm_vp8_20480kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..c147461
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1920x1080_webm_vp8_20480kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1920x1080_webm_vp8_20480kbps_60fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_1920x1080_webm_vp8_20480kbps_60fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..10a1a5d
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1920x1080_webm_vp8_20480kbps_60fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1920x1080_webm_vp9_10240kbps_30fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_1920x1080_webm_vp9_10240kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..949b327
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1920x1080_webm_vp9_10240kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_2840x2160_mp4_hevc_20480kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_2840x2160_mp4_hevc_20480kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..7b663a4
--- /dev/null
+++ b/tests/tests/media/res/raw/video_2840x2160_mp4_hevc_20480kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_320x240_mp4_h264_800kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_320x240_mp4_h264_800kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..12e07ce
--- /dev/null
+++ b/tests/tests/media/res/raw/video_320x240_mp4_h264_800kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..b060ca6
--- /dev/null
+++ b/tests/tests/media/res/raw/video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_320x240_webm_vp9_600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_320x240_webm_vp9_600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..086f144
--- /dev/null
+++ b/tests/tests/media/res/raw/video_320x240_webm_vp9_600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_352x288_mp4_hevc_600kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_352x288_mp4_hevc_600kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..4404877
--- /dev/null
+++ b/tests/tests/media/res/raw/video_352x288_mp4_hevc_600kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_3840x2160_webm_vp9_20480kbps_30fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_3840x2160_webm_vp9_20480kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..d6ed441
--- /dev/null
+++ b/tests/tests/media/res/raw/video_3840x2160_webm_vp9_20480kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz.webm b/tests/tests/media/res/raw/video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz.webm
deleted file mode 100644
index f64aec3..0000000
--- a/tests/tests/media/res/raw/video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz.webm
+++ /dev/null
Binary files differ
diff --git a/tests/tests/media/res/raw/video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..c101291
--- /dev/null
+++ b/tests/tests/media/res/raw/video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz.webm b/tests/tests/media/res/raw/video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz.webm
similarity index 86%
rename from tests/tests/media/res/raw/video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz.webm
rename to tests/tests/media/res/raw/video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz.webm
index 59b0c44..b17c5af 100644
--- a/tests/tests/media/res/raw/video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz.webm
+++ b/tests/tests/media/res/raw/video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_640x360_webm_vp8_2048kbps_30fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_640x360_webm_vp8_2048kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..60860f1
--- /dev/null
+++ b/tests/tests/media/res/raw/video_640x360_webm_vp8_2048kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_640x360_webm_vp9_1638kbps_30fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_640x360_webm_vp9_1638kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..418cc91
--- /dev/null
+++ b/tests/tests/media/res/raw/video_640x360_webm_vp9_1638kbps_30fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_720x480_mp4_h264_2048kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_720x480_mp4_h264_2048kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..055e217
--- /dev/null
+++ b/tests/tests/media/res/raw/video_720x480_mp4_h264_2048kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_720x480_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_720x480_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..87c6897
--- /dev/null
+++ b/tests/tests/media/res/raw/video_720x480_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
index dbe2c92..3b46360 100644
--- a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
@@ -50,7 +50,7 @@
public Iterable<Codec> H264(CodecFactory factory) {
return factory.createCodecList(
mContext,
- "video/avc",
+ MediaFormat.MIMETYPE_VIDEO_AVC,
"OMX.google.h264.decoder",
R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz);
@@ -59,7 +59,7 @@
public Iterable<Codec> HEVC(CodecFactory factory) {
return factory.createCodecList(
mContext,
- "video/hevc",
+ MediaFormat.MIMETYPE_VIDEO_HEVC,
"OMX.google.hevc.decoder",
R.raw.video_640x360_mp4_hevc_450kbps_30fps_aac_stereo_128kbps_48000hz,
R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz);
@@ -68,7 +68,7 @@
public Iterable<Codec> H263(CodecFactory factory) {
return factory.createCodecList(
mContext,
- "video/3gpp",
+ MediaFormat.MIMETYPE_VIDEO_H263,
"OMX.google.h263.decoder",
R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz,
R.raw.video_352x288_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz);
@@ -77,7 +77,7 @@
public Iterable<Codec> Mpeg4(CodecFactory factory) {
return factory.createCodecList(
mContext,
- "video/mp4v-es",
+ MediaFormat.MIMETYPE_VIDEO_MPEG4,
"OMX.google.mpeg4.decoder",
R.raw.video_1280x720_mp4_mpeg4_1000kbps_25fps_aac_stereo_128kbps_44100hz,
@@ -87,19 +87,19 @@
public Iterable<Codec> VP8(CodecFactory factory) {
return factory.createCodecList(
mContext,
- "video/x-vnd.on2.vp8",
+ MediaFormat.MIMETYPE_VIDEO_VP8,
"OMX.google.vp8.decoder",
- R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
- R.raw.video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz);
+ R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz,
+ R.raw.video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz);
}
public Iterable<Codec> VP9(CodecFactory factory) {
return factory.createCodecList(
mContext,
- "video/x-vnd.on2.vp9",
+ MediaFormat.MIMETYPE_VIDEO_VP9,
"OMX.google.vp9.decoder",
- R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
- R.raw.video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_44100hz);
+ R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz,
+ R.raw.video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_48000hz);
}
CodecFactory ALL = new CodecFactory();
@@ -1288,9 +1288,8 @@
}
/* enumerate codecs */
- int codecCount = MediaCodecList.getCodecCount();
- for (int codecIx = 0; codecIx < codecCount; codecIx++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(codecIx);
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ for (MediaCodecInfo codecInfo : mcl.getCodecInfos()) {
if (codecInfo.isEncoder()) {
continue;
}
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index e65fb0b..f7fcd0a 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -42,6 +42,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.media.AudioManager;
+import android.content.pm.PackageManager;
import android.media.MediaPlayer;
import android.os.Vibrator;
import android.provider.Settings;
@@ -56,6 +57,7 @@
private AudioManager mAudioManager;
private boolean mHasVibrator;
private boolean mUseFixedVolume;
+ private boolean mIsTelevision;
@Override
protected void setUp() throws Exception {
@@ -65,6 +67,10 @@
mHasVibrator = (vibrator != null) && vibrator.hasVibrator();
mUseFixedVolume = mContext.getResources().getBoolean(
Resources.getSystem().getIdentifier("config_useFixedVolume", "bool", "android"));
+ PackageManager packageManager = mContext.getPackageManager();
+ mIsTelevision = packageManager != null
+ && (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ || packageManager.hasSystemFeature(PackageManager.FEATURE_TELEVISION));
}
public void testMicrophoneMute() throws Exception {
@@ -171,7 +177,7 @@
}
public void testVibrateNotification() throws Exception {
- if (mUseFixedVolume) {
+ if (mUseFixedVolume || !mHasVibrator) {
return;
}
// VIBRATE_SETTING_ON
@@ -232,7 +238,7 @@
}
public void testVibrateRinger() throws Exception {
- if (mUseFixedVolume) {
+ if (mUseFixedVolume || !mHasVibrator) {
return;
}
// VIBRATE_TYPE_RINGER
@@ -298,14 +304,16 @@
assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- if (mUseFixedVolume) {
+ // AudioService#setRingerMode() has:
+ // if (isTelevision) return;
+ if (mUseFixedVolume || mIsTelevision) {
assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
} else {
assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
}
mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- if (mUseFixedVolume) {
+ if (mUseFixedVolume || mIsTelevision) {
assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
} else {
assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
diff --git a/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java b/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
index ff05246..c837d0a 100644
--- a/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
+++ b/tests/tests/media/src/android/media/cts/ClearKeySystemTest.java
@@ -24,6 +24,7 @@
import android.media.MediaCodecList;
import android.media.MediaDrm;
import android.media.MediaDrmException;
+import android.media.MediaFormat;
import android.media.CamcorderProfile;
import android.net.Uri;
import android.os.Environment;
@@ -63,7 +64,7 @@
private static final int VIDEO_WIDTH = 1280;
private static final int VIDEO_HEIGHT = 720;
private static final long PLAY_TIME_MS = TimeUnit.MILLISECONDS.convert(1, TimeUnit.MINUTES);
- private static final String MIME_VIDEO_AVC = "video/avc";
+ private static final String MIME_VIDEO_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
private static final Uri AUDIO_URL = Uri.parse(
"http://yt-dash-mse-test.commondatastorage.googleapis.com/media/car_cenc-20120827-8c.mp4");
@@ -303,104 +304,16 @@
}
}
- CodecCapabilities cap;
- int highestProfileLevel = 0;
- MediaCodecInfo codecInfo;
-
- for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
- codecInfo = MediaCodecList.getCodecInfoAt(i);
- if (codecInfo.isEncoder()) {
- continue;
- }
-
- String[] types = codecInfo.getSupportedTypes();
- for (int j = 0; j < types.length; ++j) {
- if (!types[j].equalsIgnoreCase(MIME_VIDEO_AVC)) {
- continue;
- }
-
- Log.d(TAG, "codec: " + codecInfo.getName() + "types: " + types[j]);
- cap = codecInfo.getCapabilitiesForType(types[j]);
- for (CodecProfileLevel profileLevel : cap.profileLevels) {
- Log.i(TAG, "codec " + codecInfo.getName() + ", level " + profileLevel.level);
- if (profileLevel.level > highestProfileLevel) {
- highestProfileLevel = profileLevel.level;
- }
- }
- Log.i(TAG, "codec " + codecInfo.getName() + ", highest level " + highestProfileLevel);
- }
+ MediaFormat format = MediaFormat.createVideoFormat(
+ MIME_VIDEO_AVC, videoWidth, videoHeight);
+ // using secure codec even though it is clear key DRM
+ format.setFeatureEnabled(CodecCapabilities.FEATURE_SecurePlayback, true);
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.ALL_CODECS);
+ if (mcl.findDecoderForFormat(format) == null) {
+ Log.i(TAG, "could not find codec for " + format);
+ return false;
}
-
- // AVCLevel and its resolution is taken from http://en.wikipedia.org/wiki/H.264/MPEG-4_AVC
- switch(highestProfileLevel) {
- case CodecProfileLevel.AVCLevel1:
- case CodecProfileLevel.AVCLevel1b:
- return (videoWidth <= 176 && videoHeight <= 144);
- case CodecProfileLevel.AVCLevel11:
- case CodecProfileLevel.AVCLevel12:
- case CodecProfileLevel.AVCLevel13:
- case CodecProfileLevel.AVCLevel2:
- return (videoWidth <= 352 && videoHeight <= 288);
- case CodecProfileLevel.AVCLevel21:
- return (videoWidth <= 352 && videoHeight <= 576);
- case CodecProfileLevel.AVCLevel22:
- case CodecProfileLevel.AVCLevel3:
- return (videoWidth <= 720 && videoHeight <= 576);
- case CodecProfileLevel.AVCLevel31:
- return (videoWidth <= 1280 && videoHeight <= 720);
- case CodecProfileLevel.AVCLevel32:
- return (videoWidth <= 1280 && videoHeight <= 1024);
- case CodecProfileLevel.AVCLevel4:
- case CodecProfileLevel.AVCLevel41:
- // 1280 x 720
- // 1920 x 1080
- // 2048 x 1024
- if (videoWidth <= 1920) {
- return (videoHeight <= 1080);
- } else if (videoWidth <= 2048) {
- return (videoHeight <= 1024);
- } else {
- return false;
- }
- case CodecProfileLevel.AVCLevel42:
- return (videoWidth <= 2048 && videoHeight <= 1080);
- case CodecProfileLevel.AVCLevel5:
- // 1920 x 1080
- // 2048 x 1024
- // 2048 x 1080
- // 2560 x 1920
- // 3672 x 1536
- if (videoWidth <= 1920) {
- return (videoHeight <= 1080);
- } else if (videoWidth <= 2048) {
- return (videoHeight <= 1080);
- } else if (videoWidth <= 2560) {
- return (videoHeight <= 1920);
- } else if (videoWidth <= 3672) {
- return (videoHeight <= 1536);
- } else {
- return false;
- }
- case CodecProfileLevel.AVCLevel51:
- default: // any future extension will cap at level 5.1
- // 1920 x 1080
- // 2560 x 1920
- // 3840 x 2160
- // 4096 x 2048
- // 4096 x 2160
- // 4096 x 2304
- if (videoWidth <= 1920) {
- return (videoHeight <= 1080);
- } else if (videoWidth <= 2560) {
- return (videoHeight <= 1920);
- } else if (videoWidth <= 3840) {
- return (videoHeight <= 2160);
- } else if (videoWidth <= 4096) {
- return (videoHeight <= 2304);
- } else {
- return false;
- }
- }
+ return true;
}
/**
@@ -410,7 +323,7 @@
if (!hasAudioOutput()) {
return;
}
-
+
MediaDrm drm = startDrm();
if (null == drm) {
throw new Error("Failed to create drm.");
diff --git a/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java b/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java
index 9ee3118..1ceb025 100644
--- a/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java
+++ b/tests/tests/media/src/android/media/cts/DecodeEditEncodeTest.java
@@ -53,7 +53,8 @@
private static final boolean DEBUG_SAVE_FILE = false; // save copy of encoded movie
// parameters for the encoder
- private static final String MIME_TYPE = "video/avc"; // H.264 Advanced Video Coding
+ // H.264 Advanced Video Coding
+ private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
private static final int FRAME_RATE = 15; // 15fps
private static final int IFRAME_INTERVAL = 10; // 10 seconds between I-frames
@@ -806,7 +807,7 @@
/**
- * The elementary stream coming out of the "video/avc" encoder needs to be fed back into
+ * The elementary stream coming out of the encoder needs to be fed back into
* the decoder one chunk at a time. If we just wrote the data to a file, we would lose
* the information about chunk boundaries. This class stores the encoded data in memory,
* retaining the chunk organization.
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index d71d38a..c8f2064 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -18,13 +18,15 @@
import com.android.cts.media.R;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
+import android.cts.util.MediaUtils;
import android.graphics.ImageFormat;
import android.media.Image;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.util.Log;
@@ -81,14 +83,15 @@
// TODO: add similar tests for other audio and video formats
public void testBug11696552() throws Exception {
- MediaCodec mMediaCodec = MediaCodec.createDecoderByType("audio/mp4a-latm");
- MediaFormat mFormat = MediaFormat.createAudioFormat("audio/mp4a-latm", 48000, 2);
+ MediaCodec mMediaCodec = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_AUDIO_AAC);
+ MediaFormat mFormat = MediaFormat.createAudioFormat(
+ MediaFormat.MIMETYPE_AUDIO_AAC, 48000 /* frequency */, 2 /* channels */);
mFormat.setByteBuffer("csd-0", ByteBuffer.wrap( new byte [] {0x13, 0x10} ));
mFormat.setInteger(MediaFormat.KEY_IS_ADTS, 1);
mMediaCodec.configure(mFormat, null, null, 0);
mMediaCodec.start();
int index = mMediaCodec.dequeueInputBuffer(250000);
- mMediaCodec.queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM );
+ mMediaCodec.queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
mMediaCodec.dequeueOutputBuffer(info, 250000);
}
@@ -165,20 +168,25 @@
}
public void testBFrames() throws Exception {
- testBFrames(R.raw.video_h264_main_b_frames);
- testBFrames(R.raw.video_h264_main_b_frames_frag);
+ int testsRun =
+ testBFrames(R.raw.video_h264_main_b_frames) +
+ testBFrames(R.raw.video_h264_main_b_frames_frag);
+ if (testsRun == 0) {
+ MediaUtils.skipTest("no codec found");
+ }
}
- public void testBFrames(int res) throws Exception {
+ public int testBFrames(int res) throws Exception {
AssetFileDescriptor fd = mResources.openRawResourceFd(res);
MediaExtractor ex = new MediaExtractor();
ex.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
MediaFormat format = ex.getTrackFormat(0);
String mime = format.getString(MediaFormat.KEY_MIME);
assertTrue("not a video track. Wrong test file?", mime.startsWith("video/"));
- if (!hasCodecForMimeType(mime, false)) {
- Log.i(TAG, "SKIPPING testBFrames(): Could not find a codec for mimeType: " + mime);
- return;
+ if (!MediaUtils.canDecode(format)) {
+ ex.release();
+ fd.close();
+ return 0; // skip
}
MediaCodec dec = MediaCodec.createDecoderByType(mime);
Surface s = getActivity().getSurfaceHolder().getSurface();
@@ -222,6 +230,8 @@
assertTrue("extractor timestamps were ordered, wrong test file?", inputoutoforder);
dec.release();
ex.release();
+ fd.close();
+ return 1;
}
private void testTrackSelection(int resid) throws Exception {
@@ -844,292 +854,312 @@
return numsamples;
}
- public void testCodecBasicH264() throws Exception {
- if (!hasH264(false)) {
- Log.i(TAG, "SKIPPING testCodecBasicH264(): No codec found.");
- return;
+ private void testDecode(int testVideo, int frameNum) throws Exception {
+ if (!MediaUtils.checkCodecForResource(mContext, testVideo, 0 /* track */)) {
+ return; // skip
}
- Surface s = getActivity().getSurfaceHolder().getSurface();
- int frames1 = countFrames(
- R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
- RESET_MODE_NONE, -1 /* eosframe */, s);
- assertEquals("wrong number of frames decoded", 240, frames1);
- int frames2 = countFrames(
- R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
- RESET_MODE_NONE, -1 /* eosframe */, null);
+ // Decode to Surface.
+ Surface s = getActivity().getSurfaceHolder().getSurface();
+ int frames1 = countFrames(testVideo, RESET_MODE_NONE, -1 /* eosframe */, s);
+ assertEquals("wrong number of frames decoded", frameNum, frames1);
+
+ // Decode to buffer.
+ int frames2 = countFrames(testVideo, RESET_MODE_NONE, -1 /* eosframe */, null);
assertEquals("different number of frames when using Surface", frames1, frames2);
}
+ public void testCodecBasicH264() throws Exception {
+ testDecode(R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, 240);
+ }
+
public void testCodecBasicHEVC() throws Exception {
- if (!hasHEVC(false)) {
- Log.i(TAG, "SKIPPING testCodecBasicHEVC(): No codec found.");
- return;
- }
- Surface s = getActivity().getSurfaceHolder().getSurface();
- int frames1 = countFrames(
- R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz,
- RESET_MODE_NONE, -1 /* eosframe */, s);
- assertEquals("wrong number of frames decoded", 300, frames1);
-
- int frames2 = countFrames(
- R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz,
- RESET_MODE_NONE, -1 /* eosframe */, null);
- assertEquals("different number of frames when using Surface", frames1, frames2);
+ testDecode(R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz, 300);
}
public void testCodecBasicH263() throws Exception {
- if (!hasH263(false)) {
- Log.i(TAG, "SKIPPING testCodecBasicH263(): No codec found.");
- return;
- }
- Surface s = getActivity().getSurfaceHolder().getSurface();
- int frames1 = countFrames(
- R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz,
- RESET_MODE_NONE, -1 /* eosframe */, s);
- assertEquals("wrong number of frames decoded", 122, frames1);
-
- int frames2 = countFrames(
- R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz,
- RESET_MODE_NONE, -1 /* eosframe */, null);
- assertEquals("different number of frames when using Surface", frames1, frames2);
+ testDecode(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz, 122);
}
public void testCodecBasicMpeg4() throws Exception {
- if (!hasMpeg4(false)) {
- Log.i(TAG, "SKIPPING testCodecBasicMpeg4(): No codec found.");
- return;
- }
- Surface s = getActivity().getSurfaceHolder().getSurface();
- int frames1 = countFrames(
- R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz,
- RESET_MODE_NONE, -1 /* eosframe */, s);
- assertEquals("wrong number of frames decoded", 249, frames1);
-
- int frames2 = countFrames(
- R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz,
- RESET_MODE_NONE, -1 /* eosframe */, null);
- assertEquals("different number of frames when using Surface", frames1, frames2);
+ testDecode(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz, 249);
}
public void testCodecBasicVP8() throws Exception {
- if (!hasVP8(false)) {
- Log.i(TAG, "SKIPPING testCodecBasicVP8(): No codec found.");
- return;
- }
- Surface s = getActivity().getSurfaceHolder().getSurface();
- int frames1 = countFrames(
- R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
- RESET_MODE_NONE, -1 /* eosframe */, s);
- assertEquals("wrong number of frames decoded", 240, frames1);
-
- int frames2 = countFrames(
- R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
- RESET_MODE_NONE, -1 /* eosframe */, null);
- assertEquals("different number of frames when using Surface", frames1, frames2);
+ testDecode(R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz, 240);
}
public void testCodecBasicVP9() throws Exception {
- if (!hasVP9(false)) {
- Log.i(TAG, "SKIPPING testCodecBasicVP9(): No codec found.");
- return;
+ testDecode(R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz, 240);
+ }
+
+ public void testH264Decode320x240() throws Exception {
+ testDecode(R.raw.video_320x240_mp4_h264_800kbps_30fps_aac_stereo_128kbps_44100hz, 299);
+ }
+
+ public void testH264Decode720x480() throws Exception {
+ testDecode(R.raw.video_720x480_mp4_h264_2048kbps_30fps_aac_stereo_128kbps_44100hz, 299);
+ }
+
+ public void testH264Decode30fps1280x720Tv() throws Exception {
+ if (checkTv()) {
+ assertTrue(MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720, 30));
+ }
+ }
+
+ public void testH264Decode30fps1280x720() throws Exception {
+ testDecode(R.raw.video_1280x720_mp4_h264_8192kbps_30fps_aac_stereo_128kbps_44100hz, 299);
+ }
+
+ public void testH264Decode60fps1280x720Tv() throws Exception {
+ if (checkTv()) {
+ assertTrue(MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720, 60));
+ }
+ }
+
+ public void testH264Decode60fps1280x720() throws Exception {
+ testDecode(R.raw.video_1280x720_mp4_h264_8192kbps_60fps_aac_stereo_128kbps_44100hz, 596);
+ }
+
+ public void testH264Decode30fps1920x1080Tv() throws Exception {
+ if (checkTv()) {
+ assertTrue(MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_AVC, 1920, 1080, 30));
+ }
+ }
+
+ public void testH264Decode30fps1920x1080() throws Exception {
+ testDecode(R.raw.video_1920x1080_mp4_h264_20480kbps_30fps_aac_stereo_128kbps_44100hz, 299);
+ }
+
+ public void testH264Decode60fps1920x1080Tv() throws Exception {
+ if (checkTv()) {
+ assertTrue(MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_AVC, 1920, 1080, 60));
+ }
+ }
+
+ public void testH264Decode60fps1920x1080() throws Exception {
+ testDecode(R.raw.video_1920x1080_mp4_h264_20480kbps_60fps_aac_stereo_128kbps_44100hz, 596);
+ }
+
+ public void testVP8Decode320x240() throws Exception {
+ testDecode(R.raw.video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_48000hz, 249);
+ }
+
+ public void testVP8Decode640x360() throws Exception {
+ testDecode(R.raw.video_640x360_webm_vp8_2048kbps_30fps_vorbis_stereo_128kbps_48000hz, 249);
+ }
+
+ public void testVP8Decode30fps1280x720Tv() throws Exception {
+ if (checkTv()) {
+ assertTrue(MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_VP8, 1280, 720, 30));
+ }
+ }
+
+ public void testVP8Decode30fps1280x720() throws Exception {
+ testDecode(R.raw.video_1280x720_webm_vp8_8192kbps_30fps_vorbis_stereo_128kbps_48000hz, 249);
+ }
+
+ public void testVP8Decode60fps1280x720Tv() throws Exception {
+ if (checkTv()) {
+ assertTrue(MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_VP8, 1280, 720, 60));
+ }
+ }
+
+ public void testVP8Decode60fps1280x720() throws Exception {
+ testDecode(R.raw.video_1280x720_webm_vp8_8192kbps_60fps_vorbis_stereo_128kbps_48000hz, 249);
+ }
+
+ public void testVP8Decode30fps1920x1080Tv() throws Exception {
+ if (checkTv()) {
+ assertTrue(MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_VP8, 1920, 1080, 30));
+ }
+ }
+
+ public void testVP8Decode30fps1920x1080() throws Exception {
+ testDecode(R.raw.video_1920x1080_webm_vp8_20480kbps_30fps_vorbis_stereo_128kbps_48000hz,
+ 249);
+ }
+
+ public void testVP8Decode60fps1920x1080Tv() throws Exception {
+ if (checkTv()) {
+ assertTrue(MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_VP8, 1920, 1080, 60));
+ }
+ }
+
+ public void testVP8Decode60fps1920x1080() throws Exception {
+ testDecode(R.raw.video_1920x1080_webm_vp8_20480kbps_60fps_vorbis_stereo_128kbps_48000hz,
+ 249);
+ }
+
+ public void testVP9Decode320x240() throws Exception {
+ testDecode(R.raw.video_320x240_webm_vp9_600kbps_30fps_vorbis_stereo_128kbps_48000hz, 249);
+ }
+
+ public void testVP9Decode640x360() throws Exception {
+ testDecode(R.raw.video_640x360_webm_vp9_1638kbps_30fps_vorbis_stereo_128kbps_48000hz, 249);
+ }
+
+ public void testVP9Decode30fps1280x720Tv() throws Exception {
+ if (checkTv()) {
+ assertTrue(MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_VP9, 1280, 720, 30));
+ }
+ }
+
+ public void testVP9Decode30fps1280x720() throws Exception {
+ testDecode(R.raw.video_1280x720_webm_vp9_4096kbps_30fps_vorbis_stereo_128kbps_48000hz, 249);
+ }
+
+ public void testVP9Decode30fps1920x1080() throws Exception {
+ testDecode(R.raw.video_1920x1080_webm_vp9_10240kbps_30fps_vorbis_stereo_128kbps_48000hz,
+ 249);
+ }
+
+ public void testVP9Decode30fps3840x2160() throws Exception {
+ testDecode(R.raw.video_3840x2160_webm_vp9_20480kbps_30fps_vorbis_stereo_128kbps_48000hz,
+ 249);
+ }
+
+ public void testHEVCDecode352x288() throws Exception {
+ testDecode(R.raw.video_352x288_mp4_hevc_600kbps_30fps_aac_stereo_128kbps_44100hz, 299);
+ }
+
+ public void testHEVCDecode720x480() throws Exception {
+ testDecode(R.raw.video_720x480_mp4_hevc_1638kbps_30fps_aac_stereo_128kbps_44100hz, 299);
+ }
+
+ public void testHEVCDecode30fps1280x720Tv() throws Exception {
+ if (checkTv()) {
+ assertTrue(MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_HEVC, 1280, 720, 30));
+ }
+ }
+
+ public void testHEVCDecode30fps1280x720() throws Exception {
+ testDecode(R.raw.video_1280x720_mp4_hevc_4096kbps_30fps_aac_stereo_128kbps_44100hz, 299);
+ }
+
+ public void testHEVCDecode30fps1920x1080Tv() throws Exception {
+ if (checkTv()) {
+ assertTrue(MediaUtils.canDecodeVideo(MediaFormat.MIMETYPE_VIDEO_HEVC, 1920, 1080, 30));
+ }
+ }
+
+ public void testHEVCDecode30fps1920x1080() throws Exception {
+ testDecode(R.raw.video_1920x1080_mp4_hevc_10240kbps_30fps_aac_stereo_128kbps_44100hz, 299);
+ }
+
+ public void testHEVCDecode30fps2840x2160() throws Exception {
+ testDecode(R.raw.video_2840x2160_mp4_hevc_20480kbps_30fps_aac_stereo_128kbps_44100hz, 299);
+ }
+
+ private void testCodecEarlyEOS(int resid, int eosFrame) throws Exception {
+ if (!MediaUtils.checkCodecForResource(mContext, resid, 0 /* track */)) {
+ return; // skip
}
Surface s = getActivity().getSurfaceHolder().getSurface();
- int frames1 = countFrames(
- R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
- RESET_MODE_NONE, -1 /* eosframe */, s);
- assertEquals("wrong number of frames decoded", 240, frames1);
-
- int frames2 = countFrames(
- R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
- RESET_MODE_NONE, -1 /* eosframe */, null);
- assertEquals("different number of frames when using Surface", frames1, frames2);
+ int frames1 = countFrames(resid, RESET_MODE_NONE, eosFrame, s);
+ assertEquals("wrong number of frames decoded", eosFrame, frames1);
}
public void testCodecEarlyEOSH263() throws Exception {
- if (!hasH263(false)) {
- Log.i(TAG, "SKIPPING testCodecEarlyEOSH263(): No codec found.");
- return;
- }
- Surface s = getActivity().getSurfaceHolder().getSurface();
- int frames1 = countFrames(
+ testCodecEarlyEOS(
R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz,
- RESET_MODE_NONE, 64 /* eosframe */, s);
- assertEquals("wrong number of frames decoded", 64, frames1);
+ 64 /* eosframe */);
}
public void testCodecEarlyEOSH264() throws Exception {
- if (!hasH264(false)) {
- Log.i(TAG, "SKIPPING testCodecEarlyEOSH264(): No codec found.");
- return;
- }
- Surface s = getActivity().getSurfaceHolder().getSurface();
- int frames1 = countFrames(
+ testCodecEarlyEOS(
R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
- RESET_MODE_NONE, 120 /* eosframe */, s);
- assertEquals("wrong number of frames decoded", 120, frames1);
+ 120 /* eosframe */);
}
public void testCodecEarlyEOSHEVC() throws Exception {
- if (!hasHEVC(false)) {
- Log.i(TAG, "SKIPPING testCodecEarlyEOSHEVC(): No codec found.");
- return;
- }
- Surface s = getActivity().getSurfaceHolder().getSurface();
- int frames1 = countFrames(
+ testCodecEarlyEOS(
R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz,
- RESET_MODE_NONE, 120 /* eosframe */, s);
- assertEquals("wrong number of frames decoded", 120, frames1);
+ 120 /* eosframe */);
}
public void testCodecEarlyEOSMpeg4() throws Exception {
- if (!hasMpeg4(false)) {
- Log.i(TAG, "SKIPPING testCodecEarlyEOSMpeg4(): No codec found.");
- return;
- }
- Surface s = getActivity().getSurfaceHolder().getSurface();
- int frames1 = countFrames(
+ testCodecEarlyEOS(
R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz,
- RESET_MODE_NONE, 120 /* eosframe */, s);
- assertEquals("wrong number of frames decoded", 120, frames1);
+ 120 /* eosframe */);
}
public void testCodecEarlyEOSVP8() throws Exception {
- if (!hasVP8(false)) {
- Log.i(TAG, "SKIPPING testCodecEarlyEOSVP8(): No codec found.");
- return;
- }
- Surface s = getActivity().getSurfaceHolder().getSurface();
- int frames1 = countFrames(
- R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
- RESET_MODE_NONE, 120 /* eosframe */, s);
- assertEquals("wrong number of frames decoded", 120, frames1);
+ testCodecEarlyEOS(
+ R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz,
+ 120 /* eosframe */);
}
public void testCodecEarlyEOSVP9() throws Exception {
- if (!hasVP9(false)) {
- Log.i(TAG, "SKIPPING testCodecEarlyEOSVP9(): No codec found.");
- return;
- }
- Surface s = getActivity().getSurfaceHolder().getSurface();
- int frames1 = countFrames(
- R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
- RESET_MODE_NONE, 120 /* eosframe */, s);
- assertEquals("wrong number of frames decoded", 120, frames1);
+ testCodecEarlyEOS(
+ R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz,
+ 120 /* eosframe */);
}
public void testCodecResetsH264WithoutSurface() throws Exception {
- if (!hasH264(false)) {
- Log.i(TAG, "SKIPPING testCodecResetsH264WithoutSurface(): No codec found.");
- return;
- }
testCodecResets(
R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, null);
}
public void testCodecResetsH264WithSurface() throws Exception {
- if (!hasH264(false)) {
- Log.i(TAG, "SKIPPING testCodecResetsH264WithSurface(): No codec found.");
- return;
- }
Surface s = getActivity().getSurfaceHolder().getSurface();
testCodecResets(
R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, s);
}
public void testCodecResetsHEVCWithoutSurface() throws Exception {
- if (!hasHEVC(false)) {
- Log.i(TAG, "SKIPPING testCodecResetsHEVCWithoutSurface(): No codec found.");
- return;
- }
testCodecResets(
R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz, null);
}
public void testCodecResetsHEVCWithSurface() throws Exception {
- if (!hasHEVC(false)) {
- Log.i(TAG, "SKIPPING testCodecResetsHEVCWithSurface(): No codec found.");
- return;
- }
Surface s = getActivity().getSurfaceHolder().getSurface();
testCodecResets(
R.raw.video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz, s);
}
public void testCodecResetsH263WithoutSurface() throws Exception {
- if (!hasH263(false)) {
- Log.i(TAG, "SKIPPING testCodecResetsH263WithoutSurface(): No codec found.");
- return;
- }
testCodecResets(
R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz, null);
}
public void testCodecResetsH263WithSurface() throws Exception {
- if (!hasH263(false)) {
- Log.i(TAG, "SKIPPING testCodecResetsH263WithSurface(): No codec found.");
- return;
- }
Surface s = getActivity().getSurfaceHolder().getSurface();
testCodecResets(
R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz, s);
}
public void testCodecResetsMpeg4WithoutSurface() throws Exception {
- if (!hasMpeg4(false)) {
- Log.i(TAG, "SKIPPING testCodecResetsMpeg4WithoutSurface(): No codec found.");
- return;
- }
testCodecResets(
R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz, null);
}
public void testCodecResetsMpeg4WithSurface() throws Exception {
- if (!hasMpeg4(false)) {
- Log.i(TAG, "SKIPPING testCodecResetsMpeg4WithSurface(): No codec found.");
- return;
- }
Surface s = getActivity().getSurfaceHolder().getSurface();
testCodecResets(
R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz, s);
}
public void testCodecResetsVP8WithoutSurface() throws Exception {
- if (!hasVP8(false)) {
- Log.i(TAG, "SKIPPING testCodecResetsVP8WithoutSurface(): No codec found.");
- return;
- }
testCodecResets(
- R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz, null);
+ R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz, null);
}
public void testCodecResetsVP8WithSurface() throws Exception {
- if (!hasVP8(false)) {
- Log.i(TAG, "SKIPPING testCodecResetsVP8WithSurface(): No codec found.");
- return;
- }
Surface s = getActivity().getSurfaceHolder().getSurface();
testCodecResets(
- R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz, s);
+ R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz, s);
}
public void testCodecResetsVP9WithoutSurface() throws Exception {
- if (!hasVP9(false)) {
- Log.i(TAG, "SKIPPING testCodecResetsVP9WithoutSurface(): No codec found.");
- return;
- }
testCodecResets(
- R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz, null);
+ R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz, null);
}
public void testCodecResetsVP9WithSurface() throws Exception {
- if (!hasVP9(false)) {
- Log.i(TAG, "SKIPPING testCodecResetsVP9WithSurface(): No codec found.");
- return;
- }
Surface s = getActivity().getSurfaceHolder().getSurface();
testCodecResets(
- R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz, s);
+ R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz, s);
}
// public void testCodecResetsOgg() throws Exception {
@@ -1155,6 +1185,10 @@
}
private void testCodecResets(int video, Surface s) throws Exception {
+ if (!MediaUtils.checkCodecForResource(mContext, video, 0 /* track */)) {
+ return; // skip
+ }
+
int frames1 = countFrames(video, RESET_MODE_NONE, -1 /* eosframe */, s);
int frames2 = countFrames(video, RESET_MODE_RECONFIGURE, -1 /* eosframe */, s);
int frames3 = countFrames(video, RESET_MODE_FLUSH, -1 /* eosframe */, s);
@@ -1234,11 +1268,8 @@
testFd.getLength());
extractor.selectTrack(0); // consider variable looping on track
MediaFormat format = extractor.getTrackFormat(0);
- String mimeType = format.getString(MediaFormat.KEY_MIME);
- if (!hasCodecForMimeType(mimeType, false)) {
- Log.i(TAG, "SKIPPING testEOSBehavior() for resid=" + movie + " No codec found for "
- + "mimeType = " + mimeType);
- return;
+ if (!MediaUtils.checkDecoderForFormat(format)) {
+ return; // skip
}
List<Long> outputChecksums = new ArrayList<Long>();
List<Long> outputTimestamps = new ArrayList<Long>();
@@ -1544,13 +1575,13 @@
public void testEOSBehaviorVP8() throws Exception {
// this video has an I frame at 46
- testEOSBehavior(R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
+ testEOSBehavior(R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz,
new int[] {46, 47, 57, 45});
}
public void testEOSBehaviorVP9() throws Exception {
// this video has an I frame at 44
- testEOSBehavior(R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
+ testEOSBehavior(R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz,
new int[] {44, 45, 55, 43});
}
diff --git a/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java b/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
index a480d97..0796515 100644
--- a/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeDecodeTest.java
@@ -51,8 +51,9 @@
private static final String DEBUG_FILE_NAME_BASE = "/sdcard/test.";
// parameters for the encoder
- private static final String MIME_TYPE_AVC = "video/avc"; // H.264 Advanced Video Coding
- private static final String MIME_TYPE_VP8 = "video/x-vnd.on2.vp8";
+ // H.264 Advanced Video Coding
+ private static final String MIME_TYPE_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
+ private static final String MIME_TYPE_VP8 = MediaFormat.MIMETYPE_VIDEO_VP8;
private static final int FRAME_RATE = 15; // 15fps
private static final int IFRAME_INTERVAL = 10; // 10 seconds between I-frames
@@ -297,20 +298,24 @@
mLargestColorDelta = -1;
try {
- MediaCodecInfo codecInfo = selectCodec(mMimeType);
- if (codecInfo == null) {
- // Don't fail CTS if they don't have an AVC codec (not here, anyway).
- Log.e(TAG, "Unable to find an appropriate codec for " + mMimeType);
- return;
- }
- if (VERBOSE) Log.d(TAG, "found codec: " + codecInfo.getName());
-
- int colorFormat = selectColorFormat(codecInfo, mMimeType);
- if (VERBOSE) Log.d(TAG, "found colorFormat: " + colorFormat);
-
// We avoid the device-specific limitations on width and height by using values that
// are multiples of 16, which all tested devices seem to be able to handle.
MediaFormat format = MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ String codec = mcl.findEncoderForFormat(format);
+ if (codec == null) {
+ // Don't fail CTS if they don't have an AVC codec (not here, anyway).
+ Log.e(TAG, "Unable to find an appropriate codec for " + format);
+ return;
+ }
+ if (VERBOSE) Log.d(TAG, "found codec: " + codec);
+
+ // Create a MediaCodec for the desired codec, then configure it as an encoder with
+ // our desired properties.
+ encoder = MediaCodec.createByCodecName(codec);
+
+ int colorFormat = selectColorFormat(encoder.getCodecInfo(), mMimeType);
+ if (VERBOSE) Log.d(TAG, "found colorFormat: " + colorFormat);
// Set some properties. Failing to specify some of these can cause the MediaCodec
// configure() call to throw an unhelpful exception.
@@ -320,9 +325,6 @@
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
if (VERBOSE) Log.d(TAG, "format: " + format);
- // Create a MediaCodec for the desired codec, then configure it as an encoder with
- // our desired properties.
- encoder = MediaCodec.createByCodecName(codecInfo.getName());
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
encoder.start();
@@ -362,19 +364,19 @@
mLargestColorDelta = -1;
try {
- MediaCodecInfo codecInfo = selectCodec(mMimeType);
- if (codecInfo == null) {
- // Don't fail CTS if they don't have an AVC codec (not here, anyway).
- Log.e(TAG, "Unable to find an appropriate codec for " + mMimeType);
- return;
- }
- if (VERBOSE) Log.d(TAG, "found codec: " + codecInfo.getName());
-
- int colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
-
// We avoid the device-specific limitations on width and height by using values that
// are multiples of 16, which all tested devices seem to be able to handle.
MediaFormat format = MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ String codec = mcl.findEncoderForFormat(format);
+ if (codec == null) {
+ // Don't fail CTS if they don't have an AVC codec (not here, anyway).
+ Log.e(TAG, "Unable to find an appropriate codec for " + format);
+ return;
+ }
+ if (VERBOSE) Log.d(TAG, "found codec: " + codec);
+
+ int colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
// Set some properties. Failing to specify some of these can cause the MediaCodec
// configure() call to throw an unhelpful exception.
@@ -396,7 +398,7 @@
// Create a MediaCodec for the desired codec, then configure it as an encoder with
// our desired properties. Request a Surface to use for input.
- encoder = MediaCodec.createByCodecName(codecInfo.getName());
+ encoder = MediaCodec.createByCodecName(codec);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
inputSurface = new InputSurface(encoder.createInputSurface());
encoder.start();
@@ -424,29 +426,6 @@
}
/**
- * Returns the first codec capable of encoding the specified MIME type, or null if no
- * match was found.
- */
- private static MediaCodecInfo selectCodec(String mimeType) {
- int numCodecs = MediaCodecList.getCodecCount();
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-
- if (!codecInfo.isEncoder()) {
- continue;
- }
-
- String[] types = codecInfo.getSupportedTypes();
- for (int j = 0; j < types.length; j++) {
- if (types[j].equalsIgnoreCase(mimeType)) {
- return codecInfo;
- }
- }
- }
- return null;
- }
-
- /**
* Returns a color format that is supported by the codec and by this test code. If no
* match is found, this throws a test failure -- the set of formats known to the test
* should be expanded for new platforms.
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
index 89b06dc..ba67a42 100755
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayTest.java
@@ -67,24 +67,24 @@
// Encoder parameters table, sort by encoder level from high to low.
private static final int[][] ENCODER_PARAM_TABLE = {
- // encoder level, width, height, bitrate, framerate
- {MediaCodecInfo.CodecProfileLevel.AVCLevel31, 1280, 720, 14000000, 30},
- {MediaCodecInfo.CodecProfileLevel.AVCLevel3, 720, 480, 10000000, 30},
- {MediaCodecInfo.CodecProfileLevel.AVCLevel22, 720, 480, 4000000, 15},
- {MediaCodecInfo.CodecProfileLevel.AVCLevel21, 352, 576, 4000000, 25},
+ // width, height, bitrate, framerate /* level */
+ { 1280, 720, 14000000, 30 }, /* AVCLevel31 */
+ { 720, 480, 10000000, 30 }, /* AVCLevel3 */
+ { 720, 480, 4000000, 15 }, /* AVCLevel22 */
+ { 352, 576, 4000000, 25 }, /* AVCLevel21 */
};
// Virtual display characteristics. Scaled down from full display size because not all
// devices can encode at the resolution of their own display.
private static final String NAME = TAG;
- private static int sWidth = ENCODER_PARAM_TABLE[ENCODER_PARAM_TABLE.length-1][1];
- private static int sHeight = ENCODER_PARAM_TABLE[ENCODER_PARAM_TABLE.length-1][2];
+ private static int sWidth = ENCODER_PARAM_TABLE[ENCODER_PARAM_TABLE.length-1][0];
+ private static int sHeight = ENCODER_PARAM_TABLE[ENCODER_PARAM_TABLE.length-1][1];
private static final int DENSITY = DisplayMetrics.DENSITY_HIGH;
private static final int UI_TIMEOUT_MS = 2000;
private static final int UI_RENDER_PAUSE_MS = 400;
// Encoder parameters. We use the same width/height as the virtual display.
- private static final String MIME_TYPE = "video/avc";
+ private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
private static int sFrameRate = 15; // 15fps
private static final int IFRAME_INTERVAL = 10; // 10 seconds between I-frames
private static int sBitRate = 6000000; // 6Mbps
@@ -161,56 +161,16 @@
}
}
- private static boolean hasCodec(String mimeType) {
- int numCodecs = MediaCodecList.getCodecCount();
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-
- if (!codecInfo.isEncoder()) {
- continue;
- }
-
- String[] types = codecInfo.getSupportedTypes();
- for (int j = 0; j < types.length; j++) {
- if (types[j].equalsIgnoreCase(mimeType)) {
- return true;
- }
- }
- }
- return false;
- }
-
/**
* Returns true if the encoder level, specified in the ENCODER_PARAM_TABLE, can be supported.
*/
- private static boolean verifySupportForEncoderLevel(int index) {
- int numCodecs = MediaCodecList.getCodecCount();
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-
- if (!codecInfo.isEncoder()) {
- continue;
- }
-
- String[] types = codecInfo.getSupportedTypes();
- for (int j = 0; j < types.length; j++) {
-
- if (false == types[j].equalsIgnoreCase(MIME_TYPE)) {
- continue;
- }
-
- MediaCodecInfo.CodecCapabilities caps = codecInfo.getCapabilitiesForType(types[j]);
- for (int k = 0; k < caps.profileLevels.length; k++) {
- int profile = caps.profileLevels[k].profile;
- int level = caps.profileLevels[k].level;
- //Log.d(TAG, "[" + k + "] supported profile = " + profile + ", level = " + level);
- if (caps.profileLevels[k].level >= ENCODER_PARAM_TABLE[index][0]) {
- return true;
- }
- }
- }
- }
- return false;
+ private static boolean verifySupportForEncoderLevel(int i) {
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ MediaFormat format = MediaFormat.createVideoFormat(
+ MIME_TYPE, ENCODER_PARAM_TABLE[i][0], ENCODER_PARAM_TABLE[i][1]);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, ENCODER_PARAM_TABLE[i][2]);
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, ENCODER_PARAM_TABLE[i][3]);
+ return mcl.findEncoderForFormat(format) != null;
}
/**
@@ -224,10 +184,10 @@
// Check if we can support it?
if (verifySupportForEncoderLevel(i)) {
- sWidth = ENCODER_PARAM_TABLE[i][1];
- sHeight = ENCODER_PARAM_TABLE[i][2];
- sBitRate = ENCODER_PARAM_TABLE[i][3];
- sFrameRate = ENCODER_PARAM_TABLE[i][4];
+ sWidth = ENCODER_PARAM_TABLE[i][0];
+ sHeight = ENCODER_PARAM_TABLE[i][1];
+ sBitRate = ENCODER_PARAM_TABLE[i][2];
+ sFrameRate = ENCODER_PARAM_TABLE[i][3];
Log.d(TAG, "encoder parameters changed: width = " + sWidth + ", height = " + sHeight
+ ", bitrate = " + sBitRate + ", framerate = " + sFrameRate);
@@ -245,11 +205,6 @@
OutputSurface outputSurface = null;
VirtualDisplay virtualDisplay = null;
- // Don't run the test of the codec isn't present.
- if (!hasCodec(MIME_TYPE)) {
- return;
- }
-
try {
// Encoded video resolution matches virtual display.
MediaFormat encoderFormat = MediaFormat.createVideoFormat(MIME_TYPE, sWidth, sHeight);
@@ -259,7 +214,15 @@
encoderFormat.setInteger(MediaFormat.KEY_FRAME_RATE, sFrameRate);
encoderFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
- encoder = MediaCodec.createEncoderByType(MIME_TYPE);
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ String codec = mcl.findEncoderForFormat(encoderFormat);
+ if (codec == null) {
+ // Don't run the test if the codec isn't present.
+ Log.i(TAG, "SKIPPING test: no support for " + encoderFormat);
+ return;
+ }
+
+ encoder = MediaCodec.createByCodecName(codec);
encoder.configure(encoderFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
Surface inputSurface = encoder.createInputSurface();
encoder.start();
diff --git a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
index 9c99c2d..89d6efa 100644
--- a/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
+++ b/tests/tests/media/src/android/media/cts/EncodeVirtualDisplayWithCompositionTest.java
@@ -46,7 +46,7 @@
import android.test.AndroidTestCase;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.Pair;
+import android.util.Size;
import android.view.Display;
import android.view.Surface;
import android.view.TextureView;
@@ -79,7 +79,7 @@
public class EncodeVirtualDisplayWithCompositionTest extends AndroidTestCase {
private static final String TAG = "EncodeVirtualDisplayWithCompositionTest";
private static final boolean DBG = true;
- private static final String MIME_TYPE = "video/avc";
+ private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
private static final long DEFAULT_WAIT_TIMEOUT_MS = 3000;
private static final long DEFAULT_WAIT_TIMEOUT_US = 3000000;
@@ -92,6 +92,8 @@
private static final int BITRATE_1080p = 20000000;
private static final int BITRATE_720p = 14000000;
private static final int BITRATE_800x480 = 14000000;
+ private static final int BITRATE_DEFAULT = 10000000;
+
private static final int IFRAME_INTERVAL = 10;
private static final int MAX_NUM_WINDOWS = 3;
@@ -138,79 +140,59 @@
public void testRendering800x480Locally() throws Throwable {
Log.i(TAG, "testRendering800x480Locally");
- Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
- if (maxRes == null) {
- Log.i(TAG, "SKIPPING testRendering800x480Locally(): codec not supported");
- return;
- }
- if (maxRes.first >= 800 && maxRes.second >= 480) {
+ if (isConcurrentEncodingDecodingSupported(800, 480, BITRATE_800x480)) {
runTestRenderingInSeparateThread(800, 480, false, false);
} else {
- Log.w(TAG, "This H/W does not support 800x480");
+ Log.i(TAG, "SKIPPING testRendering800x480Locally(): codec not supported");
}
}
public void testRenderingMaxResolutionLocally() throws Throwable {
Log.i(TAG, "testRenderingMaxResolutionLocally");
- Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
+ Size maxRes = checkMaxConcurrentEncodingDecodingResolution();
if (maxRes == null) {
Log.i(TAG, "SKIPPING testRenderingMaxResolutionLocally(): codec not supported");
- return;
+ } else {
+ Log.w(TAG, "Trying resolution " + maxRes);
+ runTestRenderingInSeparateThread(maxRes.getWidth(), maxRes.getHeight(), false, false);
}
- Log.w(TAG, "Trying resolution w:" + maxRes.first + " h:" + maxRes.second);
- runTestRenderingInSeparateThread(maxRes.first, maxRes.second, false, false);
}
public void testRendering800x480Remotely() throws Throwable {
Log.i(TAG, "testRendering800x480Remotely");
- Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
- if (maxRes == null) {
- Log.i(TAG, "SKIPPING testRendering800x480Remotely(): codec not supported");
- return;
- }
- if (maxRes.first >= 800 && maxRes.second >= 480) {
+ if (isConcurrentEncodingDecodingSupported(800, 480, BITRATE_800x480)) {
runTestRenderingInSeparateThread(800, 480, true, false);
} else {
- Log.w(TAG, "This H/W does not support 800x480");
+ Log.i(TAG, "SKIPPING testRendering800x480Remotely(): codec not supported");
}
}
public void testRenderingMaxResolutionRemotely() throws Throwable {
Log.i(TAG, "testRenderingMaxResolutionRemotely");
- Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
+ Size maxRes = checkMaxConcurrentEncodingDecodingResolution();
if (maxRes == null) {
Log.i(TAG, "SKIPPING testRenderingMaxResolutionRemotely(): codec not supported");
- return;
+ } else {
+ Log.w(TAG, "Trying resolution " + maxRes);
+ runTestRenderingInSeparateThread(maxRes.getWidth(), maxRes.getHeight(), true, false);
}
- Log.w(TAG, "Trying resolution w:" + maxRes.first + " h:" + maxRes.second);
- runTestRenderingInSeparateThread(maxRes.first, maxRes.second, true, false);
}
public void testRendering800x480RemotelyWith3Windows() throws Throwable {
Log.i(TAG, "testRendering800x480RemotelyWith3Windows");
- Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
- if (maxRes == null) {
- Log.i(TAG, "SKIPPING testRendering800x480RemotelyWith3Windows(): codec not supported");
- return;
- }
- if (maxRes.first >= 800 && maxRes.second >= 480) {
+ if (isConcurrentEncodingDecodingSupported(800, 480, BITRATE_800x480)) {
runTestRenderingInSeparateThread(800, 480, true, true);
} else {
- Log.w(TAG, "This H/W does not support 800x480");
+ Log.i(TAG, "SKIPPING testRendering800x480RemotelyWith3Windows(): codec not supported");
}
}
public void testRendering800x480LocallyWith3Windows() throws Throwable {
Log.i(TAG, "testRendering800x480LocallyWith3Windows");
- Pair<Integer, Integer> maxRes = checkMaxConcurrentEncodingDecodingResolution();
- if (maxRes == null) {
- Log.i(TAG, "SKIPPING testRendering800x480LocallyWith3Windows(): codec not supported");
- return;
- }
- if (maxRes.first >= 800 && maxRes.second >= 480) {
+ if (isConcurrentEncodingDecodingSupported(800, 480, BITRATE_800x480)) {
runTestRenderingInSeparateThread(800, 480, false, true);
} else {
- Log.w(TAG, "This H/W does not support 800x480");
+ Log.i(TAG, "SKIPPING testRendering800x480LocallyWith3Windows(): codec not supported");
}
}
@@ -424,8 +406,8 @@
private static final int NUM_DISPLAY_CREATION = 10;
private static final int NUM_RENDERING = 10;
private void doTestVirtualDisplayRecycles(int numDisplays) throws Exception {
- CodecInfo codecInfo = getAvcSupportedFormatInfo();
- if (codecInfo == null) {
+ Size maxSize = getMaxSupportedEncoderSize();
+ if (maxSize == null) {
Log.i(TAG, "no codec found, skipping");
return;
}
@@ -437,13 +419,13 @@
Log.i(TAG, "start encoding");
}
EncodingHelper encodingHelper = new EncodingHelper();
- mEncodingSurface = encodingHelper.startEncoding(codecInfo.mMaxW, codecInfo.mMaxH,
+ mEncodingSurface = encodingHelper.startEncoding(maxSize.getWidth(), maxSize.getHeight(),
mEncoderEventListener);
GlCompositor compositor = new GlCompositor();
if (DBG) {
Log.i(TAG, "start composition");
}
- compositor.startComposition(mEncodingSurface, codecInfo.mMaxW, codecInfo.mMaxH,
+ compositor.startComposition(mEncodingSurface, maxSize.getWidth(), maxSize.getHeight(),
numDisplays);
for (int j = 0; j < NUM_DISPLAY_CREATION; j++) {
if (DBG) {
@@ -453,7 +435,7 @@
virtualDisplays[k] =
new VirtualDisplayPresentation(getContext(),
compositor.getWindowSurface(k),
- codecInfo.mMaxW/numDisplays, codecInfo.mMaxH);
+ maxSize.getWidth()/numDisplays, maxSize.getHeight());
virtualDisplays[k].createVirtualDisplay();
virtualDisplays[k].createPresentation();
}
@@ -549,7 +531,7 @@
MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mW, mH);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
- int bitRate = 10000000;
+ int bitRate = BITRATE_DEFAULT;
if (mW == 1920 && mH == 1080) {
bitRate = BITRATE_1080p;
} else if (mW == 1280 && mH == 720) {
@@ -1335,152 +1317,56 @@
}
}
- private static class CodecInfo {
- public int mMaxW;
- public int mMaxH;
- public int mFps;
- public int mBitRate;
- public String mCodecName;
- };
+ private static Size getMaxSupportedEncoderSize() {
+ final Size[] standardSizes = new Size[] {
+ new Size(1920, 1080),
+ new Size(1280, 720),
+ new Size(720, 480),
+ new Size(352, 576)
+ };
- /**
- * Returns the first codec capable of encoding the specified MIME type, or null if no
- * match was found.
- */
- private static MediaCodecInfo selectCodec(String mimeType) {
- int numCodecs = MediaCodecList.getCodecCount();
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-
- if (!codecInfo.isEncoder()) {
- continue;
- }
-
- String[] types = codecInfo.getSupportedTypes();
- for (int j = 0; j < types.length; j++) {
- if (types[j].equalsIgnoreCase(mimeType)) {
- return codecInfo;
- }
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ for (Size sz : standardSizes) {
+ MediaFormat format = MediaFormat.createVideoFormat(
+ MIME_TYPE, sz.getWidth(), sz.getHeight());
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, 15); // require at least 15fps
+ if (mcl.findEncoderForFormat(format) != null) {
+ return sz;
}
}
return null;
}
- private static CodecInfo getAvcSupportedFormatInfo() {
- MediaCodecInfo mediaCodecInfo = selectCodec(MIME_TYPE);
- if (mediaCodecInfo == null) {
- return null;
- }
- CodecCapabilities cap = mediaCodecInfo.getCapabilitiesForType(MIME_TYPE);
- if (cap == null) { // not supported
- return null;
- }
- CodecInfo info = new CodecInfo();
- int highestLevel = 0;
- for (CodecProfileLevel lvl : cap.profileLevels) {
- if (lvl.level > highestLevel) {
- highestLevel = lvl.level;
- }
- }
- int maxW = 0;
- int maxH = 0;
- int bitRate = 0;
- int fps = 0; // frame rate for the max resolution
- switch(highestLevel) {
- // Do not support Level 1 to 2.
- case CodecProfileLevel.AVCLevel1:
- case CodecProfileLevel.AVCLevel11:
- case CodecProfileLevel.AVCLevel12:
- case CodecProfileLevel.AVCLevel13:
- case CodecProfileLevel.AVCLevel1b:
- case CodecProfileLevel.AVCLevel2:
- return null;
- case CodecProfileLevel.AVCLevel21:
- maxW = 352;
- maxH = 576;
- bitRate = 4000000;
- fps = 25;
- break;
- case CodecProfileLevel.AVCLevel22:
- maxW = 720;
- maxH = 480;
- bitRate = 4000000;
- fps = 15;
- break;
- case CodecProfileLevel.AVCLevel3:
- maxW = 720;
- maxH = 480;
- bitRate = 10000000;
- fps = 30;
- break;
- case CodecProfileLevel.AVCLevel31:
- maxW = 1280;
- maxH = 720;
- bitRate = 14000000;
- fps = 30;
- break;
- case CodecProfileLevel.AVCLevel32:
- maxW = 1280;
- maxH = 720;
- bitRate = 20000000;
- fps = 60;
- break;
- case CodecProfileLevel.AVCLevel4: // only try up to 1080p
- default:
- maxW = 1920;
- maxH = 1080;
- bitRate = 20000000;
- fps = 30;
- break;
- }
- info.mMaxW = maxW;
- info.mMaxH = maxH;
- info.mFps = fps;
- info.mBitRate = bitRate;
- info.mCodecName = mediaCodecInfo.getName();
- Log.i(TAG, "AVC Level 0x" + Integer.toHexString(highestLevel) + " bit rate " + bitRate +
- " fps " + info.mFps + " w " + maxW + " h " + maxH);
-
- return info;
- }
-
/**
* Check maximum concurrent encoding / decoding resolution allowed.
* Some H/Ws cannot support maximum resolution reported in encoder if decoder is running
* at the same time.
- * Check is done for 4 different levels: 1080p, 720p, 800x480 and max of encoder if is is
- * smaller than 800x480.
+ * Check is done for 4 different levels: 1080p, 720p, 800x480, 480p
+ * (The last one is required by CDD.)
*/
- private Pair<Integer, Integer> checkMaxConcurrentEncodingDecodingResolution() {
- CodecInfo codecInfo = getAvcSupportedFormatInfo();
- if (codecInfo == null) {
- return null;
+ private Size checkMaxConcurrentEncodingDecodingResolution() {
+ if (isConcurrentEncodingDecodingSupported(1920, 1080, BITRATE_1080p)) {
+ return new Size(1920, 1080);
+ } else if (isConcurrentEncodingDecodingSupported(1280, 720, BITRATE_720p)) {
+ return new Size(1280, 720);
+ } else if (isConcurrentEncodingDecodingSupported(800, 480, BITRATE_800x480)) {
+ return new Size(800, 480);
+ } else if (isConcurrentEncodingDecodingSupported(720, 480, BITRATE_DEFAULT)) {
+ return new Size(720, 480);
}
- int maxW = codecInfo.mMaxW;
- int maxH = codecInfo.mMaxH;
- if (maxW >= 1920 && maxH >= 1080) {
- if (isConcurrentEncodingDecodingSupported(1920, 1080, BITRATE_1080p)) {
- return new Pair<Integer, Integer>(1920, 1080);
- }
- }
- if (maxW >= 1280 && maxH >= 720) {
- if (isConcurrentEncodingDecodingSupported(1280, 720, BITRATE_720p)) {
- return new Pair<Integer, Integer>(1280, 720);
- }
- }
- if (maxW >= 800 && maxH >= 480) {
- if (isConcurrentEncodingDecodingSupported(800, 480, BITRATE_800x480)) {
- return new Pair<Integer, Integer>(800, 480);
- }
- }
- if (!isConcurrentEncodingDecodingSupported(codecInfo.mMaxW, codecInfo.mMaxH,
- codecInfo.mBitRate)) {
- fail("should work with advertised resolution");
- }
- return new Pair<Integer, Integer>(maxW, maxH);
+ Log.i(TAG, "SKIPPING test: concurrent encoding and decoding is not supported");
+ return null;
}
private boolean isConcurrentEncodingDecodingSupported(int w, int h, int bitRate) {
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ MediaFormat testFormat = MediaFormat.createVideoFormat(MIME_TYPE, w, h);
+ testFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
+ if (mcl.findDecoderForFormat(testFormat) == null
+ || mcl.findEncoderForFormat(testFormat) == null) {
+ return false;
+ }
+
MediaCodec decoder = null;
OutputSurface decodingSurface = null;
MediaCodec encoder = null;
diff --git a/tests/tests/media/src/android/media/cts/EncoderTest.java b/tests/tests/media/src/android/media/cts/EncoderTest.java
index c2e59d4..4b2a168 100644
--- a/tests/tests/media/src/android/media/cts/EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/EncoderTest.java
@@ -50,14 +50,14 @@
for (int j = 0; j < kBitRates.length; ++j) {
MediaFormat format = new MediaFormat();
- format.setString(MediaFormat.KEY_MIME, "audio/3gpp");
+ format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AMR_NB);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 8000);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
format.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates[j]);
formats.push(format);
}
- testEncoderWithFormats("audio/3gpp", formats);
+ testEncoderWithFormats(MediaFormat.MIMETYPE_AUDIO_AMR_NB, formats);
}
public void testAMRWBEncoders() {
@@ -68,14 +68,14 @@
for (int j = 0; j < kBitRates.length; ++j) {
MediaFormat format = new MediaFormat();
- format.setString(MediaFormat.KEY_MIME, "audio/amr-wb");
+ format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AMR_WB);
format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 16000);
format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
format.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates[j]);
formats.push(format);
}
- testEncoderWithFormats("audio/amr-wb", formats);
+ testEncoderWithFormats(MediaFormat.MIMETYPE_AUDIO_AMR_WB, formats);
}
public void testAACEncoders() {
@@ -99,7 +99,7 @@
for (int j = 0; j < kBitRates.length; ++j) {
for (int ch = 1; ch <= 2; ++ch) {
MediaFormat format = new MediaFormat();
- format.setString(MediaFormat.KEY_MIME, "audio/mp4a-latm");
+ format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AAC);
format.setInteger(
MediaFormat.KEY_AAC_PROFILE, kAACProfiles[k]);
@@ -115,7 +115,7 @@
}
}
- testEncoderWithFormats("audio/mp4a-latm", formats);
+ testEncoderWithFormats(MediaFormat.MIMETYPE_AUDIO_AAC, formats);
}
private void testEncoderWithFormats(
@@ -135,27 +135,13 @@
private List<String> getEncoderNamesForType(String mime) {
LinkedList<String> names = new LinkedList<String>();
- int n = MediaCodecList.getCodecCount();
- for (int i = 0; i < n; ++i) {
- MediaCodecInfo info = MediaCodecList.getCodecInfoAt(i);
-
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ for (MediaCodecInfo info : mcl.getCodecInfos()) {
if (!info.isEncoder()) {
continue;
}
-
- 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 '" + info.getName() + "'.");
- continue;
- }
-
- String[] supportedTypes = info.getSupportedTypes();
-
- for (int j = 0; j < supportedTypes.length; ++j) {
- if (supportedTypes[j].equalsIgnoreCase(mime)) {
+ for (String type : info.getSupportedTypes()) {
+ if (type.equalsIgnoreCase(mime)) {
names.push(info.getName());
break;
}
diff --git a/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java b/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
index 43b769a..029a632 100644
--- a/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
+++ b/tests/tests/media/src/android/media/cts/ExtractDecodeEditEncodeMuxTest.java
@@ -62,16 +62,18 @@
private static final File OUTPUT_FILENAME_DIR = Environment.getExternalStorageDirectory();
// parameters for the video encoder
- private static final String OUTPUT_VIDEO_MIME_TYPE = "video/avc"; // H.264 Advanced Video Coding
- private static final int OUTPUT_VIDEO_BIT_RATE = 2000000; // 2Mbps
- private static final int OUTPUT_VIDEO_FRAME_RATE = 15; // 15fps
+ // H.264 Advanced Video Coding
+ private static final String OUTPUT_VIDEO_MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
+ private static final int OUTPUT_VIDEO_BIT_RATE = 2000000; // 2Mbps
+ private static final int OUTPUT_VIDEO_FRAME_RATE = 15; // 15fps
private static final int OUTPUT_VIDEO_IFRAME_INTERVAL = 10; // 10 seconds between I-frames
private static final int OUTPUT_VIDEO_COLOR_FORMAT =
MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
// parameters for the audio encoder
- private static final String OUTPUT_AUDIO_MIME_TYPE = "audio/mp4a-latm"; // Advanced Audio Coding
- private static final int OUTPUT_AUDIO_CHANNEL_COUNT = 2; // Must match the input stream.
+ // Advanced Audio Coding
+ private static final String OUTPUT_AUDIO_MIME_TYPE = MediaFormat.MIMETYPE_AUDIO_AAC;
+ private static final int OUTPUT_AUDIO_CHANNEL_COUNT = 2; // Must match the input stream.
private static final int OUTPUT_AUDIO_BIT_RATE = 128 * 1024;
private static final int OUTPUT_AUDIO_AAC_PROFILE =
MediaCodecInfo.CodecProfileLevel.AACObjectHE;
@@ -259,21 +261,45 @@
// Exception that may be thrown during release.
Exception exception = null;
- MediaCodecInfo videoCodecInfo = selectCodec(OUTPUT_VIDEO_MIME_TYPE);
- if (videoCodecInfo == null) {
- // Don't fail CTS if they don't have an AVC codec (not here, anyway).
- Log.e(TAG, "Unable to find an appropriate codec for " + OUTPUT_VIDEO_MIME_TYPE);
- return;
- }
- if (VERBOSE) Log.d(TAG, "video found codec: " + videoCodecInfo.getName());
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- MediaCodecInfo audioCodecInfo = selectCodec(OUTPUT_AUDIO_MIME_TYPE);
- if (audioCodecInfo == null) {
- // Don't fail CTS if they don't have an AAC codec (not here, anyway).
- Log.e(TAG, "Unable to find an appropriate codec for " + OUTPUT_AUDIO_MIME_TYPE);
+ // We avoid the device-specific limitations on width and height by using values
+ // that are multiples of 16, which all tested devices seem to be able to handle.
+ MediaFormat outputVideoFormat =
+ MediaFormat.createVideoFormat(OUTPUT_VIDEO_MIME_TYPE, mWidth, mHeight);
+
+ // Set some properties. Failing to specify some of these can cause the MediaCodec
+ // configure() call to throw an unhelpful exception.
+ outputVideoFormat.setInteger(
+ MediaFormat.KEY_COLOR_FORMAT, OUTPUT_VIDEO_COLOR_FORMAT);
+ outputVideoFormat.setInteger(MediaFormat.KEY_BIT_RATE, OUTPUT_VIDEO_BIT_RATE);
+ outputVideoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, OUTPUT_VIDEO_FRAME_RATE);
+ outputVideoFormat.setInteger(
+ MediaFormat.KEY_I_FRAME_INTERVAL, OUTPUT_VIDEO_IFRAME_INTERVAL);
+ if (VERBOSE) Log.d(TAG, "video format: " + outputVideoFormat);
+
+ String videoEncoderName = mcl.findEncoderForFormat(outputVideoFormat);
+ if (videoEncoderName == null) {
+ // Don't fail CTS if they don't have an AVC codec (not here, anyway).
+ Log.e(TAG, "Unable to find an appropriate codec for " + outputVideoFormat);
return;
}
- if (VERBOSE) Log.d(TAG, "audio found codec: " + audioCodecInfo.getName());
+ if (VERBOSE) Log.d(TAG, "video found codec: " + videoEncoderName);
+
+ MediaFormat outputAudioFormat =
+ MediaFormat.createAudioFormat(
+ OUTPUT_AUDIO_MIME_TYPE, OUTPUT_AUDIO_SAMPLE_RATE_HZ,
+ OUTPUT_AUDIO_CHANNEL_COUNT);
+ outputAudioFormat.setInteger(MediaFormat.KEY_BIT_RATE, OUTPUT_AUDIO_BIT_RATE);
+ outputAudioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, OUTPUT_AUDIO_AAC_PROFILE);
+
+ String audioEncoderName = mcl.findEncoderForFormat(outputAudioFormat);
+ if (audioEncoderName == null) {
+ // Don't fail CTS if they don't have an AAC codec (not here, anyway).
+ Log.e(TAG, "Unable to find an appropriate codec for " + outputAudioFormat);
+ return;
+ }
+ if (VERBOSE) Log.d(TAG, "audio found codec: " + audioEncoderName);
MediaExtractor videoExtractor = null;
MediaExtractor audioExtractor = null;
@@ -293,32 +319,17 @@
assertTrue("missing video track in test video", videoInputTrack != -1);
MediaFormat inputFormat = videoExtractor.getTrackFormat(videoInputTrack);
- // We avoid the device-specific limitations on width and height by using values
- // that are multiples of 16, which all tested devices seem to be able to handle.
- MediaFormat outputVideoFormat =
- MediaFormat.createVideoFormat(OUTPUT_VIDEO_MIME_TYPE, mWidth, mHeight);
-
- // Set some properties. Failing to specify some of these can cause the MediaCodec
- // configure() call to throw an unhelpful exception.
- outputVideoFormat.setInteger(
- MediaFormat.KEY_COLOR_FORMAT, OUTPUT_VIDEO_COLOR_FORMAT);
- outputVideoFormat.setInteger(MediaFormat.KEY_BIT_RATE, OUTPUT_VIDEO_BIT_RATE);
- outputVideoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, OUTPUT_VIDEO_FRAME_RATE);
- outputVideoFormat.setInteger(
- MediaFormat.KEY_I_FRAME_INTERVAL, OUTPUT_VIDEO_IFRAME_INTERVAL);
- if (VERBOSE) Log.d(TAG, "video format: " + outputVideoFormat);
-
// Create a MediaCodec for the desired codec, then configure it as an encoder with
// our desired properties. Request a Surface to use for input.
AtomicReference<Surface> inputSurfaceReference = new AtomicReference<Surface>();
videoEncoder = createVideoEncoder(
- videoCodecInfo, outputVideoFormat, inputSurfaceReference);
+ videoEncoderName, outputVideoFormat, inputSurfaceReference);
inputSurface = new InputSurface(inputSurfaceReference.get());
inputSurface.makeCurrent();
// Create a MediaCodec for the decoder, based on the extractor's format.
outputSurface = new OutputSurface();
outputSurface.changeFragmentShader(FRAGMENT_SHADER);
- videoDecoder = createVideoDecoder(inputFormat, outputSurface.getSurface());
+ videoDecoder = createVideoDecoder(mcl, inputFormat, outputSurface.getSurface());
}
if (mCopyAudio) {
@@ -327,18 +338,11 @@
assertTrue("missing audio track in test video", audioInputTrack != -1);
MediaFormat inputFormat = audioExtractor.getTrackFormat(audioInputTrack);
- MediaFormat outputAudioFormat =
- MediaFormat.createAudioFormat(
- OUTPUT_AUDIO_MIME_TYPE, OUTPUT_AUDIO_SAMPLE_RATE_HZ,
- OUTPUT_AUDIO_CHANNEL_COUNT);
- outputAudioFormat.setInteger(MediaFormat.KEY_BIT_RATE, OUTPUT_AUDIO_BIT_RATE);
- outputAudioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, OUTPUT_AUDIO_AAC_PROFILE);
-
// Create a MediaCodec for the desired codec, then configure it as an encoder with
// our desired properties. Request a Surface to use for input.
- audioEncoder = createAudioEncoder(audioCodecInfo, outputAudioFormat);
+ audioEncoder = createAudioEncoder(audioEncoderName, outputAudioFormat);
// Create a MediaCodec for the decoder, based on the extractor's format.
- audioDecoder = createAudioDecoder(inputFormat);
+ audioDecoder = createAudioDecoder(mcl, inputFormat);
}
// Creates a muxer but do not start or add tracks just yet.
@@ -517,9 +521,9 @@
* @param inputFormat the format of the stream to decode
* @param surface into which to decode the frames
*/
- private MediaCodec createVideoDecoder(MediaFormat inputFormat, Surface surface)
- throws IOException {
- MediaCodec decoder = MediaCodec.createDecoderByType(getMimeTypeFor(inputFormat));
+ private MediaCodec createVideoDecoder(
+ MediaCodecList mcl, MediaFormat inputFormat, Surface surface) throws IOException {
+ MediaCodec decoder = MediaCodec.createByCodecName(mcl.findDecoderForFormat(inputFormat));
decoder.configure(inputFormat, surface, null, 0);
decoder.start();
return decoder;
@@ -536,11 +540,11 @@
* @param surfaceReference to store the surface to use as input
*/
private MediaCodec createVideoEncoder(
- MediaCodecInfo codecInfo,
+ String codecName,
MediaFormat format,
AtomicReference<Surface> surfaceReference)
throws IOException {
- MediaCodec encoder = MediaCodec.createByCodecName(codecInfo.getName());
+ MediaCodec encoder = MediaCodec.createByCodecName(codecName);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
// Must be called before start() is.
surfaceReference.set(encoder.createInputSurface());
@@ -553,9 +557,9 @@
*
* @param inputFormat the format of the stream to decode
*/
- private MediaCodec createAudioDecoder(MediaFormat inputFormat)
- throws IOException {
- MediaCodec decoder = MediaCodec.createDecoderByType(getMimeTypeFor(inputFormat));
+ private MediaCodec createAudioDecoder(
+ MediaCodecList mcl, MediaFormat inputFormat) throws IOException {
+ MediaCodec decoder = MediaCodec.createByCodecName(mcl.findDecoderForFormat(inputFormat));
decoder.configure(inputFormat, null, null, 0);
decoder.start();
return decoder;
@@ -567,9 +571,9 @@
* @param codecInfo of the codec to use
* @param format of the stream to be produced
*/
- private MediaCodec createAudioEncoder(MediaCodecInfo codecInfo, MediaFormat format)
+ private MediaCodec createAudioEncoder(String codecName, MediaFormat format)
throws IOException {
- MediaCodec encoder = MediaCodec.createByCodecName(codecInfo.getName());
+ MediaCodec encoder = MediaCodec.createByCodecName(codecName);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
encoder.start();
return encoder;
@@ -1126,28 +1130,4 @@
private static String getMimeTypeFor(MediaFormat format) {
return format.getString(MediaFormat.KEY_MIME);
}
-
- /**
- * Returns the first codec capable of encoding the specified MIME type, or null if no match was
- * found.
- */
- private static MediaCodecInfo selectCodec(String mimeType) {
- int numCodecs = MediaCodecList.getCodecCount();
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-
- if (!codecInfo.isEncoder()) {
- continue;
- }
-
- String[] types = codecInfo.getSupportedTypes();
- for (int j = 0; j < types.length; j++) {
- if (types[j].equalsIgnoreCase(mimeType)) {
- return codecInfo;
- }
- }
- }
- return null;
- }
-
}
diff --git a/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java b/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java
index 9528db9..5f326ee 100644
--- a/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/ImageReaderDecoderTest.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
+import android.cts.util.MediaUtils;
import android.graphics.ImageFormat;
import android.media.Image;
import android.media.Image.Plane;
@@ -28,7 +29,6 @@
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
-import android.media.MediaCodecList;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Handler;
@@ -100,10 +100,6 @@
* to be supported by hw decoder.
*/
public void testHwAVCDecode360pForFlexibleYuv() throws Exception {
- if (!MediaPlayerTestBase.hasH264(false)) {
- Log.i(TAG, "SKIPPING testSwAVCDecode360pForFlexibleYuv(): no codec found.");
- return;
- }
try {
int format = ImageFormat.YUV_420_888;
videoDecodeToSurface(
@@ -119,10 +115,6 @@
* to be supported by sw decoder.
*/
public void testSwAVCDecode360pForFlexibleYuv() throws Exception {
- if (!MediaPlayerTestBase.hasH264(false)) {
- Log.i(TAG, "SKIPPING testSwAVCDecode360pForFlexibleYuv(): no codec found.");
- return;
- }
try {
int format = ImageFormat.YUV_420_888;
videoDecodeToSurface(
@@ -168,6 +160,10 @@
ByteBuffer[] decoderInputBuffers;
ByteBuffer[] decoderOutputBuffers;
+ if (!MediaUtils.checkCodecForResource(mContext, video, 0 /* track */)) {
+ return; // skip
+ }
+
AssetFileDescriptor vidFD = mResources.openRawResourceFd(video);
extractor = new MediaExtractor();
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
index 723652f..afed27b 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecCapabilitiesTest.java
@@ -16,10 +16,15 @@
package android.media.cts;
import android.content.pm.PackageManager;
+import android.cts.util.MediaUtils;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.CodecProfileLevel;
+import static android.media.MediaCodecInfo.CodecProfileLevel.*;
+import static android.media.MediaFormat.MIMETYPE_VIDEO_AVC;
+import static android.media.MediaFormat.MIMETYPE_VIDEO_HEVC;
import android.media.MediaCodecList;
+import android.media.MediaFormat;
import android.media.MediaPlayer;
import android.os.Build;
@@ -32,27 +37,84 @@
public class MediaCodecCapabilitiesTest extends MediaPlayerTestBase {
private static final String TAG = "MediaCodecCapabilitiesTest";
- private static final String AVC_MIME = "video/avc";
- private static final String HEVC_MIME = "video/hevc";
private static final int PLAY_TIME_MS = 30000;
- public void testAvcBaseline1() throws Exception {
- if (hasCodec(AVC_MIME) && !supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline,
- CodecProfileLevel.AVCLevel1)) {
- throw new RuntimeException("AVCLevel1 support is required by CDD");
+ // Android device implementations with H.264 encoders, MUST support Baseline Profile Level 3.
+ // SHOULD support Main Profile/ Level 4, if supported the device must also support Main
+ // Profile/Level 4 decoding.
+ public void testH264EncoderProfileAndLevel() throws Exception {
+ if (!MediaUtils.checkEncoder(MIMETYPE_VIDEO_AVC)) {
+ return; // skip
}
- // We don't have a test stream, but at least we're testing
- // that supports() returns true for something.
+
+ assertTrue(
+ "H.264 must support Baseline Profile Level 3",
+ hasEncoder(MIMETYPE_VIDEO_AVC, AVCProfileBaseline, AVCLevel3));
+
+ if (hasEncoder(MIMETYPE_VIDEO_AVC, AVCProfileMain, AVCLevel4)) {
+ assertTrue(
+ "H.264 decoder must support Main Profile Level 4 if it can encode it",
+ hasDecoder(MIMETYPE_VIDEO_AVC, AVCProfileMain, AVCLevel4));
+ }
+ }
+
+ // Android device implementations with H.264 decoders, MUST support Baseline Profile Level 3.
+ // Android Television Devices MUST support High Profile Level 4.2.
+ public void testH264DecoderProfileAndLevel() throws Exception {
+ if (!MediaUtils.checkDecoder(MIMETYPE_VIDEO_AVC)) {
+ return; // skip
+ }
+
+ assertTrue(
+ "H.264 must support Baseline Profile Level 3",
+ hasDecoder(MIMETYPE_VIDEO_AVC, AVCProfileBaseline, AVCLevel3));
+
+ if (isTv()) {
+ assertTrue(
+ "H.264 must support High Profile Level 4.2 on TV",
+ checkDecoder(MIMETYPE_VIDEO_AVC, AVCProfileHigh, AVCLevel42));
+ }
+ }
+
+ // Android device implementations, when supporting H.265 codec MUST support the Main Profile
+ // Level 3 Main tier.
+ // Android Television Devices MUST support the Main Profile Level 4.1 Main tier.
+ // When the UHD video decoding profile is supported, it MUST support Main10 Level 5 Main
+ // Tier profile.
+ public void testH265DecoderProfileAndLevel() throws Exception {
+ if (!MediaUtils.checkDecoder(MIMETYPE_VIDEO_HEVC)) {
+ return; // skip
+ }
+
+ assertTrue(
+ "H.265 must support Main Profile Main Tier Level 3",
+ hasDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain, HEVCMainTierLevel3));
+
+ if (isTv()) {
+ assertTrue(
+ "H.265 must support Main Profile Main Tier Level 4.1 on TV",
+ hasDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain, HEVCMainTierLevel41));
+ }
+
+ if (MediaUtils.canDecodeVideo(MIMETYPE_VIDEO_HEVC, 3840, 2160, 30)) {
+ assertTrue(
+ "H.265 must support Main10 Profile Main Tier Level 5 if UHD is supported",
+ hasDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain10, HEVCMainTierLevel5));
+ }
+ }
+
+ public void testAvcBaseline1() throws Exception {
+ if (!checkDecoder(MIMETYPE_VIDEO_AVC, AVCProfileBaseline, AVCLevel1)) {
+ return; // skip
+ }
+
+ // TODO: add a test stream
+ MediaUtils.skipTest(TAG, "no test stream");
}
public void testAvcBaseline12() throws Exception {
- if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline)) {
- return;
- }
- if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline,
- CodecProfileLevel.AVCLevel12)) {
- Log.i(TAG, "AvcBaseline12 not supported");
- return; // TODO: Can we make this mandatory?
+ if (!checkDecoder(MIMETYPE_VIDEO_AVC, AVCProfileBaseline, AVCLevel12)) {
+ return; // skip
}
playVideoWithRetries("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=160&source=youtube&user=android-device-test"
@@ -64,13 +126,8 @@
}
public void testAvcBaseline30() throws Exception {
- if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline)) {
- return;
- }
- if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileBaseline,
- CodecProfileLevel.AVCLevel3)) {
- Log.i(TAG, "AvcBaseline30 not supported");
- return;
+ if (!checkDecoder(MIMETYPE_VIDEO_AVC, AVCProfileBaseline, AVCLevel3)) {
+ return; // skip
}
playVideoWithRetries("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=18&source=youtube&user=android-device-test"
@@ -82,13 +139,8 @@
}
public void testAvcHigh31() throws Exception {
- if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileHigh)) {
- return;
- }
- if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileHigh,
- CodecProfileLevel.AVCLevel31)) {
- Log.i(TAG, "AvcHigh31 not supported");
- return;
+ if (!checkDecoder(MIMETYPE_VIDEO_AVC, AVCProfileHigh, AVCLevel31)) {
+ return; // skip
}
playVideoWithRetries("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
+ "&itag=22&source=youtube&user=android-device-test"
@@ -101,16 +153,11 @@
}
public void testAvcHigh40() throws Exception {
- if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileHigh)) {
- return;
- }
- if (!supports(AVC_MIME, CodecProfileLevel.AVCProfileHigh,
- CodecProfileLevel.AVCLevel4)) {
- Log.i(TAG, "AvcHigh40 not supported");
- return;
+ if (!checkDecoder(MIMETYPE_VIDEO_AVC, AVCProfileHigh, AVCLevel4)) {
+ return; // skip
}
if (Build.VERSION.SDK_INT < 18) {
- Log.i(TAG, "fragmented mp4 not supported");
+ MediaUtils.skipTest(TAG, "fragmented mp4 not supported");
return;
}
playVideoWithRetries("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
@@ -123,126 +170,118 @@
}
public void testHevcMain1() throws Exception {
- if (hasCodec(HEVC_MIME) && !supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
- CodecProfileLevel.HEVCMainTierLevel1)) {
- throw new RuntimeException("HECLevel1 support is required by CDD");
+ if (!checkDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain, HEVCMainTierLevel1)) {
+ return; // skip
}
- // We don't have a test stream, but at least we're testing
- // that supports() returns true for something.
+
+ // TODO: add a test stream
+ MediaUtils.skipTest(TAG, "no test stream");
}
+
public void testHevcMain2() throws Exception {
- if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
- CodecProfileLevel.HEVCMainTierLevel2)) {
- Log.i(TAG, "HevcMain2 not supported");
- return;
+ if (!checkDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain, HEVCMainTierLevel2)) {
+ return; // skip
}
+
+ // TODO: add a test stream
+ MediaUtils.skipTest(TAG, "no test stream");
}
public void testHevcMain21() throws Exception {
- if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
- CodecProfileLevel.HEVCMainTierLevel21)) {
- Log.i(TAG, "HevcMain21 not supported");
- return;
+ if (!checkDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain, HEVCMainTierLevel21)) {
+ return; // skip
}
+
+ // TODO: add a test stream
+ MediaUtils.skipTest(TAG, "no test stream");
}
public void testHevcMain3() throws Exception {
- if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
- CodecProfileLevel.HEVCMainTierLevel3)) {
- Log.i(TAG, "HevcMain3 not supported");
- return;
+ if (!checkDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain, HEVCMainTierLevel3)) {
+ return; // skip
}
+
+ // TODO: add a test stream
+ MediaUtils.skipTest(TAG, "no test stream");
}
public void testHevcMain31() throws Exception {
- if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
- CodecProfileLevel.HEVCMainTierLevel31)) {
- Log.i(TAG, "HevcMain31 not supported");
- return;
+ if (!checkDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain, HEVCMainTierLevel31)) {
+ return; // skip
}
+
+ // TODO: add a test stream
+ MediaUtils.skipTest(TAG, "no test stream");
}
public void testHevcMain4() throws Exception {
- if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
- CodecProfileLevel.HEVCMainTierLevel4)) {
- Log.i(TAG, "HevcMain4 not supported");
- return;
+ if (!checkDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain, HEVCMainTierLevel4)) {
+ return; // skip
}
+
+ // TODO: add a test stream
+ MediaUtils.skipTest(TAG, "no test stream");
}
public void testHevcMain41() throws Exception {
- if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
- CodecProfileLevel.HEVCMainTierLevel41)) {
- Log.i(TAG, "HevcMain41 not supported");
- return;
+ if (!checkDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain, HEVCMainTierLevel41)) {
+ return; // skip
}
+
+ // TODO: add a test stream
+ MediaUtils.skipTest(TAG, "no test stream");
}
public void testHevcMain5() throws Exception {
- if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
- CodecProfileLevel.HEVCMainTierLevel5)) {
- Log.i(TAG, "HevcMain5 not supported");
- return;
+ if (!checkDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain, HEVCMainTierLevel5)) {
+ return; // skip
}
+
+ // TODO: add a test stream
+ MediaUtils.skipTest(TAG, "no test stream");
}
public void testHevcMain51() throws Exception {
- if (!supports(HEVC_MIME, CodecProfileLevel.HEVCProfileMain,
- CodecProfileLevel.HEVCMainTierLevel51)) {
- Log.i(TAG, "HevcMain51 not supported");
- return;
+ if (!checkDecoder(MIMETYPE_VIDEO_HEVC, HEVCProfileMain, HEVCMainTierLevel51)) {
+ return; // skip
}
+
+ // TODO: add a test stream
+ MediaUtils.skipTest(TAG, "no test stream");
}
- private boolean supports(String mimeType, int profile) {
- return supports(mimeType, profile, 0, false);
+ private boolean checkDecoder(String mime, int profile, int level) {
+ if (!hasDecoder(mime, profile, level)) {
+ MediaUtils.skipTest(TAG, "no " + mime + " decoder for profile "
+ + profile + " and level " + level);
+ return false;
+ }
+ return true;
}
- private boolean supports(String mimeType, int profile, int level) {
- return supports(mimeType, profile, level, true);
+ private boolean hasDecoder(String mime, int profile, int level) {
+ return supports(mime, false /* isEncoder */, profile, level);
}
- private boolean supports(String mimeType, int profile, int level, boolean testLevel) {
- int numCodecs = MediaCodecList.getCodecCount();
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
- if (codecInfo.isEncoder()) {
+ private boolean hasEncoder(String mime, int profile, int level) {
+ return supports(mime, true /* isEncoder */, profile, level);
+ }
+
+ private boolean supports(
+ String mime, boolean isEncoder, int profile, int level) {
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ for (MediaCodecInfo info : mcl.getCodecInfos()) {
+ if (isEncoder != info.isEncoder()) {
continue;
}
-
- if (!supportsMimeType(codecInfo, mimeType)) {
- continue;
- }
-
- CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mimeType);
- for (CodecProfileLevel profileLevel : capabilities.profileLevels) {
- if (profileLevel.profile == profile
- && (!testLevel || profileLevel.level >= level)) {
- return true;
+ try {
+ CodecCapabilities caps = info.getCapabilitiesForType(mime);
+ for (CodecProfileLevel pl : caps.profileLevels) {
+ if (pl.profile == profile && pl.level >= level) {
+ return true;
+ }
}
- }
- }
-
- return false;
- }
-
- private static boolean supportsMimeType(MediaCodecInfo codecInfo, String mimeType) {
- String[] supportedMimeTypes = codecInfo.getSupportedTypes();
- for (String supportedMimeType : supportedMimeTypes) {
- if (mimeType.equalsIgnoreCase(supportedMimeType)) {
- return true;
- }
- }
- return false;
- }
-
- private static boolean hasCodec(String mimeType) {
- MediaCodecList list = new MediaCodecList(MediaCodecList.ALL_CODECS);
- for (MediaCodecInfo info : list.getCodecInfos()) {
- for (String type : info.getSupportedTypes()) {
- if (type.equalsIgnoreCase(mimeType)) {
- return true;
- }
+ } catch (IllegalArgumentException e) {
}
}
return false;
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
index 865780e..4030636 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
@@ -249,6 +249,25 @@
pm.hasSystemFeature(pm.FEATURE_CAMERA);
}
+ private boolean hasMicrophone() {
+ PackageManager pm = getContext().getPackageManager();
+ return pm.hasSystemFeature(pm.FEATURE_MICROPHONE);
+ }
+
+ private boolean isWatch() {
+ PackageManager pm = getContext().getPackageManager();
+ return pm.hasSystemFeature(pm.FEATURE_WATCH);
+ }
+
+ private boolean isHandheld() {
+ // handheld nature is not exposed to package manager, for now
+ // we check for touchscreen and NOT watch and NOT tv
+ PackageManager pm = getContext().getPackageManager();
+ return pm.hasSystemFeature(pm.FEATURE_TOUCHSCREEN)
+ && !pm.hasSystemFeature(pm.FEATURE_WATCH)
+ && !pm.hasSystemFeature(pm.FEATURE_TELEVISION);
+ }
+
// H263 baseline profile must be supported
public void testIsH263BaselineProfileSupported() {
if (!hasCamera()) {
@@ -257,21 +276,21 @@
}
int profile = CodecProfileLevel.H263ProfileBaseline;
- assertTrue(checkProfileSupported("video/3gpp", false, profile));
- assertTrue(checkProfileSupported("video/3gpp", true, profile));
+ assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_H263, false, profile));
+ assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_H263, true, profile));
}
// AVC baseline profile must be supported
public void testIsAVCBaselineProfileSupported() {
int profile = CodecProfileLevel.AVCProfileBaseline;
- assertTrue(checkProfileSupported("video/avc", false, profile));
- assertTrue(checkProfileSupported("video/avc", true, profile));
+ assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_AVC, false, profile));
+ assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_AVC, true, profile));
}
// HEVC main profile must be supported
public void testIsHEVCMainProfileSupported() {
int profile = CodecProfileLevel.HEVCProfileMain;
- assertTrue(checkProfileSupported("video/hevc", false, profile));
+ assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_HEVC, false, profile));
}
// MPEG4 simple profile must be supported
@@ -282,10 +301,10 @@
}
int profile = CodecProfileLevel.MPEG4ProfileSimple;
- assertTrue(checkProfileSupported("video/mp4v-es", false, profile));
+ assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_MPEG4, false, profile));
// FIXME: no support for M4v simple profile video encoder
- // assertTrue(checkProfileSupported("video/mp4v-es", true, profile));
+ // assertTrue(checkProfileSupported(MediaFormat.MIMETYPE_VIDEO_MPEG4, true, profile));
}
/*
@@ -375,29 +394,40 @@
List<CodecType> list = new ArrayList<CodecType>(16);
// Mandatory audio codecs
- list.add(new CodecType("audio/amr-wb", false)); // amrwb decoder
- list.add(new CodecType("audio/amr-wb", true)); // amrwb encoder
// flac decoder is not omx-based yet
- // list.add(new CodecType("audio/flac", false)); // flac decoder
- list.add(new CodecType("audio/flac", true)); // flac encoder
- list.add(new CodecType("audio/mpeg", false)); // mp3 decoder
- list.add(new CodecType("audio/mp4a-latm", false)); // aac decoder
- list.add(new CodecType("audio/mp4a-latm", true)); // aac encoder
- list.add(new CodecType("audio/vorbis", false)); // vorbis decoder
- list.add(new CodecType("audio/3gpp", false)); // amrnb decoder
- list.add(new CodecType("audio/3gpp", true)); // amrnb encoder
+ // list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_FLAC, false)); // flac decoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_MPEG, false)); // mp3 decoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_VORBIS, false)); // vorbis decoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_AAC, false)); // aac decoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_RAW, false)); // raw/pcm decoder
+ if (hasMicrophone() && !isWatch()) {
+ list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_AAC, true)); // aac encoder
+ // flac encoder is not required
+ // list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_FLAC, true)); // flac encoder
+ }
+ if (isHandheld()) {
+ list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_AMR_NB, false)); // amrnb decoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_AMR_NB, true)); // amrnb encoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_AMR_WB, false)); // amrwb decoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_AUDIO_AMR_WB, true)); // amrwb encoder
+ }
// Mandatory video codecs
- list.add(new CodecType("video/avc", false)); // avc decoder
- list.add(new CodecType("video/avc", true)); // avc encoder
- list.add(new CodecType("video/hevc", false)); // hevc decoder
- list.add(new CodecType("video/3gpp", false)); // h263 decoder
- list.add(new CodecType("video/3gpp", true)); // h263 encoder
- list.add(new CodecType("video/mp4v-es", false)); // m4v decoder
- list.add(new CodecType("video/x-vnd.on2.vp8", false)); // vp8 decoder
- list.add(new CodecType("video/x-vnd.on2.vp8", true)); // vp8 encoder
- list.add(new CodecType("video/x-vnd.on2.vp9", false)); // vp9 decoder
+
+ if (!isWatch()) {
+ list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_AVC, false)); // avc decoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_AVC, true)); // avc encoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_VP8, false)); // vp8 decoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_VP8, true)); // vp8 encoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_VP9, false)); // vp9 decoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_HEVC, false)); // hevc decoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_MPEG4, false)); // m4v decoder
+ list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_H263, false)); // h263 decoder
+ if (hasCamera()) {
+ list.add(new CodecType(MediaFormat.MIMETYPE_VIDEO_H263, true)); // h263 encoder
+ }
+ }
return list;
}
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index 5f8885d..1ff5048 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -50,14 +50,15 @@
private static final boolean VERBOSE = false; // lots of logging
// parameters for the video encoder
- private static final String MIME_TYPE = "video/avc"; // H.264 Advanced Video Coding
+ // H.264 Advanced Video Coding
+ private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
private static final int BIT_RATE = 2000000; // 2Mbps
private static final int FRAME_RATE = 15; // 15fps
private static final int IFRAME_INTERVAL = 10; // 10 seconds between I-frames
private static final int WIDTH = 1280;
private static final int HEIGHT = 720;
// parameters for the audio encoder
- private static final String MIME_TYPE_AUDIO = "audio/mp4a-latm";
+ private static final String MIME_TYPE_AUDIO = MediaFormat.MIMETYPE_AUDIO_AAC;
private static final int AUDIO_SAMPLE_RATE = 44100;
private static final int AUDIO_AAC_PROFILE = 2; /* OMX_AUDIO_AACObjectLC */
private static final int AUDIO_CHANNEL_COUNT = 2; // mono
@@ -79,7 +80,7 @@
* methods when called in incorrect operational states.
*/
public void testException() throws Exception {
- String mimeType = "audio/amr-wb";
+ String mimeType = MediaFormat.MIMETYPE_AUDIO_AMR_WB;
if (!supportsCodec(mimeType, false)) {
Log.i(TAG, "No decoder found for mimeType= " + mimeType);
return;
@@ -1004,18 +1005,17 @@
* match was found.
*/
private static MediaCodecInfo selectCodec(String mimeType) {
- int numCodecs = MediaCodecList.getCodecCount();
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-
- if (!codecInfo.isEncoder()) {
+ // FIXME: select codecs based on the complete use-case, not just the mime
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ for (MediaCodecInfo info : mcl.getCodecInfos()) {
+ if (!info.isEncoder()) {
continue;
}
- String[] types = codecInfo.getSupportedTypes();
+ String[] types = info.getSupportedTypes();
for (int j = 0; j < types.length; j++) {
if (types[j].equalsIgnoreCase(mimeType)) {
- return codecInfo;
+ return info;
}
}
}
diff --git a/tests/tests/media/src/android/media/cts/MediaMuxerTest.java b/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
index 6591555..67eeca0 100644
--- a/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
@@ -97,7 +97,7 @@
// Throws exception b/c start() is not called.
muxer = new MediaMuxer(outputFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
- muxer.addTrack(MediaFormat.createVideoFormat("video/avc", 480, 320));
+ muxer.addTrack(MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 480, 320));
try {
muxer.stop();
@@ -108,10 +108,10 @@
// Throws exception b/c 2 video tracks were added.
muxer = new MediaMuxer(outputFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
- muxer.addTrack(MediaFormat.createVideoFormat("video/avc", 480, 320));
+ muxer.addTrack(MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 480, 320));
try {
- muxer.addTrack(MediaFormat.createVideoFormat("video/avc", 480, 320));
+ muxer.addTrack(MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 480, 320));
fail("should throw IllegalStateException.");
} catch (IllegalStateException e) {
// expected
@@ -119,9 +119,9 @@
// Throws exception b/c 2 audio tracks were added.
muxer = new MediaMuxer(outputFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
- muxer.addTrack(MediaFormat.createAudioFormat("audio/mp4a-latm", 48000, 1));
+ muxer.addTrack(MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC, 48000, 1));
try {
- muxer.addTrack(MediaFormat.createAudioFormat("audio/mp4a-latm", 48000, 1));
+ muxer.addTrack(MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC, 48000, 1));
fail("should throw IllegalStateException.");
} catch (IllegalStateException e) {
// expected
@@ -129,11 +129,11 @@
// Throws exception b/c 3 tracks were added.
muxer = new MediaMuxer(outputFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
- muxer.addTrack(MediaFormat.createVideoFormat("video/avc", 480, 320));
- muxer.addTrack(MediaFormat.createAudioFormat("audio/mp4a-latm", 48000, 1));
+ muxer.addTrack(MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 480, 320));
+ muxer.addTrack(MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC, 48000, 1));
try {
- muxer.addTrack(MediaFormat.createVideoFormat("video/avc", 480, 320));
+ muxer.addTrack(MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 480, 320));
fail("should throw IllegalStateException.");
} catch (IllegalStateException e) {
// expected
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
index c5cd04e..a498eac 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerFlakyNetworkTest.java
@@ -15,6 +15,7 @@
*/
package android.media.cts;
+import android.cts.util.MediaUtils;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Looper;
@@ -34,6 +35,7 @@
import java.net.Socket;
import java.util.Random;
+import java.util.Vector;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
@@ -42,6 +44,7 @@
* from an HTTP server over a simulated "flaky" network.
*/
public class MediaPlayerFlakyNetworkTest extends MediaPlayerTestBase {
+ private static final String PKG = "com.android.cts.media";
private static final String[] TEST_VIDEOS = {
"raw/video_480x360_mp4_h264_1350kbps_30fps_aac_stereo_192kbps_44100hz",
@@ -92,24 +95,36 @@
doPlayStreams(6, 0.00002f);
}
- private void doPlayStreams(int seed, float probability) throws Throwable {
- if (!hasH264(false)) {
- return;
+ private String[] getSupportedVideos() {
+ Vector<String> supported = new Vector<String>();
+ for (String video : TEST_VIDEOS) {
+ if (MediaUtils.hasCodecsForPath(mContext, "android.resource://" + PKG + "/" + video)) {
+ supported.add(video);
+ }
}
+ return supported.toArray(new String[supported.size()]);
+ }
+
+ private void doPlayStreams(int seed, float probability) throws Throwable {
+ String[] supported = getSupportedVideos();
+ if (supported.length == 0) {
+ MediaUtils.skipTest("no codec found");
+ }
+
Random random = new Random(seed);
createHttpServer(seed, probability);
for (int i = 0; i < 10; i++) {
- String video = getRandomTestVideo(random);
+ String video = getRandomTestVideo(random, supported);
doPlayMp4Stream(video, 20000, 5000);
doAsyncPrepareAndRelease(video);
doRandomOperations(video);
}
- doPlayMp4Stream(getRandomTestVideo(random), 30000, 20000);
+ doPlayMp4Stream(getRandomTestVideo(random, supported), 30000, 20000);
releaseHttpServer();
}
- private String getRandomTestVideo(Random random) {
- return TEST_VIDEOS[random.nextInt(TEST_VIDEOS.length)];
+ private String getRandomTestVideo(Random random, String[] videos) {
+ return videos[random.nextInt(videos.length)];
}
private void doPlayMp4Stream(String video, int millisToPrepare, int millisToPlay)
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index 108aa8b..65a34f4 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -20,10 +20,9 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
+import android.cts.util.MediaUtils;
import android.media.AudioManager;
import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaPlayer;
@@ -674,11 +673,8 @@
}
});
- try {
- loadResource(R.raw.testvideo);
- } catch (UnsupportedCodecException e) {
- Log.i(LOG_TAG, "SKIPPING testVideoSurfaceResetting(). Could not find codec.");
- return;
+ if (!checkLoadResource(R.raw.testvideo)) {
+ return; // skip;
}
playLoadedVideo(352, 288, -1);
@@ -1030,11 +1026,8 @@
}
public void testDeselectTrack() throws Throwable {
- try {
- loadResource(R.raw.testvideo_with_2_subtitles);
- } catch (UnsupportedCodecException e) {
- Log.i(LOG_TAG, "SKIPPING testDeselectTrack(). Could not find codec.");
- return;
+ if (!checkLoadResource(R.raw.testvideo_with_2_subtitles)) {
+ return; // skip;
}
runTestOnUiThread(new Runnable() {
public void run() {
@@ -1106,11 +1099,8 @@
}
public void testChangeSubtitleTrack() throws Throwable {
- try {
- loadResource(R.raw.testvideo_with_2_subtitles);
- } catch (UnsupportedCodecException e) {
- Log.i(LOG_TAG, "SKIPPING testChangeSubtitleTrack(). Could not find codec.");
- return;
+ if (!checkLoadResource(R.raw.testvideo_with_2_subtitles)) {
+ return; // skip;
}
mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
@@ -1199,11 +1189,8 @@
}
public void testGetTrackInfo() throws Throwable {
- try {
- loadResource(R.raw.testvideo_with_2_subtitles);
- } catch (UnsupportedCodecException e) {
- Log.i(LOG_TAG, "SKIPPING testGetTrackInfo(). Could not find codec.");
- return;
+ if (!checkLoadResource(R.raw.testvideo_with_2_subtitles)) {
+ return; // skip;
}
runTestOnUiThread(new Runnable() {
public void run() {
@@ -1246,17 +1233,23 @@
* The ones being used here are 10 seconds long.
*/
public void testResumeAtEnd() throws Throwable {
- testResumeAtEnd(R.raw.loudsoftmp3);
- testResumeAtEnd(R.raw.loudsoftwav);
- testResumeAtEnd(R.raw.loudsoftogg);
- testResumeAtEnd(R.raw.loudsoftitunes);
- testResumeAtEnd(R.raw.loudsoftfaac);
- testResumeAtEnd(R.raw.loudsoftaac);
+ int testsRun =
+ testResumeAtEnd(R.raw.loudsoftmp3) +
+ testResumeAtEnd(R.raw.loudsoftwav) +
+ testResumeAtEnd(R.raw.loudsoftogg) +
+ testResumeAtEnd(R.raw.loudsoftitunes) +
+ testResumeAtEnd(R.raw.loudsoftfaac) +
+ testResumeAtEnd(R.raw.loudsoftaac);
+ if (testsRun == 0) {
+ MediaUtils.skipTest("no decoder found");
+ }
}
- private void testResumeAtEnd(int res) throws Throwable {
-
- loadResource(res);
+ // returns 1 if test was run, 0 otherwise
+ private int testResumeAtEnd(int res) throws Throwable {
+ if (!loadResource(res)) {
+ return 0; // skip
+ }
mMediaPlayer.prepare();
mOnCompletionCalled.reset();
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@@ -1274,16 +1267,14 @@
assertTrue("MediaPlayer should still be playing", mMediaPlayer.isPlaying());
mMediaPlayer.reset();
assertEquals("wrong number of repetitions", 1, mOnCompletionCalled.getNumSignal());
+ return 1;
}
public void testCallback() throws Throwable {
final int mp4Duration = 8484;
- try {
- loadResource(R.raw.testvideo);
- } catch (UnsupportedCodecException e) {
- Log.i(LOG_TAG, "SKIPPING testCallback(). Could not find codec.");
- return;
+ if (!checkLoadResource(R.raw.testvideo)) {
+ return; // skip;
}
mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
@@ -1357,12 +1348,12 @@
public void testRecordAndPlay() throws Exception {
if (!hasMicrophone()) {
- Log.i(LOG_TAG, "SKIPPING testRecordAndPlay(). No microphone.");
+ MediaUtils.skipTest(LOG_TAG, "no microphone");
return;
}
- if (!hasH263(false)) {
- Log.i(LOG_TAG, "SKIPPING testRecordAndPlay(). Cound not find codec.");
- return;
+ if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_AUDIO_AMR_NB)
+ || !MediaUtils.checkEncoder(MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
+ return; // skip
}
File outputFile = new File(Environment.getExternalStorageDirectory(),
"record_and_play.3gp");
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
index 9225203..d089658 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
@@ -16,15 +16,10 @@
package android.media.cts;
import android.content.Context;
-
import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
-import android.media.MediaExtractor;
-import android.media.MediaFormat;
+import android.cts.util.MediaUtils;
import android.media.MediaPlayer;
import android.test.ActivityInstrumentationTestCase2;
@@ -149,9 +144,10 @@
super.tearDown();
}
- protected void loadResource(int resid) throws Exception {
- if (!supportsPlayback(resid)) {
- throw new UnsupportedCodecException();
+ // returns true on success
+ protected boolean loadResource(int resid) throws Exception {
+ if (!MediaUtils.hasCodecsForResource(mContext, resid)) {
+ return false;
}
AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
@@ -170,6 +166,11 @@
afd.close();
}
sUseScaleToFitMode = !sUseScaleToFitMode; // Alternate the scaling mode
+ return true;
+ }
+
+ protected boolean checkLoadResource(int resid) throws Exception {
+ return MediaUtils.check(loadResource(resid), "no decoder found");
}
protected void loadSubtitleSource(int resid) throws Exception {
@@ -208,13 +209,10 @@
}
protected void playVideoTest(int resid, int width, int height) throws Exception {
- if (!supportsPlayback(resid)) {
- LOG.info("SKIPPING playVideoTest() for resid=" + resid
- + " Could not find a codec for playback.");
- return;
+ if (!checkLoadResource(resid)) {
+ return; // skip
}
- loadResource(resid);
playLoadedVideo(width, height, 0);
}
@@ -295,69 +293,19 @@
}
private static class PrepareFailedException extends Exception {}
- public static class UnsupportedCodecException extends Exception {}
-
- public boolean supportsPlayback(int resid) throws IOException {
- // First determine if the device supports playback of the requested resource.
- AssetFileDescriptor fd = mResources.openRawResourceFd(resid);
- MediaExtractor ex = new MediaExtractor();
- ex.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
- MediaFormat format = ex.getTrackFormat(0);
- String mimeType = format.getString(MediaFormat.KEY_MIME);
- return hasCodecForMimeType(mimeType, false);
- }
-
- public boolean supportsPlayback(String path) throws IOException {
- MediaExtractor ex = new MediaExtractor();
- ex.setDataSource(path);
- MediaFormat format = ex.getTrackFormat(0);
- String mimeType = format.getString(MediaFormat.KEY_MIME);
- return hasCodecForMimeType(mimeType, false);
- }
-
- public static boolean hasCodecForMimeType(String mimeType, boolean encoder) {
- MediaCodecList list = new MediaCodecList(MediaCodecList.ALL_CODECS);
- for (MediaCodecInfo info : list.getCodecInfos()) {
- if (encoder != info.isEncoder()) {
- continue;
- }
-
- for (String type : info.getSupportedTypes()) {
- if (type.equalsIgnoreCase(mimeType)) {
- LOG.info("Found codec for mimeType=" + mimeType + " codec=" + info.getName());
- return true;
- }
- }
- }
- return false;
- }
-
- public static boolean hasH264(boolean encoder) {
- return hasCodecForMimeType("video/avc", encoder);
- }
-
- public static boolean hasHEVC(boolean encoder) {
- return hasCodecForMimeType("video/hevc", encoder);
- }
-
- public static boolean hasH263(boolean encoder) {
- return hasCodecForMimeType("video/3gpp", encoder);
- }
-
- public static boolean hasMpeg4(boolean encoder) {
- return hasCodecForMimeType("video/mp4v-es", encoder);
- }
-
- public static boolean hasVP8(boolean encoder) {
- return hasCodecForMimeType("video/x-vnd.on2.vp8", encoder);
- }
-
- public static boolean hasVP9(boolean encoder) {
- return hasCodecForMimeType("video/x-vnd.on2.vp9", encoder);
- }
public boolean hasAudioOutput() {
return getInstrumentation().getTargetContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
}
+
+ public boolean isTv() {
+ PackageManager pm = getInstrumentation().getTargetContext().getPackageManager();
+ return pm.hasSystemFeature(pm.FEATURE_TELEVISION)
+ && pm.hasSystemFeature(pm.FEATURE_LEANBACK);
+ }
+
+ public boolean checkTv() {
+ return MediaUtils.check(isTv(), "not a TV");
+ }
}
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index 85966ce..78b5cfd 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -17,9 +17,8 @@
import android.content.pm.PackageManager;
+import android.cts.util.MediaUtils;
import android.hardware.Camera;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.media.MediaMetadataRetriever;
import android.media.MediaRecorder;
@@ -309,36 +308,40 @@
}
public void testRecordingAudioInRawFormats() throws Exception {
- if (hasAmrnb()) {
- testRecordAudioInRawFormat(
+ int testsRun = 0;
+ if (hasAmrNb()) {
+ testsRun += testRecordAudioInRawFormat(
MediaRecorder.OutputFormat.AMR_NB,
MediaRecorder.AudioEncoder.AMR_NB);
}
- if (hasAmrwb()) {
- testRecordAudioInRawFormat(
+ if (hasAmrWb()) {
+ testsRun += testRecordAudioInRawFormat(
MediaRecorder.OutputFormat.AMR_WB,
MediaRecorder.AudioEncoder.AMR_WB);
}
- if (hasAcc()) {
- testRecordAudioInRawFormat(
+ if (hasAac()) {
+ testsRun += testRecordAudioInRawFormat(
MediaRecorder.OutputFormat.AAC_ADTS,
MediaRecorder.AudioEncoder.AAC);
}
+ if (testsRun == 0) {
+ MediaUtils.skipTest("no audio codecs or microphone");
+ }
}
- private void testRecordAudioInRawFormat(
+ private int testRecordAudioInRawFormat(
int fileFormat, int codec) throws Exception {
-
if (!hasMicrophone()) {
- return;
+ return 0; // skip
}
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setOutputFormat(fileFormat);
mMediaRecorder.setOutputFile(OUTPUT_PATH);
mMediaRecorder.setAudioEncoder(codec);
recordMedia(MAX_FILE_SIZE, mOutFile);
+ return 1;
}
public void testGetAudioSourceMax() throws Exception {
@@ -354,10 +357,8 @@
}
public void testRecorderAudio() throws Exception {
- if (!hasMicrophone()) {
- return;
- }
- if (!hasAmrnb()) {
+ if (!hasMicrophone() || !hasAmrNb()) {
+ MediaUtils.skipTest("no audio codecs or microphone");
return;
}
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
@@ -372,10 +373,8 @@
}
public void testOnInfoListener() throws Exception {
- if (!hasMicrophone()) {
- return;
- }
- if (!hasAmrnb()) {
+ if (!hasMicrophone() || !hasAmrNb()) {
+ MediaUtils.skipTest("no audio codecs or microphone");
return;
}
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
@@ -389,10 +388,8 @@
}
public void testSetMaxDuration() throws Exception {
- if (!hasMicrophone()) {
- return;
- }
- if (!hasAmrnb()) {
+ if (!hasMicrophone() || !hasAmrNb()) {
+ MediaUtils.skipTest("no audio codecs or microphone");
return;
}
testSetMaxDuration(RECORD_TIME_LONG_MS, RECORDED_DUR_TOLERANCE_MS);
@@ -430,14 +427,15 @@
}
public void testSetMaxFileSize() throws Exception {
- if (!hasMicrophone() || !hasCamera()) {
- return;
- }
testSetMaxFileSize(512 * 1024, 50 * 1024);
}
private void testSetMaxFileSize(
long fileSize, long tolerance) throws Exception {
+ if (!hasMicrophone() || !hasCamera() || !hasAmrNb() || !hasH264()) {
+ MediaUtils.skipTest("no microphone, camera, or codecs");
+ return;
+ }
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
@@ -466,10 +464,8 @@
}
public void testOnErrorListener() throws Exception {
- if (!hasMicrophone()) {
- return;
- }
- if (!hasAmrnb()) {
+ if (!hasMicrophone() || !hasAmrNb()) {
+ MediaUtils.skipTest("no audio codecs or microphone");
return;
}
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
@@ -505,31 +501,19 @@
PackageManager.FEATURE_MICROPHONE);
}
- private static boolean hasCodecForMimeType(String mimeType, boolean encoder) {
- MediaCodecList list = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- for (MediaCodecInfo info : list.getCodecInfos()) {
- if (encoder != info.isEncoder()) {
- continue;
- }
-
- for (String type : info.getSupportedTypes()) {
- if (type.equalsIgnoreCase(mimeType)) {
- return true;
- }
- }
- }
- return false;
+ private static boolean hasAmrNb() {
+ return MediaUtils.hasEncoder(MediaFormat.MIMETYPE_AUDIO_AMR_NB);
}
- private static boolean hasAmrnb() {
- return hasCodecForMimeType(MediaFormat.MIMETYPE_AUDIO_AMR_NB, true);
+ private static boolean hasAmrWb() {
+ return MediaUtils.hasEncoder(MediaFormat.MIMETYPE_AUDIO_AMR_WB);
}
- private static boolean hasAmrwb() {
- return hasCodecForMimeType(MediaFormat.MIMETYPE_AUDIO_AMR_WB, true);
+ private static boolean hasAac() {
+ return MediaUtils.hasEncoder(MediaFormat.MIMETYPE_AUDIO_AAC);
}
- private static boolean hasAcc() {
- return hasCodecForMimeType(MediaFormat.MIMETYPE_AUDIO_AAC, true);
+ private static boolean hasH264() {
+ return MediaUtils.hasEncoder(MediaFormat.MIMETYPE_VIDEO_AVC);
}
}
diff --git a/tests/tests/media/src/android/media/cts/NativeDecoderTest.java b/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
index 81c5113..d7bcd78 100644
--- a/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
@@ -20,6 +20,7 @@
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
+import android.cts.util.MediaUtils;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaCodecInfo;
@@ -90,8 +91,8 @@
testExtractor(R.raw.sinesweepwav);
testExtractor(R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz);
- testExtractor(R.raw.video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz);
- testExtractor(R.raw.video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_44100hz);
+ testExtractor(R.raw.video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz);
+ testExtractor(R.raw.video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_48000hz);
testExtractor(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz);
testExtractor(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz);
@@ -183,24 +184,27 @@
public void testDecoder() throws Exception {
- testDecoder(R.raw.sinesweepogg);
- testDecoder(R.raw.sinesweepmp3lame);
- testDecoder(R.raw.sinesweepmp3smpb);
- testDecoder(R.raw.sinesweepm4a);
- testDecoder(R.raw.sinesweepflac);
- testDecoder(R.raw.sinesweepwav);
+ int testsRun =
+ testDecoder(R.raw.sinesweepogg) +
+ testDecoder(R.raw.sinesweepmp3lame) +
+ testDecoder(R.raw.sinesweepmp3smpb) +
+ testDecoder(R.raw.sinesweepm4a) +
+ testDecoder(R.raw.sinesweepflac) +
+ testDecoder(R.raw.sinesweepwav) +
- testDecoder(R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz);
- testDecoder(R.raw.video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz);
- testDecoder(R.raw.video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_44100hz);
- testDecoder(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz);
- testDecoder(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz);
+ testDecoder(R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz) +
+ testDecoder(R.raw.video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz) +
+ testDecoder(R.raw.video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_48000hz) +
+ testDecoder(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz) +
+ testDecoder(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz);
+ if (testsRun == 0) {
+ MediaUtils.skipTest("no decoders found");
+ }
}
- private void testDecoder(int res) throws Exception {
- if (!supportsPlayback(res)) {
- Log.i(TAG, "SKIPPING testDecoder() resid=" + res + " Unsupported decorder.");
- return;
+ private int testDecoder(int res) throws Exception {
+ if (!MediaUtils.hasCodecsForResource(mContext, res)) {
+ return 0; // skip
}
AssetFileDescriptor fd = mResources.openRawResourceFd(res);
@@ -215,6 +219,7 @@
Log.i("@@@", Arrays.toString(ndata));
assertEquals("number of samples differs", jdata.length, ndata.length);
assertTrue("different decoded data", Arrays.equals(jdata, ndata));
+ return 1;
}
private static int[] getDecodedData(FileDescriptor fd, long offset, long size)
@@ -378,17 +383,25 @@
throws IOException;
public void testVideoPlayback() throws Exception {
- testVideoPlayback(R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz);
- testVideoPlayback(R.raw.video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz);
- testVideoPlayback(R.raw.video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_44100hz);
- testVideoPlayback(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz);
- testVideoPlayback(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz);
+ int testsRun =
+ testVideoPlayback(
+ R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz) +
+ testVideoPlayback(
+ R.raw.video_1280x720_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz) +
+ testVideoPlayback(
+ R.raw.video_1280x720_webm_vp9_309kbps_25fps_vorbis_stereo_128kbps_48000hz) +
+ testVideoPlayback(
+ R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_mono_24kbps_11025hz) +
+ testVideoPlayback(
+ R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz);
+ if (testsRun == 0) {
+ MediaUtils.skipTest("no decoders found");
+ }
}
- private void testVideoPlayback(int res) throws Exception {
- if (!supportsPlayback(res)) {
- Log.i(TAG, "SKIPPING testVideoPlayback() resid=" + res + " Unsupported decorder.");
- return;
+ private int testVideoPlayback(int res) throws Exception {
+ if (!MediaUtils.checkCodecsForResource(mContext, res)) {
+ return 0; // skip
}
AssetFileDescriptor fd = mResources.openRawResourceFd(res);
@@ -396,6 +409,7 @@
boolean ret = testPlaybackNative(mActivity.getSurfaceHolder().getSurface(),
fd.getParcelFileDescriptor().getFd(), fd.getStartOffset(), fd.getLength());
assertTrue("native playback error", ret);
+ return 1;
}
private static native boolean testPlaybackNative(Surface surface,
@@ -406,10 +420,10 @@
}
private void testMuxer(int res, boolean webm) throws Exception {
- if (!supportsPlayback(res)) {
- Log.i(TAG, "SKIPPING testMuxer() resid=" + res + " Unsupported decorder.");
- return;
+ if (!MediaUtils.checkCodecsForResource(mContext, res)) {
+ return; // skip
}
+
AssetFileDescriptor infd = mResources.openRawResourceFd(res);
File base = mContext.getExternalFilesDir(null);
diff --git a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
index 6198d5f..748cda7 100644
--- a/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/StreamingMediaPlayerTest.java
@@ -15,6 +15,8 @@
*/
package android.media.cts;
+import android.cts.util.MediaUtils;
+import android.media.MediaFormat;
import android.media.MediaPlayer;
import android.os.Looper;
import android.os.SystemClock;
@@ -23,7 +25,6 @@
import java.io.IOException;
-
/**
* Tests of MediaPlayer streaming capabilities.
*/
@@ -64,9 +65,8 @@
*/
// Streaming HTTP video from YouTube
public void testHTTP_H263_AMR_Video1() throws Exception {
- if (!hasH263(false)) {
- Log.i(TAG, "Skipping testHTTP_H263_AMR_Video1(): No codec found.");
- return;
+ if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_H263, MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
+ return; // skip
}
playVideoTest("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
@@ -77,9 +77,8 @@
+ "&key=test_key1&user=android-device-test", 176, 144);
}
public void testHTTP_H263_AMR_Video2() throws Exception {
- if (!hasH263(false)) {
- Log.i(TAG, "Skipping testHTTP_H263_AMR_Video2(): No codec found.");
- return;
+ if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_H263, MediaFormat.MIMETYPE_AUDIO_AMR_NB)) {
+ return; // skip
}
playVideoTest("http://redirector.c.youtube.com/videoplayback?id=c80658495af60617"
@@ -91,9 +90,8 @@
}
public void testHTTP_MPEG4SP_AAC_Video1() throws Exception {
- if (!hasH264(false)) {
- Log.i(TAG, "Skipping testHTTP_MPEG4SP_AAC_Video1(): No codec found.");
- return;
+ if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
+ return; // skip
}
playVideoTest("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
@@ -104,9 +102,8 @@
+ "&key=test_key1&user=android-device-test", 176, 144);
}
public void testHTTP_MPEG4SP_AAC_Video2() throws Exception {
- if (!hasH264(false)) {
- Log.i(TAG, "Skipping testHTTP_MPEG4SP_AAC_Video2(): No codec found.");
- return;
+ if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
+ return; // skip
}
playVideoTest("http://redirector.c.youtube.com/videoplayback?id=c80658495af60617"
@@ -118,9 +115,8 @@
}
public void testHTTP_H264Base_AAC_Video1() throws Exception {
- if (!hasH264(false)) {
- Log.i(TAG, "Skipping testHTTP_H264Base_AAC_Video1(): No codec found.");
- return;
+ if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+ return; // skip
}
playVideoTest("http://redirector.c.youtube.com/videoplayback?id=271de9756065677e"
@@ -131,9 +127,8 @@
+ "&key=test_key1&user=android-device-test", 640, 360);
}
public void testHTTP_H264Base_AAC_Video2() throws Exception {
- if (!hasH264(false)) {
- Log.i(TAG, "Skipping testHTTP_H264Base_AAC_Video2(): No codec found.");
- return;
+ if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+ return; // skip
}
playVideoTest("http://redirector.c.youtube.com/videoplayback?id=c80658495af60617"
@@ -146,9 +141,8 @@
// Streaming HLS video from YouTube
public void testHLS() throws Exception {
- if (!hasH264(false)) {
- Log.i(TAG, "Skipping testHLS(): No codec found.");
- return;
+ if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+ return; // skip
}
// Play stream for 60 seconds
@@ -202,9 +196,8 @@
stream_url = stream_url + "?" + CtsTestServer.NOLENGTH_POSTFIX;
}
- if (!supportsPlayback(stream_url)) {
- Log.i(TAG, "Failed to find codec for: '" + stream_url + "'. Skipping test.");
- return;
+ if (!MediaUtils.checkCodecsForPath(mContext, stream_url)) {
+ return; // skip
}
mMediaPlayer.setDataSource(stream_url);
@@ -294,25 +287,22 @@
}
public void testPlayHlsStream() throws Throwable {
- if (!hasH264(false)) {
- Log.i(TAG, "Skipping testPlayHlsStream(): No codec found.");
- return;
+ if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+ return; // skip
}
localHlsTest("hls.m3u8", false, false);
}
public void testPlayHlsStreamWithQueryString() throws Throwable {
- if (!hasH264(false)) {
- Log.i(TAG, "Skipping testPlayHlsStreamWithQueryString(): No codec found.");
- return;
+ if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+ return; // skip
}
localHlsTest("hls.m3u8", true, false);
}
public void testPlayHlsStreamWithRedirect() throws Throwable {
- if (!hasH264(false)) {
- Log.i(TAG, "Skipping testPlayHlsStreamWithRedirect(): No codec found.");
- return;
+ if (!MediaUtils.checkDecoder(MediaFormat.MIMETYPE_VIDEO_AVC)) {
+ return; // skip
}
localHlsTest("hls.m3u8", false, true);
}
diff --git a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java b/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
index 586b9ef..133b91d 100644
--- a/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
+++ b/tests/tests/media/src/android/media/cts/Vp8CodecTestBase.java
@@ -53,10 +53,8 @@
public class Vp8CodecTestBase extends AndroidTestCase {
protected static final String TAG = "VP8CodecTestBase";
- protected static final String VP8_MIME = "video/x-vnd.on2.vp8";
- private static final String VPX_SW_DECODER_NAME = "OMX.google.vp8.decoder";
- private static final String VPX_SW_ENCODER_NAME = "OMX.google.vp8.encoder";
- private static final String OMX_SW_CODEC_PREFIX = "OMX.google";
+ protected static final String VP8_MIME = MediaFormat.MIMETYPE_VIDEO_VP8;
+ private static final String GOOGLE_CODEC_PREFIX = "omx.google.";
protected static final String SDCARD_DIR =
Environment.getExternalStorageDirectory().getAbsolutePath();
@@ -93,29 +91,6 @@
}
/**
- * Returns the first codec capable of encoding the specified MIME type, or null if no
- * match was found.
- */
- protected static MediaCodecInfo selectCodec(String mimeType) {
- int numCodecs = MediaCodecList.getCodecCount();
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-
- if (!codecInfo.isEncoder()) {
- continue;
- }
-
- String[] types = codecInfo.getSupportedTypes();
- for (int j = 0; j < types.length; j++) {
- if (types[j].equalsIgnoreCase(mimeType)) {
- return codecInfo;
- }
- }
- }
- return null;
- }
-
- /**
* VP8 codec properties generated by getVp8CodecProperties() function.
*/
private class CodecProperties {
@@ -123,8 +98,8 @@
this.codecName = codecName;
this.colorFormat = colorFormat;
}
- public boolean isGoogleSwCodec() {
- return codecName.startsWith(OMX_SW_CODEC_PREFIX);
+ public boolean isGoogleCodec() {
+ return codecName.toLowerCase().startsWith(GOOGLE_CODEC_PREFIX);
}
public final String codecName; // OpenMax component name for VP8 codec.
@@ -135,76 +110,75 @@
* Function to find VP8 codec.
*
* Iterates through the list of available codecs and tries to find
- * VP8 codec, which can support either YUV420 planar or NV12 color formats.
- * If forceSwGoogleCodec parameter set to true the function always returns
- * Google sw VP8 codec.
- * If forceSwGoogleCodec parameter set to false the functions looks for platform
- * specific VP8 codec first. If no platform specific codec exist, falls back to
- * Google sw VP8 codec.
+ * VPX codec, which can support either YUV420 planar or NV12 color formats.
+ * If forceGoogleCodec parameter set to true the function always returns
+ * Google VPX codec.
+ * If forceGoogleCodec parameter set to false the functions looks for platform
+ * specific VPX codec first. If no platform specific codec exist, falls back to
+ * Google VPX codec.
*
* @param isEncoder Flag if encoder is requested.
- * @param forceSwGoogleCodec Forces to use Google sw codec.
+ * @param forceGoogleCodec Forces to use Google codec.
*/
- private CodecProperties getVp8CodecProperties(boolean isEncoder,
- boolean forceSwGoogleCodec) throws Exception {
+ private CodecProperties getVpxCodecProperties(
+ boolean isEncoder,
+ MediaFormat format,
+ boolean forceGoogleCodec) throws Exception {
CodecProperties codecProperties = null;
+ String mime = format.getString(MediaFormat.KEY_MIME);
- if (!forceSwGoogleCodec) {
- // Loop through the list of omx components in case platform specific codec
- // is requested.
- for (int i = 0; i < MediaCodecList.getCodecCount(); i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
- if (isEncoder != codecInfo.isEncoder()) {
+ // Loop through the list of omx components in case platform specific codec
+ // is requested.
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ for (MediaCodecInfo codecInfo : mcl.getCodecInfos()) {
+ if (isEncoder != codecInfo.isEncoder()) {
+ continue;
+ }
+ Log.v(TAG, codecInfo.getName());
+ // TODO: remove dependence of Google from the test
+ // Check if this is Google codec - we should ignore it.
+ boolean isGoogleCodec =
+ codecInfo.getName().toLowerCase().startsWith(GOOGLE_CODEC_PREFIX);
+ if (!isGoogleCodec && forceGoogleCodec) {
+ continue;
+ }
+
+ for (String type : codecInfo.getSupportedTypes()) {
+ if (!type.equalsIgnoreCase(mime)) {
continue;
}
- Log.v(TAG, codecInfo.getName());
- // Check if this is sw Google codec - we should ignore it.
- boolean isGoogleSwCodec = codecInfo.getName().startsWith(OMX_SW_CODEC_PREFIX);
- if (isGoogleSwCodec) {
+ CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(type);
+ if (!capabilities.isFormatSupported(format)) {
continue;
}
- for (String type : codecInfo.getSupportedTypes()) {
- if (!type.equalsIgnoreCase(VP8_MIME)) {
- continue;
- }
- CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(VP8_MIME);
+ // Get candidate codec properties.
+ Log.v(TAG, "Found candidate codec " + codecInfo.getName());
+ for (int colorFormat: capabilities.colorFormats) {
+ Log.v(TAG, " Color: 0x" + Integer.toHexString(colorFormat));
+ }
- // Get candidate codec properties.
- Log.v(TAG, "Found candidate codec " + codecInfo.getName());
- for (int colorFormat : capabilities.colorFormats) {
- Log.v(TAG, " Color: 0x" + Integer.toHexString(colorFormat));
- }
-
- // Check supported color formats.
- for (int supportedColorFormat : mSupportedColorList) {
- for (int codecColorFormat : capabilities.colorFormats) {
- if (codecColorFormat == supportedColorFormat) {
- codecProperties = new CodecProperties(codecInfo.getName(),
- codecColorFormat);
- Log.v(TAG, "Found target codec " + codecProperties.codecName +
- ". Color: 0x" + Integer.toHexString(codecColorFormat));
+ // Check supported color formats.
+ for (int supportedColorFormat : mSupportedColorList) {
+ for (int codecColorFormat : capabilities.colorFormats) {
+ if (codecColorFormat == supportedColorFormat) {
+ codecProperties = new CodecProperties(codecInfo.getName(),
+ codecColorFormat);
+ Log.v(TAG, "Found target codec " + codecProperties.codecName +
+ ". Color: 0x" + Integer.toHexString(codecColorFormat));
+ // return first HW codec found
+ if (!isGoogleCodec) {
return codecProperties;
}
}
}
- // HW codec we found does not support one of necessary color formats.
- throw new RuntimeException("No hw codec with YUV420 or NV12 color formats");
}
}
}
- // If no hw vp8 codec exist or sw codec is requested use default Google sw codec.
if (codecProperties == null) {
- Log.v(TAG, "Use SW VP8 codec");
- if (isEncoder) {
- codecProperties = new CodecProperties(VPX_SW_ENCODER_NAME,
- CodecCapabilities.COLOR_FormatYUV420Planar);
- } else {
- codecProperties = new CodecProperties(VPX_SW_DECODER_NAME,
- CodecCapabilities.COLOR_FormatYUV420Planar);
- }
+ Log.i(TAG, "no suitable " + (forceGoogleCodec ? "google " : "")
+ + (isEncoder ? "encoder " : "decoder ") + "found for " + format);
}
-
return codecProperties;
}
@@ -223,8 +197,8 @@
int inputResourceId;
// Name of the IVF file to write encoded bitsream
public String outputIvfFilename;
- // Force to use Google SW VP8 encoder.
- boolean forceSwEncoder;
+ // Force to use Google VP8 encoder.
+ boolean forceGoogleEncoder;
// Number of frames to encode.
int frameCount;
// Frame rate of input file in frames per second.
@@ -286,7 +260,7 @@
params.inputResourceId = R.raw.football_qvga;
params.outputIvfFilename = SDCARD_DIR + File.separator +
outputIvfBaseName + resolutionScales[i] + ".ivf";
- params.forceSwEncoder = false;
+ params.forceGoogleEncoder = false;
params.frameCount = encodeSeconds * frameRate;
params.frameRate = frameRate;
params.frameWidth = Math.min(frameWidth * resolutionScales[i], 1280);
@@ -532,15 +506,15 @@
* @param inputIvfFilename The name of the IVF file containing encoded bitsream.
* @param outputYuvFilename The name of the output YUV file (optional).
* @param frameRate Frame rate of input file in frames per second
- * @param forceSwDecoder Force to use Googlw sw VP8 decoder.
+ * @param forceGoogleDecoder Force to use Google VP8 decoder.
*/
protected ArrayList<MediaCodec.BufferInfo> decode(
String inputIvfFilename,
String outputYuvFilename,
int frameRate,
- boolean forceSwDecoder) throws Exception {
+ boolean forceGoogleDecoder) throws Exception {
ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
- CodecProperties properties = getVp8CodecProperties(false, forceSwDecoder);
+
// Open input/output.
IvfReader ivf = new IvfReader(inputIvfFilename);
int frameWidth = ivf.getWidth();
@@ -548,21 +522,27 @@
int frameCount = ivf.getFrameCount();
int frameStride = frameWidth;
int frameSliceHeight = frameHeight;
- int frameColorFormat = properties.colorFormat;
assertTrue(frameWidth > 0);
assertTrue(frameHeight > 0);
assertTrue(frameCount > 0);
+ // Create decoder.
+ MediaFormat format = MediaFormat.createVideoFormat(
+ VP8_MIME, ivf.getWidth(), ivf.getHeight());
+ CodecProperties properties = getVpxCodecProperties(
+ false /* encoder */, format, forceGoogleDecoder);
+ if (properties == null) {
+ ivf.close();
+ return null;
+ }
+ int frameColorFormat = properties.colorFormat;
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
+
FileOutputStream yuv = null;
if (outputYuvFilename != null) {
yuv = new FileOutputStream(outputYuvFilename, false);
}
- // Create decoder.
- MediaFormat format = MediaFormat.createVideoFormat(VP8_MIME,
- ivf.getWidth(),
- ivf.getHeight());
- format.setInteger(MediaFormat.KEY_COLOR_FORMAT, properties.colorFormat);
Log.d(TAG, "Creating decoder " + properties.codecName +
". Color format: 0x" + Integer.toHexString(frameColorFormat) +
". " + frameWidth + " x " + frameHeight);
@@ -1282,11 +1262,20 @@
EncoderOutputStreamParameters streamParams) throws Exception {
ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
- CodecProperties properties = getVp8CodecProperties(true, streamParams.forceSwEncoder);
- Log.d(TAG, "Source reslution: " + streamParams.frameWidth + " x " +
+ Log.d(TAG, "Source resolution: "+streamParams.frameWidth + " x " +
streamParams.frameHeight);
int bitrate = streamParams.bitrateSet[0];
+ // Create minimal media format signifying desired output.
+ MediaFormat format = MediaFormat.createVideoFormat(
+ VP8_MIME, streamParams.frameWidth, streamParams.frameHeight);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+ CodecProperties properties = getVpxCodecProperties(
+ true, format, streamParams.forceGoogleEncoder);
+ if (properties == null) {
+ return null;
+ }
+
// Open input/output
InputStream yuvStream = OpenFileOrResourceId(
streamParams.inputYuvFilename, streamParams.inputResourceId);
@@ -1294,9 +1283,6 @@
streamParams.outputIvfFilename, streamParams.frameWidth, streamParams.frameHeight);
// Create a media format signifying desired output.
- MediaFormat format = MediaFormat.createVideoFormat(
- VP8_MIME, streamParams.frameWidth, streamParams.frameHeight);
- format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
if (streamParams.bitrateType == VIDEO_ControlRateConstant) {
format.setInteger("bitrate-mode", VIDEO_ControlRateConstant); // set CBR
}
@@ -1451,19 +1437,25 @@
}
ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
- CodecProperties properties = getVp8CodecProperties(true, streamParams.forceSwEncoder);
- Log.d(TAG, "Source reslution: " + streamParams.frameWidth + " x " +
+ Log.d(TAG, "Source resolution: "+streamParams.frameWidth + " x " +
streamParams.frameHeight);
int bitrate = streamParams.bitrateSet[0];
+ // Create minimal media format signifying desired output.
+ MediaFormat format = MediaFormat.createVideoFormat(
+ VP8_MIME, streamParams.frameWidth, streamParams.frameHeight);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+ CodecProperties properties = getVpxCodecProperties(
+ true, format, streamParams.forceGoogleEncoder);
+ if (properties == null) {
+ return null;
+ }
+
// Open input/output
IvfWriter ivf = new IvfWriter(
streamParams.outputIvfFilename, streamParams.frameWidth, streamParams.frameHeight);
// Create a media format signifying desired output.
- MediaFormat format = MediaFormat.createVideoFormat(
- VP8_MIME, streamParams.frameWidth, streamParams.frameHeight);
- format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
if (streamParams.bitrateType == VIDEO_ControlRateConstant) {
format.setInteger("bitrate-mode", VIDEO_ControlRateConstant); // set CBR
}
@@ -1546,9 +1538,22 @@
boolean bufferConsumedTotal = false;
CodecProperties[] codecProperties = new CodecProperties[numEncoders];
- for (int i = 0; i < numEncoders; i++) {
- EncoderOutputStreamParameters params = encodingParams.get(i);
- CodecProperties properties = getVp8CodecProperties(true, params.forceSwEncoder);
+ numEncoders = 0;
+ for (EncoderOutputStreamParameters params : encodingParams) {
+ int i = numEncoders;
+ Log.d(TAG, "Source resolution: " + params.frameWidth + " x " +
+ params.frameHeight);
+ int bitrate = params.bitrateSet[0];
+
+ // Create minimal media format signifying desired output.
+ format[i] = MediaFormat.createVideoFormat(VP8_MIME,
+ params.frameWidth, params.frameHeight);
+ format[i].setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+ CodecProperties properties = getVpxCodecProperties(
+ true, format[i], params.forceGoogleEncoder);
+ if (properties == null) {
+ continue;
+ }
// Check if scaled image was created
int scale = params.frameWidth / srcFrameWidth;
@@ -1574,10 +1579,6 @@
srcFrame[i] = new byte[frameSize];
// Create a media format signifying desired output.
- int bitrate = params.bitrateSet[0];
- format[i] = MediaFormat.createVideoFormat(VP8_MIME,
- params.frameWidth, params.frameHeight);
- format[i].setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
if (params.bitrateType == VIDEO_ControlRateConstant) {
format[i].setInteger("bitrate-mode", VIDEO_ControlRateConstant); // set CBR
}
@@ -1607,6 +1608,11 @@
codecProperties[i] = new CodecProperties(properties.codecName, properties.colorFormat);
inputConsumed[i] = true;
+ ++numEncoders;
+ }
+ if (numEncoders == 0) {
+ Log.i(TAG, "no suitable encoders found for any of the streams");
+ return null;
}
while (!sawOutputEOSTotal) {
@@ -1644,7 +1650,8 @@
// Convert YUV420 to NV12 if necessary
if (codecProperties[i].colorFormat !=
CodecCapabilities.COLOR_FormatYUV420Planar) {
- srcFrame[i] = YUV420ToNV(params.frameWidth, params.frameHeight, srcFrame[i]);
+ srcFrame[i] =
+ YUV420ToNV(params.frameWidth, params.frameHeight, srcFrame[i]);
}
}
diff --git a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java b/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
index 57e397f..be7e721 100644
--- a/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/Vp8EncoderTest.java
@@ -18,6 +18,8 @@
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaFormat;
import android.util.Log;
import com.android.cts.media.R;
@@ -52,13 +54,13 @@
private static final int[] TEST_BITRATES_SET = { 300000, 500000, 700000, 900000 };
// Maximum allowed bitrate variation from the target value.
private static final double MAX_BITRATE_VARIATION = 0.2;
- // Average PSNR values for reference SW VP8 codec for the above bitrates.
+ // Average PSNR values for reference Google VP8 codec for the above bitrates.
private static final double[] REFERENCE_AVERAGE_PSNR = { 33.1, 35.2, 36.6, 37.8 };
- // Minimum PSNR values for reference SW VP8 codec for the above bitrates.
+ // Minimum PSNR values for reference Google VP8 codec for the above bitrates.
private static final double[] REFERENCE_MINIMUM_PSNR = { 25.9, 27.5, 28.4, 30.3 };
- // Maximum allowed average PSNR difference of HW encoder comparing to reference SW encoder.
+ // Maximum allowed average PSNR difference of encoder comparing to reference Google encoder.
private static final double MAX_AVERAGE_PSNR_DIFFERENCE = 2;
- // Maximum allowed minimum PSNR difference of HW encoder comparing to reference SW encoder.
+ // Maximum allowed minimum PSNR difference of encoder comparing to reference Google encoder.
private static final double MAX_MINIMUM_PSNR_DIFFERENCE = 4;
// Maximum allowed average PSNR difference of the encoder running in a looper thread with 0 ms
// buffer dequeue timeout comparing to the encoder running in a callee's thread with 100 ms
@@ -80,13 +82,8 @@
* Also checks the average bitrate is within MAX_BITRATE_VARIATION of the target value.
*/
public void testBasic() throws Exception {
- MediaCodecInfo codecInfo = selectCodec(VP8_MIME);
- if (codecInfo == null) {
- Log.w(TAG, "Codec " + VP8_MIME + " not supported. Return from testBasic.");
- return;
- }
-
int encodeSeconds = 9;
+ boolean skipped = true;
for (int targetBitrate : TEST_BITRATES_SET) {
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
@@ -100,6 +97,11 @@
targetBitrate,
true);
ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+ if (bufInfo == null) {
+ continue;
+ }
+ skipped = false;
+
Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
assertEquals("Stream bitrate " + statistics.mAverageBitrate +
@@ -107,7 +109,11 @@
targetBitrate, statistics.mAverageBitrate,
MAX_BITRATE_VARIATION * targetBitrate);
- decode(params.outputIvfFilename, null, FPS, params.forceSwEncoder);
+ decode(params.outputIvfFilename, null, FPS, params.forceGoogleEncoder);
+ }
+
+ if (skipped) {
+ Log.i(TAG, "SKIPPING testBasic(): codec is not supported");
}
}
@@ -119,12 +125,6 @@
* does not change much for two different ways of the encoder call.
*/
public void testAsyncEncoding() throws Exception {
- MediaCodecInfo codecInfo = selectCodec(VP8_MIME);
- if (codecInfo == null) {
- Log.w(TAG, "Codec " + VP8_MIME + " not supported. Return from testAsyncEncoding.");
- return;
- }
-
int encodeSeconds = 9;
// First test the encoder running in a looper thread with buffer callbacks enabled.
@@ -140,8 +140,12 @@
BITRATE,
syncEncoding);
ArrayList<MediaCodec.BufferInfo> bufInfos = encodeAsync(params);
+ if (bufInfos == null) {
+ Log.i(TAG, "SKIPPING testAsyncEncoding(): no suitable encoder found");
+ return;
+ }
computeEncodingStatistics(bufInfos);
- decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceSwEncoder);
+ decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
Vp8DecodingStatistics statisticsAsync = computeDecodingStatistics(
params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -160,8 +164,12 @@
BITRATE,
syncEncoding);
bufInfos = encode(params);
+ if (bufInfos == null) {
+ Log.i(TAG, "SKIPPING testAsyncEncoding(): no suitable encoder found");
+ return;
+ }
computeEncodingStatistics(bufInfos);
- decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceSwEncoder);
+ decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
Vp8DecodingStatistics statisticsSync = computeDecodingStatistics(
params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -186,12 +194,6 @@
* The test does not verify the output stream.
*/
public void testSyncFrame() throws Exception {
- MediaCodecInfo codecInfo = selectCodec(VP8_MIME);
- if (codecInfo == null) {
- Log.w(TAG, "Codec " + VP8_MIME + " not supported. Return from testSyncFrame.");
- return;
- }
-
int encodeSeconds = 9;
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
@@ -207,6 +209,11 @@
params.syncFrameInterval = encodeSeconds * FPS;
params.syncForceFrameInterval = FPS;
ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+ if (bufInfo == null) {
+ Log.i(TAG, "SKIPPING testSyncFrame(): no suitable encoder found");
+ return;
+ }
+
Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
// First check if we got expected number of key frames.
@@ -236,12 +243,6 @@
* bitrate after 6 seconds and ensure the encoder responds.
*/
public void testDynamicBitrateChange() throws Exception {
- MediaCodecInfo codecInfo = selectCodec(VP8_MIME);
- if (codecInfo == null) {
- Log.w(TAG, "Codec " + VP8_MIME + " not supported. Return from testDynamicBitrateChange.");
- return;
- }
-
int encodeSeconds = 12; // Encoding sequence duration in seconds.
int[] bitrateTargetValues = { 400000, 800000 }; // List of bitrates to test.
@@ -268,6 +269,11 @@
}
ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+ if (bufInfo == null) {
+ Log.i(TAG, "SKIPPING testDynamicBitrateChange(): no suitable encoder found");
+ return;
+ }
+
Vp8EncodingStatistics statistics = computeEncodingStatistics(bufInfo);
// Calculate actual average bitrates for every [stepSeconds] second.
@@ -304,10 +310,12 @@
* Compares average bitrate and PSNR for sequential and parallel runs.
*/
public void testParallelEncodingAndDecoding() throws Exception {
- MediaCodecInfo codecInfo = selectCodec(VP8_MIME);
- if (codecInfo == null) {
- Log.w(TAG, "Codec " + VP8_MIME + " not supported. "
- + "Return from testParallelEncodingAndDecoding.");
+ // check for encoder up front, as by the time we detect lack of
+ // encoder support, we may have already started decoding.
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ MediaFormat format = MediaFormat.createVideoFormat(VP8_MIME, WIDTH, HEIGHT);
+ if (mcl.findEncoderForFormat(format) == null) {
+ Log.i(TAG, "SKIPPING testParallelEncodingAndDecoding(): no suitable encoder found");
return;
}
@@ -343,7 +351,7 @@
Runnable runDecoder = new Runnable() {
public void run() {
try {
- decode(inputIvfFilename, OUTPUT_YUV, FPS, params.forceSwEncoder);
+ decode(inputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
Vp8DecodingStatistics statistics = computeDecodingStatistics(
params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -400,21 +408,17 @@
* Run the the encoder for 9 seconds for each bitrate and calculate PSNR
* for each encoded stream.
* Video streams with higher bitrates should have higher PSNRs.
- * Also compares average and minimum PSNR of HW codec with PSNR values of reference SW codec.
+ * Also compares average and minimum PSNR of codec with PSNR values of reference Google codec.
*/
public void testEncoderQuality() throws Exception {
- MediaCodecInfo codecInfo = selectCodec(VP8_MIME);
- if (codecInfo == null) {
- Log.w(TAG, "Codec " + VP8_MIME + " not supported. Return from testEncoderQuality.");
- return;
- }
-
int encodeSeconds = 9; // Encoding sequence duration in seconds for each bitrate.
double[] psnrPlatformCodecAverage = new double[TEST_BITRATES_SET.length];
double[] psnrPlatformCodecMin = new double[TEST_BITRATES_SET.length];
+ boolean[] completed = new boolean[TEST_BITRATES_SET.length];
+ boolean skipped = true;
// Run platform specific encoder for different bitrates
- // and compare PSNR of hw codec with PSNR of reference sw codec.
+ // and compare PSNR of codec with PSNR of reference Google codec.
for (int i = 0; i < TEST_BITRATES_SET.length; i++) {
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
@@ -426,9 +430,15 @@
BITRATE_MODE,
TEST_BITRATES_SET[i],
true);
- encode(params);
+ if (encode(params) == null) {
+ // parameters not supported, try other bitrates
+ completed[i] = false;
+ continue;
+ }
+ completed[i] = true;
+ skipped = false;
- decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceSwEncoder);
+ decode(params.outputIvfFilename, OUTPUT_YUV, FPS, params.forceGoogleEncoder);
Vp8DecodingStatistics statistics = computeDecodingStatistics(
params.inputYuvFilename, R.raw.football_qvga, OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -436,9 +446,20 @@
psnrPlatformCodecMin[i] = statistics.mMinimumPSNR;
}
+ if (skipped) {
+ Log.i(TAG, "SKIPPING testEncoderQuality(): no bitrates supported");
+ return;
+ }
+
// First do a sanity check - higher bitrates should results in higher PSNR.
for (int i = 1; i < TEST_BITRATES_SET.length ; i++) {
+ if (!completed[i]) {
+ continue;
+ }
for (int j = 0; j < i; j++) {
+ if (!completed[j]) {
+ continue;
+ }
double differenceBitrate = TEST_BITRATES_SET[i] - TEST_BITRATES_SET[j];
double differencePSNR = psnrPlatformCodecAverage[i] - psnrPlatformCodecAverage[j];
if (differenceBitrate * differencePSNR < 0) {
@@ -450,12 +471,16 @@
}
}
- // Then compare average and minimum PSNR of platform codec with reference sw codec -
+ // Then compare average and minimum PSNR of platform codec with reference Google codec -
// average PSNR for platform codec should be no more than 2 dB less than reference PSNR
// and minumum PSNR - no more than 4 dB less than reference minimum PSNR.
// These PSNR difference numbers are arbitrary for now, will need further estimation
- // when more devices with hw VP8 codec will appear.
+ // when more devices with HW VP8 codec will appear.
for (int i = 0; i < TEST_BITRATES_SET.length ; i++) {
+ if (!completed[i]) {
+ continue;
+ }
+
Log.d(TAG, "Bitrate " + TEST_BITRATES_SET[i]);
Log.d(TAG, "Reference: Average: " + REFERENCE_AVERAGE_PSNR[i] + ". Minimum: " +
REFERENCE_MINIMUM_PSNR[i]);
@@ -470,7 +495,7 @@
if (psnrPlatformCodecMin[i] < REFERENCE_MINIMUM_PSNR[i] -
MAX_MINIMUM_PSNR_DIFFERENCE) {
throw new RuntimeException("Low minimum PSNR " + psnrPlatformCodecMin[i] +
- " comparing to sw PSNR " + REFERENCE_MINIMUM_PSNR[i] +
+ " comparing to reference PSNR " + REFERENCE_MINIMUM_PSNR[i] +
" for bitrate " + TEST_BITRATES_SET[i]);
}
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/MediaFrameworkTest.java b/tests/tests/mediastress/src/android/mediastress/cts/MediaFrameworkTest.java
index 09cc8b8..d39bc16 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/MediaFrameworkTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/MediaFrameworkTest.java
@@ -19,15 +19,13 @@
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
-import android.graphics.Bitmap;
+import android.media.MediaFormat;
import android.net.Uri;
import android.os.Bundle;
import android.os.PowerManager;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
-import android.view.ViewGroup;
-import android.widget.ImageView;
import com.android.cts.mediastress.R;
@@ -85,7 +83,7 @@
}
public void startPlayback(String filename){
- String mimetype = "audio/mpeg";
+ String mimetype = MediaFormat.MIMETYPE_AUDIO_MPEG;
Uri path = Uri.parse(filename);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(path, mimetype);
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/NativeMediaTest.java b/tests/tests/mediastress/src/android/mediastress/cts/NativeMediaTest.java
index 2119d75..05145f5 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/NativeMediaTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/NativeMediaTest.java
@@ -17,11 +17,11 @@
import android.app.Instrumentation;
import android.content.Intent;
+import android.cts.util.MediaUtils;
import android.media.CamcorderProfile;
+import android.media.MediaFormat;
import android.media.MediaRecorder.AudioEncoder;
import android.media.MediaRecorder.VideoEncoder;
-import android.media.MediaCodecInfo;
-import android.media.MediaCodecList;
import android.os.Environment;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
@@ -30,31 +30,11 @@
public class NativeMediaTest extends ActivityInstrumentationTestCase2<NativeMediaActivity> {
private static final String TAG = "NativeMediaTest";
- private static final String MIME_TYPE = "video/h264";
+ private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
private static final int VIDEO_CODEC = VideoEncoder.H264;
private static final int NUMBER_PLAY_PAUSE_REPEATITIONS = 10;
private static final long PLAY_WAIT_TIME_MS = 4000;
- private static boolean hasCodec(String mimeType) {
- int numCodecs = MediaCodecList.getCodecCount();
-
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-
- if (!codecInfo.isEncoder()) {
- continue;
- }
-
- String[] types = codecInfo.getSupportedTypes();
- for (int j = 0; j < types.length; j++) {
- if (types[j].equalsIgnoreCase(mimeType)) {
- return true;
- }
- }
- }
- return false;
- }
-
public NativeMediaTest() {
super(NativeMediaActivity.class);
}
@@ -77,9 +57,8 @@
private void runPlayTest(int quality) throws InterruptedException {
// Don't run the test if the codec isn't supported.
- if (!hasCodec(MIME_TYPE)) {
- Log.w(TAG, "Codec " + MIME_TYPE + " not supported.");
- return;
+ if (!MediaUtils.checkDecoder(MIME_TYPE)) {
+ return; // skip
}
// Don't run the test if the quality level isn't supported.
if (quality != 0) {
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
index b6175be..974eeb7 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStore_Video_ThumbnailsTest.java
@@ -22,6 +22,7 @@
import android.content.ContentUris;
import android.content.ContentValues;
import android.cts.util.FileCopyHelper;
+import android.cts.util.MediaUtils;
import android.database.Cursor;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
@@ -38,32 +39,13 @@
public class MediaStore_Video_ThumbnailsTest extends AndroidTestCase {
private static final String TAG = "MediaStore_Video_ThumbnailsTest";
- private static final String MIME_TYPE = "video/3gpp";
private ContentResolver mResolver;
private FileCopyHelper mFileHelper;
- // TODO: Make a public method selectCodec() in common libraries (e.g. cts/libs/), to avoid
- // redundant function definitions in this and other media related test files.
- private static boolean hasCodec(String mimeType) {
- int numCodecs = MediaCodecList.getCodecCount();
-
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-
- if (!codecInfo.isEncoder()) {
- continue;
- }
-
- String[] types = codecInfo.getSupportedTypes();
- for (int j = 0; j < types.length; j++) {
- if (types[j].equalsIgnoreCase(mimeType)) {
- return true;
- }
- }
- }
- return false;
+ private boolean hasCodec() {
+ return MediaUtils.hasCodecForResourceAndDomain(mContext, R.raw.testvideo, "video/");
}
@Override
@@ -98,10 +80,10 @@
int count = getThumbnailCount(Thumbnails.EXTERNAL_CONTENT_URI);
// Don't run the test if the codec isn't supported.
- if (!hasCodec(MIME_TYPE)) {
+ if (!hasCodec()) {
// Calling getThumbnail should not generate a new thumbnail.
assertNull(Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.MINI_KIND, null));
- Log.w(TAG, "Codec " + MIME_TYPE + " not supported. Return from testGetThumbnail.");
+ Log.i(TAG, "SKIPPING testGetThumbnail(): codec not supported");
return;
}
diff --git a/tests/tests/widget/src/android/widget/cts/VideoViewTest.java b/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
index 6e514f8..d9af514 100644
--- a/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/VideoViewTest.java
@@ -21,6 +21,7 @@
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
+import android.cts.util.MediaUtils;
import android.cts.util.PollingCheck;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
@@ -53,8 +54,6 @@
private static final int TEST_VIDEO_DURATION = 11047;
/** The full name of R.raw.testvideo. */
private static final String VIDEO_NAME = "testvideo.3gp";
- /** The MIME type. */
- private static final String MIME_TYPE = "video/3gpp";
/** delta for duration in case user uses different decoders on different
hardware that report a duration that's different by a few milliseconds */
private static final int DURATION_DELTA = 100;
@@ -101,26 +100,8 @@
}
}
- // TODO: Make a public method selectCodec() in common libraries (e.g. cts/libs/), to avoid
- // redundant function definitions in this and other media related test files.
- private static boolean hasCodec(String mimeType) {
- int numCodecs = MediaCodecList.getCodecCount();
-
- for (int i = 0; i < numCodecs; i++) {
- MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
-
- if (!codecInfo.isEncoder()) {
- continue;
- }
-
- String[] types = codecInfo.getSupportedTypes();
- for (int j = 0; j < types.length; j++) {
- if (types[j].equalsIgnoreCase(mimeType)) {
- return true;
- }
- }
- }
- return false;
+ private boolean hasCodec() {
+ return MediaUtils.hasCodecsForResource(mActivity, R.raw.testvideo);
}
/**
@@ -204,8 +185,8 @@
public void testPlayVideo1() throws Throwable {
makeVideoView();
// Don't run the test if the codec isn't supported.
- if (!hasCodec(MIME_TYPE)) {
- Log.w(TAG, "Codec " + MIME_TYPE + " not supported. Return from testPlayVideo1.");
+ if (!hasCodec()) {
+ Log.i(TAG, "SKIPPING testPlayVideo1(): codec is not supported");
return;
}
@@ -266,8 +247,8 @@
public void testGetBufferPercentage() throws Throwable {
makeVideoView();
// Don't run the test if the codec isn't supported.
- if (!hasCodec(MIME_TYPE)) {
- Log.w(TAG, MIME_TYPE + " not supported. Return from testGetBufferPercentage.");
+ if (!hasCodec()) {
+ Log.i(TAG, "SKIPPING testGetBufferPercentage(): codec is not supported");
return;
}
@@ -309,8 +290,8 @@
public void testGetDuration() throws Throwable {
// Don't run the test if the codec isn't supported.
- if (!hasCodec(MIME_TYPE)) {
- Log.w(TAG, "Codec " + MIME_TYPE + " not supported. Return from testGetDuration.");
+ if (!hasCodec()) {
+ Log.i(TAG, "SKIPPING testGetDuration(): codec is not supported");
return;
}