• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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