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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "NativeAMediaCodecInfoUnitTest"
19
20 #include <jni.h>
21 #include <media/NdkMediaCodecInfo.h>
22 #include <media/NdkMediaCodecStore.h>
23 #include <media/NdkMediaExtractor.h>
24 #include <sys/stat.h>
25
26 #include "NativeMediaCommon.h"
27
28 #include <vector>
29
30 template <typename T>
equals(const T & op1,const T & op2)31 bool equals(const T& op1, const T& op2) {
32 return op1 == op2;
33 }
34
35 template <>
equals(const char * const & op1,const char * const & op2)36 bool equals(const char* const& op1, const char* const& op2) {
37 if (op1 != nullptr && op2 != nullptr)
38 return strcmp(op1, op2) == 0;
39 else
40 return op1 == op2;
41 }
42
43 template <>
equals(const AIntRange & op1,const AIntRange & op2)44 bool equals(const AIntRange& op1, const AIntRange& op2) {
45 return op1.mLower == op2.mLower && op1.mUpper == op2.mUpper;
46 }
47
48 template <>
equals(const AMediaCodecKind & kind1,const AMediaCodecKind & kind2)49 bool equals(const AMediaCodecKind& kind1, const AMediaCodecKind& kind2) {
50 return kind1 == kind2;
51 }
52
53 template <>
equals(const ADoubleRange & op1,const ADoubleRange & op2)54 bool equals(const ADoubleRange& op1, const ADoubleRange& op2) {
55 return op1.mLower == op2.mLower && op1.mUpper == op2.mUpper;
56 }
57
58 template <typename T>
toString(const T & val)59 std::string toString(const T& val) {
60 return std::to_string(val);
61 }
62
63 template <>
toString(const char * const & val)64 std::string toString(const char* const& val) {
65 if (val == nullptr) return "null";
66 return std::string(val);
67 }
68
69 template <>
toString(const AIntRange & val)70 std::string toString(const AIntRange& val) {
71 return StringFormat("range lower %d, range upper %d", val.mLower, val.mUpper);
72 }
73
74 template <>
toString(const ADoubleRange & val)75 std::string toString(const ADoubleRange& val) {
76 return StringFormat("range lower %f, range upper %f", val.mLower, val.mUpper);
77 }
78
79 template <>
toString(const AMediaFormat * const & val)80 std::string toString(const AMediaFormat* const& val) {
81 return std::string(AMediaFormat_toString((AMediaFormat*)val));
82 }
83
84 #define CLEANUP_IF_FALSE(cond) \
85 if (!(isPass = (cond))) { \
86 goto CleanUp; \
87 }
88
89 class NativeAMediaCodecInfoUnitTest {
90 private:
91 const char* mCodecName;
92 const AMediaCodecInfo* mCodecInfo;
93 const ACodecVideoCapabilities* mVideoCaps;
94 const ACodecAudioCapabilities* mAudioCaps;
95 const ACodecEncoderCapabilities* mEncoderCaps;
96 std::vector<const ACodecPerformancePoint*> mPerformancePoints;
97 std::string mErrorLogs;
98
99 template <typename T, typename U>
100 bool validateGetCodecMetadata(const T* obj, U (*func)(const T* obj), U expResultForInvalidArgs,
101 U expResult, const char* funcName);
102
103 template <typename T, typename U>
104 bool validateGetCodecMetadataArgs(const T* obj, int32_t (*func)(const T* obj, const U arg),
105 int32_t expResultForInvalidArgs, U arg, int32_t expResult,
106 const char* funcName);
107
108 template <typename T>
109 bool validateGetCapabilities(const T* obj,
110 media_status_t (*func)(const AMediaCodecInfo* info, const T** obj),
111 media_status_t expResult, const char* funcName);
112
113 template <typename T>
114 bool validateGetCodecMetadataIntRange(const T* obj,
115 media_status_t (*func)(const T* obj, AIntRange* outRange),
116 AIntRange& expRange, const char* funcName);
117
118 template <typename T, typename U>
119 bool validateGetCodecMetadataArgsArray(const T* obj,
120 media_status_t (*func)(const T* obj, const U** outArray,
121 size_t* outCount),
122 const U* expArray, size_t expCount,
123 const char* funcName);
124
125 template <typename T, typename U>
126 bool validateGetCodecMetadataIntRangeFor(
127 const T* obj, media_status_t (*func)(const T* obj, U input, AIntRange* outRange),
128 U input, const AIntRange& expRange, const char* funcName);
129
130 template <typename T, typename U>
131 bool validateGetCodecMetadataDoubleRangeFor(
132 const T* obj,
133 media_status_t (*func)(const T* obj, U width, U height, ADoubleRange* outRange),
134 U width, U height, const ADoubleRange& expRange, const char* funcName);
135
136 template <typename T>
137 bool validatePerformancePoint(const ACodecPerformancePoint* pp, const T* arg,
138 int32_t (*func)(const ACodecPerformancePoint*, const T*),
139 int32_t expected, const char* funcName);
140
141 public:
142 NativeAMediaCodecInfoUnitTest(const char* codecName);
143 NativeAMediaCodecInfoUnitTest(const char* codecName, bool testAudio, bool testVideo);
144 ~NativeAMediaCodecInfoUnitTest() = default;
145
146 bool validateCodecKind(int codecKind);
147 bool validateIsVendor(bool isVendor);
148 bool validateCanonicalName(const char* name);
149 bool validateMaxSupportedInstances(int maxSupportedInstances);
150 bool validateMediaCodecInfoType(int expectedCodecType);
151 bool validateMediaType(const char* expectedMediaType);
152 bool validateIsFeatureSupported(const char* feature, int hasSupport);
153 bool validateIsFeatureRequired(const char* feature, int isRequired);
154 bool validateIsFormatSupported(const char* file, const char* mediaType, bool isSupported);
155 bool validateGetAudioCaps(bool isAudio);
156 bool validateGetVideoCaps(bool isVideo);
157 bool validateGetEncoderCaps(bool isEncoder);
158
159 bool validateVideoCodecBitRateRange(int lower, int higher);
160 bool validateVideoCodecWidthRange(int lower, int higher);
161 bool validateVideoCodecHeightRange(int lower, int higher);
162 bool validateVideoCodecFrameRatesRange(int lower, int higher);
163 bool validateVideoCodecWidthAlignment(int alignment);
164 bool validateVideoCodecHeightAlignment(int alignment);
165
166 bool validateGetSupportedWidthsFor(int height, int expectedLower, int expectedUpper);
167 bool validateGetSupportedHeightsFor(int width, int expectedLower, int expectedUpper);
168 bool validateGetSupportedFrameRatesFor(int width, int height, double expectedLower,
169 double expectedUpper);
170 bool validateGetAchievableFrameRatesFor(int width, int height, double expectedLower,
171 double expectedUpper);
172 bool validateSizeSupport(int width, int height, bool expected);
173 bool validateSizeAndRateSupport(int width, int height, double frameRate, bool expected);
174
175 bool getPerformancePointsList(int expSize);
176 bool validatePerformancePointCoversFormat(int width, int height, float frameRate, int expMap);
177 bool validatePerformancePointCoversEqualsPoint(int width, int height, int frameRate,
178 int coversMap, int equalsMap);
179
180 bool validateAudioCodecBitRateRange(int mLower, int mUpper);
181 bool validateAudioCodecMaxInputChannelCount(int maxInputChannelCount);
182 bool validateAudioCodecMinInputChannelCount(int minInputChannelCount);
183 bool validateAudioCodecSupportedSampleRates(int* sampleRates, int count);
184 bool validateAudioCodecSupportedSampleRateRanges(int* sampleRateRanges, int count);
185 bool validateAudioCodecInputChannelCountRanges(int* channelCountRanges, int count);
186 bool validateAudioCodecIsSampleRateSupported(int sampleRate, int isSupported);
187
188 bool validateEncoderComplexityRange(int lower, int higher);
189 bool validateEncoderQualityRange(int lower, int higher);
190 bool validateEncoderIsBitrateModeSupported(int bitrateMode, int isSupported);
191
getErrorMsg()192 std::string getErrorMsg() { return mErrorLogs; };
193 };
194
NativeAMediaCodecInfoUnitTest(const char * codecName)195 NativeAMediaCodecInfoUnitTest::NativeAMediaCodecInfoUnitTest(const char* codecName) {
196 mCodecName = codecName;
197 mCodecInfo = nullptr;
198 mVideoCaps = nullptr;
199 mAudioCaps = nullptr;
200 mEncoderCaps = nullptr;
201 if (__builtin_available(android 36, *)) {
202 media_status_t val = AMediaCodecStore_getCodecInfo(codecName, &mCodecInfo);
203 if (AMEDIA_OK != val) {
204 mErrorLogs.append(
205 StringFormat("AMediaCodecStore_getCodecInfo returned with error %d \n", val));
206 return;
207 }
208 if (equals(AMediaCodecInfo_getKind(mCodecInfo), AMediaCodecKind_ENCODER)) {
209 val = AMediaCodecInfo_getEncoderCapabilities(mCodecInfo, &mEncoderCaps);
210 if (AMEDIA_OK != val) {
211 mErrorLogs.append(StringFormat("AMediaCodecInfo_getEncoderCapabilities "
212 "returned with error %d \n",
213 val));
214 }
215 }
216 }
217 }
218
NativeAMediaCodecInfoUnitTest(const char * codecName,bool testAudio,bool testVideo)219 NativeAMediaCodecInfoUnitTest::NativeAMediaCodecInfoUnitTest(const char* codecName, bool testAudio,
220 bool testVideo)
221 : NativeAMediaCodecInfoUnitTest(codecName) {
222 if (__builtin_available(android 36, *)) {
223 if (mCodecInfo != nullptr) {
224 if (testVideo) {
225 media_status_t val = AMediaCodecInfo_getVideoCapabilities(mCodecInfo, &mVideoCaps);
226 if (AMEDIA_OK != val) {
227 mErrorLogs.append(StringFormat("AMediaCodecInfo_getVideoCapabilities returned "
228 "with error %d \n",
229 val));
230 }
231 }
232 if (testAudio) {
233 media_status_t val = AMediaCodecInfo_getAudioCapabilities(mCodecInfo, &mAudioCaps);
234 if (AMEDIA_OK != val) {
235 mErrorLogs.append(StringFormat("AMediaCodecInfo_getAudioCapabilities returned "
236 "with error %d \n",
237 val));
238 }
239 }
240 }
241 }
242 }
243
244 template <typename T, typename U>
validateGetCodecMetadata(const T * obj,U (* func)(const T * obj),U expResultForInvalidArgs,U expResult,const char * funcName)245 bool NativeAMediaCodecInfoUnitTest::validateGetCodecMetadata(const T* obj, U (*func)(const T* obj),
246 U expResultForInvalidArgs, U expResult,
247 const char* funcName) {
248 if (__builtin_available(android 36, *)) {
249 U got = func(nullptr);
250 if (!equals(got, expResultForInvalidArgs)) {
251 mErrorLogs.append(StringFormat("For invalid args %s returned %s expected %s \n",
252 funcName, toString(got).c_str(),
253 toString(expResultForInvalidArgs).c_str()));
254 } else if (nullptr != obj) {
255 got = func(obj);
256 if (!equals(got, expResult)) {
257 mErrorLogs.append(StringFormat("For codec %s, %s returned %s expected %s \n",
258 mCodecName, funcName, toString(got).c_str(),
259 toString(expResult).c_str()));
260 } else {
261 return true;
262 }
263 }
264 }
265 return false;
266 }
267
validateCodecKind(int expectedKind)268 bool NativeAMediaCodecInfoUnitTest::validateCodecKind(int expectedKind) {
269 if (__builtin_available(android 36, *)) {
270 return validateGetCodecMetadata<AMediaCodecInfo,
271 AMediaCodecKind>(mCodecInfo, AMediaCodecInfo_getKind,
272 AMediaCodecKind_INVALID,
273 (AMediaCodecKind)expectedKind,
274 "AMediaCodecInfo_getKind");
275 }
276 return false;
277 }
278
validateIsVendor(bool isVendor)279 bool NativeAMediaCodecInfoUnitTest::validateIsVendor(bool isVendor) {
280 if (__builtin_available(android 36, *)) {
281 return validateGetCodecMetadata<AMediaCodecInfo, int32_t>(mCodecInfo,
282 AMediaCodecInfo_isVendor, -1,
283 isVendor,
284 "AMediaCodecInfo_isVendor");
285 }
286 return false;
287 }
288
validateCanonicalName(const char * name)289 bool NativeAMediaCodecInfoUnitTest::validateCanonicalName(const char* name) {
290 if (__builtin_available(android 36, *)) {
291 return validateGetCodecMetadata<AMediaCodecInfo,
292 const char*>(mCodecInfo, AMediaCodecInfo_getCanonicalName,
293 nullptr, name,
294 "AMediaCodecInfo_getCanonicalName");
295 }
296 return false;
297 }
298
validateMaxSupportedInstances(int maxSupportedInstances)299 bool NativeAMediaCodecInfoUnitTest::validateMaxSupportedInstances(int maxSupportedInstances) {
300 if (__builtin_available(android 36, *)) {
301 return validateGetCodecMetadata<AMediaCodecInfo,
302 int32_t>(mCodecInfo,
303 AMediaCodecInfo_getMaxSupportedInstances, -1,
304 maxSupportedInstances,
305 "AMediaCodecInfo_getMaxSupportedInstances");
306 }
307 return false;
308 }
309
validateMediaCodecInfoType(int expectedCodecType)310 bool NativeAMediaCodecInfoUnitTest::validateMediaCodecInfoType(int expectedCodecType) {
311 if (__builtin_available(android 36, *)) {
312 return validateGetCodecMetadata<AMediaCodecInfo,
313 AMediaCodecType>(mCodecInfo,
314 AMediaCodecInfo_getMediaCodecInfoType,
315 AMediaCodecType_INVALID_CODEC_INFO,
316 (AMediaCodecType)expectedCodecType,
317 "AMediaCodecInfo_getMediaCodecInfoType");
318 }
319 return false;
320 }
321
validateMediaType(const char * expectedMediaType)322 bool NativeAMediaCodecInfoUnitTest::validateMediaType(const char* expectedMediaType) {
323 if (__builtin_available(android 36, *)) {
324 return validateGetCodecMetadata<AMediaCodecInfo,
325 const char*>(mCodecInfo, AMediaCodecInfo_getMediaType,
326 nullptr, expectedMediaType,
327 "AMediaCodecInfo_getMediaType");
328 }
329 return false;
330 }
331
332 template <typename T, typename U>
validateGetCodecMetadataArgs(const T * obj,int32_t (* func)(const T * obj,const U arg),int32_t expResultForInvalidArgs,U arg,int32_t expResult,const char * funcName)333 bool NativeAMediaCodecInfoUnitTest::validateGetCodecMetadataArgs(
334 const T* obj, int32_t (*func)(const T* obj, const U arg), int32_t expResultForInvalidArgs,
335 U arg, int32_t expResult, const char* funcName) {
336 if (__builtin_available(android 36, *)) {
337 int got = func(nullptr, arg);
338 if (!equals(got, expResultForInvalidArgs)) {
339 mErrorLogs.append(StringFormat("For invalid args %s returned %s expected %s \n",
340 funcName, toString(got).c_str(),
341 toString(expResultForInvalidArgs).c_str()));
342 return false;
343 }
344 if (std::is_pointer_v<U>) {
345 got = func(nullptr, (U)0);
346 if (!equals(got, expResultForInvalidArgs)) {
347 mErrorLogs.append(StringFormat("For invalid args %s returned %s expected %s \n",
348 funcName, toString(got).c_str(),
349 toString(expResultForInvalidArgs).c_str()));
350 return false;
351 }
352 }
353 if (nullptr != obj) {
354 if (std::is_pointer_v<U>) {
355 got = func(obj, (U)0);
356 if (!equals(got, expResultForInvalidArgs)) {
357 mErrorLogs.append(StringFormat("For invalid args %s returned %s expected %s \n",
358 funcName, toString(got).c_str(),
359 toString(expResultForInvalidArgs).c_str()));
360 return false;
361 }
362 }
363 got = func(obj, arg);
364 if (!equals(got, expResult)) {
365 mErrorLogs.append(
366 StringFormat("For codec %s, input %s, %s returned %s expected %s \n",
367 mCodecName, toString(arg).c_str(), funcName,
368 toString(got).c_str(), toString(expResult).c_str()));
369 return false;
370 }
371 return true;
372 }
373 }
374 return false;
375 }
376
validateIsFeatureSupported(const char * feature,int hasSupport)377 bool NativeAMediaCodecInfoUnitTest::validateIsFeatureSupported(const char* feature,
378 int hasSupport) {
379 if (__builtin_available(android 36, *)) {
380 return validateGetCodecMetadataArgs<AMediaCodecInfo,
381 const char*>(mCodecInfo,
382 AMediaCodecInfo_isFeatureSupported, -1,
383 feature, hasSupport,
384 "AMediaCodecInfo_isFeatureSupported");
385 }
386 return false;
387 }
388
validateIsFeatureRequired(const char * feature,int isRequired)389 bool NativeAMediaCodecInfoUnitTest::validateIsFeatureRequired(const char* feature, int isRequired) {
390 if (__builtin_available(android 36, *)) {
391 return validateGetCodecMetadataArgs<AMediaCodecInfo,
392 const char*>(mCodecInfo,
393 AMediaCodecInfo_isFeatureRequired, -1,
394 feature, isRequired,
395 "AMediaCodecInfo_isFeatureRequired");
396 }
397 return false;
398 }
399
setUpExtractor(const char * srcFile,const char * mediaType)400 AMediaFormat* setUpExtractor(const char* srcFile, const char* mediaType) {
401 FILE* fp = fopen(srcFile, "rbe");
402 if (!fp) return nullptr;
403 struct stat buf {};
404 AMediaFormat* currFormat = nullptr;
405 if (!fstat(fileno(fp), &buf)) {
406 AMediaExtractor* extractor = AMediaExtractor_new();
407 media_status_t res = AMediaExtractor_setDataSourceFd(extractor, fileno(fp), 0, buf.st_size);
408 if (res == AMEDIA_OK) {
409 for (size_t trackID = 0; trackID < AMediaExtractor_getTrackCount(extractor);
410 trackID++) {
411 currFormat = AMediaExtractor_getTrackFormat(extractor, trackID);
412 const char* currMediaType = nullptr;
413 AMediaFormat_getString(currFormat, AMEDIAFORMAT_KEY_MIME, &currMediaType);
414 if (strcmp(currMediaType, mediaType) == 0) {
415 break;
416 }
417 AMediaFormat_delete(currFormat);
418 currFormat = nullptr;
419 }
420 }
421 AMediaExtractor_delete(extractor);
422 }
423 fclose(fp);
424 return currFormat;
425 }
426
validateIsFormatSupported(const char * file,const char * mediaType,bool isSupported)427 bool NativeAMediaCodecInfoUnitTest::validateIsFormatSupported(const char* file,
428 const char* mediaType,
429 bool isSupported) {
430 bool isPass = false;
431 if (__builtin_available(android 36, *)) {
432 AMediaFormat* format = setUpExtractor(file, mediaType);
433 if (format == nullptr) {
434 mErrorLogs.append(StringFormat("Encountered unknown error while getting track format "
435 "from file %s, mediaType %s \n",
436 file, mediaType));
437 return false;
438 }
439 isPass = validateGetCodecMetadataArgs<
440 AMediaCodecInfo, const AMediaFormat*>(mCodecInfo, AMediaCodecInfo_isFormatSupported,
441 -1, format, isSupported,
442 "AMediaCodecInfo_isFormatSupported");
443 AMediaFormat_delete(format);
444 }
445 return isPass;
446 }
447
448 template <typename T>
validateGetCapabilities(const T * obj,media_status_t (* func)(const AMediaCodecInfo * info,const T ** obj),media_status_t expResult,const char * funcName)449 bool NativeAMediaCodecInfoUnitTest::validateGetCapabilities(
450 const T* obj, media_status_t (*func)(const AMediaCodecInfo* info, const T** obj),
451 media_status_t expResult, const char* funcName) {
452 if (__builtin_available(android 36, *)) {
453 media_status_t status = func(nullptr, nullptr);
454 if (AMEDIA_ERROR_INVALID_PARAMETER != status) {
455 mErrorLogs.append(StringFormat("For invalid args, %s returned %d, expected %d\n",
456 funcName, status, AMEDIA_ERROR_INVALID_PARAMETER));
457 return false;
458 }
459 status = func(nullptr, &obj);
460 if (AMEDIA_ERROR_INVALID_PARAMETER != status) {
461 mErrorLogs.append(StringFormat("For invalid args, %s returned %d, expected %d\n",
462 funcName, status, AMEDIA_ERROR_INVALID_PARAMETER));
463 return false;
464 }
465 if (mCodecInfo != nullptr) {
466 status = func(mCodecInfo, nullptr);
467 if (AMEDIA_ERROR_INVALID_PARAMETER != status) {
468 mErrorLogs.append(StringFormat("For invalid args, %s returned %d, expected %d\n",
469 funcName, status, AMEDIA_ERROR_INVALID_PARAMETER));
470 return false;
471 }
472 status = func(mCodecInfo, &obj);
473 if (expResult != status) {
474 mErrorLogs.append(StringFormat("For codec %s, %s returned %d, expected %d\n",
475 mCodecName, funcName, status, expResult));
476 return false;
477 }
478 return true;
479 }
480 }
481 return false;
482 }
483
validateGetAudioCaps(bool isAudio)484 bool NativeAMediaCodecInfoUnitTest::validateGetAudioCaps(bool isAudio) {
485 if (__builtin_available(android 36, *)) {
486 return validateGetCapabilities<
487 ACodecAudioCapabilities>(mAudioCaps, AMediaCodecInfo_getAudioCapabilities,
488 isAudio ? AMEDIA_OK : AMEDIA_ERROR_UNSUPPORTED,
489 "AMediaCodecInfo_getAudioCapabilities");
490 }
491 return false;
492 }
493
validateGetVideoCaps(bool isVideo)494 bool NativeAMediaCodecInfoUnitTest::validateGetVideoCaps(bool isVideo) {
495 if (__builtin_available(android 36, *)) {
496 return validateGetCapabilities<
497 ACodecVideoCapabilities>(mVideoCaps, AMediaCodecInfo_getVideoCapabilities,
498 isVideo ? AMEDIA_OK : AMEDIA_ERROR_UNSUPPORTED,
499 "AMediaCodecInfo_getVideoCapabilities");
500 }
501 return false;
502 }
503
validateGetEncoderCaps(bool isEncoder)504 bool NativeAMediaCodecInfoUnitTest::validateGetEncoderCaps(bool isEncoder) {
505 if (__builtin_available(android 36, *)) {
506 return validateGetCapabilities<
507 ACodecEncoderCapabilities>(mEncoderCaps, AMediaCodecInfo_getEncoderCapabilities,
508 isEncoder ? AMEDIA_OK : AMEDIA_ERROR_UNSUPPORTED,
509 "AMediaCodecInfo_getEncoderCapabilities");
510 }
511 return false;
512 }
513
514 template <typename T>
validateGetCodecMetadataIntRange(const T * obj,media_status_t (* func)(const T * obj,AIntRange * outRange),AIntRange & expRange,const char * funcName)515 bool NativeAMediaCodecInfoUnitTest::validateGetCodecMetadataIntRange(
516 const T* obj, media_status_t (*func)(const T* obj, AIntRange* outRange),
517 AIntRange& expRange, const char* funcName) {
518 if (__builtin_available(android 36, *)) {
519 media_status_t status = func(nullptr, nullptr);
520 if (AMEDIA_ERROR_INVALID_PARAMETER != status) {
521 mErrorLogs.append(StringFormat("For invalid args %s returned %d expected %d \n",
522 funcName, status, AMEDIA_ERROR_INVALID_PARAMETER));
523 return false;
524 }
525 AIntRange got;
526 status = func(nullptr, &got);
527 if (AMEDIA_ERROR_INVALID_PARAMETER != status) {
528 mErrorLogs.append(StringFormat("For invalid args %s returned %d expected %d \n",
529 funcName, status, AMEDIA_ERROR_INVALID_PARAMETER));
530 return false;
531 }
532 if (obj != nullptr) {
533 status = func(obj, nullptr);
534 if (AMEDIA_ERROR_INVALID_PARAMETER != status) {
535 mErrorLogs.append(StringFormat("For invalid args %s returned %d expected %d \n",
536 funcName, status, AMEDIA_ERROR_INVALID_PARAMETER));
537 return false;
538 }
539 status = func(obj, &got);
540 if (AMEDIA_OK != status) {
541 mErrorLogs.append(StringFormat("For codec %s, %s returned %d expected %d \n",
542 mCodecName, funcName, status, AMEDIA_OK));
543 return false;
544 }
545 if (!equals(expRange, got)) {
546 mErrorLogs.append(StringFormat("For codec %s, %s returned %s, expected %s \n",
547 mCodecName, funcName, toString(got).c_str(),
548 toString(expRange).c_str()));
549 return false;
550 }
551 return true;
552 }
553 }
554 return false;
555 }
556
validateVideoCodecBitRateRange(int lower,int higher)557 bool NativeAMediaCodecInfoUnitTest::validateVideoCodecBitRateRange(int lower, int higher) {
558 if (__builtin_available(android 36, *)) {
559 AIntRange expected = {lower, higher};
560 return validateGetCodecMetadataIntRange<
561 ACodecVideoCapabilities>(mVideoCaps, ACodecVideoCapabilities_getBitrateRange,
562 expected, "ACodecVideoCapabilities_getBitrateRange");
563 }
564 return false;
565 }
566
validateVideoCodecWidthRange(int lower,int higher)567 bool NativeAMediaCodecInfoUnitTest::validateVideoCodecWidthRange(int lower, int higher) {
568 if (__builtin_available(android 36, *)) {
569 AIntRange expected = {lower, higher};
570 return validateGetCodecMetadataIntRange<
571 ACodecVideoCapabilities>(mVideoCaps, ACodecVideoCapabilities_getSupportedWidths,
572 expected, "ACodecVideoCapabilities_getSupportedWidths");
573 }
574 return false;
575 }
576
validateVideoCodecHeightRange(int lower,int higher)577 bool NativeAMediaCodecInfoUnitTest::validateVideoCodecHeightRange(int lower, int higher) {
578 if (__builtin_available(android 36, *)) {
579 AIntRange expected = {lower, higher};
580 return validateGetCodecMetadataIntRange<
581 ACodecVideoCapabilities>(mVideoCaps, ACodecVideoCapabilities_getSupportedHeights,
582 expected, "ACodecVideoCapabilities_getSupportedHeights");
583 }
584 return false;
585 }
586
validateVideoCodecFrameRatesRange(int lower,int higher)587 bool NativeAMediaCodecInfoUnitTest::validateVideoCodecFrameRatesRange(int lower, int higher) {
588 if (__builtin_available(android 36, *)) {
589 AIntRange expected = {lower, higher};
590 return validateGetCodecMetadataIntRange<
591 ACodecVideoCapabilities>(mVideoCaps, ACodecVideoCapabilities_getSupportedFrameRates,
592 expected,
593 "ACodecVideoCapabilities_getSupportedFrameRates");
594 }
595 return false;
596 }
597
validateVideoCodecWidthAlignment(int alignment)598 bool NativeAMediaCodecInfoUnitTest::validateVideoCodecWidthAlignment(int alignment) {
599 if (__builtin_available(android 36, *)) {
600 return validateGetCodecMetadata<ACodecVideoCapabilities,
601 int32_t>(mVideoCaps,
602 ACodecVideoCapabilities_getWidthAlignment, -1,
603 alignment,
604 "ACodecVideoCapabilities_getWidthAlignment");
605 }
606 return false;
607 }
608
validateVideoCodecHeightAlignment(int alignment)609 bool NativeAMediaCodecInfoUnitTest::validateVideoCodecHeightAlignment(int alignment) {
610 if (__builtin_available(android 36, *)) {
611 return validateGetCodecMetadata<ACodecVideoCapabilities,
612 int32_t>(mVideoCaps,
613 ACodecVideoCapabilities_getHeightAlignment, -1,
614 alignment,
615 "ACodecVideoCapabilities_getHeightAlignment");
616 }
617 return false;
618 }
619
validateAudioCodecBitRateRange(int lower,int higher)620 bool NativeAMediaCodecInfoUnitTest::validateAudioCodecBitRateRange(int lower, int higher) {
621 if (__builtin_available(android 36, *)) {
622 AIntRange expected = {lower, higher};
623 return validateGetCodecMetadataIntRange<
624 ACodecAudioCapabilities>(mAudioCaps, ACodecAudioCapabilities_getBitrateRange,
625 expected, "ACodecAudioCapabilities_getBitrateRange");
626 }
627 return false;
628 }
629
validateAudioCodecMaxInputChannelCount(int maxInputChannelCount)630 bool NativeAMediaCodecInfoUnitTest::validateAudioCodecMaxInputChannelCount(
631 int maxInputChannelCount) {
632 if (__builtin_available(android 36, *)) {
633 return validateGetCodecMetadata<ACodecAudioCapabilities,
634 int32_t>(mAudioCaps,
635 ACodecAudioCapabilities_getMaxInputChannelCount,
636 -1, maxInputChannelCount,
637 "ACodecAudioCapabilities_getMaxInputChannelCount");
638 }
639 return false;
640 }
641
validateAudioCodecMinInputChannelCount(int minInputChannelCount)642 bool NativeAMediaCodecInfoUnitTest::validateAudioCodecMinInputChannelCount(
643 int minInputChannelCount) {
644 if (__builtin_available(android 36, *)) {
645 return validateGetCodecMetadata<ACodecAudioCapabilities,
646 int32_t>(mAudioCaps,
647 ACodecAudioCapabilities_getMinInputChannelCount,
648 -1, minInputChannelCount,
649 "ACodecAudioCapabilities_getMinInputChannelCount");
650 }
651 return false;
652 }
653
654 template <typename T, typename U>
validateGetCodecMetadataArgsArray(const T * obj,media_status_t (* func)(const T * obj,const U ** outArray,size_t * outCount),const U * expArray,size_t expCount,const char * funcName)655 bool NativeAMediaCodecInfoUnitTest::validateGetCodecMetadataArgsArray(
656 const T* obj, media_status_t (*func)(const T* obj, const U** outArray, size_t* outCount),
657 const U* expArray, size_t expCount, const char* funcName) {
658 if (__builtin_available(android 36, *)) {
659 const U* gotArray = nullptr;
660 size_t gotCount = 0;
661
662 media_status_t status = func(nullptr, &gotArray, &gotCount);
663 if (status != AMEDIA_ERROR_INVALID_PARAMETER) {
664 mErrorLogs.append(StringFormat("For invalid args %s returned %d, expected %d\n",
665 funcName, status, AMEDIA_ERROR_INVALID_PARAMETER));
666 return false;
667 }
668 if (nullptr != obj) {
669 status = func(obj, nullptr, &gotCount);
670 if (status != AMEDIA_ERROR_INVALID_PARAMETER) {
671 mErrorLogs.append(StringFormat("For invalid args %s returned %d, expected %d\n",
672 funcName, status, AMEDIA_ERROR_INVALID_PARAMETER));
673 return false;
674 }
675 status = func(obj, &gotArray, nullptr);
676 if (status != AMEDIA_ERROR_INVALID_PARAMETER) {
677 mErrorLogs.append(StringFormat("For invalid args %s returned %d, expected %d\n",
678 funcName, status, AMEDIA_ERROR_INVALID_PARAMETER));
679 return false;
680 }
681 status = func(obj, &gotArray, &gotCount);
682 if (status != AMEDIA_OK) {
683 mErrorLogs.append(
684 StringFormat("%s returned %d, expected %d\n", funcName, status, AMEDIA_OK));
685 return false;
686 }
687 if (gotCount != expCount) {
688 mErrorLogs.append(StringFormat("%s returned array count as %d, expected %d\n",
689 funcName, gotCount, expCount));
690 return false;
691 }
692 for (int i = 0; i < expCount; ++i) {
693 if (!equals(expArray[i], gotArray[i])) {
694 mErrorLogs.append(StringFormat("For %s, array item at index %d: returned %s, "
695 "expected %s\n",
696 funcName, i, toString(gotArray[i]).c_str(),
697 toString(expArray[i]).c_str()));
698 return false;
699 }
700 }
701 return true;
702 }
703 }
704 return false;
705 }
706
validateAudioCodecSupportedSampleRates(int * sampleRates,int count)707 bool NativeAMediaCodecInfoUnitTest::validateAudioCodecSupportedSampleRates(int* sampleRates,
708 int count) {
709 if (__builtin_available(android 36, *)) {
710 return validateGetCodecMetadataArgsArray<
711 ACodecAudioCapabilities, int>(mAudioCaps,
712 ACodecAudioCapabilities_getSupportedSampleRates,
713 sampleRates, count,
714 "ACodecAudioCapabilities_getSupportedSampleRates");
715 }
716 return false;
717 }
718
validateAudioCodecSupportedSampleRateRanges(int * sampleRateRanges,int count)719 bool NativeAMediaCodecInfoUnitTest::validateAudioCodecSupportedSampleRateRanges(
720 int* sampleRateRanges, int count) {
721 if (__builtin_available(android 36, *)) {
722 AIntRange ranges[count];
723 for (int i = 0; i < count; i++) {
724 ranges[i].mLower = sampleRateRanges[2 * i];
725 ranges[i].mUpper = sampleRateRanges[2 * i + 1];
726 }
727 return validateGetCodecMetadataArgsArray<
728 ACodecAudioCapabilities,
729 AIntRange>(mAudioCaps, ACodecAudioCapabilities_getSupportedSampleRateRanges, ranges,
730 count, "ACodecAudioCapabilities_getSupportedSampleRateRanges");
731 }
732 return false;
733 }
734
validateAudioCodecInputChannelCountRanges(int * channelCountRanges,int count)735 bool NativeAMediaCodecInfoUnitTest::validateAudioCodecInputChannelCountRanges(
736 int* channelCountRanges, int count) {
737 if (__builtin_available(android 36, *)) {
738 AIntRange ranges[count];
739 for (int i = 0; i < count; i++) {
740 ranges[i].mLower = channelCountRanges[2 * i];
741 ranges[i].mUpper = channelCountRanges[2 * i + 1];
742 }
743 return validateGetCodecMetadataArgsArray<
744 ACodecAudioCapabilities,
745 AIntRange>(mAudioCaps, ACodecAudioCapabilities_getInputChannelCountRanges, ranges,
746 count, "ACodecAudioCapabilities_getInputChannelCountRanges");
747 }
748 return false;
749 }
750
validateAudioCodecIsSampleRateSupported(int sampleRate,int isSupported)751 bool NativeAMediaCodecInfoUnitTest::validateAudioCodecIsSampleRateSupported(int sampleRate,
752 int isSupported) {
753 if (__builtin_available(android 36, *)) {
754 return validateGetCodecMetadataArgs<
755 ACodecAudioCapabilities, int32_t>(mAudioCaps,
756 ACodecAudioCapabilities_isSampleRateSupported, -1,
757 sampleRate, isSupported,
758 "ACodecAudioCapabilities_isSampleRateSupported");
759 }
760 return false;
761 }
762
validateEncoderIsBitrateModeSupported(int bitrateMode,int isSupported)763 bool NativeAMediaCodecInfoUnitTest::validateEncoderIsBitrateModeSupported(int bitrateMode,
764 int isSupported) {
765 if (__builtin_available(android 36, *)) {
766 return validateGetCodecMetadataArgs<
767 ACodecEncoderCapabilities,
768 ABitrateMode>(mEncoderCaps, ACodecEncoderCapabilities_isBitrateModeSupported, -1,
769 (ABitrateMode)bitrateMode, isSupported,
770 "ACodecEncoderCapabilities_isBitrateModeSupported");
771 }
772 return false;
773 }
774
validateEncoderComplexityRange(int lower,int higher)775 bool NativeAMediaCodecInfoUnitTest::validateEncoderComplexityRange(int lower, int higher) {
776 if (__builtin_available(android 36, *)) {
777 AIntRange expected = {lower, higher};
778 return validateGetCodecMetadataIntRange<
779 ACodecEncoderCapabilities>(mEncoderCaps,
780 ACodecEncoderCapabilities_getComplexityRange, expected,
781 "ACodecEncoderCapabilities_getComplexityRange");
782 }
783 return false;
784 }
785
validateEncoderQualityRange(int lower,int higher)786 bool NativeAMediaCodecInfoUnitTest::validateEncoderQualityRange(int lower, int higher) {
787 if (__builtin_available(android 36, *)) {
788 AIntRange expected = {lower, higher};
789 return validateGetCodecMetadataIntRange<
790 ACodecEncoderCapabilities>(mEncoderCaps, ACodecEncoderCapabilities_getQualityRange,
791 expected, "ACodecEncoderCapabilities_getQualityRange");
792 }
793 return false;
794 }
795
796 template <typename T, typename U>
validateGetCodecMetadataIntRangeFor(const T * obj,media_status_t (* func)(const T * obj,U input,AIntRange * outRange),U input,const AIntRange & expRange,const char * funcName)797 bool NativeAMediaCodecInfoUnitTest::validateGetCodecMetadataIntRangeFor(
798 const T* obj, media_status_t (*func)(const T* obj, U input, AIntRange* outRange), U input,
799 const AIntRange& expRange, const char* funcName) {
800 if (__builtin_available(android 36, *)) {
801 AIntRange range;
802 media_status_t status = func(nullptr, input, &range);
803 if (status != AMEDIA_ERROR_INVALID_PARAMETER) {
804 mErrorLogs.append(StringFormat("For invalid args %s returned %d expected "
805 "AMEDIA_ERROR_INVALID_PARAMETER\n",
806 funcName, status));
807 return false;
808 }
809 if (nullptr != obj) {
810 status = func(obj, input, nullptr);
811 if (status != AMEDIA_ERROR_INVALID_PARAMETER) {
812 mErrorLogs.append(StringFormat("For invalid args %s returned %d expected "
813 "AMEDIA_ERROR_INVALID_PARAMETER\n",
814 funcName, status));
815 return false;
816 }
817 status = func(obj, input, &range);
818 if (AMEDIA_ERROR_UNSUPPORTED == status) {
819 if (!equals({-1, -1}, expRange)) {
820 mErrorLogs.append(StringFormat("For codec %s, %s returned "
821 "AMEDIA_ERROR_UNSUPPORTED but expected is %s \n",
822 mCodecName, funcName,
823 toString(expRange).c_str()));
824 return false;
825 }
826 return true;
827 } else {
828 if (AMEDIA_OK != status) {
829 mErrorLogs.append(
830 StringFormat("For codec %s, %s returned %d expected AMEDIA_OK\n",
831 mCodecName, funcName, status));
832 return false;
833 }
834 if (!equals(range, expRange)) {
835 mErrorLogs.append(StringFormat("For codec %s with input %s, %s returned %s, "
836 "expected %s\n",
837 mCodecName, toString(input).c_str(), funcName,
838 toString(range).c_str(),
839 toString(expRange).c_str()));
840 return false;
841 }
842 }
843 }
844 return true;
845 }
846 return false;
847 }
848
validateGetSupportedWidthsFor(int height,int expectedLower,int expectedUpper)849 bool NativeAMediaCodecInfoUnitTest::validateGetSupportedWidthsFor(int height, int expectedLower,
850 int expectedUpper) {
851 if (__builtin_available(android 36, *)) {
852 AIntRange expectedRange = {expectedLower, expectedUpper};
853 return validateGetCodecMetadataIntRangeFor<
854 ACodecVideoCapabilities, int>(mVideoCaps,
855 ACodecVideoCapabilities_getSupportedWidthsFor, height,
856 expectedRange,
857 "ACodecVideoCapabilities_getSupportedWidthsFor");
858 }
859 return false;
860 }
861
validateGetSupportedHeightsFor(int width,int expectedLower,int expectedUpper)862 bool NativeAMediaCodecInfoUnitTest::validateGetSupportedHeightsFor(int width, int expectedLower,
863 int expectedUpper) {
864 if (__builtin_available(android 36, *)) {
865 AIntRange expectedRange = {expectedLower, expectedUpper};
866 return validateGetCodecMetadataIntRangeFor<
867 ACodecVideoCapabilities, int>(mVideoCaps,
868 ACodecVideoCapabilities_getSupportedHeightsFor, width,
869 expectedRange,
870 "ACodecVideoCapabilities_getSupportedHeightsFor");
871 }
872 return false;
873 }
874
875 template <typename T, typename U>
validateGetCodecMetadataDoubleRangeFor(const T * obj,media_status_t (* func)(const T * obj,U width,U height,ADoubleRange * outRange),U width,U height,const ADoubleRange & expRange,const char * funcName)876 bool NativeAMediaCodecInfoUnitTest::validateGetCodecMetadataDoubleRangeFor(
877 const T* obj,
878 media_status_t (*func)(const T* obj, U width, U height, ADoubleRange* outRange), U width,
879 U height, const ADoubleRange& expRange, const char* funcName) {
880 if (__builtin_available(android 36, *)) {
881 ADoubleRange range;
882 media_status_t status = func(nullptr, width, height, &range);
883 if (status != AMEDIA_ERROR_INVALID_PARAMETER) {
884 mErrorLogs.append(StringFormat("For invalid args %s returned %d expected "
885 "AMEDIA_ERROR_INVALID_PARAMETER\n",
886 funcName, status));
887 return false;
888 }
889 if (nullptr != obj) {
890 status = func(obj, width, height, nullptr);
891 if (status != AMEDIA_ERROR_INVALID_PARAMETER) {
892 mErrorLogs.append(StringFormat("For invalid args %s returned %d expected "
893 "AMEDIA_ERROR_INVALID_PARAMETER\n",
894 funcName, status));
895 return false;
896 }
897 status = func(obj, width, height, &range);
898 if (AMEDIA_ERROR_UNSUPPORTED == status) {
899 if (!(equals({-1, -1}, expRange) || equals({-2, -2}, expRange))) {
900 mErrorLogs.append(
901 StringFormat("For codec %s with width %s, height %s, %s returned "
902 "AMEDIA_ERROR_UNSUPPORTED but expected %s \n",
903 mCodecName, toString(width).c_str(),
904 toString(height).c_str(), funcName,
905 toString(expRange).c_str()));
906 return false;
907 }
908 return true;
909 } else {
910 if (AMEDIA_OK != status) {
911 mErrorLogs.append(
912 StringFormat("For codec %s, %s returned %d expected AMEDIA_OK\n",
913 mCodecName, funcName, status));
914 return false;
915 }
916 if (!equals(range, expRange)) {
917 mErrorLogs.append(
918 StringFormat("For codec %s with width %s, height %s %s returned "
919 "%s, expected %s\n",
920 mCodecName, toString(width).c_str(),
921 toString(height).c_str(), funcName,
922 toString(range).c_str(), toString(expRange).c_str()));
923 return false;
924 }
925 }
926 }
927 return true;
928 }
929 return false;
930 }
931
validateGetSupportedFrameRatesFor(int width,int height,double expectedLower,double expectedUpper)932 bool NativeAMediaCodecInfoUnitTest::validateGetSupportedFrameRatesFor(int width, int height,
933 double expectedLower,
934 double expectedUpper) {
935 if (__builtin_available(android 36, *)) {
936 ADoubleRange expectedRange = {expectedLower, expectedUpper};
937 return validateGetCodecMetadataDoubleRangeFor<
938 ACodecVideoCapabilities, int>(mVideoCaps,
939 ACodecVideoCapabilities_getSupportedFrameRatesFor,
940 width, height, expectedRange,
941 "ACodecVideoCapabilities_getSupportedFrameRatesFor");
942 }
943 return false;
944 }
945
validateGetAchievableFrameRatesFor(int width,int height,double expectedLower,double expectedUpper)946 bool NativeAMediaCodecInfoUnitTest::validateGetAchievableFrameRatesFor(int width, int height,
947 double expectedLower,
948 double expectedUpper) {
949 if (__builtin_available(android 36, *)) {
950 ADoubleRange expectedRange = {expectedLower, expectedUpper};
951 return validateGetCodecMetadataDoubleRangeFor<
952 ACodecVideoCapabilities, int>(mVideoCaps,
953 ACodecVideoCapabilities_getAchievableFrameRatesFor,
954 width, height, expectedRange,
955 "ACodecVideoCapabilities_getAchievableFrameRatesFor");
956 }
957 return false;
958 }
959
validateSizeSupport(int width,int height,bool expectedResult)960 bool NativeAMediaCodecInfoUnitTest::validateSizeSupport(int width, int height,
961 bool expectedResult) {
962 if (__builtin_available(android 36, *)) {
963 int got = ACodecVideoCapabilities_isSizeSupported(nullptr, width, height);
964 if (got != -1) {
965 mErrorLogs.append(
966 StringFormat("For invalid args ACodecVideoCapabilities_isSizeSupported "
967 "returned %d expected -1\n",
968 got));
969 return false;
970 }
971 if (mVideoCaps != nullptr) {
972 got = ACodecVideoCapabilities_isSizeSupported(mVideoCaps, width, height);
973 if (got != expectedResult) {
974 mErrorLogs.append(StringFormat("For ACodecVideoCapabilities_isSizeSupported width "
975 "%d, height %d, expected %d, returned %d\n",
976 width, height, expectedResult, got));
977 return false;
978 }
979 return true;
980 }
981 }
982 return false;
983 }
984
validateSizeAndRateSupport(int width,int height,double frameRate,bool expected)985 bool NativeAMediaCodecInfoUnitTest::validateSizeAndRateSupport(int width, int height,
986 double frameRate, bool expected) {
987 if (__builtin_available(android 36, *)) {
988 int got =
989 ACodecVideoCapabilities_areSizeAndRateSupported(nullptr, width, height, frameRate);
990 if (got != -1) {
991 mErrorLogs.append(
992 StringFormat("For invalid args ACodecVideoCapabilities_areSizeAndRateSupported "
993 "returned %d expected -1\n",
994 got));
995 return false;
996 }
997 if (mVideoCaps != nullptr) {
998 got = ACodecVideoCapabilities_areSizeAndRateSupported(mVideoCaps, width, height,
999 frameRate);
1000 if (got != expected) {
1001 mErrorLogs.append(
1002 StringFormat("For ACodecVideoCapabilities_areSizeAndRateSupported width "
1003 "%d, height %d, rate %f, expected %d, "
1004 "returned %d\n",
1005 width, height, frameRate, expected, got));
1006 return false;
1007 }
1008 return true;
1009 }
1010 }
1011 return false;
1012 }
1013
getPerformancePointsList(int expSize)1014 bool NativeAMediaCodecInfoUnitTest::getPerformancePointsList(int expSize) {
1015 if (__builtin_available(android 36, *)) {
1016 const ACodecPerformancePoint* outPoint = nullptr;
1017 media_status_t status =
1018 ACodecVideoCapabilities_getNextSupportedPerformancePoint(nullptr, &outPoint);
1019 if (AMEDIA_ERROR_INVALID_PARAMETER != status) {
1020 mErrorLogs.append(
1021 StringFormat("For invalid args "
1022 "ACodecVideoCapabilities_getNextSupportedPerformancePoint "
1023 "returned %d expected %d\n",
1024 status, AMEDIA_ERROR_INVALID_PARAMETER));
1025 return false;
1026 }
1027 status = ACodecVideoCapabilities_getNextSupportedPerformancePoint(mVideoCaps, nullptr);
1028 if (AMEDIA_ERROR_INVALID_PARAMETER != status) {
1029 mErrorLogs.append(
1030 StringFormat("For invalid args "
1031 "ACodecVideoCapabilities_getNextSupportedPerformancePoint "
1032 "returned %d expected %d\n",
1033 status, AMEDIA_ERROR_INVALID_PARAMETER));
1034 return false;
1035 }
1036 do {
1037 status =
1038 ACodecVideoCapabilities_getNextSupportedPerformancePoint(mVideoCaps, &outPoint);
1039 if (AMEDIA_ERROR_UNSUPPORTED == status && outPoint != nullptr) {
1040 mErrorLogs.append("reached end of performance points list, but outPerformancePoint "
1041 "is not null\n");
1042 return false;
1043 }
1044 if (AMEDIA_OK == status && outPoint == nullptr) {
1045 mErrorLogs.append(
1046 "call to ACodecVideoCapabilities_getNextSupportedPerformancePoint "
1047 "succeeded, but outPerformancePoint is null\n");
1048 return false;
1049 }
1050 if (AMEDIA_OK == status) {
1051 mPerformancePoints.push_back(outPoint);
1052 }
1053 } while (outPoint != nullptr);
1054 if (mPerformancePoints.size() != expSize) {
1055 mErrorLogs.append(StringFormat("Performance points list size exp %d, got %d \n",
1056 expSize, mPerformancePoints.size()));
1057 return false;
1058 }
1059 return true;
1060 }
1061 return false;
1062 }
1063
1064 template <typename T>
validatePerformancePoint(const ACodecPerformancePoint * pp,const T * arg,int32_t (* func)(const ACodecPerformancePoint *,const T *),int32_t expected,const char * funcName)1065 bool NativeAMediaCodecInfoUnitTest::validatePerformancePoint(
1066 const ACodecPerformancePoint* pp, const T* arg,
1067 int32_t (*func)(const ACodecPerformancePoint*, const T*), int32_t expected,
1068 const char* funcName) {
1069 if (__builtin_available(android 36, *)) {
1070 auto got = func(nullptr, arg);
1071 if (-1 != got) {
1072 mErrorLogs.append(
1073 StringFormat("for invalid args, %s returned %d expected -1\n", funcName, got));
1074 return false;
1075 }
1076 got = func(pp, nullptr);
1077 if (-1 != got) {
1078 mErrorLogs.append(
1079 StringFormat("for invalid args, %s returned %d expected -1\n", funcName, got));
1080 return false;
1081 }
1082 got = func(pp, arg);
1083 if (expected != got) {
1084 mErrorLogs.append(
1085 StringFormat("%s returned %d expected %d\n", funcName, got, expected));
1086 return false;
1087 }
1088 return true;
1089 }
1090 return false;
1091 }
1092
validatePerformancePointCoversFormat(int width,int height,float frameRate,int expMap)1093 bool NativeAMediaCodecInfoUnitTest::validatePerformancePointCoversFormat(int width, int height,
1094 float frameRate,
1095 int expMap) {
1096 if (__builtin_available(android 36, *)) {
1097 AMediaFormat* format = AMediaFormat_new();
1098 const char* mediaType = AMediaCodecInfo_getMediaType(mCodecInfo);
1099 AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, mediaType);
1100 AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_WIDTH, width);
1101 AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_HEIGHT, height);
1102 AMediaFormat_setFloat(format, AMEDIAFORMAT_KEY_FRAME_RATE, frameRate);
1103 bool res;
1104 for (auto& it : mPerformancePoints) {
1105 res = validatePerformancePoint<AMediaFormat>(it, format,
1106 ACodecPerformancePoint_coversFormat,
1107 expMap & 1,
1108 "ACodecPerformancePoint_coversFormat");
1109 if (!res) break;
1110 expMap >>= 1;
1111 }
1112 AMediaFormat_delete(format);
1113 return res;
1114 }
1115 return false;
1116 }
1117
validatePerformancePointCoversEqualsPoint(int width,int height,int frameRate,int coversMap,int equalsMap)1118 bool NativeAMediaCodecInfoUnitTest::validatePerformancePointCoversEqualsPoint(int width, int height,
1119 int frameRate,
1120 int coversMap,
1121 int equalsMap) {
1122 if (__builtin_available(android 36, *)) {
1123 ACodecPerformancePoint* point = ACodecPerformancePoint_create(width, height, frameRate);
1124 if (point == nullptr) {
1125 mErrorLogs.append("ACodecPerformancePoint_create failed, expected non-null\n");
1126 return false;
1127 }
1128 bool res;
1129 for (auto& it : mPerformancePoints) {
1130 res = validatePerformancePoint<ACodecPerformancePoint>(it, point,
1131 ACodecPerformancePoint_covers,
1132 coversMap & 1,
1133 "ACodecPerformancePoint_covers");
1134 if (!res) break;
1135 coversMap >>= 1;
1136 res = validatePerformancePoint<ACodecPerformancePoint>(it, point,
1137 ACodecPerformancePoint_equals,
1138 equalsMap & 1,
1139 "ACodecPerformancePoint_equals");
1140 if (!res) break;
1141 equalsMap >>= 1;
1142 }
1143 ACodecPerformancePoint_destroy(point);
1144 if (res) {
1145 ACodecPerformancePoint_destroy(nullptr);
1146 }
1147 return res;
1148 }
1149 return false;
1150 }
1151
nativeTestAMediaCodecInfo(JNIEnv * env,jobject,jstring jCodecName,jboolean isEncoder,jint jCodecKind,jboolean isVendor,jstring jCanonicalName,jint jMaxSupportedInstances,jint jExpectedCodecType,jstring jMediaType,jobjectArray jFeaturesList,jint jFeatureSupportMap,jint jFeatureRequiredMap,jobjectArray jFileArray,jbooleanArray jIsFormatSupportedArray,jobject jRetMsg)1152 jboolean nativeTestAMediaCodecInfo(JNIEnv* env, jobject, jstring jCodecName, jboolean isEncoder,
1153 jint jCodecKind, jboolean isVendor, jstring jCanonicalName,
1154 jint jMaxSupportedInstances, jint jExpectedCodecType,
1155 jstring jMediaType, jobjectArray jFeaturesList,
1156 jint jFeatureSupportMap, jint jFeatureRequiredMap,
1157 jobjectArray jFileArray, jbooleanArray jIsFormatSupportedArray,
1158 jobject jRetMsg) {
1159 const char* codecName = env->GetStringUTFChars(jCodecName, nullptr);
1160 const char* canonicalName = env->GetStringUTFChars(jCanonicalName, nullptr);
1161 const char* mediaType = env->GetStringUTFChars(jMediaType, nullptr);
1162 auto testUtil = new NativeAMediaCodecInfoUnitTest(codecName);
1163 jsize featureCount = env->GetArrayLength(jFeaturesList);
1164 jsize formatCount = env->GetArrayLength(jFileArray);
1165 jstring jFeature, jFile;
1166 const char *feature = nullptr, *file = nullptr;
1167 jboolean* isFormatSupportedArray = nullptr;
1168 bool isPass;
1169 CLEANUP_IF_FALSE(testUtil->validateCodecKind(jCodecKind))
1170 CLEANUP_IF_FALSE(testUtil->validateIsVendor(isVendor))
1171 CLEANUP_IF_FALSE(testUtil->validateCanonicalName(canonicalName))
1172 CLEANUP_IF_FALSE(testUtil->validateMaxSupportedInstances(jMaxSupportedInstances))
1173 CLEANUP_IF_FALSE(testUtil->validateMediaCodecInfoType(jExpectedCodecType))
1174 CLEANUP_IF_FALSE(testUtil->validateMediaType(mediaType))
1175 for (auto i = 0; i < featureCount; i++) {
1176 jFeature = (jstring)env->GetObjectArrayElement(jFeaturesList, i);
1177 feature = env->GetStringUTFChars(jFeature, nullptr);
1178 CLEANUP_IF_FALSE(testUtil->validateIsFeatureSupported(feature, jFeatureSupportMap & 1))
1179 jFeatureSupportMap >>= 1;
1180 CLEANUP_IF_FALSE(testUtil->validateIsFeatureRequired(feature, jFeatureRequiredMap & 1))
1181 jFeatureRequiredMap >>= 1;
1182 env->ReleaseStringUTFChars(jFeature, feature);
1183 feature = nullptr;
1184 }
1185 isFormatSupportedArray = env->GetBooleanArrayElements(jIsFormatSupportedArray, nullptr);
1186 for (auto i = 0; i < formatCount; i++) {
1187 jFile = (jstring)env->GetObjectArrayElement(jFileArray, i);
1188 file = env->GetStringUTFChars(jFile, nullptr);
1189 CLEANUP_IF_FALSE(
1190 testUtil->validateIsFormatSupported(file, mediaType, isFormatSupportedArray[i]))
1191 env->ReleaseStringUTFChars(jFile, file);
1192 file = nullptr;
1193 }
1194 CLEANUP_IF_FALSE(
1195 testUtil->validateGetAudioCaps(strncmp(mediaType, "audio/", strlen("audio/")) == 0))
1196 CLEANUP_IF_FALSE(
1197 testUtil->validateGetVideoCaps(strncmp(mediaType, "video/", strlen("video/")) == 0 ||
1198 strcasecmp(mediaType, "image/vnd.android.heic") == 0))
1199 CLEANUP_IF_FALSE(testUtil->validateGetEncoderCaps(isEncoder))
1200 CleanUp:
1201 std::string msg = isPass ? std::string{} : testUtil->getErrorMsg();
1202 delete testUtil;
1203 jclass clazz = env->GetObjectClass(jRetMsg);
1204 jmethodID mId =
1205 env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1206 env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
1207 env->ReleaseStringUTFChars(jCodecName, codecName);
1208 env->ReleaseStringUTFChars(jCanonicalName, canonicalName);
1209 env->ReleaseStringUTFChars(jMediaType, mediaType);
1210 if (feature) env->ReleaseStringUTFChars(jFeature, feature);
1211 if (file) env->ReleaseStringUTFChars(jFile, file);
1212 if (isFormatSupportedArray)
1213 env->ReleaseBooleanArrayElements(jIsFormatSupportedArray, isFormatSupportedArray, 0);
1214 return static_cast<jboolean>(isPass);
1215 }
1216
nativeTestAMediaCodecInfoVideoCaps(JNIEnv * env,jobject,jstring jCodecName,jint jBitRateRangeLower,jint jBitRateRangeUpper,jint jSupportedWidthLower,jint jSupportedWidthUpper,jint jSupportedHeightLower,jint jSupportedHeightUpper,jint jSupportedFrameRateLower,jint jSupportedFrameRateUpper,jint jWidthAlignment,jint jHeightAlignment,jobject jRetMsg)1217 jboolean nativeTestAMediaCodecInfoVideoCaps(JNIEnv* env, jobject, jstring jCodecName,
1218 jint jBitRateRangeLower, jint jBitRateRangeUpper,
1219 jint jSupportedWidthLower, jint jSupportedWidthUpper,
1220 jint jSupportedHeightLower, jint jSupportedHeightUpper,
1221 jint jSupportedFrameRateLower,
1222 jint jSupportedFrameRateUpper, jint jWidthAlignment,
1223 jint jHeightAlignment, jobject jRetMsg) {
1224 const char* codecName = env->GetStringUTFChars(jCodecName, nullptr);
1225 auto testUtil = new NativeAMediaCodecInfoUnitTest(codecName, false, true);
1226 bool isPass;
1227 CLEANUP_IF_FALSE(
1228 testUtil->validateVideoCodecBitRateRange(jBitRateRangeLower, jBitRateRangeUpper))
1229 CLEANUP_IF_FALSE(
1230 testUtil->validateVideoCodecWidthRange(jSupportedWidthLower, jSupportedWidthUpper))
1231 CLEANUP_IF_FALSE(
1232 testUtil->validateVideoCodecHeightRange(jSupportedHeightLower, jSupportedHeightUpper))
1233 CLEANUP_IF_FALSE(testUtil->validateVideoCodecFrameRatesRange(jSupportedFrameRateLower,
1234 jSupportedFrameRateUpper))
1235 CLEANUP_IF_FALSE(testUtil->validateVideoCodecWidthAlignment(jWidthAlignment))
1236 CLEANUP_IF_FALSE(testUtil->validateVideoCodecHeightAlignment(jHeightAlignment))
1237 CleanUp:
1238 std::string msg = isPass ? std::string{} : testUtil->getErrorMsg();
1239 delete testUtil;
1240 jclass clazz = env->GetObjectClass(jRetMsg);
1241 jmethodID mId =
1242 env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1243 env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
1244 env->ReleaseStringUTFChars(jCodecName, codecName);
1245 return static_cast<jboolean>(isPass);
1246 }
1247
nativeTestAMediaCodecInfoVideoCapsGetSupportFor(JNIEnv * env,jobject,jstring jCodecName,jint jTestWidth,jint jTestHeight,jdouble jFrameRate,jint jSupportedWidthLowerForHeight,jint jSupportedWidthUpperForHeight,jint jSupportedHeightLowerForWidth,jint jSupportedHeightUpperForWidth,jdouble jSupportedFrameRateLower,jdouble jSupportedFrameRateUpper,jdouble jAchievedFrameRateLower,jdouble jAchievedFrameRateUpper,jboolean jIsSizeSupported,jboolean jAreSizeAndRateSupported,jobject jRetMsg)1248 jboolean nativeTestAMediaCodecInfoVideoCapsGetSupportFor(
1249 JNIEnv* env, jobject, jstring jCodecName, jint jTestWidth, jint jTestHeight,
1250 jdouble jFrameRate, jint jSupportedWidthLowerForHeight, jint jSupportedWidthUpperForHeight,
1251 jint jSupportedHeightLowerForWidth, jint jSupportedHeightUpperForWidth,
1252 jdouble jSupportedFrameRateLower, jdouble jSupportedFrameRateUpper,
1253 jdouble jAchievedFrameRateLower, jdouble jAchievedFrameRateUpper, jboolean jIsSizeSupported,
1254 jboolean jAreSizeAndRateSupported, jobject jRetMsg) {
1255 const char* codecName = env->GetStringUTFChars(jCodecName, nullptr);
1256 auto testUtil = new NativeAMediaCodecInfoUnitTest(codecName, false, true);
1257 bool isPass;
1258 CLEANUP_IF_FALSE(testUtil->validateGetSupportedWidthsFor(jTestHeight,
1259 jSupportedWidthLowerForHeight,
1260 jSupportedWidthUpperForHeight))
1261 CLEANUP_IF_FALSE(testUtil->validateGetSupportedHeightsFor(jTestWidth,
1262 jSupportedHeightLowerForWidth,
1263 jSupportedHeightUpperForWidth))
1264 CLEANUP_IF_FALSE(testUtil->validateGetSupportedFrameRatesFor(jTestWidth, jTestHeight,
1265 jSupportedFrameRateLower,
1266 jSupportedFrameRateUpper))
1267 CLEANUP_IF_FALSE(testUtil->validateGetAchievableFrameRatesFor(jTestWidth, jTestHeight,
1268 jAchievedFrameRateLower,
1269 jAchievedFrameRateUpper))
1270 CLEANUP_IF_FALSE(testUtil->validateSizeSupport(jTestWidth, jTestHeight, jIsSizeSupported))
1271 CLEANUP_IF_FALSE(testUtil->validateSizeAndRateSupport(jTestWidth, jTestHeight, jFrameRate,
1272 jAreSizeAndRateSupported))
1273 CleanUp:
1274 std::string msg = isPass ? std::string{} : testUtil->getErrorMsg();
1275 delete testUtil;
1276 jclass clazz = env->GetObjectClass(jRetMsg);
1277 jmethodID mId =
1278 env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1279 env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
1280 env->ReleaseStringUTFChars(jCodecName, codecName);
1281 return static_cast<jboolean>(isPass);
1282 }
1283
nativeTestACodecPerformancePoint(JNIEnv * env,jobject,jstring jCodecName,jint jWidth,jint jHeight,jdouble jFrameRate,jint jCoversFormat,jint jCoversPoint,jint jEqualsPoint,jint jPpListSize,jobject jRetMsg)1284 jboolean nativeTestACodecPerformancePoint(JNIEnv* env, jobject, jstring jCodecName, jint jWidth,
1285 jint jHeight, jdouble jFrameRate, jint jCoversFormat,
1286 jint jCoversPoint, jint jEqualsPoint, jint jPpListSize,
1287 jobject jRetMsg) {
1288 const char* codecName = env->GetStringUTFChars(jCodecName, nullptr);
1289 auto testUtil = new NativeAMediaCodecInfoUnitTest(codecName, false, true);
1290 bool isPass;
1291 CLEANUP_IF_FALSE(testUtil->getPerformancePointsList(jPpListSize))
1292 if (jPpListSize != 0) {
1293 CLEANUP_IF_FALSE(testUtil->validatePerformancePointCoversFormat(jWidth, jHeight,
1294 (float)jFrameRate,
1295 jCoversFormat))
1296 CLEANUP_IF_FALSE(testUtil->validatePerformancePointCoversEqualsPoint(jWidth, jHeight,
1297 (int)jFrameRate,
1298 jCoversPoint,
1299 jEqualsPoint))
1300 }
1301 CleanUp:
1302 std::string msg = isPass ? std::string{} : testUtil->getErrorMsg();
1303 delete testUtil;
1304 env->ReleaseStringUTFChars(jCodecName, codecName);
1305 jclass clazz = env->GetObjectClass(jRetMsg);
1306 jmethodID mId =
1307 env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1308 env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
1309 return static_cast<jboolean>(isPass);
1310 }
1311
nativeTestAMediaCodecInfoGetAudioCapabilities(JNIEnv * env,jobject,jstring jCodecName,jint jBitRateRangeLower,jint jBitRateRangeUpper,jint jMaxInputChannelCount,jint jMinInputChannelCount,jintArray jSampleRates,jintArray jSampleRateRanges,jintArray jInputChannelCountRanges,jintArray jStandardSampleRatesArray,jint jStandardSampleRatesSupportMap,jobject jRetMsg)1312 jboolean nativeTestAMediaCodecInfoGetAudioCapabilities(
1313 JNIEnv* env, jobject, jstring jCodecName, jint jBitRateRangeLower, jint jBitRateRangeUpper,
1314 jint jMaxInputChannelCount, jint jMinInputChannelCount, jintArray jSampleRates,
1315 jintArray jSampleRateRanges, jintArray jInputChannelCountRanges,
1316 jintArray jStandardSampleRatesArray, jint jStandardSampleRatesSupportMap, jobject jRetMsg) {
1317 const char* codecName = env->GetStringUTFChars(jCodecName, nullptr);
1318 jint* sampleRatesArray = nullptr;
1319 jsize sampleRatesCount = 0;
1320 if (jSampleRates != nullptr) {
1321 sampleRatesArray = env->GetIntArrayElements(jSampleRates, nullptr);
1322 sampleRatesCount = env->GetArrayLength(jSampleRates);
1323 }
1324 jint* sampleRateRanges = env->GetIntArrayElements(jSampleRateRanges, nullptr);
1325 jsize sampleRateRangeCount = env->GetArrayLength(jSampleRateRanges);
1326 jint* channelCountRanges = env->GetIntArrayElements(jInputChannelCountRanges, nullptr);
1327 jsize channelCountRangeCount = env->GetArrayLength(jInputChannelCountRanges);
1328 jint* standardSampleRatesArray = env->GetIntArrayElements(jStandardSampleRatesArray, nullptr);
1329 jsize standardSampleRatesCount = env->GetArrayLength(jStandardSampleRatesArray);
1330 auto testUtil = new NativeAMediaCodecInfoUnitTest(codecName, true, false);
1331 bool isPass;
1332 CLEANUP_IF_FALSE(
1333 testUtil->validateAudioCodecBitRateRange(jBitRateRangeLower, jBitRateRangeUpper))
1334 CLEANUP_IF_FALSE(testUtil->validateAudioCodecMinInputChannelCount(jMinInputChannelCount))
1335 CLEANUP_IF_FALSE(testUtil->validateAudioCodecMaxInputChannelCount(jMaxInputChannelCount))
1336 if (sampleRatesArray) {
1337 CLEANUP_IF_FALSE(testUtil->validateAudioCodecSupportedSampleRates(sampleRatesArray,
1338 sampleRatesCount))
1339 }
1340 CLEANUP_IF_FALSE(
1341 testUtil->validateAudioCodecSupportedSampleRateRanges(sampleRateRanges,
1342 sampleRateRangeCount / 2))
1343 CLEANUP_IF_FALSE(
1344 testUtil->validateAudioCodecInputChannelCountRanges(channelCountRanges,
1345 channelCountRangeCount / 2))
1346 for (auto i = 0; i < standardSampleRatesCount; i++) {
1347 CLEANUP_IF_FALSE(
1348 testUtil->validateAudioCodecIsSampleRateSupported(standardSampleRatesArray[i],
1349 jStandardSampleRatesSupportMap &
1350 1))
1351 jStandardSampleRatesSupportMap >>= 1;
1352 }
1353 CleanUp:
1354 std::string msg = isPass ? std::string{} : testUtil->getErrorMsg();
1355 delete testUtil;
1356 env->ReleaseStringUTFChars(jCodecName, codecName);
1357 env->ReleaseIntArrayElements(jStandardSampleRatesArray, standardSampleRatesArray, 0);
1358 if (sampleRatesArray) env->ReleaseIntArrayElements(jSampleRates, sampleRatesArray, 0);
1359 env->ReleaseIntArrayElements(jSampleRateRanges, sampleRateRanges, 0);
1360 env->ReleaseIntArrayElements(jInputChannelCountRanges, channelCountRanges, 0);
1361 jclass clazz = env->GetObjectClass(jRetMsg);
1362 jmethodID mId =
1363 env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1364 env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
1365 return static_cast<jboolean>(isPass);
1366 }
1367
nativeTestAMediaCodecInfoGetEncoderCapabilities(JNIEnv * env,jobject,jstring jCodecName,jint jComplexityRangeLower,jint jComplexityRangeUpper,jint jQualityRangeLower,jint jQualityRangeUpper,jint jBitrateModeSupportMap,jobject jRetMsg)1368 jboolean nativeTestAMediaCodecInfoGetEncoderCapabilities(
1369 JNIEnv* env, jobject, jstring jCodecName, jint jComplexityRangeLower,
1370 jint jComplexityRangeUpper, jint jQualityRangeLower, jint jQualityRangeUpper,
1371 jint jBitrateModeSupportMap, jobject jRetMsg) {
1372 const char* codecName = env->GetStringUTFChars(jCodecName, nullptr);
1373 auto testUtil = new NativeAMediaCodecInfoUnitTest(codecName);
1374 bool isPass;
1375 CLEANUP_IF_FALSE(
1376 testUtil->validateEncoderComplexityRange(jComplexityRangeLower, jComplexityRangeUpper))
1377 CLEANUP_IF_FALSE(testUtil->validateEncoderQualityRange(jQualityRangeLower, jQualityRangeUpper))
1378 for (int i = 0; i < 4; i++) {
1379 CLEANUP_IF_FALSE(
1380 testUtil->validateEncoderIsBitrateModeSupported(i, jBitrateModeSupportMap & 1))
1381 jBitrateModeSupportMap >>= 1;
1382 }
1383 CleanUp:
1384 std::string msg = isPass ? std::string{} : testUtil->getErrorMsg();
1385 delete testUtil;
1386 env->ReleaseStringUTFChars(jCodecName, codecName);
1387 jclass clazz = env->GetObjectClass(jRetMsg);
1388 jmethodID mId =
1389 env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1390 env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
1391 return static_cast<jboolean>(isPass);
1392 }
1393
nativeTestAMediaCodecStoreGetSupportedTypes(JNIEnv * env,jobject,jobjectArray jMediaTypesArray,jintArray jModesArray,jobject jRetMsg)1394 jboolean nativeTestAMediaCodecStoreGetSupportedTypes(JNIEnv* env, jobject,
1395 jobjectArray jMediaTypesArray,
1396 jintArray jModesArray, jobject jRetMsg) {
1397 bool isPass = false;
1398 if (__builtin_available(android 36, *)) {
1399 const AMediaCodecSupportedMediaType* outMediaTypes = nullptr;
1400 size_t outCount = 0;
1401 std::string errorLogs;
1402 jint* modesArray = env->GetIntArrayElements(jModesArray, nullptr);
1403 jsize modesCount = env->GetArrayLength(jModesArray);
1404 jstring jMediaType = nullptr;
1405 const char* mediaType = nullptr;
1406
1407 auto status = AMediaCodecStore_getSupportedMediaTypes(nullptr, nullptr);
1408 if (status != AMEDIA_ERROR_INVALID_PARAMETER) {
1409 errorLogs.append(StringFormat("For invalid args, %s returned %d, expected "
1410 "AMEDIA_ERROR_INVALID_PARAMETER\n",
1411 "AMediaCodecSupportedMediaType", status));
1412 goto CleanUp;
1413 }
1414 status = AMediaCodecStore_getSupportedMediaTypes(nullptr, &outCount);
1415 if (status != AMEDIA_ERROR_INVALID_PARAMETER) {
1416 errorLogs.append(StringFormat("For invalid args, %s returned %d, expected "
1417 "AMEDIA_ERROR_INVALID_PARAMETER\n",
1418 "AMediaCodecSupportedMediaType", status));
1419 goto CleanUp;
1420 }
1421 status = AMediaCodecStore_getSupportedMediaTypes(&outMediaTypes, nullptr);
1422 if (status != AMEDIA_ERROR_INVALID_PARAMETER) {
1423 errorLogs.append(StringFormat("For invalid args, %s returned %d, expected "
1424 "AMEDIA_ERROR_INVALID_PARAMETER\n",
1425 "AMediaCodecSupportedMediaType", status));
1426 goto CleanUp;
1427 }
1428 status = AMediaCodecStore_getSupportedMediaTypes(&outMediaTypes, &outCount);
1429 if (status != AMEDIA_OK) {
1430 errorLogs.append(StringFormat("%s returned %d, expected AMEDIA_OK\n",
1431 "AMediaCodecSupportedMediaType", status));
1432 goto CleanUp;
1433 }
1434 if (outCount != modesCount) {
1435 errorLogs.append(StringFormat("%s returned %d supported media types, expected %d\n",
1436 "AMediaCodecSupportedMediaType", outCount, modesCount));
1437 goto CleanUp;
1438 }
1439 for (auto i = 0; i < modesCount; i++) {
1440 jMediaType = (jstring)env->GetObjectArrayElement(jMediaTypesArray, i);
1441 mediaType = env->GetStringUTFChars(jMediaType, nullptr);
1442 bool found = false;
1443 for (auto j = 0; j < outCount; j++) {
1444 if (strcmp(outMediaTypes[j].mMediaType, mediaType) == 0) {
1445 found = true;
1446 if (outMediaTypes[j].mMode != modesArray[i]) {
1447 errorLogs.append(StringFormat("For mediaType %s, supported modes got is "
1448 "%d, expected %d \n",
1449 mediaType, outMediaTypes[j].mMode,
1450 modesArray[i]));
1451 goto CleanUp;
1452 }
1453 }
1454 }
1455 if (!found) {
1456 errorLogs.append(
1457 StringFormat("no entry seen for mediaType %s.\nAvailable entries are : ",
1458 mediaType));
1459 for (auto j = 0; j < outCount; j++) {
1460 errorLogs.append(StringFormat("%s, ", outMediaTypes[j].mMediaType));
1461 }
1462 goto CleanUp;
1463 }
1464 env->ReleaseStringUTFChars(jMediaType, mediaType);
1465 mediaType = nullptr;
1466 }
1467 isPass = true;
1468 CleanUp:
1469 std::string msg = isPass ? std::string{} : errorLogs;
1470 env->ReleaseIntArrayElements(jModesArray, modesArray, 0);
1471 if (mediaType) env->ReleaseStringUTFChars(jMediaType, mediaType);
1472 jclass clazz = env->GetObjectClass(jRetMsg);
1473 jmethodID mId =
1474 env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1475 env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
1476 }
1477 return static_cast<jboolean>(isPass);
1478 }
1479
nativeTestAMediaCodecStoreGetNextCodecsForFormat(JNIEnv * env,jobject,jstring jFormatString,jstring jFormatSeparator,jobjectArray jCodecs,jboolean isEncoder,jobject jRetMsg)1480 jboolean nativeTestAMediaCodecStoreGetNextCodecsForFormat(JNIEnv* env, jobject,
1481 jstring jFormatString,
1482 jstring jFormatSeparator,
1483 jobjectArray jCodecs, jboolean isEncoder,
1484 jobject jRetMsg) {
1485 bool isPass = false;
1486 if (__builtin_available(android 36, *)) {
1487 media_status_t (*func)(const AMediaFormat* format, const AMediaCodecInfo** outCodecInfo);
1488 func = isEncoder ? AMediaCodecStore_findNextEncoderForFormat
1489 : AMediaCodecStore_findNextDecoderForFormat;
1490 const char* label = isEncoder ? "AMediaCodecStore_findNextEncoderForFormat"
1491 : "AMediaCodecStore_findNextDecoderForFormat";
1492 std::string errorLogs;
1493 const AMediaCodecInfo* outCodecInfo;
1494 std::vector<const char*> codecs;
1495 media_status_t status;
1496 AMediaFormat* format = nullptr;
1497 const char* formatString = nullptr;
1498 const char* formatSeparator = nullptr;
1499 const char* formatStringBeautify = "null format";
1500 if (jFormatString != nullptr) {
1501 formatString = env->GetStringUTFChars(jFormatString, nullptr);
1502 }
1503 if (jFormatSeparator != nullptr) {
1504 formatSeparator = env->GetStringUTFChars(jFormatSeparator, nullptr);
1505 }
1506 if (formatString && formatSeparator) {
1507 format = deSerializeMediaFormat(formatString, formatSeparator);
1508 formatStringBeautify = AMediaFormat_toString(format);
1509 }
1510 jsize codecsCount = env->GetArrayLength(jCodecs);
1511 jstring jCodec;
1512 const char* codec = nullptr;
1513 status = func(format, nullptr);
1514 if (status != AMEDIA_ERROR_INVALID_PARAMETER) {
1515 errorLogs.append(StringFormat("For invalid args, %s returned %d, expected "
1516 "AMEDIA_ERROR_INVALID_PARAMETER\n",
1517 label, status));
1518 goto CleanUp;
1519 }
1520 outCodecInfo = nullptr;
1521 if (format != nullptr) {
1522 AMediaFormat* formatDup = AMediaFormat_new();
1523 AMediaFormat_clear(formatDup);
1524 status = func(formatDup, &outCodecInfo);
1525 AMediaFormat_delete(formatDup);
1526 if (status != AMEDIA_ERROR_INVALID_PARAMETER) {
1527 if (outCodecInfo != nullptr) {
1528 errorLogs.append(
1529 StringFormat("%s returned %d but format does not have key - 'mime'. "
1530 "expected AMEDIA_ERROR_INVALID_PARAMETER \n",
1531 label, status));
1532 goto CleanUp;
1533 }
1534 }
1535 }
1536 while (1) {
1537 status = func(format, &outCodecInfo);
1538 if (status == AMEDIA_OK) {
1539 if (outCodecInfo == nullptr) {
1540 errorLogs.append(StringFormat("%s returned AMEDIA_OK but outCodecInfo is "
1541 "pointing to nullptr \n",
1542 label));
1543 goto CleanUp;
1544 }
1545 codecs.push_back(AMediaCodecInfo_getCanonicalName(outCodecInfo));
1546 } else if (status == AMEDIA_ERROR_UNSUPPORTED) {
1547 if (outCodecInfo != nullptr) {
1548 errorLogs.append(StringFormat("%s returned AMEDIA_ERROR_UNSUPPORTED but "
1549 "outCodecInfo is not pointing to nullptr \n",
1550 label));
1551 goto CleanUp;
1552 }
1553 break;
1554 }
1555 }
1556 if (codecs.size() != codecsCount) {
1557 errorLogs.append(StringFormat("For format %s codecs %d supported, expected %d\n",
1558 formatStringBeautify, codecs.size(), codecsCount));
1559 goto CleanUp;
1560 }
1561 for (auto i = 0; i < codecsCount; i++) {
1562 jCodec = (jstring)env->GetObjectArrayElement(jCodecs, i);
1563 codec = env->GetStringUTFChars(jCodec, nullptr);
1564 bool found = false;
1565 for (auto j = 0; j < codecs.size(); j++) {
1566 if (strcmp(codecs[j], codec) == 0) {
1567 found = true;
1568 break;
1569 }
1570 }
1571 if (!found) {
1572 errorLogs.append(StringFormat("For format %s, sdk indicates %s is supported, but "
1573 "ndk indicates otherwise. List of ndk entries, \n",
1574 formatStringBeautify, codec));
1575 for (auto j = 0; j < codecs.size(); j++) {
1576 errorLogs.append(StringFormat("%s, ", codecs[i]));
1577 }
1578 goto CleanUp;
1579 }
1580 env->ReleaseStringUTFChars(jCodec, codec);
1581 codec = nullptr;
1582 }
1583 isPass = true;
1584 CleanUp:
1585 std::string msg = isPass ? std::string{} : errorLogs;
1586 if (formatString) env->ReleaseStringUTFChars(jFormatString, formatString);
1587 if (formatSeparator) env->ReleaseStringUTFChars(jFormatSeparator, formatSeparator);
1588 if (format) AMediaFormat_delete(format);
1589 if (codec) env->ReleaseStringUTFChars(jCodec, codec);
1590 jclass clazz = env->GetObjectClass(jRetMsg);
1591 jmethodID mId =
1592 env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1593 env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
1594 }
1595 return static_cast<jboolean>(isPass);
1596 }
1597
nativeTestAMediaCodecStoreGetCodecInfo(JNIEnv * env,jobject,jobject retMsg)1598 jboolean nativeTestAMediaCodecStoreGetCodecInfo(JNIEnv* env, jobject, jobject retMsg) {
1599 bool isPass = false;
1600 if (__builtin_available(android 36, *)) {
1601 std::string errorLogs;
1602 media_status_t status;
1603 const AMediaCodecInfo* outCodecInfo = nullptr;
1604 status = AMediaCodecStore_getCodecInfo(nullptr, nullptr);
1605 if (AMEDIA_ERROR_INVALID_PARAMETER != status) {
1606 errorLogs.append(StringFormat("For null parameters, returned %d, expected "
1607 "AMEDIA_ERROR_INVALID_PARAMETER\n",
1608 status));
1609 goto CleanUp;
1610 }
1611 status = AMediaCodecStore_getCodecInfo(nullptr, &outCodecInfo);
1612 if (AMEDIA_ERROR_INVALID_PARAMETER != status) {
1613 errorLogs.append(StringFormat("For null name parameter, returned %d, expected "
1614 "AMEDIA_ERROR_INVALID_PARAMETER\n",
1615 status));
1616 goto CleanUp;
1617 }
1618 status = AMediaCodecStore_getCodecInfo("c2.android.avc.decoder", nullptr);
1619 if (AMEDIA_ERROR_INVALID_PARAMETER != status) {
1620 errorLogs.append(StringFormat("For null output parameter, returned %d, expected "
1621 "AMEDIA_ERROR_INVALID_PARAMETER\n",
1622 status));
1623 goto CleanUp;
1624 }
1625 status = AMediaCodecStore_getCodecInfo("non.existent.codec", &outCodecInfo);
1626 if (AMEDIA_ERROR_UNSUPPORTED != status) {
1627 errorLogs.append(StringFormat("For non-existent codec, returned %d, expected "
1628 "AMEDIA_ERROR_UNSUPPORTED\n",
1629 status));
1630 goto CleanUp;
1631 }
1632 if (outCodecInfo != nullptr) {
1633 errorLogs.append("CodecInfo should be null for non-existent codec\n");
1634 goto CleanUp;
1635 }
1636 isPass = true;
1637 CleanUp:
1638 std::string msg = isPass ? std::string{} : errorLogs;
1639 jstring jErrorMsg = env->NewStringUTF(errorLogs.c_str());
1640 jclass clazz = env->GetObjectClass(retMsg);
1641 jmethodID mId =
1642 env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
1643 env->CallObjectMethod(retMsg, mId, jErrorMsg);
1644 env->DeleteLocalRef(jErrorMsg);
1645 }
1646 return static_cast<jboolean>(isPass);
1647 }
1648
registerAndroidMediaV2CtsNativeMediaCodecInfoUnitTest(JNIEnv * env)1649 int registerAndroidMediaV2CtsNativeMediaCodecInfoUnitTest(JNIEnv* env) {
1650 const JNINativeMethod methodTable[] = {
1651 {"nativeTestAMediaCodecInfo",
1652 "(Ljava/lang/String;ZIZLjava/lang/String;IILjava/lang/String;[Ljava/lang/"
1653 "String;II[Ljava/lang/String;[ZLjava/lang/StringBuilder;)Z",
1654 (void*)nativeTestAMediaCodecInfo},
1655 {"nativeTestAMediaCodecInfoVideoCaps",
1656 "(Ljava/lang/String;IIIIIIIIIILjava/lang/StringBuilder;)Z",
1657 (void*)nativeTestAMediaCodecInfoVideoCaps},
1658 {"nativeTestAMediaCodecInfoVideoCapsGetSupportFor",
1659 "(Ljava/lang/String;IIDIIIIDDDDZZLjava/lang/StringBuilder;)Z",
1660 (void*)nativeTestAMediaCodecInfoVideoCapsGetSupportFor},
1661 {"nativeTestACodecPerformancePoint",
1662 "(Ljava/lang/String;IIDIIIILjava/lang/StringBuilder;)Z",
1663 (void*)nativeTestACodecPerformancePoint},
1664 {"nativeTestAMediaCodecInfoGetAudioCapabilities",
1665 "(Ljava/lang/String;IIII[I[I[I[IILjava/lang/StringBuilder;)Z",
1666 (void*)nativeTestAMediaCodecInfoGetAudioCapabilities},
1667 {"nativeTestAMediaCodecInfoGetEncoderCapabilities",
1668 "(Ljava/lang/String;IIIIILjava/lang/StringBuilder;)Z",
1669 (void*)nativeTestAMediaCodecInfoGetEncoderCapabilities},
1670 };
1671 jclass c = env->FindClass("android/mediav2/cts/NativeAMediaCodecInfoTest");
1672 return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
1673 }
1674
registerAndroidMediaV2CtsNativeMediaCodecStoreUnitTest(JNIEnv * env)1675 int registerAndroidMediaV2CtsNativeMediaCodecStoreUnitTest(JNIEnv* env) {
1676 const JNINativeMethod methodTable[] = {
1677 {"nativeTestAMediaCodecStoreGetSupportedTypes",
1678 "([Ljava/lang/String;[ILjava/lang/StringBuilder;)Z",
1679 (void*)nativeTestAMediaCodecStoreGetSupportedTypes},
1680 {"nativeTestAMediaCodecStoreGetNextCodecsForFormat",
1681 "(Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;ZLjava/lang/StringBuilder;)Z",
1682 (void*)nativeTestAMediaCodecStoreGetNextCodecsForFormat},
1683 {"nativeTestAMediaCodecStoreGetCodecInfo", "(Ljava/lang/StringBuilder;)Z",
1684 (void*)nativeTestAMediaCodecStoreGetCodecInfo},
1685 };
1686 jclass c = env->FindClass("android/mediav2/cts/NativeAMediaCodecStoreTest");
1687 return env->RegisterNatives(c, methodTable, sizeof(methodTable) / sizeof(JNINativeMethod));
1688 }
1689
JNI_OnLoad(JavaVM * vm,void *)1690 extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
1691 JNIEnv* env;
1692 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) return JNI_ERR;
1693 if (registerAndroidMediaV2CtsNativeMediaCodecInfoUnitTest(env) != JNI_OK) return JNI_ERR;
1694 if (registerAndroidMediaV2CtsNativeMediaCodecStoreUnitTest(env) != JNI_OK) return JNI_ERR;
1695 return JNI_VERSION_1_6;
1696 }
1697