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