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 "NdkMediaCodecInfo"
19
20 #include "NdkMediaCodecInfoPriv.h"
21
22 #include <media/NdkMediaFormatPriv.h>
23
24 using namespace android;
25
26 extern "C" {
27
28 // Utils
29
30 EXPORT
AIntRange_delete(AIntRange * range)31 void AIntRange_delete(AIntRange *range) {
32 free(range);
33 }
34
35 EXPORT
ADoubleRange_delete(ADoubleRange * range)36 void ADoubleRange_delete(ADoubleRange *range) {
37 free(range);
38 }
39
40 // AMediaCodecInfo
41
42 EXPORT
AMediaCodecInfo_getCanonicalName(const AMediaCodecInfo * info)43 const char* AMediaCodecInfo_getCanonicalName(const AMediaCodecInfo *info) {
44 if (info == nullptr || info->mInfo == nullptr) {
45 return nullptr;
46 }
47
48 return info->mInfo->getCodecName();
49 }
50
51 EXPORT
AMediaCodecInfo_isEncoder(const AMediaCodecInfo * info)52 bool AMediaCodecInfo_isEncoder(const AMediaCodecInfo *info) {
53 return info->mInfo->isEncoder();
54 }
55
56 EXPORT
AMediaCodecInfo_isVendor(const AMediaCodecInfo * info)57 bool AMediaCodecInfo_isVendor(const AMediaCodecInfo *info) {
58 int32_t attributes = info->mInfo->getAttributes();
59 return (attributes & android::MediaCodecInfo::kFlagIsVendor);
60 }
61
62 EXPORT
AMediaCodecInfo_getMediaCodecInfoType(const AMediaCodecInfo * info)63 AMediaCodecType AMediaCodecInfo_getMediaCodecInfoType(const AMediaCodecInfo *info) {
64 if (info == nullptr || info->mInfo == nullptr) {
65 return (AMediaCodecType)0;
66 }
67
68 int32_t attributes = info->mInfo->getAttributes();
69
70 if (attributes & android::MediaCodecInfo::kFlagIsSoftwareOnly) {
71 return SOFTWARE_ONLY;
72 }
73 if (attributes & android::MediaCodecInfo::kFlagIsHardwareAccelerated) {
74 return HARDWARE_ACCELERATED;
75 }
76 return SOFTWARE_WITH_DEVICE_ACCESS;
77 }
78
79 EXPORT
AMediaCodecInfo_getMediaType(const AMediaCodecInfo * info)80 const char* AMediaCodecInfo_getMediaType(const AMediaCodecInfo *info) {
81 if (info == nullptr || info->mInfo == nullptr) {
82 return nullptr;
83 }
84
85 return info->mMediaType.c_str();
86 }
87
88 EXPORT
AMediaCodecInfo_getMaxSupportedInstances(const AMediaCodecInfo * info)89 int32_t AMediaCodecInfo_getMaxSupportedInstances(const AMediaCodecInfo *info) {
90 if (info == nullptr) {
91 return -1;
92 }
93
94 return info->mCodecCaps->getMaxSupportedInstances();
95 }
96
97 EXPORT
AMediaCodecInfo_isFeatureSupported(const AMediaCodecInfo * info,const char * featureName)98 int32_t AMediaCodecInfo_isFeatureSupported(const AMediaCodecInfo *info, const char *featureName) {
99 if (featureName == nullptr) {
100 return -1;
101 }
102 return info->mCodecCaps->isFeatureSupported(std::string(featureName));
103 }
104
105 EXPORT
AMediaCodecInfo_isFeatureRequired(const AMediaCodecInfo * info,const char * featureName)106 int32_t AMediaCodecInfo_isFeatureRequired(const AMediaCodecInfo *info, const char *featureName) {
107 if (featureName == nullptr) {
108 return -1;
109 }
110 return info->mCodecCaps->isFeatureRequired(std::string(featureName));
111 }
112
113 EXPORT
AMediaCodecInfo_isFormatSupported(const AMediaCodecInfo * info,const AMediaFormat * format)114 int32_t AMediaCodecInfo_isFormatSupported(const AMediaCodecInfo *info, const AMediaFormat *format) {
115 if (format == nullptr) {
116 return -1;
117 }
118
119 sp<AMessage> nativeFormat;
120 AMediaFormat_getFormat(format, &nativeFormat);
121
122 return info->mCodecCaps->isFormatSupported(nativeFormat);
123 }
124
125 EXPORT
AMediaCodecInfo_getAudioCapabilities(const AMediaCodecInfo * info,const ACodecAudioCapabilities ** outAudioCaps)126 media_status_t AMediaCodecInfo_getAudioCapabilities(const AMediaCodecInfo *info,
127 const ACodecAudioCapabilities **outAudioCaps) {
128 if (info == nullptr || info->mInfo == nullptr) {
129 return AMEDIA_ERROR_INVALID_PARAMETER;
130 }
131
132 *outAudioCaps = info->mAAudioCaps.get();
133
134 if ((*outAudioCaps) == nullptr) {
135 return AMEDIA_ERROR_UNSUPPORTED;
136 }
137
138 return AMEDIA_OK;
139 }
140
141 EXPORT
AMediaCodecInfo_getVideoCapabilities(const AMediaCodecInfo * info,const ACodecVideoCapabilities ** outVideoCaps)142 media_status_t AMediaCodecInfo_getVideoCapabilities(const AMediaCodecInfo *info,
143 const ACodecVideoCapabilities **outVideoCaps) {
144 if (info == nullptr || info->mInfo == nullptr) {
145 return AMEDIA_ERROR_INVALID_PARAMETER;
146 }
147
148 *outVideoCaps = info->mAVideoCaps.get();
149
150 if ((*outVideoCaps) == nullptr) {
151 return AMEDIA_ERROR_UNSUPPORTED;
152 }
153
154 return AMEDIA_OK;
155 }
156
157 EXPORT
AMediaCodecInfo_getEncoderCapabilities(const AMediaCodecInfo * info,const ACodecEncoderCapabilities ** outEncoderCaps)158 media_status_t AMediaCodecInfo_getEncoderCapabilities(const AMediaCodecInfo *info,
159 const ACodecEncoderCapabilities **outEncoderCaps) {
160 if (info == nullptr || info->mInfo == nullptr) {
161 return AMEDIA_ERROR_INVALID_PARAMETER;
162 }
163
164 *outEncoderCaps = info->mAEncoderCaps.get();
165
166 if ((*outEncoderCaps) == nullptr) {
167 return AMEDIA_ERROR_UNSUPPORTED;
168 }
169
170 return AMEDIA_OK;
171 }
172
173 // ACodecAudioCapabilities
174
175 EXPORT
ACodecAudioCapabilities_getBitrateRange(const ACodecAudioCapabilities * audioCaps,AIntRange * outRange)176 media_status_t ACodecAudioCapabilities_getBitrateRange(const ACodecAudioCapabilities *audioCaps,
177 AIntRange *outRange) {
178 if (audioCaps == nullptr || outRange == nullptr) {
179 return AMEDIA_ERROR_INVALID_PARAMETER;
180 }
181
182 const Range<int32_t>& bitrateRange = audioCaps->mAudioCaps->getBitrateRange();
183 outRange->mLower = bitrateRange.lower();
184 outRange->mUpper = bitrateRange.upper();
185
186 return AMEDIA_OK;
187 }
188
189 EXPORT
ACodecAudioCapabilities_getSupportedSampleRates(const ACodecAudioCapabilities * audioCaps,const int ** outArrayPtr,size_t * outCount)190 media_status_t ACodecAudioCapabilities_getSupportedSampleRates(
191 const ACodecAudioCapabilities *audioCaps, const int **outArrayPtr, size_t *outCount) {
192 if (audioCaps == nullptr || outArrayPtr == nullptr || outCount == nullptr) {
193 return AMEDIA_ERROR_INVALID_PARAMETER;
194 }
195
196 if (audioCaps->mSampleRates.empty()) {
197 return AMEDIA_ERROR_UNSUPPORTED;
198 }
199
200 *outArrayPtr = audioCaps->mSampleRates.data();
201 *outCount = audioCaps->mSampleRates.size();
202
203 return AMEDIA_OK;
204 }
205
206 EXPORT
ACodecAudioCapabilities_getSupportedSampleRateRanges(const ACodecAudioCapabilities * audioCaps,const AIntRange ** outArrayPtr,size_t * outCount)207 media_status_t ACodecAudioCapabilities_getSupportedSampleRateRanges(
208 const ACodecAudioCapabilities *audioCaps, const AIntRange **outArrayPtr, size_t *outCount) {
209 if (audioCaps == nullptr || outArrayPtr == nullptr || outCount == nullptr) {
210 return AMEDIA_ERROR_INVALID_PARAMETER;
211 }
212
213 *outArrayPtr = audioCaps->mSampleRateRanges.data();
214 *outCount = audioCaps->mSampleRateRanges.size();
215
216 return AMEDIA_OK;
217 }
218
219 EXPORT
ACodecAudioCapabilities_getMaxInputChannelCount(const ACodecAudioCapabilities * audioCaps)220 int32_t ACodecAudioCapabilities_getMaxInputChannelCount(const ACodecAudioCapabilities *audioCaps) {
221 if (audioCaps == nullptr) {
222 return -1;
223 }
224 return audioCaps->mAudioCaps->getMaxInputChannelCount();
225 }
226
227 EXPORT
ACodecAudioCapabilities_getMinInputChannelCount(const ACodecAudioCapabilities * audioCaps)228 int32_t ACodecAudioCapabilities_getMinInputChannelCount(const ACodecAudioCapabilities *audioCaps) {
229 if (audioCaps == nullptr) {
230 return -1;
231 }
232 return audioCaps->mAudioCaps->getMinInputChannelCount();
233 }
234
235 EXPORT
ACodecAudioCapabilities_getInputChannelCountRanges(const ACodecAudioCapabilities * audioCaps,const AIntRange ** outArrayPtr,size_t * outCount)236 media_status_t ACodecAudioCapabilities_getInputChannelCountRanges(
237 const ACodecAudioCapabilities *audioCaps, const AIntRange **outArrayPtr, size_t *outCount) {
238 if (audioCaps == nullptr || outArrayPtr == nullptr || outCount == nullptr) {
239 return AMEDIA_ERROR_INVALID_PARAMETER;
240 }
241
242 *outArrayPtr = audioCaps->mInputChannelCountRanges.data();
243 *outCount = audioCaps->mInputChannelCountRanges.size();
244
245 return AMEDIA_OK;
246 }
247
248 EXPORT
ACodecAudioCapabilities_isSampleRateSupported(const ACodecAudioCapabilities * audioCaps,int32_t sampleRate)249 int32_t ACodecAudioCapabilities_isSampleRateSupported(const ACodecAudioCapabilities *audioCaps,
250 int32_t sampleRate) {
251 if (audioCaps == nullptr) {
252 return -1;
253 }
254 return audioCaps->mAudioCaps->isSampleRateSupported(sampleRate);
255 }
256
257 // ACodecPerformancePoint
258
259 EXPORT
ACodecPerformancePoint_create(int32_t width,int32_t height,int32_t frameRate)260 ACodecPerformancePoint* ACodecPerformancePoint_create(int32_t width, int32_t height,
261 int32_t frameRate) {
262 return new ACodecPerformancePoint(
263 std::make_shared<VideoCapabilities::PerformancePoint>(width, height, frameRate));
264 }
265
266 EXPORT
ACodecPerformancePoint_delete(ACodecPerformancePoint * performancePoint)267 media_status_t ACodecPerformancePoint_delete(ACodecPerformancePoint *performancePoint) {
268 if (performancePoint == nullptr) {
269 return AMEDIA_ERROR_INVALID_PARAMETER;
270 }
271
272 delete performancePoint;
273
274 return AMEDIA_OK;
275 }
276
277 EXPORT
ACodecPerformancePoint_coversFormat(const ACodecPerformancePoint * performancePoint,const AMediaFormat * format)278 bool ACodecPerformancePoint_coversFormat(const ACodecPerformancePoint *performancePoint,
279 const AMediaFormat *format) {
280 sp<AMessage> nativeFormat;
281 AMediaFormat_getFormat(format, &nativeFormat);
282
283 return performancePoint->mPerformancePoint->covers(nativeFormat);
284 }
285
286 EXPORT
ACodecPerformancePoint_covers(const ACodecPerformancePoint * one,const ACodecPerformancePoint * another)287 bool ACodecPerformancePoint_covers(const ACodecPerformancePoint *one,
288 const ACodecPerformancePoint *another) {
289 return one->mPerformancePoint->covers(*(another->mPerformancePoint));
290 }
291
292 EXPORT
ACodecPerformancePoint_equals(const ACodecPerformancePoint * one,const ACodecPerformancePoint * another)293 bool ACodecPerformancePoint_equals(const ACodecPerformancePoint *one,
294 const ACodecPerformancePoint *another) {
295 return one->mPerformancePoint->equals(*(another->mPerformancePoint));
296 }
297
298 // ACodecVideoCapabilities
299
300 EXPORT
ACodecVideoCapabilities_getBitrateRange(const ACodecVideoCapabilities * videoCaps,AIntRange * outRange)301 media_status_t ACodecVideoCapabilities_getBitrateRange(const ACodecVideoCapabilities *videoCaps,
302 AIntRange *outRange) {
303 if (videoCaps == nullptr || outRange == nullptr) {
304 return AMEDIA_ERROR_INVALID_PARAMETER;
305 }
306
307 const Range<int32_t>& bitrateRange = videoCaps->mVideoCaps->getBitrateRange();
308 outRange->mLower = bitrateRange.lower();
309 outRange->mUpper = bitrateRange.upper();
310
311 return AMEDIA_OK;
312 }
313
314 EXPORT
ACodecVideoCapabilities_getSupportedWidths(const ACodecVideoCapabilities * videoCaps,AIntRange * outRange)315 media_status_t ACodecVideoCapabilities_getSupportedWidths(const ACodecVideoCapabilities *videoCaps,
316 AIntRange *outRange) {
317 if (videoCaps == nullptr || outRange == nullptr) {
318 return AMEDIA_ERROR_INVALID_PARAMETER;
319 }
320
321 const Range<int32_t>& supportedWidths = videoCaps->mVideoCaps->getSupportedWidths();
322 outRange->mLower = supportedWidths.lower();
323 outRange->mUpper = supportedWidths.upper();
324
325 return AMEDIA_OK;
326 }
327
328 EXPORT
ACodecVideoCapabilities_getSupportedHeights(const ACodecVideoCapabilities * videoCaps,AIntRange * outRange)329 media_status_t ACodecVideoCapabilities_getSupportedHeights(const ACodecVideoCapabilities *videoCaps,
330 AIntRange *outRange) {
331 if (videoCaps == nullptr || outRange == nullptr) {
332 return AMEDIA_ERROR_INVALID_PARAMETER;
333 }
334
335 const Range<int32_t>& supportedHeights = videoCaps->mVideoCaps->getSupportedHeights();
336 outRange->mLower = supportedHeights.lower();
337 outRange->mUpper = supportedHeights.upper();
338
339 return AMEDIA_OK;
340 }
341
342 EXPORT
ACodecVideoCapabilities_getWidthAlignment(const ACodecVideoCapabilities * videoCaps)343 int32_t ACodecVideoCapabilities_getWidthAlignment(const ACodecVideoCapabilities *videoCaps) {
344 if (videoCaps == nullptr) {
345 return -1;
346 }
347 return videoCaps->mVideoCaps->getWidthAlignment();
348 }
349
350 EXPORT
ACodecVideoCapabilities_getHeightAlignment(const ACodecVideoCapabilities * videoCaps)351 int32_t ACodecVideoCapabilities_getHeightAlignment(const ACodecVideoCapabilities *videoCaps) {
352 if (videoCaps == nullptr) {
353 return -1;
354 }
355 return videoCaps->mVideoCaps->getHeightAlignment();
356 }
357
358 EXPORT
ACodecVideoCapabilities_getSupportedFrameRates(const ACodecVideoCapabilities * videoCaps,AIntRange * outRange)359 media_status_t ACodecVideoCapabilities_getSupportedFrameRates(
360 const ACodecVideoCapabilities *videoCaps, AIntRange *outRange) {
361 if (videoCaps == nullptr || outRange == nullptr) {
362 return AMEDIA_ERROR_INVALID_PARAMETER;
363 }
364
365 const Range<int32_t>& frameRateRange = videoCaps->mVideoCaps->getSupportedFrameRates();
366 outRange->mLower = frameRateRange.lower();
367 outRange->mUpper = frameRateRange.upper();
368
369 return AMEDIA_OK;
370 }
371
372 EXPORT
ACodecVideoCapabilities_getSupportedWidthsFor(const ACodecVideoCapabilities * videoCaps,int32_t height,AIntRange * outRange)373 media_status_t ACodecVideoCapabilities_getSupportedWidthsFor(
374 const ACodecVideoCapabilities *videoCaps, int32_t height, AIntRange *outRange) {
375 if (videoCaps == nullptr || outRange == nullptr) {
376 return AMEDIA_ERROR_INVALID_PARAMETER;
377 }
378
379 std::optional<Range<int32_t>> widthRange = videoCaps->mVideoCaps->getSupportedWidthsFor(height);
380 if (!widthRange) {
381 return AMEDIA_ERROR_UNSUPPORTED;
382 }
383
384 outRange->mLower = widthRange.value().lower();
385 outRange->mUpper = widthRange.value().upper();
386
387 return AMEDIA_OK;
388 }
389
390 EXPORT
ACodecVideoCapabilities_getSupportedHeightsFor(const ACodecVideoCapabilities * videoCaps,int32_t width,AIntRange * outRange)391 media_status_t ACodecVideoCapabilities_getSupportedHeightsFor(
392 const ACodecVideoCapabilities *videoCaps, int32_t width, AIntRange *outRange) {
393 if (videoCaps == nullptr || outRange == nullptr) {
394 return AMEDIA_ERROR_INVALID_PARAMETER;
395 }
396
397 std::optional<Range<int32_t>> heightRange
398 = videoCaps->mVideoCaps->getSupportedHeightsFor(width);
399 if (!heightRange) {
400 return AMEDIA_ERROR_UNSUPPORTED;
401 }
402
403 outRange->mLower = heightRange.value().lower();
404 outRange->mUpper = heightRange.value().upper();
405
406 return AMEDIA_OK;
407 }
408
409 EXPORT
ACodecVideoCapabilities_getSupportedFrameRatesFor(const ACodecVideoCapabilities * videoCaps,int32_t width,int32_t height,ADoubleRange * outRange)410 media_status_t ACodecVideoCapabilities_getSupportedFrameRatesFor(
411 const ACodecVideoCapabilities *videoCaps, int32_t width, int32_t height,
412 ADoubleRange *outRange) {
413 if (videoCaps == nullptr || outRange == nullptr) {
414 return AMEDIA_ERROR_INVALID_PARAMETER;
415 }
416
417 std::optional<Range<double>> frameRates
418 = videoCaps->mVideoCaps->getSupportedFrameRatesFor(width, height);
419 if (!frameRates) {
420 return AMEDIA_ERROR_UNSUPPORTED;
421 }
422
423 outRange->mLower = frameRates.value().lower();
424 outRange->mUpper = frameRates.value().upper();
425
426 return AMEDIA_OK;
427 }
428
429 EXPORT
ACodecVideoCapabilities_getAchievableFrameRatesFor(const ACodecVideoCapabilities * videoCaps,int32_t width,int32_t height,ADoubleRange * outRange)430 media_status_t ACodecVideoCapabilities_getAchievableFrameRatesFor(
431 const ACodecVideoCapabilities *videoCaps, int32_t width, int32_t height,
432 ADoubleRange *outRange) {
433 if (videoCaps == nullptr || outRange == nullptr) {
434 return AMEDIA_ERROR_INVALID_PARAMETER;
435 }
436
437 std::optional<Range<double>> frameRates
438 = videoCaps->mVideoCaps->getAchievableFrameRatesFor(width, height);
439 if (!frameRates) {
440 return AMEDIA_ERROR_UNSUPPORTED;
441 }
442
443 outRange->mLower = frameRates.value().lower();
444 outRange->mUpper = frameRates.value().upper();
445
446 return AMEDIA_OK;
447 }
448
449 EXPORT
ACodecVideoCapabilities_getSupportedPerformancePoints(const ACodecVideoCapabilities * videoCaps,const ACodecPerformancePoint ** outPerformancePointArray,size_t * outCount)450 media_status_t ACodecVideoCapabilities_getSupportedPerformancePoints(
451 const ACodecVideoCapabilities *videoCaps,
452 const ACodecPerformancePoint **outPerformancePointArray, size_t *outCount) {
453 if (videoCaps == nullptr) {
454 return AMEDIA_ERROR_INVALID_PARAMETER;
455 }
456
457 *outPerformancePointArray = videoCaps->mPerformancePoints.data();
458 *outCount = videoCaps->mPerformancePoints.size();
459
460 return AMEDIA_OK;
461 }
462
463 EXPORT
ACodecVideoCapabilities_areSizeAndRateSupported(const ACodecVideoCapabilities * videoCaps,int32_t width,int32_t height,double frameRate)464 int32_t ACodecVideoCapabilities_areSizeAndRateSupported(const ACodecVideoCapabilities *videoCaps,
465 int32_t width, int32_t height, double frameRate) {
466 if (videoCaps == nullptr) {
467 return -1;
468 }
469 return videoCaps->mVideoCaps->areSizeAndRateSupported(width, height, frameRate);
470 }
471
472 EXPORT
ACodecVideoCapabilities_isSizeSupported(const ACodecVideoCapabilities * videoCaps,int32_t width,int32_t height)473 int32_t ACodecVideoCapabilities_isSizeSupported(const ACodecVideoCapabilities *videoCaps,
474 int32_t width, int32_t height) {
475 if (videoCaps == nullptr) {
476 return -1;
477 }
478 return videoCaps->mVideoCaps->isSizeSupported(width, height);
479 }
480
481 // ACodecEncoderCapabilities
482
483 EXPORT
ACodecEncoderCapabilities_getQualityRange(const ACodecEncoderCapabilities * encoderCaps,AIntRange * outRange)484 media_status_t ACodecEncoderCapabilities_getQualityRange(
485 const ACodecEncoderCapabilities *encoderCaps, AIntRange *outRange) {
486 if (encoderCaps == nullptr || outRange == nullptr) {
487 return AMEDIA_ERROR_INVALID_PARAMETER;
488 }
489
490 const Range<int32_t>& qualityRange = encoderCaps->mEncoderCaps->getQualityRange();
491 outRange->mLower = qualityRange.lower();
492 outRange->mUpper = qualityRange.upper();
493
494 return AMEDIA_OK;
495 }
496
497 EXPORT
ACodecEncoderCapabilities_getComplexityRange(const ACodecEncoderCapabilities * encoderCaps,AIntRange * outRange)498 media_status_t ACodecEncoderCapabilities_getComplexityRange(
499 const ACodecEncoderCapabilities *encoderCaps, AIntRange *outRange) {
500 if (encoderCaps == nullptr || outRange == nullptr) {
501 return AMEDIA_ERROR_INVALID_PARAMETER;
502 }
503
504 const Range<int32_t>& complexityRange = encoderCaps->mEncoderCaps->getComplexityRange();
505 outRange->mLower = complexityRange.lower();
506 outRange->mUpper = complexityRange.upper();
507
508 return AMEDIA_OK;
509 }
510
ACodecEncoderCapabilities_isBitrateModeSupported(const ACodecEncoderCapabilities * encoderCaps,ABiterateMode mode)511 int32_t ACodecEncoderCapabilities_isBitrateModeSupported(
512 const ACodecEncoderCapabilities *encoderCaps, ABiterateMode mode) {
513 if (encoderCaps == nullptr) {
514 return -1;
515 }
516 return encoderCaps->mEncoderCaps->isBitrateModeSupported(mode);
517 }
518
519
520 }