CP MediaStress and MediaPreparer dynamic config changes to nougat
bug:33573055
bug:31443110
bug:32420751
Test: run cts -m CtsMediaStressTestCases
Change-Id: I96ce1be09f75b7ab75a9317fbf8f3a8f5e53bf0a
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
index c7acdcd..52294205 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
@@ -66,7 +66,7 @@
void setPreparerWhitelist(Set<String> preparerWhitelist);
/**
- * Runs the module's precondition checks and setup tasks.
+ * Pushes dynamic configuration, then runs the module's precondition checks and setup tasks.
* @param skipPrep whether preparation should be skipped
* @param preconditionArgs arguments to set on precondition preparers for the module, taking
* format arg-name:arg-value. If "arg-value" is unset, the value will default to "true".
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
index 5ed6870..d8a2adb 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
@@ -17,6 +17,7 @@
import com.android.compatibility.common.tradefed.result.IModuleListener;
import com.android.compatibility.common.tradefed.result.ModuleListener;
+import com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher;
import com.android.compatibility.common.tradefed.targetprep.PreconditionPreparer;
import com.android.compatibility.common.tradefed.targetprep.TokenRequirement;
import com.android.compatibility.common.util.AbiUtils;
@@ -58,6 +59,7 @@
private final IAbi mAbi;
private final Set<String> mTokens = new HashSet<>();
private IRemoteTest mTest = null;
+ private List<ITargetPreparer> mDynamicConfigPreparers = new ArrayList<>();
private List<ITargetPreparer> mPreconditions = new ArrayList<>();
private List<ITargetPreparer> mPreparers = new ArrayList<>();
private List<ITargetCleaner> mCleaners = new ArrayList<>();
@@ -76,9 +78,11 @@
if (preparer instanceof IAbiReceiver) {
hasAbiReceiver = true;
}
- // Separate preconditions from target preparers.
+ // Separate preconditions and dynamicconfigpushers from other target preparers.
if (preparer instanceof PreconditionPreparer) {
mPreconditions.add(preparer);
+ }else if (preparer instanceof DynamicConfigPusher) {
+ mDynamicConfigPreparers.add(preparer);
} else if (preparer instanceof TokenRequirement) {
mTokens.addAll(((TokenRequirement) preparer).getTokens());
} else {
@@ -216,34 +220,16 @@
@Override
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
IModuleListener moduleListener = new ModuleListener(this, listener);
-
+ // Run DynamicConfigPusher setup once more, in case cleaner has previously
+ // removed dynamic config file from the target (see b/32877809)
+ for (ITargetPreparer preparer : mDynamicConfigPreparers) {
+ runPreparerSetup(preparer);
+ }
// Setup
for (ITargetPreparer preparer : mPreparers) {
- String preparerName = preparer.getClass().getCanonicalName();
- if (!mPreparerWhitelist.isEmpty() && !mPreparerWhitelist.contains(preparerName)) {
- CLog.w("Skipping Preparer: %s since it is not in the whitelist %s",
- preparerName, mPreparerWhitelist);
- continue;
- }
- CLog.d("Preparer: %s", preparer.getClass().getSimpleName());
- if (preparer instanceof IAbiReceiver) {
- ((IAbiReceiver) preparer).setAbi(mAbi);
- }
- try {
- preparer.setUp(mDevice, mBuild);
- } catch (BuildError e) {
- // This should only happen for flashing new build
- CLog.e("Unexpected BuildError from precondition: %s",
- preparer.getClass().getCanonicalName());
- } catch (TargetSetupError e) {
- // log precondition class then rethrow & let caller handle
- CLog.e("TargetSetupError in precondition: %s",
- preparer.getClass().getCanonicalName());
- throw new RuntimeException(e);
- }
+ runPreparerSetup(preparer);
}
-
CLog.d("Test: %s", mTest.getClass().getSimpleName());
if (mTest instanceof IAbiReceiver) {
((IAbiReceiver) mTest).setAbi(mAbi);
@@ -270,34 +256,51 @@
@Override
public boolean prepare(boolean skipPrep, List<String> preconditionArgs)
throws DeviceNotAvailableException {
+ for (ITargetPreparer preparer : mDynamicConfigPreparers) {
+ runPreparerSetup(preparer);
+ }
for (ITargetPreparer preparer : mPreconditions) {
- CLog.d("Preparer: %s", preparer.getClass().getSimpleName());
- if (preparer instanceof IAbiReceiver) {
- ((IAbiReceiver) preparer).setAbi(mAbi);
- }
setOption(preparer, CompatibilityTest.SKIP_PRECONDITIONS_OPTION,
Boolean.toString(skipPrep));
for (String preconditionArg : preconditionArgs) {
setOption(preparer, CompatibilityTest.PRECONDITION_ARG_OPTION, preconditionArg);
}
try {
- preparer.setUp(mDevice, mBuild);
- } catch (BuildError e) {
- // This should only happen for flashing new build
- CLog.e("Unexpected BuildError from precondition: %s",
- preparer.getClass().getCanonicalName());
- return false;
- } catch (TargetSetupError e) {
- // log precondition class then rethrow & let caller handle
- CLog.e("TargetSetupError in precondition: %s",
- preparer.getClass().getCanonicalName());
- e.printStackTrace();
+ runPreparerSetup(preparer);
+ } catch (RuntimeException e) {
+ CLog.e("Precondition class %s failed", preparer.getClass().getCanonicalName());
return false;
}
}
return true;
}
+ private void runPreparerSetup(ITargetPreparer preparer) throws DeviceNotAvailableException {
+ String preparerName = preparer.getClass().getCanonicalName();
+ if (!mPreparerWhitelist.isEmpty() && !mPreparerWhitelist.contains(preparerName)) {
+ CLog.w("Skipping Preparer: %s since it is not in the whitelist %s",
+ preparerName, mPreparerWhitelist);
+ return;
+ }
+ CLog.d("Preparer: %s", preparer.getClass().getSimpleName());
+ if (preparer instanceof IAbiReceiver) {
+ ((IAbiReceiver) preparer).setAbi(mAbi);
+ }
+ try {
+ preparer.setUp(mDevice, mBuild);
+ } catch (BuildError e) {
+ // This should only happen for flashing new build
+ CLog.e("Unexpected BuildError from preparer: %s",
+ preparer.getClass().getCanonicalName());
+ throw new RuntimeException(e);
+ } catch (TargetSetupError e) {
+ // log preparer class then rethrow & let caller handle
+ CLog.e("TargetSetupError in preparer: %s",
+ preparer.getClass().getCanonicalName());
+ throw new RuntimeException(e);
+ }
+ }
+
private void setOption(Object target, String option, String value) {
try {
OptionSetter setter = new OptionSetter(target);
diff --git a/common/util/src/com/android/compatibility/common/util/DynamicConfig.java b/common/util/src/com/android/compatibility/common/util/DynamicConfig.java
index 8317203..d316b9d 100644
--- a/common/util/src/com/android/compatibility/common/util/DynamicConfig.java
+++ b/common/util/src/com/android/compatibility/common/util/DynamicConfig.java
@@ -29,6 +29,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* Load dynamic config for test cases
@@ -67,6 +68,10 @@
return mDynamicConfigMap.get(key);
}
+ public Set<String> keySet() {
+ return mDynamicConfigMap.keySet();
+ }
+
public static File getConfigFile(File configFolder, String moduleName)
throws FileNotFoundException {
File config = new File(configFolder, String.format("%s.dynamic", moduleName));
diff --git a/libs/deviceutil/src/android/cts/util/MediaUtils.java b/libs/deviceutil/src/android/cts/util/MediaUtils.java
index 2c6aeae..56868a5 100644
--- a/libs/deviceutil/src/android/cts/util/MediaUtils.java
+++ b/libs/deviceutil/src/android/cts/util/MediaUtils.java
@@ -154,12 +154,11 @@
public static void skipTest(String tag, String reason) {
Log.i(tag, "SKIPPING " + getTestName() + "(): " + reason);
DeviceReportLog log = new DeviceReportLog("CtsMediaSkippedTests", "test_skipped");
- log.addValue("reason", reason, ResultType.NEUTRAL, ResultUnit.NONE);
- log.addValue(
- "test", getTestNameWithClass(), ResultType.NEUTRAL, ResultUnit.NONE);
- // TODO: replace with submit() when it is added to DeviceReportLog
try {
- log.submit(null);
+ log.addValue("reason", reason, ResultType.NEUTRAL, ResultUnit.NONE);
+ log.addValue(
+ "test", getTestNameWithClass(), ResultType.NEUTRAL, ResultUnit.NONE);
+ log.submit();
} catch (NullPointerException e) { }
}
diff --git a/tests/tests/mediastress/Android.mk b/tests/tests/mediastress/Android.mk
index 8667e68..4cbc4cc 100644
--- a/tests/tests/mediastress/Android.mk
+++ b/tests/tests/mediastress/Android.mk
@@ -26,7 +26,7 @@
# Include both the 32 and 64 bit versions
LOCAL_MULTILIB := both
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctsdeviceutil compatibility-device-util
LOCAL_HOST_SHARED_LIBRARIES := compatibility-device-media-preconditions
diff --git a/tests/tests/mediastress/AndroidTest.xml b/tests/tests/mediastress/AndroidTest.xml
index c01bbdf..a0cc68a 100644
--- a/tests/tests/mediastress/AndroidTest.xml
+++ b/tests/tests/mediastress/AndroidTest.xml
@@ -19,6 +19,10 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsMediaStressTestCases.apk" />
</target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="device" />
+ <option name="config-filename" value="CtsMediaStressTestCases" />
+ </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.mediastress.cts" />
<!-- test-timeout unit is ms, value = 30 min -->
diff --git a/tests/tests/mediastress/DynamicConfig.xml b/tests/tests/mediastress/DynamicConfig.xml
new file mode 100644
index 0000000..2f8cfb0
--- /dev/null
+++ b/tests/tests/mediastress/DynamicConfig.xml
@@ -0,0 +1,347 @@
+<!-- Copyright (C) 2016 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.
+-->
+
+<dynamicConfig>
+ <entry key="bbb_full_1280x720_mp4_libx264_libfaac_bbb_full_ffmpeg_1280x720_mp4_libx264_1350kbps_25fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_full_1280x720_mp4_libx264_libfaac_bbb_full_ffmpeg_1280x720_mp4_libx264_1750kbps_30fps_libfaac_stereo_192kbps_48000hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_full_1280x720_mp4_libx265_libfaac_bbb_full_ffmpeg_1280x720_mp4_libx265_1140kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,bitrate=999120,width=1280,height=720,frame-rate=30,profile=1,level=256;mime=audio/mp4a-latm,bitrate=127968,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_full_1280x720_mp4_libx265_libfaac_bbb_full_ffmpeg_1280x720_mp4_libx265_880kbps_24fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,bitrate=748632,width=1280,height=720,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,bitrate=127976,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_full_176x144_3gp_h263_libfaac_bbb_full_ffmpeg_176x144_3gp_h263_56kbps_12fps_libfaac_mono_24kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=1,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_full_1920x1080_mp4_libx264_libfaac_bbb_full_ffmpeg_1920x1080_mp4_libx264_10000kbps_30fps_libfaac_stereo_192kbps_48000hz_mp4">
+ <value>mime=video/avc,width=1920,height=1080,frame-rate=24,profile=1,level=4096;mime=audio/mp4a-latm,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_full_1920x1080_mp4_libx265_libfaac_bbb_full_ffmpeg_1920x1080_mp4_libx265_6500kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1920,height=1080,frame-rate=30,profile=1,level=1024;mime=audio/mp4a-latm,bitrate=128006,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_full_480x360_webm_libvpx_libvorbis_bbb_full_ffmpeg_480x360_webm_libvpx_500kbps_25fps_libvorbis_stereo_128kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_full_720x480_mp4_libx264_libfaac_bbb_full_ffmpeg_720x480_mp4_libx264_500kbps_25fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_full_720x480_mp4_libx265_libfaac_bbb_full_ffmpeg_720x480_mp4_libx265_325kbps_24fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,bitrate=280872,width=720,height=480,frame-rate=24,profile=1,level=64;mime=audio/mp4a-latm,bitrate=127976,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_1000kbps_25fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_1000kbps_25fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_1000kbps_30fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_1000kbps_30fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_1350kbps_25fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_1350kbps_25fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_1350kbps_30fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_1350kbps_30fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_1750kbps_30fps_libfaac_stereo_192kbps_48000hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_500kbps_25fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_500kbps_25fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_500kbps_30fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx264_libfaac_bbb_short_ffmpeg_1280x720_mp4_libx264_500kbps_30fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=1280,height=720,frame-rate=24,profile=1,level=512;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx265_libfaac_bbb_short_fmpeg_1280x720_mp4_libx265_1140kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1280,height=720,frame-rate=30,profile=1,level=256;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx265_libfaac_bbb_short_fmpeg_1280x720_mp4_libx265_3250kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1280,height=720,frame-rate=30,profile=1,level=256;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx265_libfaac_bbb_short_fmpeg_1280x720_mp4_libx265_325kbps_24fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1280,height=720,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,bitrate=129452,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx265_libfaac_bbb_short_fmpeg_1280x720_mp4_libx265_325kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1280,height=720,frame-rate=30,profile=1,level=256;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx265_libfaac_bbb_short_fmpeg_1280x720_mp4_libx265_6500kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1280,height=720,frame-rate=30,profile=1,level=256;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx265_libfaac_bbb_short_fmpeg_1280x720_mp4_libx265_650kbps_24fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1280,height=720,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,bitrate=129452,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx265_libfaac_bbb_short_fmpeg_1280x720_mp4_libx265_650kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1280,height=720,frame-rate=30,profile=1,level=256;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx265_libfaac_bbb_short_fmpeg_1280x720_mp4_libx265_880kbps_24fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1280,height=720,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,bitrate=129452,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1280x720_mp4_libx265_libfaac_bbb_short_fmpeg_1280x720_mp4_libx265_880kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1280,height=720,frame-rate=30,profile=1,level=256;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_300kbps_12fps_libfaac_mono_24kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=1,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_300kbps_12fps_libfaac_mono_24kbps_22050hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=22050,channel-count=1,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_300kbps_12fps_libfaac_stereo_128kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_300kbps_12fps_libfaac_stereo_128kbps_22050hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=22050,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_300kbps_12fps_libfaac_stereo_24kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_300kbps_12fps_libfaac_stereo_24kbps_22050hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=22050,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_300kbps_25fps_libfaac_mono_24kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=25,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=1,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_300kbps_25fps_libfaac_mono_24kbps_22050hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=25,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=22050,channel-count=1,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_300kbps_25fps_libfaac_stereo_128kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=25,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_300kbps_25fps_libfaac_stereo_128kbps_22050hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=25,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=22050,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_300kbps_25fps_libfaac_stereo_24kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=25,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_300kbps_25fps_libfaac_stereo_24kbps_22050hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=25,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=22050,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_56kbps_12fps_libfaac_mono_24kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=1,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_56kbps_12fps_libfaac_mono_24kbps_22050hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=22050,channel-count=1,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_56kbps_12fps_libfaac_stereo_128kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_56kbps_12fps_libfaac_stereo_128kbps_22050hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=22050,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_56kbps_12fps_libfaac_stereo_24kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_56kbps_12fps_libfaac_stereo_24kbps_22050hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=12,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=22050,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_56kbps_25fps_libfaac_mono_24kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=25,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=1,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_56kbps_25fps_libfaac_mono_24kbps_22050hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=25,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=22050,channel-count=1,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_56kbps_25fps_libfaac_stereo_128kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=25,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_56kbps_25fps_libfaac_stereo_128kbps_22050hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=25,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=22050,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_56kbps_25fps_libfaac_stereo_24kbps_11025hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=25,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=11025,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_176x144_3gp_h263_libfaac_bbb_short_ffmpeg_176x144_3gp_h263_56kbps_25fps_libfaac_stereo_24kbps_22050hz_3gp">
+ <value>mime=video/3gpp,width=176,height=144,frame-rate=25,profile=1,level=1;mime=audio/mp4a-latm,sample-rate=22050,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1920x1080_mp4_libx264_libfaac_bbb_short_ffmpeg_1920x1080_mp4_libx264_10000kbps_30fps_libfaac_stereo_192kbps_48000hz_mp4">
+ <value>mime=video/avc,width=1920,height=1080,frame-rate=24,profile=1,level=4096;mime=audio/mp4a-latm,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1920x1080_mp4_libx264_libfaac_bbb_short_ffmpeg_1920x1080_mp4_libx264_1750kbps_30fps_libfaac_stereo_192kbps_48000hz_mp4">
+ <value>mime=video/avc,width=1920,height=1080,frame-rate=24,profile=1,level=2048;mime=audio/mp4a-latm,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1920x1080_mp4_libx264_libfaac_bbb_short_ffmpeg_1920x1080_mp4_libx264_5000kbps_30fps_libfaac_stereo_192kbps_48000hz_mp4">
+ <value>mime=video/avc,width=1920,height=1080,frame-rate=24,profile=1,level=2048;mime=audio/mp4a-latm,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1920x1080_mp4_libx265_libfaac_bbb_short_fmpeg_1920x1080_mp4_libx265_1140kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1920,height=1080,frame-rate=30,profile=1,level=1024;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1920x1080_mp4_libx265_libfaac_bbb_short_fmpeg_1920x1080_mp4_libx265_3250kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1920,height=1080,frame-rate=30,profile=1,level=1024;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_1920x1080_mp4_libx265_libfaac_bbb_short_fmpeg_1920x1080_mp4_libx265_6500kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=1920,height=1080,frame-rate=30,profile=1,level=1024;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx264_libfaac_bbb_short_ffmpeg_480x360_mp4_libx264_1000kbps_25fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=480,height=360,frame-rate=24,profile=1,level=64;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx264_libfaac_bbb_short_ffmpeg_480x360_mp4_libx264_1000kbps_25fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=480,height=360,frame-rate=24,profile=1,level=64;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx264_libfaac_bbb_short_ffmpeg_480x360_mp4_libx264_1000kbps_30fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=480,height=360,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx264_libfaac_bbb_short_ffmpeg_480x360_mp4_libx264_1000kbps_30fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=480,height=360,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx264_libfaac_bbb_short_ffmpeg_480x360_mp4_libx264_1350kbps_25fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=480,height=360,frame-rate=24,profile=1,level=64;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx264_libfaac_bbb_short_ffmpeg_480x360_mp4_libx264_1350kbps_25fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=480,height=360,frame-rate=24,profile=1,level=64;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx264_libfaac_bbb_short_ffmpeg_480x360_mp4_libx264_1350kbps_30fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=480,height=360,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx264_libfaac_bbb_short_ffmpeg_480x360_mp4_libx264_1350kbps_30fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=480,height=360,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx264_libfaac_bbb_short_ffmpeg_480x360_mp4_libx264_500kbps_25fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=480,height=360,frame-rate=24,profile=1,level=64;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx264_libfaac_bbb_short_ffmpeg_480x360_mp4_libx264_500kbps_25fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=480,height=360,frame-rate=24,profile=1,level=64;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx264_libfaac_bbb_short_ffmpeg_480x360_mp4_libx264_500kbps_30fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=480,height=360,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx264_libfaac_bbb_short_ffmpeg_480x360_mp4_libx264_500kbps_30fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=480,height=360,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx265_libfaac_bbb_short_fmpeg_480x360_mp4_libx265_325kbps_24fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=640,height=480,frame-rate=24,profile=1,level=64;mime=audio/mp4a-latm,bitrate=129452,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx265_libfaac_bbb_short_fmpeg_480x360_mp4_libx265_325kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=640,height=480,frame-rate=30,profile=1,level=64;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx265_libfaac_bbb_short_fmpeg_480x360_mp4_libx265_650kbps_24fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=480,height=360,frame-rate=24,profile=1,level=16;mime=audio/mp4a-latm,bitrate=129452,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx265_libfaac_bbb_short_fmpeg_480x360_mp4_libx265_650kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=480,height=360,frame-rate=30,profile=1,level=16;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx265_libfaac_bbb_short_fmpeg_480x360_mp4_libx265_880kbps_24fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=480,height=360,frame-rate=24,profile=1,level=16;mime=audio/mp4a-latm,bitrate=129452,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_mp4_libx265_libfaac_bbb_short_fmpeg_480x360_mp4_libx265_880kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=480,height=360,frame-rate=30,profile=1,level=16;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_webm_libvpx_libvorbis_bbb_short_ffmpeg_480x360_webm_libvpx_1000kbps_25fps_libvorbis_stereo_128kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_webm_libvpx_libvorbis_bbb_short_ffmpeg_480x360_webm_libvpx_1000kbps_25fps_libvorbis_stereo_192kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_webm_libvpx_libvorbis_bbb_short_ffmpeg_480x360_webm_libvpx_1000kbps_30fps_libvorbis_stereo_128kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_webm_libvpx_libvorbis_bbb_short_ffmpeg_480x360_webm_libvpx_1000kbps_30fps_libvorbis_stereo_192kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_webm_libvpx_libvorbis_bbb_short_ffmpeg_480x360_webm_libvpx_1350kbps_25fps_libvorbis_stereo_128kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_webm_libvpx_libvorbis_bbb_short_ffmpeg_480x360_webm_libvpx_1350kbps_25fps_libvorbis_stereo_192kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_webm_libvpx_libvorbis_bbb_short_ffmpeg_480x360_webm_libvpx_1350kbps_30fps_libvorbis_stereo_128kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_webm_libvpx_libvorbis_bbb_short_ffmpeg_480x360_webm_libvpx_1350kbps_30fps_libvorbis_stereo_192kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_webm_libvpx_libvorbis_bbb_short_ffmpeg_480x360_webm_libvpx_500kbps_25fps_libvorbis_stereo_128kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_webm_libvpx_libvorbis_bbb_short_ffmpeg_480x360_webm_libvpx_500kbps_25fps_libvorbis_stereo_192kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_webm_libvpx_libvorbis_bbb_short_ffmpeg_480x360_webm_libvpx_500kbps_30fps_libvorbis_stereo_128kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_short_480x360_webm_libvpx_libvorbis_bbb_short_ffmpeg_480x360_webm_libvpx_500kbps_30fps_libvorbis_stereo_192kbps_44100hz_webm">
+ <value>mime=video/x-vnd.on2.vp8,width=480,height=360;mime=audio/vorbis,sample-rate=44100,channel-count=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx264_libfaac_bbb_short_ffmpeg_720x480_mp4_libx264_1000kbps_25fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx264_libfaac_bbb_short_ffmpeg_720x480_mp4_libx264_1000kbps_25fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx264_libfaac_bbb_short_ffmpeg_720x480_mp4_libx264_1000kbps_30fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx264_libfaac_bbb_short_ffmpeg_720x480_mp4_libx264_1000kbps_30fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx264_libfaac_bbb_short_ffmpeg_720x480_mp4_libx264_1350kbps_25fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx264_libfaac_bbb_short_ffmpeg_720x480_mp4_libx264_1350kbps_25fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx264_libfaac_bbb_short_ffmpeg_720x480_mp4_libx264_1350kbps_30fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx264_libfaac_bbb_short_ffmpeg_720x480_mp4_libx264_1350kbps_30fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx264_libfaac_bbb_short_ffmpeg_720x480_mp4_libx264_500kbps_25fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx264_libfaac_bbb_short_ffmpeg_720x480_mp4_libx264_500kbps_25fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx264_libfaac_bbb_short_ffmpeg_720x480_mp4_libx264_500kbps_30fps_libfaac_stereo_128kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx264_libfaac_bbb_short_ffmpeg_720x480_mp4_libx264_500kbps_30fps_libfaac_stereo_192kbps_44100hz_mp4">
+ <value>mime=video/avc,width=720,height=480,frame-rate=24,profile=1,level=256;mime=audio/mp4a-latm,sample-rate=44100,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx265_libfaac_bbb_short_fmpeg_720x480_mp4_libx265_325kbps_24fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=720,height=480,frame-rate=24,profile=1,level=64;mime=audio/mp4a-latm,bitrate=129452,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx265_libfaac_bbb_short_fmpeg_720x480_mp4_libx265_325kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=720,height=480,frame-rate=30,profile=1,level=64;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx265_libfaac_bbb_short_fmpeg_720x480_mp4_libx265_650kbps_24fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=720,height=480,frame-rate=24,profile=1,level=64;mime=audio/mp4a-latm,bitrate=129452,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx265_libfaac_bbb_short_fmpeg_720x480_mp4_libx265_650kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=720,height=480,frame-rate=30,profile=1,level=64;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx265_libfaac_bbb_short_fmpeg_720x480_mp4_libx265_880kbps_24fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=720,height=480,frame-rate=24,profile=1,level=64;mime=audio/mp4a-latm,bitrate=129452,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+ <entry key="bbb_short_720x480_mp4_libx265_libfaac_bbb_short_fmpeg_720x480_mp4_libx265_880kbps_30fps_libfaac_stereo_128kbps_48000hz_mp4">
+ <value>mime=video/hevc,width=720,height=480,frame-rate=30,profile=1,level=64;mime=audio/mp4a-latm,bitrate=128918,sample-rate=48000,channel-count=2,profile=2,aac-profile=2</value>
+ </entry>
+</dynamicConfig>
diff --git a/tests/tests/mediastress/preconditions/app/Android.mk b/tests/tests/mediastress/preconditions/app/Android.mk
new file mode 100644
index 0000000..b8aa32a
--- /dev/null
+++ b/tests/tests/mediastress/preconditions/app/Android.mk
@@ -0,0 +1,39 @@
+# Copyright (C) 2016 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-util ctsdeviceutil
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsMediaPreparerApp
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/tests/tests/mediastress/preconditions/app/AndroidManifest.xml b/tests/tests/mediastress/preconditions/app/AndroidManifest.xml
new file mode 100644
index 0000000..da8d3d2
--- /dev/null
+++ b/tests/tests/mediastress/preconditions/app/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2016 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.mediastress.cts.preconditions.app">
+
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.mediastress.cts.preconditions.app"
+ android:label="Device-side CTS mediastress preparation" />
+</manifest>
diff --git a/tests/tests/mediastress/preconditions/app/src/android/mediastress/cts/preconditions/app/MediaPreparerAppTest.java b/tests/tests/mediastress/preconditions/app/src/android/mediastress/cts/preconditions/app/MediaPreparerAppTest.java
new file mode 100644
index 0000000..9830cff
--- /dev/null
+++ b/tests/tests/mediastress/preconditions/app/src/android/mediastress/cts/preconditions/app/MediaPreparerAppTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2016 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.mediastress.cts.preconditions.app;
+
+import com.android.compatibility.common.util.DynamicConfigDeviceSide;
+
+import android.app.Instrumentation;
+import android.cts.util.MediaUtils;
+import android.media.MediaFormat;
+import android.os.Bundle;
+import android.support.test.InstrumentationRegistry;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Test class that uses device-side media APIs to determine up to which resolution MediaPreparer
+ * should copy media files for CtsMediaStressTestCases.
+ */
+@RunWith(JUnit4.class)
+public class MediaPreparerAppTest {
+
+ /** The module name used to retrieve Dynamic Configuration data */
+ private static final String MODULE_NAME = "CtsMediaStressTestCases";
+
+ /** The default (minimum) resolution of media file to copy to the device */
+ private static final int DEFAULT_MAX_WIDTH = 480;
+ private static final int DEFAULT_MAX_HEIGHT = 360;
+
+ /** Instrumentation status code used to write resolution to metrics */
+ private static final int INST_STATUS_IN_PROGRESS = 2;
+
+ /** Helper class for generating and retrieving width-height pairs */
+ private static final class Resolution {
+ // regex that matches a resolution string
+ private static final String PATTERN = "(\\d+)x(\\d+)";
+ // group indices for accessing resolution witdh/height from a Matcher created from PATTERN
+ private static final int WIDTH_INDEX = 1;
+ private static final int HEIGHT_INDEX = 2;
+
+ private final int width;
+ private final int height;
+
+ private Resolution(int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+
+ private Resolution(String resolution) {
+ Pattern pattern = Pattern.compile(PATTERN);
+ Matcher matcher = pattern.matcher(resolution);
+ matcher.find();
+ this.width = Integer.parseInt(matcher.group(WIDTH_INDEX));
+ this.height = Integer.parseInt(matcher.group(HEIGHT_INDEX));
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%dx%d", width, height);
+ }
+ }
+
+ @Test
+ public void testGetResolutions() throws Exception {
+ Resolution maxRes = new Resolution(DEFAULT_MAX_WIDTH, DEFAULT_MAX_HEIGHT);
+ DynamicConfigDeviceSide config = new DynamicConfigDeviceSide(MODULE_NAME);
+ for (String key : config.keySet()) {
+ int width = 0;
+ int height = 0;
+ for (MediaFormat format : stringsToFormats(config.getValues(key))) {
+ try {
+ width = Math.max(width, format.getInteger(MediaFormat.KEY_WIDTH));
+ height = Math.max(height, format.getInteger(MediaFormat.KEY_HEIGHT));
+ } catch (NullPointerException | ClassCastException e) {
+ // audio format, or invalid format created by unrelated dynamic config entry
+ // simply continue in this case
+ }
+ }
+ Resolution fileResolution = new Resolution(width, height);
+ // if the file is of greater resolution than maxRes, check for support
+ if (fileResolution.width > maxRes.width) {
+ boolean supported = true;
+ for (MediaFormat format : stringsToFormats(config.getValues(key))) {
+ supported &= MediaUtils.checkDecoderForFormat(format);
+ }
+ if (supported) {
+ // update if all MediaFormats for file are supported by device
+ maxRes = fileResolution;
+ }
+ }
+ }
+ // write resolution string to metrics
+ Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+ Bundle maxResBundle = new Bundle();
+ maxResBundle.putString("resolution", maxRes.toString());
+ inst.sendStatus(INST_STATUS_IN_PROGRESS, maxResBundle);
+ }
+
+ /**
+ * Converts string representations of MediaFormats into actual MediaFormats
+ * @param formatStrings a list of string representations of MediaFormats. Each input string
+ * may represent one or more MediaFormats
+ * @return a list of MediaFormats
+ */
+ private List<MediaFormat> stringsToFormats(List<String> formatStrings) {
+ List<MediaFormat> formats = new ArrayList<MediaFormat>();
+ for (String formatString : formatStrings) {
+ for (String trackFormatString : formatString.split(";")) {
+ formats.add(parseTrackFormat(trackFormatString));
+ }
+ }
+ return formats;
+ }
+
+ /**
+ * Converts a single media track format string into a MediaFormat object
+ * @param trackFormatString a string representation of the format of one media track
+ * @return a MediaFormat
+ */
+ private static MediaFormat parseTrackFormat(String trackFormatString) {
+ MediaFormat format = new MediaFormat();
+ format.setString(MediaFormat.KEY_MIME, "");
+ for (String entry : trackFormatString.split(",")) {
+ String[] kv = entry.split("=");
+ if (kv.length < 2) {
+ continue;
+ }
+ String k = kv[0];
+ String v = kv[1];
+ try {
+ format.setInteger(k, Integer.parseInt(v));
+ } catch(NumberFormatException e) {
+ format.setString(k, v);
+ }
+ }
+ return format;
+ }
+}
diff --git a/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java b/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
index f4ac511..a780317 100644
--- a/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
+++ b/tests/tests/mediastress/preconditions/src/android/mediastress/cts/preconditions/MediaPreparer.java
@@ -15,25 +15,31 @@
*/
package android.mediastress.cts.preconditions;
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.tradefed.targetprep.PreconditionPreparer;
import com.android.compatibility.common.util.DynamicConfigHostSide;
import com.android.ddmlib.IDevice;
+import com.android.ddmlib.testrunner.TestIdentifier;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.result.StubTestInvocationListener;
import com.android.tradefed.targetprep.BuildError;
import com.android.tradefed.targetprep.TargetSetupError;
+import com.android.tradefed.testtype.AndroidJUnitTest;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.ZipUtil;
-import java.awt.Dimension;
import java.io.File;
+import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
+import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipFile;
@@ -56,6 +62,26 @@
protected boolean mSkipMediaDownload = false;
/*
+ * The pathnames of the device's directories that hold media files for the tests.
+ * These depend on the device's mount point, which is retrieved in the MediaPreparer's run
+ * method.
+ *
+ * These fields are exposed for unit testing
+ */
+ protected String mBaseDeviceShortDir;
+ protected String mBaseDeviceFullDir;
+
+ /*
+ * Variables set by the MediaPreparerListener during retrieval of maximum media file
+ * resolution. After the MediaPreparerApp has been instrumented on the device:
+ *
+ * testMetrics contains the string representation of the resolution
+ * testFailures contains a stacktrace if retrieval of the resolution was unsuccessful
+ */
+ protected Resolution mMaxRes = null;
+ protected String mFailureStackTrace = null;
+
+ /*
* The default name of local directory into which media files will be downloaded, if option
* "local-media-path" is not provided. This directory will live inside the temp directory.
*/
@@ -68,99 +94,52 @@
private static final String DYNAMIC_CONFIG_MODULE = "cts";
/*
- * The message printed when the maximum video playback resolution cannot be found in the
- * output of 'dumpsys'. When this is the case, media files of all resolutions must be pushed
- * to the device.
+ * Info used to install and uninstall the MediaPreparerApp
*/
- private static final String MAX_PLAYBACK_RES_FAILURE_MSG =
- "Unable to parse maximum video playback resolution, pushing all media files";
+ private static final String APP_APK = "CtsMediaPreparerApp.apk";
+ private static final String APP_PKG_NAME = "android.mediastress.cts.preconditions.app";
- private static final String LOG_TAG = MediaPreparer.class.getSimpleName();
+ /* Key to retrieve resolution string in metrics upon MediaPreparerListener.testEnded() */
+ private static final String RESOLUTION_STRING_KEY = "resolution";
- /* Constants identifying resolutions of the media files to be copied */
- protected static final int RES_176_144 = 0; // 176x144 resolution
- protected static final int RES_DEFAULT = 1; // default max video playback resolution, 480x360
- protected static final int RES_720_480 = 2; // 720x480 resolution
- protected static final int RES_1280_720 = 3; // 1280x720 resolution
- protected static final int RES_1920_1080 = 4; // 1920x1080 resolution
+ protected static final Resolution DEFAULT_MAX_RESOLUTION = new Resolution(480, 360);
- protected static final Dimension[] resolutions = { // indices meant to align with constants above
- new Dimension(176, 144),
- new Dimension(480, 360),
- new Dimension(720, 480),
- new Dimension(1280, 720),
- new Dimension(1920, 1080)
+ protected static final Resolution[] RESOLUTIONS = {
+ new Resolution(176, 144),
+ new Resolution(480, 360),
+ new Resolution(720, 480),
+ new Resolution(1280, 720),
+ new Resolution(1920, 1080)
};
- /*
- * The pathnames of the device's directories that hold media files for the tests.
- * These depend on the device's mount point, which is retrieved in the MediaPreparer's run
- * method.
- *
- * These fields are exposed for unit testing
- */
- protected String mBaseDeviceShortDir;
- protected String mBaseDeviceFullDir;
+ /** Helper class for generating and retrieving width-height pairs */
+ protected static final class Resolution {
+ // regex that matches a resolution string
+ private static final String PATTERN = "(\\d+)x(\\d+)";
+ // group indices for accessing resolution width and height from a PATTERN-based Matcher
+ private static final int WIDTH_INDEX = 1;
+ private static final int HEIGHT_INDEX = 2;
- /*
- * Returns a string representation of the dimension
- * For dimension of width = 480 and height = 360, the resolution string is "480x360"
- */
- private static String resolutionString(Dimension resolution) {
- return String.format("%dx%d", resolution.width, resolution.height);
- }
+ private final int width;
+ private final int height;
- /*
- * Loops through the predefined maximum video playback resolutions from largest to smallest,
- * And returns the greatest resolution that is strictly smaller than the width and height
- * provided in the arguments
- */
- private Dimension getMaxVideoPlaybackResolution(int width, int height) {
- for (int resIndex = resolutions.length - 1; resIndex >= RES_DEFAULT; resIndex--) {
- Dimension resolution = resolutions[resIndex];
- if (width >= resolution.width && height >= resolution.height) {
- return resolution;
- }
- }
- return resolutions[RES_DEFAULT];
- }
-
- /*
- * Returns the maximum video playback resolution of the device, in the form of a Dimension
- * object. This method parses dumpsys output to find resolutions listed under the
- * 'mBaseDisplayInfo' field. The value for 'smallest app' is used as an estimate for
- * maximum video playback resolution, and is rounded down to the nearest dimension in the
- * resolutions array.
- *
- * This method is exposed for unit testing.
- */
- protected Dimension getMaxVideoPlaybackResolution(ITestDevice device)
- throws DeviceNotAvailableException {
- String dumpsysOutput =
- device.executeShellCommand("dumpsys display | grep mBaseDisplayInfo");
- Pattern pattern = Pattern.compile("smallest app (\\d+) x (\\d+)");
- Matcher matcher = pattern.matcher(dumpsysOutput);
- if(!matcher.find()) {
- // could not find resolution in dumpsysOutput, return largest max playback resolution
- // so that preparer copies all media files
- logError(MAX_PLAYBACK_RES_FAILURE_MSG);
- return resolutions[RES_1920_1080];
+ private Resolution(int width, int height) {
+ this.width = width;
+ this.height = height;
}
- int first;
- int second;
- try {
- first = Integer.parseInt(matcher.group(1));
- second = Integer.parseInt(matcher.group(2));
- } catch (NumberFormatException e) {
- logError(MAX_PLAYBACK_RES_FAILURE_MSG);
- return resolutions[RES_1920_1080];
+ private Resolution(String resolution) {
+ Pattern pattern = Pattern.compile(PATTERN);
+ Matcher matcher = pattern.matcher(resolution);
+ matcher.find();
+ this.width = Integer.parseInt(matcher.group(WIDTH_INDEX));
+ this.height = Integer.parseInt(matcher.group(HEIGHT_INDEX));
}
- // dimensions in dumpsys output seem consistently reversed
- // here we make note of which dimension is the larger of the two
- int height = Math.min(first, second);
- int width = Math.max(first, second);
- return getMaxVideoPlaybackResolution(width, height);
+
+ @Override
+ public String toString() {
+ return String.format("%dx%d", width, height);
+ }
}
/*
@@ -168,22 +147,18 @@
*
* This method is exposed for unit testing.
*/
- protected boolean mediaFilesExistOnDevice(ITestDevice device, Dimension mvpr)
- throws DeviceNotAvailableException{
- int resIndex = RES_176_144;
- while (resIndex <= RES_1920_1080) {
- Dimension copiedResolution = resolutions[resIndex];
- if (copiedResolution.width > mvpr.width || copiedResolution.height > mvpr.height) {
- break; // we don't need to check for resolutions greater than or equal to this
+ protected boolean mediaFilesExistOnDevice(ITestDevice device)
+ throws DeviceNotAvailableException {
+ for (Resolution resolution : RESOLUTIONS) {
+ if (resolution.width > mMaxRes.width) {
+ break; // no need to check for resolutions greater than this
}
- String resString = resolutionString(copiedResolution);
- String deviceShortFilePath = mBaseDeviceShortDir + resString;
- String deviceFullFilePath = mBaseDeviceFullDir + resString;
- if (!device.doesFileExist(deviceShortFilePath) ||
- !device.doesFileExist(deviceFullFilePath)) { // media files must be copied
+ String deviceShortFilePath = mBaseDeviceShortDir + resolution.toString();
+ String deviceFullFilePath = mBaseDeviceFullDir + resolution.toString();
+ if (!device.doesFileExist(deviceShortFilePath)
+ || !device.doesFileExist(deviceFullFilePath)) {
return false;
}
- resIndex++;
}
return true;
}
@@ -212,7 +187,6 @@
* bbb_full media directories.
*/
private void downloadMediaToHost(File mediaFolder) throws TargetSetupError {
-
URL url;
try {
// Get download URL from dynamic configuration service
@@ -223,7 +197,6 @@
throw new TargetSetupError("Trouble finding media file download location with " +
"dynamic configuration", e);
}
-
File mediaFolderZip = new File(mediaFolder.getAbsolutePath() + ".zip");
try {
logInfo("Downloading media files from %s", url.toString());
@@ -233,7 +206,6 @@
FileUtil.writeToFile(in, mediaFolderZip);
logInfo("Unzipping media files");
ZipUtil.extractZip(new ZipFile(mediaFolderZip), mediaFolder);
-
} catch (IOException e) {
FileUtil.recursiveDelete(mediaFolder);
throw new TargetSetupError("Failed to download and open media files on host, the"
@@ -251,25 +223,20 @@
*
* This method is exposed for unit testing.
*/
- protected void copyMediaFiles(ITestDevice device, Dimension mvpr)
+ protected void copyMediaFiles(ITestDevice device)
throws DeviceNotAvailableException {
-
- int resIndex = RES_176_144;
- while (resIndex <= RES_1920_1080) {
- Dimension copiedResolution = resolutions[resIndex];
- String resString = resolutionString(copiedResolution);
- if (copiedResolution.width > mvpr.width || copiedResolution.height > mvpr.height) {
- logInfo("Device cannot support resolutions %s and larger, media copying complete",
- resString);
+ for (Resolution resolution : RESOLUTIONS) {
+ if (resolution.width > mMaxRes.width) {
+ logInfo("Media file copying complete");
return;
}
- String deviceShortFilePath = mBaseDeviceShortDir + resString;
- String deviceFullFilePath = mBaseDeviceFullDir + resString;
+ String deviceShortFilePath = mBaseDeviceShortDir + resolution.toString();
+ String deviceFullFilePath = mBaseDeviceFullDir + resolution.toString();
if (!device.doesFileExist(deviceShortFilePath) ||
!device.doesFileExist(deviceFullFilePath)) {
- logInfo("Copying files of resolution %s to device", resString);
- String localShortDirName = "bbb_short/" + resString;
- String localFullDirName = "bbb_full/" + resString;
+ logInfo("Copying files of resolution %s to device", resolution.toString());
+ String localShortDirName = "bbb_short/" + resolution.toString();
+ String localFullDirName = "bbb_full/" + resolution.toString();
File localShortDir = new File(mLocalMediaPath, localShortDirName);
File localFullDir = new File(mLocalMediaPath, localFullDirName);
// push short directory of given resolution, if not present on device
@@ -281,7 +248,6 @@
device.pushDir(localFullDir, deviceFullFilePath);
}
}
- resIndex++;
}
}
@@ -300,15 +266,13 @@
logInfo("Skipping media preparation");
return; // skip this precondition
}
-
setMountPoint(device);
- Dimension mvpr = getMaxVideoPlaybackResolution(device);
- if (mediaFilesExistOnDevice(device, mvpr)) {
+ setMaxRes(device, buildInfo);
+ if (mediaFilesExistOnDevice(device)) {
// if files already on device, do nothing
logInfo("Media files found on the device");
return;
}
-
if (mLocalMediaPath == null) {
// Option 'local-media-path' has not been defined
// Get directory to store media files on this host
@@ -323,9 +287,62 @@
// set mLocalMediaPath to where the CTS media files have been extracted
updateLocalMediaPath(mediaFolder);
}
-
logInfo("Media files located on host at: %s", mLocalMediaPath);
- copyMediaFiles(device, mvpr);
+ copyMediaFiles(device);
}
+ // Initialize maximum resolution of media files to copy
+ private void setMaxRes(ITestDevice device, IBuildInfo buildInfo)
+ throws DeviceNotAvailableException {
+ ITestInvocationListener listener = new MediaPreparerListener();
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(buildInfo);
+ File apkFile = null;
+ try {
+ apkFile = new File(buildHelper.getTestsDir(), APP_APK);
+ if (!apkFile.exists()) {
+ // handle both missing tests dir and missing APK in catch block
+ throw new FileNotFoundException();
+ }
+ } catch (FileNotFoundException e) {
+ mMaxRes = DEFAULT_MAX_RESOLUTION;
+ logWarning("Cound not find %s to determine maximum resolution, copying up to %s",
+ APP_APK, DEFAULT_MAX_RESOLUTION.toString());
+ return;
+ }
+ if (device.getAppPackageInfo(APP_PKG_NAME) != null) {
+ device.uninstallPackage(APP_PKG_NAME);
+ }
+ logInfo("Instrumenting package %s:", APP_PKG_NAME);
+ AndroidJUnitTest instrTest = new AndroidJUnitTest();
+ instrTest.setDevice(device);
+ instrTest.setInstallFile(apkFile);
+ instrTest.setPackageName(APP_PKG_NAME);
+ instrTest.run(listener);
+ if (mFailureStackTrace != null) {
+ mMaxRes = DEFAULT_MAX_RESOLUTION;
+ logWarning("Retrieving maximum resolution failed with trace:\n%s", mFailureStackTrace);
+ logWarning("Copying up to %s", DEFAULT_MAX_RESOLUTION.toString());
+ } else if (mMaxRes == null) {
+ mMaxRes = DEFAULT_MAX_RESOLUTION;
+ logWarning("Failed to pull resolution capabilities from device, copying up to %s",
+ DEFAULT_MAX_RESOLUTION.toString());
+ }
+ }
+
+ /* Special listener for setting MediaPreparer instance variable values */
+ private class MediaPreparerListener extends StubTestInvocationListener {
+
+ @Override
+ public void testEnded(TestIdentifier test, Map<String, String> metrics) {
+ String resString = metrics.get(RESOLUTION_STRING_KEY);
+ if (resString != null) {
+ mMaxRes = new Resolution(resString);
+ }
+ }
+
+ @Override
+ public void testFailed(TestIdentifier test, String trace) {
+ mFailureStackTrace = trace;
+ }
+ }
}
diff --git a/tests/tests/mediastress/preconditions/tests/src/android/mediastress/cts/preconditions/MediaPreparerTest.java b/tests/tests/mediastress/preconditions/tests/src/android/mediastress/cts/preconditions/MediaPreparerTest.java
index 4f71069..04c3900 100644
--- a/tests/tests/mediastress/preconditions/tests/src/android/mediastress/cts/preconditions/MediaPreparerTest.java
+++ b/tests/tests/mediastress/preconditions/tests/src/android/mediastress/cts/preconditions/MediaPreparerTest.java
@@ -23,8 +23,6 @@
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.targetprep.TargetSetupError;
-import java.awt.Dimension;
-
import junit.framework.TestCase;
import org.easymock.EasyMock;
@@ -36,9 +34,6 @@
private ITestDevice mMockDevice;
private OptionSetter mOptionSetter;
- private final Dimension DEFAULT_DIMENSION =
- MediaPreparer.resolutions[MediaPreparer.RES_DEFAULT];
-
@Override
public void setUp() throws Exception {
super.setUp();
@@ -58,53 +53,44 @@
}
public void testCopyMediaFiles() throws Exception {
- // by jumping directly into copyMediaFiles, the baseDeviceShortDir variable won't be set
- // thus, the string "null" replaces the variable
- EasyMock.expect(mMockDevice.doesFileExist("null176x144")).andReturn(true).anyTimes();
- EasyMock.expect(mMockDevice.doesFileExist("null480x360")).andReturn(true).anyTimes();
+ mMediaPreparer.mMaxRes = MediaPreparer.DEFAULT_MAX_RESOLUTION;
+ mMediaPreparer.mBaseDeviceShortDir = "/sdcard/test/bbb_short/";
+ mMediaPreparer.mBaseDeviceFullDir = "/sdcard/test/bbb_full/";
+ for (MediaPreparer.Resolution resolution : MediaPreparer.RESOLUTIONS) {
+ String shortFile = String.format("%s%s", mMediaPreparer.mBaseDeviceShortDir,
+ resolution.toString());
+ String fullFile = String.format("%s%s", mMediaPreparer.mBaseDeviceFullDir,
+ resolution.toString());
+ EasyMock.expect(mMockDevice.doesFileExist(shortFile)).andReturn(true).once();
+ EasyMock.expect(mMockDevice.doesFileExist(fullFile)).andReturn(true).once();
+ }
EasyMock.replay(mMockDevice);
- mMediaPreparer.copyMediaFiles(mMockDevice, DEFAULT_DIMENSION);
+ mMediaPreparer.copyMediaFiles(mMockDevice);
}
public void testMediaFilesExistOnDeviceTrue() throws Exception {
- // by jumping directly into copyMediaFiles, the baseDeviceShortDir variable won't be set
- // thus, the string "null" replaces the variable
- EasyMock.expect(mMockDevice.doesFileExist("null176x144")).andReturn(true).anyTimes();
- EasyMock.expect(mMockDevice.doesFileExist("null480x360")).andReturn(true).anyTimes();
+ mMediaPreparer.mMaxRes = MediaPreparer.DEFAULT_MAX_RESOLUTION;
+ mMediaPreparer.mBaseDeviceShortDir = "/sdcard/test/bbb_short/";
+ mMediaPreparer.mBaseDeviceFullDir = "/sdcard/test/bbb_full/";
+ for (MediaPreparer.Resolution resolution : MediaPreparer.RESOLUTIONS) {
+ String shortFile = String.format("%s%s", mMediaPreparer.mBaseDeviceShortDir,
+ resolution.toString());
+ String fullFile = String.format("%s%s", mMediaPreparer.mBaseDeviceFullDir,
+ resolution.toString());
+ EasyMock.expect(mMockDevice.doesFileExist(shortFile)).andReturn(true).anyTimes();
+ EasyMock.expect(mMockDevice.doesFileExist(fullFile)).andReturn(true).anyTimes();
+ }
EasyMock.replay(mMockDevice);
- assertTrue(mMediaPreparer.mediaFilesExistOnDevice(mMockDevice, DEFAULT_DIMENSION));
+ assertTrue(mMediaPreparer.mediaFilesExistOnDevice(mMockDevice));
}
public void testMediaFilesExistOnDeviceFalse() throws Exception {
- // by jumping directly into copyMediaFiles, the baseDeviceShortDir variable won't be set
- // thus, the string "null" replaces the variable
- EasyMock.expect(mMockDevice.doesFileExist("null176x144")).andReturn(false).anyTimes();
- EasyMock.expect(mMockDevice.doesFileExist("null480x360")).andReturn(true).anyTimes();
+ mMediaPreparer.mMaxRes = MediaPreparer.DEFAULT_MAX_RESOLUTION;
+ mMediaPreparer.mBaseDeviceShortDir = "/sdcard/test/bbb_short/";
+ String firstFileChecked = "/sdcard/test/bbb_short/176x144";
+ EasyMock.expect(mMockDevice.doesFileExist(firstFileChecked)).andReturn(false).once();
EasyMock.replay(mMockDevice);
- assertFalse(mMediaPreparer.mediaFilesExistOnDevice(mMockDevice, DEFAULT_DIMENSION));
- }
-
- public void testGetMaxVideoPlaybackResolutionFound() throws Exception {
- String mockDumpsysOutput = "mBaseDisplayInfo=DisplayInfo{\"Built-in Screen\", uniqueId " +
- "\"local:0\", app 1440 x 2560, real 1440 x 2560, largest app 1440 x 2560, " +
- "smallest app 360 x 480, mode 1, defaultMode 1, modes [{id=1, width=1440, " +
- "height=2560, fps=60.0}], rotation 0, density 560 (494.27 x 492.606) dpi, " +
- "layerStack 0, appVsyncOff 2500000, presDeadline 17666667, type BUILT_IN, state " +
- "ON, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}\n";
- EasyMock.expect(mMockDevice.executeShellCommand(
- "dumpsys display | grep mBaseDisplayInfo")).andReturn(mockDumpsysOutput).once();
- EasyMock.replay(mMockDevice);
- Dimension result = mMediaPreparer.getMaxVideoPlaybackResolution(mMockDevice);
- assertEquals(result, DEFAULT_DIMENSION);
- }
-
- public void testGetMaxVideoPlaybackResolutionNotFound() throws Exception {
- String mockDumpsysOutput = "incorrect output";
- EasyMock.expect(mMockDevice.executeShellCommand(
- "dumpsys display | grep mBaseDisplayInfo")).andReturn(mockDumpsysOutput).once();
- EasyMock.replay(mMockDevice);
- Dimension result = mMediaPreparer.getMaxVideoPlaybackResolution(mMockDevice);
- assertEquals(result, MediaPreparer.resolutions[MediaPreparer.RES_1920_1080]);
+ assertFalse(mMediaPreparer.mediaFilesExistOnDevice(mMockDevice));
}
public void testSkipMediaDownload() throws Exception {
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java b/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
index b33451b..400aedf 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
@@ -16,10 +16,13 @@
package android.mediastress.cts;
+import com.android.compatibility.common.util.DynamicConfigDeviceSide;
+
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Intent;
import android.cts.util.MediaUtils;
+import android.media.MediaFormat;
import android.media.MediaRecorder.AudioEncoder;
import android.media.MediaRecorder.VideoEncoder;
import android.os.Environment;
@@ -30,6 +33,8 @@
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
import android.test.InstrumentationTestCase;
@@ -42,6 +47,7 @@
protected static final int REPEAT_NUMBER_FOR_LONG_CLIPS = 1;
protected static final int REPEAT_NUMBER_FOR_REPEATED_PLAYBACK = 20;
private static final String TAG = "MediaPlayerStressTest";
+ private static final String MODULE_NAME = "CtsMediaStressTestCases";
/**
* provides full path name of video clip for the given media number
@@ -96,6 +102,48 @@
mTotalMetaDataUpdate += CodecTest.mMediaInfoMetdataUpdateCount;
}
+ private static MediaFormat parseTrackFormat(String trackFormatString) {
+ MediaFormat format = new MediaFormat();
+ format.setString(MediaFormat.KEY_MIME, "");
+
+ for (String entry : trackFormatString.split(",")) {
+ String[] kv = entry.split("=");
+ if (kv.length < 2) {
+ continue;
+ }
+
+ String k = kv[0];
+ String v = kv[1];
+ try {
+ format.setInteger(k, Integer.parseInt(v));
+ } catch(NumberFormatException e) {
+ format.setString(k, v);
+ }
+ }
+
+ return format;
+ }
+
+ private List<MediaFormat> getClipFormats(String mediaName) throws Exception {
+ List<MediaFormat> mediaFormats = new ArrayList<MediaFormat>();
+ DynamicConfigDeviceSide config = new DynamicConfigDeviceSide(MODULE_NAME);
+ String[] components = mediaName.split(VIDEO_TOP_DIR);
+ String key = mediaNameToKey(components[components.length -1]);
+ List<String> mediaFormatStrings = config.getValues(key);
+ for (String mediaFormatString : mediaFormatStrings) {
+ String[] trackFormatStrings = mediaFormatString.split(";");
+ for (String trackFormatString : trackFormatStrings) {
+ MediaFormat format = parseTrackFormat(trackFormatString);
+ mediaFormats.add(format);
+ }
+ }
+ return mediaFormats;
+ }
+
+ private String mediaNameToKey(String mediaName) {
+ return mediaName.replaceAll("[\\./]", "_").toLowerCase();
+ }
+
/**
* runs video playback test for the given mediaNumber
* @param mediaNumber number of media to be used for playback.
@@ -106,8 +154,12 @@
protected void doTestVideoPlayback(int mediaNumber, int repeatCounter) throws Exception {
Instrumentation inst = getInstrumentation();
String mediaName = getFullVideoClipName(mediaNumber);
- if (!MediaUtils.checkCodecsForPath(inst.getTargetContext(), mediaName)) {
- return; // not supported, message is already logged
+ for (MediaFormat format: getClipFormats(mediaName)) {
+ if (!MediaUtils.checkDecoderForFormat(format)) {
+ Log.i(TAG, "skipping " + this.getClass().getSimpleName()
+ + " test clip " + mediaName + " format " + format);
+ return; // not supported
+ }
}
File playbackOutput = new File(WorkDir.getTopDir(), "PlaybackTestResult.txt");
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index c74615c..7983c75 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -135,8 +135,6 @@
<!-- b/25850508 -->
<option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testCopyMediaFiles" />
- <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testGetMaxVideoPlaybackResolutionFound" />
- <option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testGetMaxVideoPlaybackResolutionNotFound" />
<option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testMediaFilesExistOnDeviceFalse" />
<option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testMediaFilesExistOnDeviceTrue" />
<option name="compatibility:exclude-filter" value="CtsMediaStressTestCases android.mediastress.cts.preconditions.MediaPreparerTest#testSetMountPoint" />