1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.mediapc.cts; 18 19 import android.media.MediaCodec; 20 import android.media.MediaCodecInfo; 21 import android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint; 22 import android.media.MediaFormat; 23 import android.util.Pair; 24 25 import org.junit.Before; 26 27 import java.io.IOException; 28 import java.util.ArrayList; 29 import java.util.Arrays; 30 import java.util.HashMap; 31 import java.util.List; 32 import java.util.Map; 33 34 import static android.mediapc.cts.CodecTestBase.selectHardwareCodecs; 35 import static org.junit.Assert.assertTrue; 36 import static org.junit.Assume.assumeTrue; 37 38 public class MultiCodecPerfTestBase { 39 private static final String LOG_TAG = MultiCodecPerfTestBase.class.getSimpleName(); 40 static final boolean[] boolStates = {true, false}; 41 static final int REQUIRED_MIN_CONCURRENT_INSTANCES = 6; 42 static final int REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9 = 2; 43 // allowed tolerance in measured fps vs expected fps in percentage, i.e. codecs achieving fps 44 // that is greater than (FPS_TOLERANCE_FACTOR * expectedFps) will be considered as 45 // passing the test 46 static final double FPS_TOLERANCE_FACTOR = 0.95; 47 static ArrayList<String> mMimeList = new ArrayList<String>(); 48 static Map<String, String> mTestFiles = new HashMap<>(); 49 static { 50 mMimeList.add(MediaFormat.MIMETYPE_VIDEO_AVC); 51 mMimeList.add(MediaFormat.MIMETYPE_VIDEO_HEVC); 52 mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1280x720_3mbps_30fps_avc.mp4")53 mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1280x720_3mbps_30fps_avc.mp4"); mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_1280x720_3mbps_30fps_hevc.mp4")54 mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_1280x720_3mbps_30fps_hevc.mp4"); 55 56 // Test VP9 and AV1 as well for Build.VERSION_CODES.S 57 if (Utils.isSPerfClass()) { 58 mMimeList.add(MediaFormat.MIMETYPE_VIDEO_VP9); 59 mMimeList.add(MediaFormat.MIMETYPE_VIDEO_AV1); 60 mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_1280x720_3mbps_30fps_vp9.webm")61 mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_1280x720_3mbps_30fps_vp9.webm"); mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1280x720_3mbps_30fps_av1.mp4")62 mTestFiles.put(MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_1280x720_3mbps_30fps_av1.mp4"); 63 } 64 } 65 66 String mMime; 67 String mTestFile; 68 final boolean mIsAsync; 69 70 double mMaxFrameRate; 71 72 @Before isPerformanceClass()73 public void isPerformanceClass() { 74 assumeTrue("Test requires performance class.", Utils.isPerfClass()); 75 } 76 MultiCodecPerfTestBase(String mime, String testFile, boolean isAsync)77 public MultiCodecPerfTestBase(String mime, String testFile, boolean isAsync) { 78 mMime = mime; 79 mTestFile = testFile; 80 mIsAsync = isAsync; 81 } 82 83 // Returns the list of hardware codecs supporting the 720p 30fps format. getHardwareCodecsFor720p(String mime, boolean isEncoder)84 public static ArrayList<String> getHardwareCodecsFor720p(String mime, boolean isEncoder) { 85 MediaFormat fmt = MediaFormat.createVideoFormat(mime, 1280, 720); 86 fmt.setInteger(MediaFormat.KEY_FRAME_RATE, 30); 87 ArrayList<MediaFormat> formatsList = new ArrayList<>(); 88 formatsList.add(fmt); 89 return selectHardwareCodecs(mime, formatsList, null, isEncoder); 90 } 91 92 // Returns the max number of 720p 30 fps instances that the given list of mimeCodecPairs 93 // supports. It also checks that the each codec supports 720p 180 fps PerformancePoint. checkAndGetMaxSupportedInstancesFor720p( ArrayList<Pair<String, String>> mimeCodecPairs)94 public int checkAndGetMaxSupportedInstancesFor720p( 95 ArrayList<Pair<String, String>> mimeCodecPairs) throws IOException { 96 int[] maxInstances = new int[mimeCodecPairs.size()]; 97 int[] maxFrameRates = new int[mimeCodecPairs.size()]; 98 int[] maxMacroBlockRates = new int[mimeCodecPairs.size()]; 99 int loopCount = 0; 100 for (Pair<String, String> mimeCodecPair : mimeCodecPairs) { 101 MediaCodec codec = MediaCodec.createByCodecName(mimeCodecPair.second); 102 MediaCodecInfo.CodecCapabilities cap = codec.getCodecInfo() 103 .getCapabilitiesForType(mimeCodecPair.first); 104 List<PerformancePoint> pps = cap.getVideoCapabilities().getSupportedPerformancePoints(); 105 assertTrue(pps.size() > 0); 106 107 int requiredFrameRate = 180; 108 // VP9 requires 60 fps at 720p and minimum of 2 instances 109 if (mimeCodecPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) { 110 requiredFrameRate = 60; 111 } 112 113 maxInstances[loopCount] = cap.getMaxSupportedInstances(); 114 PerformancePoint PP720p = new PerformancePoint(1280, 720, requiredFrameRate); 115 116 maxMacroBlockRates[loopCount] = 0; 117 boolean supports720pPerformance = false; 118 for (PerformancePoint pp : pps) { 119 if (pp.covers(PP720p)) { 120 supports720pPerformance = true; 121 if (pp.getMaxMacroBlockRate() > maxMacroBlockRates[loopCount]) { 122 maxMacroBlockRates[loopCount] = (int) pp.getMaxMacroBlockRate(); 123 maxFrameRates[loopCount] = pp.getMaxFrameRate(); 124 } 125 } 126 } 127 codec.release(); 128 assertTrue("Codec " + mimeCodecPair.second + " doesn't support 720p " + 129 requiredFrameRate + " performance point", supports720pPerformance); 130 loopCount++; 131 } 132 Arrays.sort(maxInstances); 133 Arrays.sort(maxFrameRates); 134 Arrays.sort(maxMacroBlockRates); 135 int minOfMaxInstances = maxInstances[0]; 136 int minOfMaxFrameRates = maxFrameRates[0]; 137 int minOfMaxMacroBlockRates = maxMacroBlockRates[0]; 138 139 // Allow a tolerance in expected frame rate 140 mMaxFrameRate = minOfMaxFrameRates * FPS_TOLERANCE_FACTOR; 141 142 // Calculate how many 720p 30fps max instances it can support from it's mMaxFrameRate 143 // amd maxMacroBlockRate. (720p is 3,600 macro blocks assuming 16x16 macroblocks) 144 return Math.min(minOfMaxInstances, Math.min((int) (minOfMaxFrameRates / 30.0), 145 (int) (minOfMaxMacroBlockRates / 3600.0 / 30))); 146 } 147 } 148