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.video.cts; 18 19 import android.media.MediaFormat; 20 import android.util.Log; 21 22 import androidx.test.filters.LargeTest; 23 24 import org.junit.Test; 25 import org.junit.runner.RunWith; 26 import org.junit.runners.Parameterized; 27 28 import java.io.IOException; 29 import java.util.ArrayList; 30 import java.util.Arrays; 31 import java.util.Collection; 32 import java.util.List; 33 34 import static org.junit.Assert.assertTrue; 35 36 /** 37 * Operating rate is expected to be met by encoder only in surface mode and not in byte buffer mode. 38 * As camera has limited frame rates and resolutions, it is not possible to test encoder 39 * operating rate alone. So we are going ahead with transcode tests as a way to verify 40 * encoder performances. This test calls decoder to decode to a surface that is coupled to encoder. 41 * This assumes encoder will not be faster than decode and expects half the operating rate 42 * to be met for encoders. 43 */ 44 @RunWith(Parameterized.class) 45 public class CodecEncoderPerformanceTest extends CodecEncoderPerformanceTestBase { 46 private static final String LOG_TAG = CodecEncoderPerformanceTest.class.getSimpleName(); 47 CodecEncoderPerformanceTest(String decoderName, String testFile, String encoderMime, String encoderName, int bitrate, int keyPriority, float scalingFactor)48 public CodecEncoderPerformanceTest(String decoderName, String testFile, String encoderMime, 49 String encoderName, int bitrate, int keyPriority, float scalingFactor) { 50 super(decoderName, testFile, encoderMime, encoderName, bitrate, keyPriority, scalingFactor); 51 } 52 53 @Parameterized.Parameters(name = "{index}({0}_{2}_{3}_{5}_{6})") input()54 public static Collection<Object[]> input() throws IOException { 55 final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{ 56 // Filename, Recommended AVC bitrate 57 {"crowd_run_720x480_30fps_avc.mp4", 2000000}, 58 {"crowd_run_1280x720_30fps_avc.mp4", 4000000}, 59 {"crowd_run_1920x1080_30fps_avc.mp4", 8000000}, 60 {"crowd_run_3840x2160_30fps_hevc.mp4", 20000000}, 61 // TODO (b/194721211) Enable 8k tests 62 //{"crowd_run_7680x4320_30fps_hevc.mp4", 40000000}, 63 }); 64 // Prepares the params list with the supported Hardware decoder, encoders in the device 65 // combined with the key priority and scaling factor 66 final List<Object[]> argsList = new ArrayList<>(); 67 for (Object[] arg : exhaustiveArgsList) { 68 // Gets the format for the first video track found 69 MediaFormat format = getVideoFormat((String) arg[0]); 70 if (format == null) { 71 Log.e(LOG_TAG, "Test vector is ignored as it has no video tracks present " + 72 "in the file: " + ((String) arg[0])); 73 continue; 74 } 75 String decoderMime = format.getString(MediaFormat.KEY_MIME); 76 ArrayList<MediaFormat> formatsList = new ArrayList<>(); 77 formatsList.add(format); 78 ArrayList<String> listOfDecoders = selectHardwareCodecs(decoderMime, formatsList, 79 null, false); 80 if (listOfDecoders.size() == 0) continue; 81 String decoder = listOfDecoders.get(0); 82 for (String encoderMime : getMimesOfAvailableHardwareVideoEncoders()) { 83 // Calculate the bitrate based on the encode mime. 84 int bitrate = (int)(((int) arg[1]) * getBitrateScalingFactor(encoderMime)); 85 MediaFormat mockFmt = setUpEncoderFormat(format, encoderMime, bitrate); 86 ArrayList<MediaFormat> mockFmtList = new ArrayList<>(); 87 mockFmtList.add(mockFmt); 88 ArrayList<String> listOfEncoders = selectHardwareCodecs(encoderMime, mockFmtList, 89 null, true); 90 for (String encoder : listOfEncoders) { 91 for (int keyPriority : KEY_PRIORITIES_LIST) { 92 for (float scalingFactor : SCALING_FACTORS_LIST) { 93 if (keyPriority == 1 || (scalingFactor > 0.0 && scalingFactor <= 1.0)) { 94 argsList.add(new Object[]{decoder, arg[0], encoderMime, encoder, 95 bitrate, keyPriority, scalingFactor}); 96 } 97 } 98 } 99 } 100 } 101 } 102 return argsList; 103 } 104 105 /** 106 * Validates performance of hardware accelerated video encoders 107 */ 108 @LargeTest 109 @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS) testPerformanceOfHardwareVideoEncoders()110 public void testPerformanceOfHardwareVideoEncoders() throws IOException { 111 encode(); 112 String log = String.format("DecodeMime: %s, Decoder: %s, resolution: %dp, EncodeMime: %s," + 113 " Encoder: %s, Key-priority: %d :: ", mDecoderMime, mDecoderName, mHeight, 114 mEncoderMime, mEncoderName, mKeyPriority); 115 int maxExpectedFps = getMaxExpectedFps(mWidth, mHeight); 116 double expectedFps = 117 Math.min(mOperatingRateExpected * FPS_TOLERANCE_FACTOR, maxExpectedFps); 118 Log.d(LOG_TAG, log + "act/exp fps: " + mAchievedFps + "/" + expectedFps); 119 assertTrue("Unable to achieve the expected rate. " + log + "act/exp fps: " + mAchievedFps 120 + "/" + expectedFps, mAchievedFps >= expectedFps); 121 } 122 } 123