1 /* 2 * Copyright (C) 2024 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.mediav2.cts; 18 19 import static android.mediav2.common.cts.CodecTestBase.MEDIA_CODEC_LIST_ALL; 20 import static android.mediav2.common.cts.CodecTestBase.PER_TEST_TIMEOUT_SMALL_TEST_MS; 21 import static android.mediav2.cts.NativeAMediaCodecInfoTest.SPECIAL_CODEC; 22 23 import android.media.MediaCodecInfo; 24 import android.media.MediaExtractor; 25 import android.media.MediaFormat; 26 import android.mediav2.common.cts.EncoderConfigParams; 27 import android.util.Log; 28 29 import androidx.test.ext.junit.runners.AndroidJUnit4; 30 import androidx.test.filters.SdkSuppress; 31 import androidx.test.filters.SmallTest; 32 33 import com.android.compatibility.common.util.ApiTest; 34 import com.android.compatibility.common.util.Preconditions; 35 36 import org.junit.Assert; 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 40 import java.io.IOException; 41 import java.nio.file.Files; 42 import java.nio.file.Path; 43 import java.nio.file.Paths; 44 import java.util.ArrayList; 45 import java.util.HashMap; 46 import java.util.List; 47 import java.util.Map; 48 import java.util.stream.Stream; 49 50 /** 51 * This class validates the NDK api for media codec store. The scope of this test is to only 52 * check if the information advertised is ok. If the component is actually capable of supporting the 53 * advertised information is beyond the scope of the test. 54 */ 55 @SdkSuppress(minSdkVersion = 36) 56 @SmallTest 57 @RunWith(AndroidJUnit4.class) 58 public class NativeAMediaCodecStoreTest { 59 private static final String LOG_TAG = NativeAMediaCodecStoreTest.class.getSimpleName(); 60 private static final String MEDIA_DIR = WorkDir.getMediaDirString(); 61 // in sync with AMediaCodecType values 62 private static final int FLAG_DECODER = 1; 63 private static final int FLAG_ENCODER = 2; 64 65 private final StringBuilder mTestResults = new StringBuilder(); 66 67 static { 68 System.loadLibrary("ctsmediav2codecinfo_jni"); 69 } 70 71 @ApiTest(apis = {"AMediaCodecStore_getSupportedMediaTypes"}) 72 @SmallTest 73 @Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS) testGetSupportedMediaTypes()74 public void testGetSupportedMediaTypes() { 75 Map<String, Integer> mediaTypeModes = new HashMap<>(); 76 MediaCodecInfo[] codecInfos = MEDIA_CODEC_LIST_ALL.getCodecInfos(); 77 for (MediaCodecInfo codecInfo : codecInfos) { 78 if (codecInfo.isAlias()) continue; 79 String[] types = codecInfo.getSupportedTypes(); 80 for (String type : types) { 81 MediaCodecInfo.CodecCapabilities codecCapabilities = 82 codecInfo.getCapabilitiesForType(type); 83 if (codecCapabilities.isFeatureSupported(SPECIAL_CODEC)) continue; 84 Integer val; 85 if (mediaTypeModes.containsKey(type)) { 86 val = mediaTypeModes.get(type); 87 val |= codecInfo.isEncoder() ? FLAG_ENCODER : FLAG_DECODER; 88 } else { 89 val = codecInfo.isEncoder() ? FLAG_ENCODER : FLAG_DECODER; 90 } 91 mediaTypeModes.put(type, val); 92 } 93 } 94 String[] mediaTypes = new String[mediaTypeModes.size()]; 95 int[] modes = new int[mediaTypeModes.size()]; 96 int i = 0; 97 for (Map.Entry<String, Integer> entry : mediaTypeModes.entrySet()) { 98 mediaTypes[i] = entry.getKey(); 99 modes[i] = entry.getValue(); 100 i++; 101 } 102 boolean isPass = 103 nativeTestAMediaCodecStoreGetSupportedTypes(mediaTypes, modes, mTestResults); 104 Assert.assertTrue(mTestResults.toString(), isPass); 105 } 106 getAllCodecs(String mediaType, List<MediaFormat> formats, boolean isEncoder)107 private static List<String> getAllCodecs(String mediaType, List<MediaFormat> formats, 108 boolean isEncoder) { 109 MediaCodecInfo[] codecInfos = MEDIA_CODEC_LIST_ALL.getCodecInfos(); 110 List<String> listOfCodecs = new ArrayList<>(); 111 for (MediaCodecInfo codecInfo : codecInfos) { 112 if (codecInfo.isEncoder() != isEncoder) continue; 113 if (codecInfo.isAlias()) continue; 114 String[] types = codecInfo.getSupportedTypes(); 115 for (String type : types) { 116 MediaCodecInfo.CodecCapabilities codecCapabilities = 117 codecInfo.getCapabilitiesForType(type); 118 if (codecCapabilities.isFeatureSupported(SPECIAL_CODEC)) continue; 119 if (mediaType != null) { 120 if (type.equalsIgnoreCase(mediaType)) { 121 boolean isOk = true; 122 if (formats != null) { 123 for (MediaFormat format : formats) { 124 if (!codecCapabilities.isFormatSupported(format)) { 125 isOk = false; 126 break; 127 } 128 } 129 } 130 if (isOk) listOfCodecs.add(codecInfo.getName()); 131 } 132 } else { 133 listOfCodecs.add(codecInfo.getName()); 134 } 135 } 136 } 137 return listOfCodecs; 138 } 139 nativeTestAMediaCodecStoreGetSupportedTypes(String[] mediaTypes, int[] modes, StringBuilder retMsg)140 private native boolean nativeTestAMediaCodecStoreGetSupportedTypes(String[] mediaTypes, 141 int[] modes, StringBuilder retMsg); 142 143 @ApiTest(apis = {"AMediaCodecStore_findNextDecoderForFormat", 144 "AMediaCodecStore_findNextEncoderForFormat"}) 145 @SmallTest 146 @Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS) testGetNextCodecForFormat()147 public void testGetNextCodecForFormat() throws IOException { 148 ArrayList<MediaFormat> formats = new ArrayList<>(); 149 try (Stream<Path> paths = Files.walk(Paths.get(MEDIA_DIR))) { 150 paths.forEach(path -> { 151 if (Files.isRegularFile(path)) { 152 MediaExtractor extractor = new MediaExtractor(); 153 try { 154 extractor.setDataSource(path.toString()); 155 for (int i = 0; i < extractor.getTrackCount(); i++) { 156 MediaFormat format = extractor.getTrackFormat(i); 157 formats.clear(); 158 formats.add(format); 159 String serialize = EncoderConfigParams.serializeMediaFormat(format); 160 String mediaType = format.getString(MediaFormat.KEY_MIME); 161 String[] codecs = 162 getAllCodecs(mediaType, formats, true).toArray(new String[0]); 163 boolean isPass = 164 nativeTestAMediaCodecStoreGetNextCodecsForFormat(serialize, 165 EncoderConfigParams.TOKEN_SEPARATOR, codecs, true, 166 mTestResults); 167 Assert.assertTrue(mTestResults.toString(), isPass); 168 codecs = getAllCodecs(mediaType, formats, false).toArray(new String[0]); 169 isPass = nativeTestAMediaCodecStoreGetNextCodecsForFormat(serialize, 170 EncoderConfigParams.TOKEN_SEPARATOR, codecs, false, 171 mTestResults); 172 Assert.assertTrue(mTestResults.toString(), isPass); 173 } 174 extractor.release(); 175 } catch (IOException ignored) { 176 Preconditions.assertTestFileExists(path.toString()); 177 Log.d(LOG_TAG, "encountered IOException for resource " + path); 178 } finally { 179 extractor.release(); 180 } 181 } 182 }); 183 } 184 List<String> encoders = getAllCodecs(null, null, true); 185 List<String> decoders = getAllCodecs(null, null, false); 186 boolean isPass; 187 isPass = nativeTestAMediaCodecStoreGetNextCodecsForFormat(null, null, 188 encoders.toArray(new String[0]), true, mTestResults); 189 Assert.assertTrue(mTestResults.toString(), isPass); 190 isPass = nativeTestAMediaCodecStoreGetNextCodecsForFormat(null, null, 191 decoders.toArray(new String[0]), false, mTestResults); 192 Assert.assertTrue(mTestResults.toString(), isPass); 193 } 194 nativeTestAMediaCodecStoreGetNextCodecsForFormat(String formatString, String formatSeparator, String[] encoders, boolean isEncoder, StringBuilder retMsg)195 private native boolean nativeTestAMediaCodecStoreGetNextCodecsForFormat(String formatString, 196 String formatSeparator, String[] encoders, boolean isEncoder, StringBuilder retMsg); 197 198 @ApiTest(apis = {"AMediaCodecStore_getCodecInfo"}) 199 @SmallTest 200 @Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS) testGetCodecInfo()201 public void testGetCodecInfo() { 202 boolean isPass = nativeTestAMediaCodecStoreGetCodecInfo(mTestResults); 203 Assert.assertTrue(mTestResults.toString(), isPass); 204 } 205 nativeTestAMediaCodecStoreGetCodecInfo(StringBuilder retMsg)206 private native boolean nativeTestAMediaCodecStoreGetCodecInfo(StringBuilder retMsg); 207 } 208