• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
20 import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
21 import static android.media.MediaCodecInfo.CodecProfileLevel.*;
22 
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertTrue;
27 
28 import android.media.MediaCodec;
29 import android.media.MediaCodecInfo;
30 import android.media.MediaFormat;
31 import android.mediav2.common.cts.EncoderConfigParams;
32 import android.mediav2.common.cts.EncoderProfileLevelTestBase;
33 import android.mediav2.common.cts.OutputManager;
34 import android.util.Log;
35 
36 import com.android.compatibility.common.util.ApiTest;
37 import com.android.compatibility.common.util.CddTest;
38 
39 import org.junit.Assume;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 import org.junit.runners.Parameterized;
43 
44 import java.io.IOException;
45 import java.util.ArrayList;
46 import java.util.Collection;
47 import java.util.HashMap;
48 import java.util.List;
49 import java.util.Objects;
50 
51 /**
52  * EncoderProfileLevelTest validates the profile, level information advertised by the component
53  * in its codec capabilities. The test sets profile and level keys in media format and uses it
54  * during encoder configuration. Upon successful configuration, frames are queued for encoding
55  * (byte buffer mode) and the encoded output (bitstream) is expected to contain the same profile
56  * that was used during configure. The level shall be at least the input configured level.
57  * <p>
58  * NOTE: The test configures level information basing on standard guidelines, not arbitrarily so
59  * encoders are expected to maintain at least the input configured level
60  * <p>
61  * The test parses the bitstream (csd or frame header) and determines profile and level
62  * information. This serves as reference for further validation. The test checks if the output
63  * format returned by component contains same profile and level information as the bitstream. The
64  * output of encoder is muxed and is extracted. The extracted format is expected to contain same
65  * profile and level information as the bitstream.
66  * <p>
67  * As per cdd, if a device contains an encoder capable of encoding a profile/level combination
68  * then it should contain a decoder capable of decoding the same profile/level combination. This
69  * is verified.
70  * <p>
71  * If device implementations support encoding in a media type, then as per cdd they are expected to
72  * handle certain profile and level configurations. This is verified.
73  */
74 @RunWith(Parameterized.class)
75 public class EncoderProfileLevelTest extends EncoderProfileLevelTestBase {
76     private static final String LOG_TAG = EncoderProfileLevelTest.class.getSimpleName();
77     private static final HashMap<String, CddRequirements> CDD_REQUIREMENTS_MAP = new HashMap<>();
78 
79     private static class CddRequirements {
80         private int[] mProfiles;
81         private int mLevel;
82         private int mHeight;
83         private int mWidth;
84 
CddRequirements(int[] profiles, int level, int width, int height)85         CddRequirements(int[] profiles, int level, int width, int height) {
86             mProfiles = profiles;
87             mLevel = level;
88             mWidth = width;
89             mHeight = height;
90         }
91 
CddRequirements(int[] profiles)92         CddRequirements(int[] profiles) {
93             this(profiles, -1 /* level */, -1 /* width */, -1 /* height */);
94         }
95 
CddRequirements(int[] profiles, int level)96         CddRequirements(int[] profiles, int level) {
97             this(profiles, level, -1 /* width */, -1 /* height */);
98         }
99 
getProfiles()100         public int[] getProfiles() {
101             return mProfiles;
102         }
103 
getLevel()104         public int getLevel() {
105             return mLevel;
106         }
107 
getWidth()108         public int getWidth() {
109             return mWidth;
110         }
111 
getHeight()112         public int getHeight() {
113             return mHeight;
114         }
115     }
EncoderProfileLevelTest(String encoder, String mediaType, EncoderConfigParams[] encCfgParams, @SuppressWarnings("unused") String testLabel, String allTestParams)116     public EncoderProfileLevelTest(String encoder, String mediaType,
117             EncoderConfigParams[] encCfgParams, @SuppressWarnings("unused") String testLabel,
118             String allTestParams) {
119         super(encoder, mediaType, encCfgParams, allTestParams);
120     }
121 
prepareTestArgs(Object[] arg, int[] profiles, int colorFormat)122     private static List<Object[]> prepareTestArgs(Object[] arg, int[] profiles, int colorFormat) {
123         List<Object[]> argsList = new ArrayList<>();
124         final int[] maxBFrames = {0, 2};
125         final String mediaType = (String) arg[0];
126         boolean isVideo = mediaType.startsWith("video/");
127         final int br = (int) arg[1];
128         final int param1 = (int) arg[2];
129         final int param2 = (int) arg[3];
130         final int fps = (int) arg[4];
131         final int level = (int) arg[5];
132         if (isVideo) {
133             for (int maxBframe : maxBFrames) {
134                 if (maxBframe != 0) {
135                     if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
136                             && !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
137                         continue;
138                     }
139                 }
140                 Object[] testArgs = new Object[3];
141                 testArgs[0] = arg[0];
142                 testArgs[1] = getVideoEncoderCfgParams(mediaType, br, param1, param2, fps,
143                         colorFormat, maxBframe, profiles, level);
144                 testArgs[2] = String.format("%dkbps_%dx%d_%dfps_%s_%d_%d-bframes", br / 1000,
145                         param1, param2, fps, colorFormatToString(colorFormat, -1),
146                         level, maxBframe);
147                 argsList.add(testArgs);
148             }
149         } else {
150             Object[] testArgs = new Object[3];
151             testArgs[0] = arg[0];
152             testArgs[1] = getAudioEncoderCfgParams(mediaType, br, param1, param2, profiles);
153             testArgs[2] = String.format("%dkbps_%dkHz_%dch", br / 1000, param1 / 1000, param2);
154             argsList.add(testArgs);
155         }
156         return argsList;
157     }
158 
getVideoEncoderCfgParams(String mediaType, int bitRate, int width, int height, int frameRate, int colorFormat, int maxBframe, int[] profiles, int level)159     private static EncoderConfigParams[] getVideoEncoderCfgParams(String mediaType, int bitRate,
160             int width, int height, int frameRate, int colorFormat, int maxBframe, int[] profiles,
161             int level) {
162         ArrayList<EncoderConfigParams> cfgParams = new ArrayList<>();
163         for (int profile : profiles) {
164             if (maxBframe != 0) {
165                 if (mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC) && (
166                         profile == AVCProfileBaseline
167                                 || profile == AVCProfileConstrainedBaseline)) {
168                     continue;
169                 }
170             }
171             cfgParams.add(new EncoderConfigParams.Builder(mediaType)
172                     .setBitRate(bitRate)
173                     .setWidth(width)
174                     .setHeight(height)
175                     .setFrameRate(frameRate)
176                     .setMaxBFrames(maxBframe)
177                     .setProfile(profile)
178                     .setLevel(level)
179                     .setColorFormat(colorFormat)
180                     .build());
181         }
182         return cfgParams.toArray(new EncoderConfigParams[0]);
183     }
184 
getAudioEncoderCfgParams(String mediaType, int bitRate, int sampleRate, int channelCount, int[] profiles)185     private static EncoderConfigParams[] getAudioEncoderCfgParams(String mediaType, int bitRate,
186             int sampleRate, int channelCount, int[] profiles) {
187         EncoderConfigParams[] cfgParams = new EncoderConfigParams[profiles.length];
188         for (int i = 0; i < profiles.length; i++) {
189             cfgParams[i] = new EncoderConfigParams.Builder(mediaType)
190                     .setBitRate(bitRate)
191                     .setSampleRate(sampleRate)
192                     .setChannelCount(channelCount)
193                     .setProfile(profiles[i])
194                     .build();
195         }
196         return cfgParams;
197     }
198 
199     @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
input()200     public static Collection<Object[]> input() {
201         final boolean isEncoder = true;
202         final boolean needAudio = true;
203         final boolean needVideo = true;
204         final Object[][] exhaustiveArgsList = new Object[][]{
205                 // Audio - CodecMediaType, bit-rate, sample rate, channel count, level
206                 {MediaFormat.MIMETYPE_AUDIO_AAC, 64000, 48000, 1, -1, -1},
207                 {MediaFormat.MIMETYPE_AUDIO_AAC, 128000, 48000, 2, -1, -1},
208                 // Video - CodecMediaType, bit-rate, height, width, frame-rate, level
209                 {MediaFormat.MIMETYPE_VIDEO_AVC, 64000, 128, 96, 30, AVCLevel1},
210                 {MediaFormat.MIMETYPE_VIDEO_AVC, 128000, 176, 144, 15, AVCLevel1b},
211                 {MediaFormat.MIMETYPE_VIDEO_AVC, 192000, 320, 240, 10, AVCLevel11},
212                 {MediaFormat.MIMETYPE_VIDEO_AVC, 384000, 320, 240, 20, AVCLevel12},
213                 {MediaFormat.MIMETYPE_VIDEO_AVC, 512000, 352, 240, 30, AVCLevel13},
214                 {MediaFormat.MIMETYPE_VIDEO_AVC, 832000, 352, 288, 30, AVCLevel2},
215                 {MediaFormat.MIMETYPE_VIDEO_AVC, 1000000, 576, 352, 25, AVCLevel21},
216                 {MediaFormat.MIMETYPE_VIDEO_AVC, 1500000, 640, 480, 15, AVCLevel22},
217                 {MediaFormat.MIMETYPE_VIDEO_AVC, 2000000, 720, 480, 30, AVCLevel3},
218                 {MediaFormat.MIMETYPE_VIDEO_AVC, 3000000, 1280, 720, 30, AVCLevel31},
219                 {MediaFormat.MIMETYPE_VIDEO_AVC, 6000000, 1280, 1024, 42, AVCLevel32},
220                 {MediaFormat.MIMETYPE_VIDEO_AVC, 10000000, 1920, 1088, 30, AVCLevel4},
221                 {MediaFormat.MIMETYPE_VIDEO_AVC, 25000000, 2048, 1024, 30, AVCLevel41},
222                 {MediaFormat.MIMETYPE_VIDEO_AVC, 50000000, 2048, 1088, 60, AVCLevel42},
223                 {MediaFormat.MIMETYPE_VIDEO_AVC, 60000000, 2560, 1920, 30, AVCLevel5},
224                 {MediaFormat.MIMETYPE_VIDEO_AVC, 80000000, 4096, 2048, 30, AVCLevel51},
225                 {MediaFormat.MIMETYPE_VIDEO_AVC, 120000000, 4096, 2160, 60, AVCLevel52},
226                 {MediaFormat.MIMETYPE_VIDEO_AVC, 240000000, 8192, 4320, 30, AVCLevel6},
227                 {MediaFormat.MIMETYPE_VIDEO_AVC, 480000000, 8192, 4320, 60, AVCLevel61},
228                 {MediaFormat.MIMETYPE_VIDEO_AVC, 800000000, 8192, 4320, 120, AVCLevel62},
229 
230                 {MediaFormat.MIMETYPE_VIDEO_MPEG2, 4000000, 352, 288, 30, MPEG2LevelLL},
231                 {MediaFormat.MIMETYPE_VIDEO_MPEG2, 15000000, 720, 480, 30, MPEG2LevelML},
232                 {MediaFormat.MIMETYPE_VIDEO_MPEG2, 60000000, 1440, 1088, 30, MPEG2LevelH14},
233                 {MediaFormat.MIMETYPE_VIDEO_MPEG2, 80000000, 1920, 1088, 30, MPEG2LevelHL},
234                 {MediaFormat.MIMETYPE_VIDEO_MPEG2, 80000000, 1920, 1088, 60, MPEG2LevelHP},
235 
236                 {MediaFormat.MIMETYPE_VIDEO_VP9, 200000, 256, 144, 15, VP9Level1},
237                 {MediaFormat.MIMETYPE_VIDEO_VP9, 512000, 384, 192, 30, VP9Level11},
238                 {MediaFormat.MIMETYPE_VIDEO_VP9, 1000000, 480, 256, 30, VP9Level2},
239                 {MediaFormat.MIMETYPE_VIDEO_VP9, 1500000, 640, 384, 30, VP9Level21},
240                 {MediaFormat.MIMETYPE_VIDEO_VP9, 1600000, 720, 480, 30, VP9Level3},
241                 {MediaFormat.MIMETYPE_VIDEO_VP9, 4000000, 1280, 720, 30, VP9Level31},
242                 {MediaFormat.MIMETYPE_VIDEO_VP9, 5000000, 1920, 1080, 30, VP9Level4},
243                 {MediaFormat.MIMETYPE_VIDEO_VP9, 16000000, 2048, 1088, 60, VP9Level41},
244                 {MediaFormat.MIMETYPE_VIDEO_VP9, 20000000, 3840, 2160, 30, VP9Level5},
245                 {MediaFormat.MIMETYPE_VIDEO_VP9, 80000000, 4096, 2176, 60, VP9Level51},
246                 {MediaFormat.MIMETYPE_VIDEO_VP9, 160000000, 4096, 2176, 120, VP9Level52},
247                 {MediaFormat.MIMETYPE_VIDEO_VP9, 180000000, 8192, 4352, 30, VP9Level6},
248                 {MediaFormat.MIMETYPE_VIDEO_VP9, 240000000, 8192, 4352, 60, VP9Level61},
249                 {MediaFormat.MIMETYPE_VIDEO_VP9, 480000000, 8192, 4352, 120, VP9Level62},
250 
251                 {MediaFormat.MIMETYPE_VIDEO_H263, 64000, 176, 144, 15, H263Level10},
252                 {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 176, 144, 15, H263Level45},
253                 {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 352, 288, 15, H263Level20},
254                 {MediaFormat.MIMETYPE_VIDEO_H263, 384000, 352, 288, 30, H263Level30},
255                 {MediaFormat.MIMETYPE_VIDEO_H263, 2048000, 352, 288, 30, H263Level40},
256                 {MediaFormat.MIMETYPE_VIDEO_H263, 4096000, 352, 240, 60, H263Level50},
257                 {MediaFormat.MIMETYPE_VIDEO_H263, 8192000, 720, 240, 60, H263Level60},
258                 {MediaFormat.MIMETYPE_VIDEO_H263, 16384000, 720, 576, 50, H263Level70},
259 
260                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 128000, 176, 144, 15, HEVCMainTierLevel1},
261                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 512000, 352, 288, 30, HEVCMainTierLevel2},
262                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 1000000, 640, 360, 30, HEVCMainTierLevel21},
263                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 1000000, 512, 512, 30, HEVCMainTierLevel3},
264                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 1600000, 720, 480, 30, HEVCMainTierLevel3},
265                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 4000000, 1280, 720, 30, HEVCMainTierLevel31},
266                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 5000000, 1920, 1080, 30, HEVCMainTierLevel4},
267                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 16000000, 1920, 1080, 30, HEVCHighTierLevel4},
268                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 20000000, 1920, 1080, 60, HEVCMainTierLevel41},
269                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 30000000, 1920, 1080, 60, HEVCHighTierLevel41},
270                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 20000000, 3840, 2160, 30, HEVCMainTierLevel5},
271                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 50000000, 3840, 2160, 30, HEVCHighTierLevel5},
272                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 40000000, 3840, 2160, 60, HEVCMainTierLevel51},
273                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 80000000, 3840, 2160, 60, HEVCHighTierLevel51},
274                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 50000000, 3840, 2160, 120, HEVCMainTierLevel52},
275                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 100000000, 3840, 2160, 120, HEVCHighTierLevel52},
276                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 50000000, 7680, 4320, 30, HEVCMainTierLevel6},
277                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 80000000, 7680, 4320, 30, HEVCHighTierLevel6},
278                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 100000000, 7680, 4320, 60, HEVCMainTierLevel61},
279                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 240000000, 7680, 4320, 60, HEVCHighTierLevel61},
280                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 200000000, 7680, 4320, 120, HEVCMainTierLevel62},
281                 {MediaFormat.MIMETYPE_VIDEO_HEVC, 360000000, 7680, 4320, 120, HEVCHighTierLevel62},
282 
283                 {MediaFormat.MIMETYPE_VIDEO_AV1, 1500000, 426, 240, 30, AV1Level2},
284                 {MediaFormat.MIMETYPE_VIDEO_AV1, 3000000, 640, 360, 30, AV1Level21},
285                 {MediaFormat.MIMETYPE_VIDEO_AV1, 6000000, 854, 480, 30, AV1Level3},
286                 {MediaFormat.MIMETYPE_VIDEO_AV1, 10000000, 1280, 720, 30, AV1Level31},
287                 {MediaFormat.MIMETYPE_VIDEO_AV1, 12000000, 1920, 1080, 30, AV1Level4},
288                 {MediaFormat.MIMETYPE_VIDEO_AV1, 20000000, 1920, 1080, 60, AV1Level41},
289                 {MediaFormat.MIMETYPE_VIDEO_AV1, 30000000, 3840, 2160, 30, AV1Level5},
290                 {MediaFormat.MIMETYPE_VIDEO_AV1, 40000000, 3840, 2160, 60, AV1Level51},
291                 {MediaFormat.MIMETYPE_VIDEO_AV1, 60000000, 3840, 2160, 120, AV1Level52},
292                 {MediaFormat.MIMETYPE_VIDEO_AV1, 60000000, 7680, 4320, 30, AV1Level6},
293                 {MediaFormat.MIMETYPE_VIDEO_AV1, 100000000, 7680, 4320, 60, AV1Level61},
294                 {MediaFormat.MIMETYPE_VIDEO_AV1, 160000000, 7680, 4320, 120, AV1Level62},
295         };
296         final List<Object[]> argsList = new ArrayList<>();
297         for (Object[] arg : exhaustiveArgsList) {
298             final String mediaType = (String) arg[0];
299             argsList.addAll(prepareTestArgs(arg,
300                     Objects.requireNonNull(PROFILE_SDR_MAP.get(mediaType)),
301                     COLOR_FormatYUV420Flexible));
302             // P010 support was added in Android T, hence limit the following tests to Android
303             // T and above
304             if (IS_AT_LEAST_T && PROFILE_HLG_MAP.get(mediaType) != null) {
305                 argsList.addAll(prepareTestArgs(arg,
306                         Objects.requireNonNull(PROFILE_HLG_MAP.get(mediaType)),
307                         COLOR_FormatYUVP010));
308             }
309         }
310         final Object[][] mpeg4SimpleProfileArgsList = new Object[][]{
311                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 64000, 176, 144, 15, MPEG4Level0},
312                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 128000, 176, 144, 15, MPEG4Level0b},
313                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 64000, 128, 96, 30, MPEG4Level1},
314                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 128000, 352, 288, 15, MPEG4Level2},
315                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 384000, 352, 288, 30, MPEG4Level3},
316                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 4000000, 640, 480, 30, MPEG4Level4a},
317                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 8000000, 720, 576, 24, MPEG4Level5},
318                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 12000000, 1280, 720, 30, MPEG4Level6},
319         };
320         for (Object[] arg : mpeg4SimpleProfileArgsList) {
321             argsList.addAll(prepareTestArgs(arg, new int[]{MPEG4ProfileSimple},
322                     COLOR_FormatYUV420Flexible));
323         }
324         final Object[][] mpeg4AdvSimpleProfileArgsList = new Object[][]{
325                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 128000, 176, 144, 30, MPEG4Level1},
326                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 384000, 352, 288, 15, MPEG4Level2},
327                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 768000, 352, 288, 30, MPEG4Level3},
328                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 1500000, 352, 288, 30, MPEG4Level3b},
329                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 3000000, 704, 576, 15, MPEG4Level4},
330                 {MediaFormat.MIMETYPE_VIDEO_MPEG4, 8000000, 720, 576, 30, MPEG4Level5},
331         };
332         for (Object[] arg : mpeg4AdvSimpleProfileArgsList) {
333             argsList.addAll(prepareTestArgs(arg, new int[]{MPEG4ProfileAdvancedSimple},
334                     COLOR_FormatYUV420Flexible));
335         }
336         return prepareParamList(argsList, isEncoder, needAudio, needVideo, false);
337     }
338 
339     static {
340         // Following lists profiles, level, maxWidth and maxHeight mandated by the CDD.
341         // CodecMediaType, profiles, level, maxWidth, maxHeight
CDD_REQUIREMENTS_MAP.put(MediaFormat.MIMETYPE_AUDIO_AAC, new CddRequirements(new int[]{AACObjectLC, AACObjectHE, AACObjectELD}))342         CDD_REQUIREMENTS_MAP.put(MediaFormat.MIMETYPE_AUDIO_AAC,
343                 new CddRequirements(new int[]{AACObjectLC, AACObjectHE, AACObjectELD}));
CDD_REQUIREMENTS_MAP.put(MediaFormat.MIMETYPE_VIDEO_H263, new CddRequirements(new int[]{H263ProfileBaseline}, H263Level45))344         CDD_REQUIREMENTS_MAP.put(MediaFormat.MIMETYPE_VIDEO_H263,
345                 new CddRequirements(new int[]{H263ProfileBaseline}, H263Level45));
CDD_REQUIREMENTS_MAP.put(MediaFormat.MIMETYPE_VIDEO_AVC, new CddRequirements(new int[]{AVCProfileBaseline}, AVCLevel3))346         CDD_REQUIREMENTS_MAP.put(MediaFormat.MIMETYPE_VIDEO_AVC,
347                 new CddRequirements(new int[]{AVCProfileBaseline}, AVCLevel3));
CDD_REQUIREMENTS_MAP.put(MediaFormat.MIMETYPE_VIDEO_HEVC, new CddRequirements(new int[]{HEVCProfileMain}, HEVCMainTierLevel3, 512, 512))348         CDD_REQUIREMENTS_MAP.put(MediaFormat.MIMETYPE_VIDEO_HEVC,
349                 new CddRequirements(new int[]{HEVCProfileMain}, HEVCMainTierLevel3, 512, 512));
CDD_REQUIREMENTS_MAP.put(MediaFormat.MIMETYPE_VIDEO_VP9, new CddRequirements(new int[]{VP9Profile0}, VP9Level3))350         CDD_REQUIREMENTS_MAP.put(MediaFormat.MIMETYPE_VIDEO_VP9,
351                 new CddRequirements(new int[]{VP9Profile0}, VP9Level3));
352         if (IS_AT_LEAST_U) {
CDD_REQUIREMENTS_MAP.put(MediaFormat.MIMETYPE_VIDEO_AV1, new CddRequirements(new int[]{AV1ProfileMain8, AV1ProfileMain10}))353             CDD_REQUIREMENTS_MAP.put(MediaFormat.MIMETYPE_VIDEO_AV1,
354                     new CddRequirements(new int[]{AV1ProfileMain8, AV1ProfileMain10}));
355         }
356     }
357 
checkIfTrackFormatIsOk(MediaFormat trackFormat)358     void checkIfTrackFormatIsOk(MediaFormat trackFormat) {
359         assertEquals("Input media type and extracted media type are not identical " + mTestEnv
360                         + mTestConfig, mActiveEncCfg.mMediaType,
361                 trackFormat.getString(MediaFormat.KEY_MIME));
362         if (mIsVideo) {
363             assertEquals("Input width and extracted width are not same " + mTestEnv + mTestConfig,
364                     mActiveEncCfg.mWidth, getWidth(trackFormat));
365             assertEquals("Input height and extracted height are not same " + mTestEnv + mTestConfig,
366                     mActiveEncCfg.mHeight, getHeight(trackFormat));
367         } else {
368             int expSampleRate = mActiveEncCfg.mProfile != AACObjectHE ? mActiveEncCfg.mSampleRate
369                     : mActiveEncCfg.mSampleRate / 2;
370             int expChCount = mActiveEncCfg.mProfile != AACObjectHE_PS ? mActiveEncCfg.mChannelCount
371                     : mActiveEncCfg.mChannelCount / 2;
372             assertEquals("Input sample rate and extracted sample rate are not same " + mTestEnv
373                             + mTestConfig, expSampleRate,
374                     trackFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE));
375             assertEquals("Input channe count and extracted channel count are not same " + mTestEnv
376                             + mTestConfig, expChCount,
377                     trackFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT));
378         }
379     }
380 
shallSupportProfileAndLevel(EncoderConfigParams cfg)381     private boolean shallSupportProfileAndLevel(EncoderConfigParams cfg) {
382         CddRequirements requirement =
383                 Objects.requireNonNull(CDD_REQUIREMENTS_MAP.get(cfg.mMediaType));
384         int[] profileCdd = requirement.getProfiles();
385         int levelCdd = requirement.getLevel();
386         int widthCdd = requirement.getWidth();
387         int heightCdd = requirement.getHeight();
388 
389         // Check if CDD doesn't require support beyond certain resolutions.
390         if (widthCdd != -1 && mActiveEncCfg.mWidth > widthCdd) {
391             return false;
392         }
393         if (heightCdd != -1 && mActiveEncCfg.mHeight > heightCdd) {
394             return false;
395         }
396 
397         for (int cddProfile : profileCdd) {
398             if (cfg.mProfile == cddProfile) {
399                 if (!cfg.mIsAudio) {
400                     if (cfg.mLevel <= levelCdd) {
401                         if (cfg.mMediaType.equalsIgnoreCase(MediaFormat.MIMETYPE_VIDEO_H263)
402                                 && cfg.mLevel != MediaCodecInfo.CodecProfileLevel.H263Level45
403                                 && cfg.mLevel > MediaCodecInfo.CodecProfileLevel.H263Level10) {
404                             continue;
405                         }
406                     } else {
407                         continue;
408                     }
409                 }
410                 return true;
411             }
412         }
413         return false;
414     }
415 
416     /**
417      * Check description of class {@link EncoderProfileLevelTest}
418      */
419     @CddTest(requirements = {"2.2.2/5.1/H-0-3", "2.2.2/5.1/H-0-4", "2.2.2/5.1/H-0-5", "5/C-0-3",
420             "5.2.1/C-1-1", "5.2.2/C-1-1", "5.2.4/C-1-2", "5.2.5/C-1-1", "5.2.6/C-1-1"})
421     @ApiTest(apis = {"android.media.MediaFormat#KEY_PROFILE",
422             "android.media.MediaFormat#KEY_AAC_PROFILE",
423             "android.media.MediaFormat#KEY_LEVEL"})
424     @Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
testValidateProfileLevel()425     public void testValidateProfileLevel() throws IOException, InterruptedException {
426         int minLevel = getMinLevel(mMediaType, mEncCfgParams[0].mWidth, mEncCfgParams[0].mHeight,
427                 mEncCfgParams[0].mFrameRate, mEncCfgParams[0].mBitRate, mEncCfgParams[0].mProfile);
428         assertEquals("Calculated minimum acceptable level does not match the entry in test table "
429                 + mTestConfig, mEncCfgParams[0].mLevel, minLevel);
430 
431         if (mIsVideo && mEncCfgParams[0].mInputBitDepth != 8) {
432             Assume.assumeTrue(mCodecName + " doesn't support " + colorFormatToString(
433                             mEncCfgParams[0].mColorFormat, mEncCfgParams[0].mInputBitDepth),
434                     hasSupportForColorFormat(mCodecName, mMediaType,
435                             mEncCfgParams[0].mColorFormat));
436         }
437         // TODO(b/280510792): Remove the following once level can be configured correctly in
438         // c2.android.av1.encoder
439         if (mCodecName.equals("c2.android.av1.encoder")) {
440             Assume.assumeFalse("Disable frame rate > 30 for " + mCodecName,
441                     mEncCfgParams[0].mFrameRate > 30);
442         }
443         boolean cddSupportedMediaType = CDD_REQUIREMENTS_MAP.get(mMediaType) != null;
444         {
445             mActiveRawRes = EncoderInput.getRawResource(mEncCfgParams[0]);
446             assertNotNull("no raw resource found for testing config : "
447                     + mEncCfgParams[0] + mTestConfig + mTestEnv, mActiveRawRes);
448             setUpSource(mActiveRawRes.mFileName);
449             mSaveToMem = true;
450             mMuxOutput = true;
451             mOutputBuff = new OutputManager();
452             mCodec = MediaCodec.createByCodecName(mCodecName);
453             MediaCodecInfo.CodecCapabilities codecCapabilities =
454                     mCodec.getCodecInfo().getCapabilitiesForType(mMediaType);
455             int configsTested = 0;
456             for (EncoderConfigParams cfg : mEncCfgParams) {
457                 mActiveEncCfg = cfg;
458                 MediaFormat format = cfg.getFormat();
459                 if (!codecCapabilities.isFormatSupported(format)) {
460                     if (cddSupportedMediaType) {
461                         if (shallSupportProfileAndLevel(cfg)) {
462                             ArrayList<MediaFormat> formats = new ArrayList<>();
463                             formats.add(format);
464                             assertFalse("No components present on the device supports cdd "
465                                     + "required encode format:- " + format + mTestConfig + mTestEnv,
466                                     selectCodecs(mMediaType, formats, null, true).isEmpty());
467                         }
468                         Log.d(LOG_TAG, mCodecName + " doesn't support format: " + format);
469                     }
470                     continue;
471                 }
472 
473                 mOutputBuff.reset();
474                 configureCodec(format, false, true, true);
475                 mCodec.start();
476                 doWork(5);
477                 queueEOS();
478                 waitForAllOutputs();
479                 mCodec.reset();
480 
481                 MediaFormat trackFormat = validateProfileAndLevel();
482 
483                 deleteMuxedFile();
484 
485                 // validate extracted format for mandatory keys
486                 if (trackFormat != null) checkIfTrackFormatIsOk(trackFormat);
487 
488                 // Verify if device has an equivalent decoder for the current format
489                 ArrayList<MediaFormat> formatList = new ArrayList<>();
490                 if (mProfileLevel != null && mProfileLevel.second != -1
491                         && cfg.mLevel != mProfileLevel.second) {
492                     format.setInteger(MediaFormat.KEY_LEVEL, mProfileLevel.second);
493                 }
494                 formatList.add(format);
495                 assertTrue("Device advertises support for encoding " + format + " but cannot"
496                                 + " decode it. \n" + mTestConfig + mTestEnv,
497                         selectCodecs(mMediaType, formatList, null, false).size() > 0);
498                 configsTested++;
499             }
500             mCodec.release();
501             Assume.assumeTrue("skipping test, formats not supported by component",
502                     configsTested > 0);
503         }
504     }
505 }
506