• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#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