blob: 6f25cec405be2588e2af5053a9350c760c75149b [file] [log] [blame]
Marco Nelissen0c3be872014-05-01 10:14:44 -07001/*
2 * Copyright (C) 2014 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
Mark Salyzyn98f28cd2014-06-18 16:32:50 -070017#include <inttypes.h>
Ray Essicka49482a2022-03-12 13:52:24 -080018#include <mutex>
19#include <set>
Mark Salyzyn98f28cd2014-06-18 16:32:50 -070020
Marco Nelissenc7a11b22014-05-30 10:13:25 -070021//#define LOG_NDEBUG 0
Marco Nelissen0c3be872014-05-01 10:14:44 -070022#define LOG_TAG "NdkMediaCodec"
23
Chong Zhangefd1c5c2020-11-18 10:33:13 -080024#include <media/NdkMediaCodecPlatform.h>
Colin Cross7e8d4ba2017-05-04 16:17:42 -070025#include <media/NdkMediaError.h>
Marco Nelissen98603d82018-07-17 11:06:55 -070026#include <media/NdkMediaFormatPriv.h>
Marco Nelissen050eb322014-05-09 15:10:23 -070027#include "NdkMediaCryptoPriv.h"
Marco Nelissen0c3be872014-05-01 10:14:44 -070028
29#include <utils/Log.h>
30#include <utils/StrongPointer.h>
31#include <gui/Surface.h>
32
Marco Nelissen0c3be872014-05-01 10:14:44 -070033#include <media/stagefright/foundation/ALooper.h>
Jin Heo2665ce82021-09-10 17:20:00 +090034#include <media/stagefright/foundation/ABuffer.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070035#include <media/stagefright/foundation/AMessage.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070036
Praveen Chavan85a53632017-01-31 12:21:33 -080037#include <media/stagefright/PersistentSurface.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070038#include <media/stagefright/MediaCodec.h>
39#include <media/stagefright/MediaErrors.h>
Wonsik Kim7e34bf52016-08-23 00:09:18 +090040#include <media/MediaCodecBuffer.h>
Praveen Chavan19431582017-01-16 11:56:18 -080041#include <android/native_window.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070042
43using namespace android;
44
45
Marco Nelissene419d7c2014-05-15 14:17:25 -070046static media_status_t translate_error(status_t err) {
Ray Essicka49482a2022-03-12 13:52:24 -080047
Marco Nelissen0c3be872014-05-01 10:14:44 -070048 if (err == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -070049 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -070050 } else if (err == -EAGAIN) {
Marco Nelissene419d7c2014-05-15 14:17:25 -070051 return (media_status_t) AMEDIACODEC_INFO_TRY_AGAIN_LATER;
Chong Zhangeb9aca62020-09-16 12:49:41 -070052 } else if (err == NO_MEMORY) {
53 return AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE;
54 } else if (err == DEAD_OBJECT) {
55 return AMEDIACODEC_ERROR_RECLAIMED;
Marco Nelissen0c3be872014-05-01 10:14:44 -070056 }
Ray Essicka49482a2022-03-12 13:52:24 -080057
58 {
59 // minimize log flooding. Some CTS behavior made this noisy and apps could do the same.
60 static std::set<status_t> untranslated;
61 static std::mutex mutex;
62 std::lock_guard lg(mutex);
63
64 if (untranslated.find(err) == untranslated.end()) {
65 ALOGE("untranslated sf error code: %d", err);
66 untranslated.insert(err);
67 }
68 }
Marco Nelissene419d7c2014-05-15 14:17:25 -070069 return AMEDIA_ERROR_UNKNOWN;
Marco Nelissen0c3be872014-05-01 10:14:44 -070070}
71
Marco Nelissencdb42cd2014-05-08 14:46:05 -070072enum {
73 kWhatActivityNotify,
Wei Jia00cc9922017-11-23 08:00:34 -080074 kWhatAsyncNotify,
Marco Nelissencdb42cd2014-05-08 14:46:05 -070075 kWhatRequestActivityNotifications,
76 kWhatStopActivityNotifications,
Jin Heo2665ce82021-09-10 17:20:00 +090077 kWhatFrameRenderedNotify,
Marco Nelissen0c3be872014-05-01 10:14:44 -070078};
79
Praveen Chavan85a53632017-01-31 12:21:33 -080080struct AMediaCodecPersistentSurface : public Surface {
81 sp<PersistentSurface> mPersistentSurface;
82 AMediaCodecPersistentSurface(
83 const sp<IGraphicBufferProducer>& igbp,
84 const sp<PersistentSurface>& ps)
85 : Surface(igbp) {
86 mPersistentSurface = ps;
87 }
88 virtual ~AMediaCodecPersistentSurface() {
89 //mPersistentSurface ref will be let go off here
90 }
91};
Marco Nelissen0c3be872014-05-01 10:14:44 -070092
Marco Nelissencdb42cd2014-05-08 14:46:05 -070093class CodecHandler: public AHandler {
94private:
95 AMediaCodec* mCodec;
96public:
Chih-Hung Hsieh090ef602016-04-27 10:39:54 -070097 explicit CodecHandler(AMediaCodec *codec);
Marco Nelissencdb42cd2014-05-08 14:46:05 -070098 virtual void onMessageReceived(const sp<AMessage> &msg);
99};
Marco Nelissen0c3be872014-05-01 10:14:44 -0700100
Marco Nelissene22a64b2014-05-23 15:49:49 -0700101typedef void (*OnCodecEvent)(AMediaCodec *codec, void *userdata);
102
Marco Nelissen0c3be872014-05-01 10:14:44 -0700103struct AMediaCodec {
104 sp<android::MediaCodec> mCodec;
105 sp<ALooper> mLooper;
106 sp<CodecHandler> mHandler;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700107 sp<AMessage> mActivityNotification;
108 int32_t mGeneration;
109 bool mRequestedActivityNotification;
110 OnCodecEvent mCallback;
111 void *mCallbackUserData;
Wei Jia00cc9922017-11-23 08:00:34 -0800112
113 sp<AMessage> mAsyncNotify;
114 mutable Mutex mAsyncCallbackLock;
115 AMediaCodecOnAsyncNotifyCallback mAsyncCallback;
116 void *mAsyncCallbackUserData;
Jin Heo2665ce82021-09-10 17:20:00 +0900117
118 sp<AMessage> mFrameRenderedNotify;
119 mutable Mutex mFrameRenderedCallbackLock;
120 AMediaCodecOnFrameRendered mFrameRenderedCallback;
121 void *mFrameRenderedCallbackUserData;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700122};
123
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700124CodecHandler::CodecHandler(AMediaCodec *codec) {
125 mCodec = codec;
126}
127
128void CodecHandler::onMessageReceived(const sp<AMessage> &msg) {
129
130 switch (msg->what()) {
131 case kWhatRequestActivityNotifications:
132 {
133 if (mCodec->mRequestedActivityNotification) {
134 break;
135 }
136
137 mCodec->mCodec->requestActivityNotification(mCodec->mActivityNotification);
138 mCodec->mRequestedActivityNotification = true;
139 break;
140 }
141
142 case kWhatActivityNotify:
143 {
144 {
145 int32_t generation;
146 msg->findInt32("generation", &generation);
147
148 if (generation != mCodec->mGeneration) {
149 // stale
150 break;
151 }
152
153 mCodec->mRequestedActivityNotification = false;
154 }
155
156 if (mCodec->mCallback) {
157 mCodec->mCallback(mCodec, mCodec->mCallbackUserData);
158 }
159 break;
160 }
161
Wei Jia00cc9922017-11-23 08:00:34 -0800162 case kWhatAsyncNotify:
163 {
164 int32_t cbID;
165 if (!msg->findInt32("callbackID", &cbID)) {
166 ALOGE("kWhatAsyncNotify: callbackID is expected.");
167 break;
168 }
169
170 ALOGV("kWhatAsyncNotify: cbID = %d", cbID);
171
172 switch (cbID) {
173 case MediaCodec::CB_INPUT_AVAILABLE:
174 {
175 int32_t index;
176 if (!msg->findInt32("index", &index)) {
177 ALOGE("CB_INPUT_AVAILABLE: index is expected.");
178 break;
179 }
180
181 Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700182 if (mCodec->mAsyncCallback.onAsyncInputAvailable != NULL) {
Wei Jia00cc9922017-11-23 08:00:34 -0800183 mCodec->mAsyncCallback.onAsyncInputAvailable(
184 mCodec,
185 mCodec->mAsyncCallbackUserData,
186 index);
187 }
188
189 break;
190 }
191
192 case MediaCodec::CB_OUTPUT_AVAILABLE:
193 {
194 int32_t index;
195 size_t offset;
196 size_t size;
197 int64_t timeUs;
198 int32_t flags;
199
200 if (!msg->findInt32("index", &index)) {
201 ALOGE("CB_OUTPUT_AVAILABLE: index is expected.");
202 break;
203 }
204 if (!msg->findSize("offset", &offset)) {
205 ALOGE("CB_OUTPUT_AVAILABLE: offset is expected.");
206 break;
207 }
208 if (!msg->findSize("size", &size)) {
209 ALOGE("CB_OUTPUT_AVAILABLE: size is expected.");
210 break;
211 }
212 if (!msg->findInt64("timeUs", &timeUs)) {
213 ALOGE("CB_OUTPUT_AVAILABLE: timeUs is expected.");
214 break;
215 }
216 if (!msg->findInt32("flags", &flags)) {
217 ALOGE("CB_OUTPUT_AVAILABLE: flags is expected.");
218 break;
219 }
220
221 AMediaCodecBufferInfo bufferInfo = {
222 (int32_t)offset,
223 (int32_t)size,
224 timeUs,
225 (uint32_t)flags};
226
227 Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700228 if (mCodec->mAsyncCallback.onAsyncOutputAvailable != NULL) {
Wei Jia00cc9922017-11-23 08:00:34 -0800229 mCodec->mAsyncCallback.onAsyncOutputAvailable(
230 mCodec,
231 mCodec->mAsyncCallbackUserData,
232 index,
233 &bufferInfo);
234 }
235
236 break;
237 }
238
239 case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
240 {
241 sp<AMessage> format;
242 if (!msg->findMessage("format", &format)) {
243 ALOGE("CB_OUTPUT_FORMAT_CHANGED: format is expected.");
244 break;
245 }
246
Chong Zhang1fa26862019-09-16 16:15:00 -0700247 // Here format is MediaCodec's internal copy of output format.
248 // Make a copy since the client might modify it.
249 sp<AMessage> copy;
250 if (format != nullptr) {
251 copy = format->dup();
252 }
253 AMediaFormat *aMediaFormat = AMediaFormat_fromMsg(&copy);
Wei Jia00cc9922017-11-23 08:00:34 -0800254
255 Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700256 if (mCodec->mAsyncCallback.onAsyncFormatChanged != NULL) {
Wei Jia00cc9922017-11-23 08:00:34 -0800257 mCodec->mAsyncCallback.onAsyncFormatChanged(
258 mCodec,
259 mCodec->mAsyncCallbackUserData,
260 aMediaFormat);
261 }
262
263 break;
264 }
265
266 case MediaCodec::CB_ERROR:
267 {
268 status_t err;
269 int32_t actionCode;
270 AString detail;
271 if (!msg->findInt32("err", &err)) {
272 ALOGE("CB_ERROR: err is expected.");
273 break;
274 }
Rakesh Kumard5ea3f32019-09-20 17:08:07 +0530275 if (!msg->findInt32("actionCode", &actionCode)) {
276 ALOGE("CB_ERROR: actionCode is expected.");
Wei Jia00cc9922017-11-23 08:00:34 -0800277 break;
278 }
279 msg->findString("detail", &detail);
Chong Zhangeb9aca62020-09-16 12:49:41 -0700280 ALOGE("Codec reported error(0x%x), actionCode(%d), detail(%s)",
Wei Jia00cc9922017-11-23 08:00:34 -0800281 err, actionCode, detail.c_str());
282
283 Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700284 if (mCodec->mAsyncCallback.onAsyncError != NULL) {
Wei Jia00cc9922017-11-23 08:00:34 -0800285 mCodec->mAsyncCallback.onAsyncError(
286 mCodec,
287 mCodec->mAsyncCallbackUserData,
288 translate_error(err),
289 actionCode,
290 detail.c_str());
291 }
292
293 break;
294 }
295
296 default:
297 {
298 ALOGE("kWhatAsyncNotify: callbackID(%d) is unexpected.", cbID);
299 break;
300 }
301 }
302 break;
303 }
304
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700305 case kWhatStopActivityNotifications:
306 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800307 sp<AReplyToken> replyID;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700308 msg->senderAwaitsResponse(&replyID);
309
310 mCodec->mGeneration++;
311 mCodec->mRequestedActivityNotification = false;
312
313 sp<AMessage> response = new AMessage;
314 response->postReply(replyID);
315 break;
316 }
317
Jin Heo2665ce82021-09-10 17:20:00 +0900318 case kWhatFrameRenderedNotify:
319 {
320 sp<AMessage> data;
321 if (!msg->findMessage("data", &data)) {
322 ALOGE("kWhatFrameRenderedNotify: data is expected.");
323 break;
324 }
325
326 AMessage::Type type;
327 int64_t mediaTimeUs, systemNano;
328 size_t index = 0;
329
330 // TODO. This code has dependency with MediaCodec::CreateFramesRenderedMessage.
331 for (size_t ix = 0; ix < data->countEntries(); ix++) {
332 AString name = data->getEntryNameAt(ix, &type);
333 if (name.startsWith(AStringPrintf("%zu-media-time-us", index).c_str())) {
334 AMessage::ItemData data = msg->getEntryAt(index);
335 data.find(&mediaTimeUs);
336 } else if (name.startsWith(AStringPrintf("%zu-system-nano", index).c_str())) {
337 AMessage::ItemData data = msg->getEntryAt(index);
338 data.find(&systemNano);
339
340 Mutex::Autolock _l(mCodec->mFrameRenderedCallbackLock);
341 if (mCodec->mFrameRenderedCallback != NULL) {
342 mCodec->mFrameRenderedCallback(
343 mCodec,
344 mCodec->mFrameRenderedCallbackUserData,
345 mediaTimeUs,
346 systemNano);
347 }
348
349 index++;
350 }
351 }
352 break;
353 }
354
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700355 default:
356 ALOGE("shouldn't be here");
357 break;
358 }
359
360}
361
362
363static void requestActivityNotification(AMediaCodec *codec) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800364 (new AMessage(kWhatRequestActivityNotifications, codec->mHandler))->post();
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700365}
366
Marco Nelissen0c3be872014-05-01 10:14:44 -0700367extern "C" {
368
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800369static AMediaCodec * createAMediaCodec(const char *name,
370 bool name_is_type,
371 bool encoder,
372 pid_t pid = android::MediaCodec::kNoPid,
373 uid_t uid = android::MediaCodec::kNoUid) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700374 AMediaCodec *mData = new AMediaCodec();
375 mData->mLooper = new ALooper;
376 mData->mLooper->setName("NDK MediaCodec_looper");
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800377 size_t res = mData->mLooper->start(
Marco Nelissen0c3be872014-05-01 10:14:44 -0700378 false, // runOnCallingThread
379 true, // canCallJava XXX
Wei Jia00cc9922017-11-23 08:00:34 -0800380 PRIORITY_AUDIO);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800381 if (res != OK) {
382 ALOGE("Failed to start the looper");
Greg Kaiser4e147802016-03-14 14:44:20 -0700383 AMediaCodec_delete(mData);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800384 return NULL;
385 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700386 if (name_is_type) {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800387 mData->mCodec = android::MediaCodec::CreateByType(
388 mData->mLooper,
389 name,
390 encoder,
391 nullptr /* err */,
392 pid,
393 uid);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700394 } else {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800395 mData->mCodec = android::MediaCodec::CreateByComponentName(
396 mData->mLooper,
397 name,
398 nullptr /* err */,
399 pid,
400 uid);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700401 }
Andy Hung6bb63ad2015-04-28 19:05:08 -0700402 if (mData->mCodec == NULL) { // failed to create codec
403 AMediaCodec_delete(mData);
404 return NULL;
405 }
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700406 mData->mHandler = new CodecHandler(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700407 mData->mLooper->registerHandler(mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700408 mData->mGeneration = 1;
409 mData->mRequestedActivityNotification = false;
410 mData->mCallback = NULL;
411
Wei Jia00cc9922017-11-23 08:00:34 -0800412 mData->mAsyncCallback = {};
413 mData->mAsyncCallbackUserData = NULL;
414
Marco Nelissen0c3be872014-05-01 10:14:44 -0700415 return mData;
416}
417
Marco Nelissen3425fd52014-05-14 11:12:46 -0700418EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700419AMediaCodec* AMediaCodec_createCodecByName(const char *name) {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800420 return createAMediaCodec(name, false /* name_is_type */, false /* encoder */);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700421}
422
Marco Nelissen3425fd52014-05-14 11:12:46 -0700423EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700424AMediaCodec* AMediaCodec_createDecoderByType(const char *mime_type) {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800425 return createAMediaCodec(mime_type, true /* name_is_type */, false /* encoder */);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700426}
427
Marco Nelissen3425fd52014-05-14 11:12:46 -0700428EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700429AMediaCodec* AMediaCodec_createEncoderByType(const char *name) {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800430 return createAMediaCodec(name, true /* name_is_type */, true /* encoder */);
431}
432
433EXPORT
434AMediaCodec* AMediaCodec_createCodecByNameForClient(const char *name,
435 pid_t pid,
436 uid_t uid) {
437 return createAMediaCodec(name, false /* name_is_type */, false /* encoder */, pid, uid);
438}
439
440EXPORT
441AMediaCodec* AMediaCodec_createDecoderByTypeForClient(const char *mime_type,
442 pid_t pid,
443 uid_t uid) {
444 return createAMediaCodec(mime_type, true /* name_is_type */, false /* encoder */, pid, uid);
445}
446
447EXPORT
448AMediaCodec* AMediaCodec_createEncoderByTypeForClient(const char *name,
449 pid_t pid,
450 uid_t uid) {
451 return createAMediaCodec(name, true /* name_is_type */, true /* encoder */, pid, uid);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700452}
453
Marco Nelissen3425fd52014-05-14 11:12:46 -0700454EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700455media_status_t AMediaCodec_delete(AMediaCodec *mData) {
Andy Hung6bb63ad2015-04-28 19:05:08 -0700456 if (mData != NULL) {
457 if (mData->mCodec != NULL) {
458 mData->mCodec->release();
459 mData->mCodec.clear();
460 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700461
Andy Hung6bb63ad2015-04-28 19:05:08 -0700462 if (mData->mLooper != NULL) {
463 if (mData->mHandler != NULL) {
464 mData->mLooper->unregisterHandler(mData->mHandler->id());
465 }
466 mData->mLooper->stop();
467 mData->mLooper.clear();
468 }
469 delete mData;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700470 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700471 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700472}
473
Marco Nelissen3425fd52014-05-14 11:12:46 -0700474EXPORT
Wei Jia00cc9922017-11-23 08:00:34 -0800475media_status_t AMediaCodec_getName(
476 AMediaCodec *mData,
477 char** out_name) {
478 if (out_name == NULL) {
479 return AMEDIA_ERROR_INVALID_PARAMETER;
480 }
481
482 AString compName;
483 status_t err = mData->mCodec->getName(&compName);
484 if (err != OK) {
485 return translate_error(err);
486 }
487 *out_name = strdup(compName.c_str());
488 return AMEDIA_OK;
489}
490
491EXPORT
492void AMediaCodec_releaseName(
493 AMediaCodec * /* mData */,
494 char* name) {
495 if (name != NULL) {
496 free(name);
497 }
498}
499
500EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700501media_status_t AMediaCodec_configure(
Marco Nelissen050eb322014-05-09 15:10:23 -0700502 AMediaCodec *mData,
503 const AMediaFormat* format,
504 ANativeWindow* window,
505 AMediaCrypto *crypto,
506 uint32_t flags) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700507 sp<AMessage> nativeFormat;
508 AMediaFormat_getFormat(format, &nativeFormat);
Manisha Jajoob821e1d2021-08-09 15:09:53 +0530509 // create our shallow copy, so we aren't victim to any later changes.
510 sp<AMessage> dupNativeFormat = nativeFormat->dup();
511 ALOGV("configure with format: %s", dupNativeFormat->debugString(0).c_str());
Marco Nelissen0c3be872014-05-01 10:14:44 -0700512 sp<Surface> surface = NULL;
513 if (window != NULL) {
514 surface = (Surface*) window;
515 }
516
Manisha Jajoob821e1d2021-08-09 15:09:53 +0530517 status_t err = mData->mCodec->configure(dupNativeFormat, surface,
Wei Jia00cc9922017-11-23 08:00:34 -0800518 crypto ? crypto->mCrypto : NULL, flags);
519 if (err != OK) {
520 ALOGE("configure: err(%d), failed with format: %s",
Manisha Jajoob821e1d2021-08-09 15:09:53 +0530521 err, dupNativeFormat->debugString(0).c_str());
Wei Jia00cc9922017-11-23 08:00:34 -0800522 }
523 return translate_error(err);
524}
525
526EXPORT
527media_status_t AMediaCodec_setAsyncNotifyCallback(
528 AMediaCodec *mData,
529 AMediaCodecOnAsyncNotifyCallback callback,
530 void *userdata) {
Wei Jia00cc9922017-11-23 08:00:34 -0800531
532 Mutex::Autolock _l(mData->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700533
534 if (mData->mAsyncNotify == NULL) {
535 mData->mAsyncNotify = new AMessage(kWhatAsyncNotify, mData->mHandler);
536 }
537
538 // always call, codec may have been reset/re-configured since last call.
539 status_t err = mData->mCodec->setCallback(mData->mAsyncNotify);
540 if (err != OK) {
541 ALOGE("setAsyncNotifyCallback: err(%d), failed to set async callback", err);
542 return translate_error(err);
543 }
544
Wei Jia00cc9922017-11-23 08:00:34 -0800545 mData->mAsyncCallback = callback;
546 mData->mAsyncCallbackUserData = userdata;
547
548 return AMEDIA_OK;
549}
550
Jin Heo2665ce82021-09-10 17:20:00 +0900551EXPORT
552media_status_t AMediaCodec_setOnFrameRenderedCallback(
553 AMediaCodec *mData,
554 AMediaCodecOnFrameRendered callback,
555 void *userdata) {
556 Mutex::Autolock _l(mData->mFrameRenderedCallbackLock);
557 if (mData->mFrameRenderedNotify == NULL) {
558 mData->mFrameRenderedNotify = new AMessage(kWhatFrameRenderedNotify, mData->mHandler);
559 }
560 status_t err = mData->mCodec->setOnFrameRenderedNotification(mData->mFrameRenderedNotify);
561 if (err != OK) {
562 ALOGE("setOnFrameRenderedNotifyCallback: err(%d), failed to set callback", err);
563 return translate_error(err);
564 }
565
566 mData->mFrameRenderedCallback = callback;
567 mData->mFrameRenderedCallbackUserData = userdata;
568
569 return AMEDIA_OK;
570}
Wei Jia00cc9922017-11-23 08:00:34 -0800571
572EXPORT
573media_status_t AMediaCodec_releaseCrypto(AMediaCodec *mData) {
574 return translate_error(mData->mCodec->releaseCrypto());
Marco Nelissen0c3be872014-05-01 10:14:44 -0700575}
576
Marco Nelissen3425fd52014-05-14 11:12:46 -0700577EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700578media_status_t AMediaCodec_start(AMediaCodec *mData) {
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700579 status_t ret = mData->mCodec->start();
580 if (ret != OK) {
581 return translate_error(ret);
582 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800583 mData->mActivityNotification = new AMessage(kWhatActivityNotify, mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700584 mData->mActivityNotification->setInt32("generation", mData->mGeneration);
585 requestActivityNotification(mData);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700586 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700587}
588
Marco Nelissen3425fd52014-05-14 11:12:46 -0700589EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700590media_status_t AMediaCodec_stop(AMediaCodec *mData) {
591 media_status_t ret = translate_error(mData->mCodec->stop());
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700592
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800593 sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700594 sp<AMessage> response;
595 msg->postAndAwaitResponse(&response);
596 mData->mActivityNotification.clear();
597
598 return ret;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700599}
600
Marco Nelissen3425fd52014-05-14 11:12:46 -0700601EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700602media_status_t AMediaCodec_flush(AMediaCodec *mData) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700603 return translate_error(mData->mCodec->flush());
604}
605
Marco Nelissen3425fd52014-05-14 11:12:46 -0700606EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700607ssize_t AMediaCodec_dequeueInputBuffer(AMediaCodec *mData, int64_t timeoutUs) {
608 size_t idx;
609 status_t ret = mData->mCodec->dequeueInputBuffer(&idx, timeoutUs);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700610 requestActivityNotification(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700611 if (ret == OK) {
612 return idx;
613 }
614 return translate_error(ret);
615}
616
Marco Nelissen3425fd52014-05-14 11:12:46 -0700617EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700618uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
Wei Jia00cc9922017-11-23 08:00:34 -0800619 if (mData->mAsyncNotify != NULL) {
620 // Asynchronous mode
621 sp<MediaCodecBuffer> abuf;
622 if (mData->mCodec->getInputBuffer(idx, &abuf) != 0) {
623 return NULL;
624 }
625
626 if (out_size != NULL) {
627 *out_size = abuf->capacity();
628 }
629 return abuf->data();
630 }
631
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900632 android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700633 if (mData->mCodec->getInputBuffers(&abufs) == 0) {
634 size_t n = abufs.size();
635 if (idx >= n) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700636 ALOGE("buffer index %zu out of range", idx);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700637 return NULL;
638 }
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900639 if (abufs[idx] == NULL) {
640 ALOGE("buffer index %zu is NULL", idx);
641 return NULL;
642 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700643 if (out_size != NULL) {
644 *out_size = abufs[idx]->capacity();
645 }
646 return abufs[idx]->data();
647 }
648 ALOGE("couldn't get input buffers");
649 return NULL;
650}
651
Marco Nelissen3425fd52014-05-14 11:12:46 -0700652EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700653uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
Wei Jia00cc9922017-11-23 08:00:34 -0800654 if (mData->mAsyncNotify != NULL) {
655 // Asynchronous mode
656 sp<MediaCodecBuffer> abuf;
657 if (mData->mCodec->getOutputBuffer(idx, &abuf) != 0) {
658 return NULL;
659 }
660
661 if (out_size != NULL) {
662 *out_size = abuf->capacity();
663 }
664 return abuf->data();
665 }
666
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900667 android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700668 if (mData->mCodec->getOutputBuffers(&abufs) == 0) {
669 size_t n = abufs.size();
670 if (idx >= n) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700671 ALOGE("buffer index %zu out of range", idx);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700672 return NULL;
673 }
674 if (out_size != NULL) {
675 *out_size = abufs[idx]->capacity();
676 }
677 return abufs[idx]->data();
678 }
679 ALOGE("couldn't get output buffers");
680 return NULL;
681}
682
Marco Nelissen3425fd52014-05-14 11:12:46 -0700683EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700684media_status_t AMediaCodec_queueInputBuffer(AMediaCodec *mData,
Marco Nelissen0c3be872014-05-01 10:14:44 -0700685 size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags) {
686
687 AString errorMsg;
688 status_t ret = mData->mCodec->queueInputBuffer(idx, offset, size, time, flags, &errorMsg);
689 return translate_error(ret);
690}
691
Marco Nelissen3425fd52014-05-14 11:12:46 -0700692EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700693ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec *mData,
694 AMediaCodecBufferInfo *info, int64_t timeoutUs) {
695 size_t idx;
696 size_t offset;
697 size_t size;
698 uint32_t flags;
699 int64_t presentationTimeUs;
700 status_t ret = mData->mCodec->dequeueOutputBuffer(&idx, &offset, &size, &presentationTimeUs,
701 &flags, timeoutUs);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700702 requestActivityNotification(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700703 switch (ret) {
704 case OK:
705 info->offset = offset;
706 info->size = size;
707 info->flags = flags;
708 info->presentationTimeUs = presentationTimeUs;
709 return idx;
710 case -EAGAIN:
711 return AMEDIACODEC_INFO_TRY_AGAIN_LATER;
712 case android::INFO_FORMAT_CHANGED:
713 return AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED;
714 case INFO_OUTPUT_BUFFERS_CHANGED:
715 return AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED;
716 default:
717 break;
718 }
719 return translate_error(ret);
720}
721
Marco Nelissen3425fd52014-05-14 11:12:46 -0700722EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700723AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec *mData) {
724 sp<AMessage> format;
725 mData->mCodec->getOutputFormat(&format);
726 return AMediaFormat_fromMsg(&format);
727}
728
Marco Nelissen3425fd52014-05-14 11:12:46 -0700729EXPORT
Wei Jia00cc9922017-11-23 08:00:34 -0800730AMediaFormat* AMediaCodec_getInputFormat(AMediaCodec *mData) {
731 sp<AMessage> format;
732 mData->mCodec->getInputFormat(&format);
733 return AMediaFormat_fromMsg(&format);
734}
735
736EXPORT
Manikanta Kanamarlapudi2c32f4d2017-07-07 16:24:31 +0530737AMediaFormat* AMediaCodec_getBufferFormat(AMediaCodec *mData, size_t index) {
738 sp<AMessage> format;
739 mData->mCodec->getOutputFormat(index, &format);
740 return AMediaFormat_fromMsg(&format);
741}
742
743EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700744media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec *mData, size_t idx, bool render) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700745 if (render) {
746 return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx));
747 } else {
748 return translate_error(mData->mCodec->releaseOutputBuffer(idx));
749 }
750}
751
Marco Nelissen3425fd52014-05-14 11:12:46 -0700752EXPORT
Marco Nelissen79e2b622014-05-16 08:07:28 -0700753media_status_t AMediaCodec_releaseOutputBufferAtTime(
754 AMediaCodec *mData, size_t idx, int64_t timestampNs) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700755 ALOGV("render @ %" PRId64, timestampNs);
Marco Nelissen79e2b622014-05-16 08:07:28 -0700756 return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx, timestampNs));
757}
758
Vineeta Srivastava8c35da52016-01-08 17:33:09 -0800759EXPORT
760media_status_t AMediaCodec_setOutputSurface(AMediaCodec *mData, ANativeWindow* window) {
761 sp<Surface> surface = NULL;
762 if (window != NULL) {
763 surface = (Surface*) window;
764 }
765 return translate_error(mData->mCodec->setSurface(surface));
766}
767
Praveen Chavan19431582017-01-16 11:56:18 -0800768EXPORT
769media_status_t AMediaCodec_createInputSurface(AMediaCodec *mData, ANativeWindow **surface) {
770 if (surface == NULL || mData == NULL) {
771 return AMEDIA_ERROR_INVALID_PARAMETER;
772 }
773 *surface = NULL;
774
775 sp<IGraphicBufferProducer> igbp = NULL;
776 status_t err = mData->mCodec->createInputSurface(&igbp);
777 if (err != NO_ERROR) {
778 return translate_error(err);
779 }
780
781 *surface = new Surface(igbp);
782 ANativeWindow_acquire(*surface);
783 return AMEDIA_OK;
784}
785
Praveen Chavan85a53632017-01-31 12:21:33 -0800786EXPORT
787media_status_t AMediaCodec_createPersistentInputSurface(ANativeWindow **surface) {
788 if (surface == NULL) {
789 return AMEDIA_ERROR_INVALID_PARAMETER;
790 }
791 *surface = NULL;
792
793 sp<PersistentSurface> ps = MediaCodec::CreatePersistentInputSurface();
794 if (ps == NULL) {
795 return AMEDIA_ERROR_UNKNOWN;
796 }
797
798 sp<IGraphicBufferProducer> igbp = ps->getBufferProducer();
799 if (igbp == NULL) {
800 return AMEDIA_ERROR_UNKNOWN;
801 }
802
803 *surface = new AMediaCodecPersistentSurface(igbp, ps);
804 ANativeWindow_acquire(*surface);
805
806 return AMEDIA_OK;
807}
808
809EXPORT
810media_status_t AMediaCodec_setInputSurface(
811 AMediaCodec *mData, ANativeWindow *surface) {
812
813 if (surface == NULL || mData == NULL) {
814 return AMEDIA_ERROR_INVALID_PARAMETER;
815 }
816
817 AMediaCodecPersistentSurface *aMediaPersistentSurface =
818 static_cast<AMediaCodecPersistentSurface *>(surface);
819 if (aMediaPersistentSurface->mPersistentSurface == NULL) {
820 return AMEDIA_ERROR_INVALID_PARAMETER;
821 }
822
823 return translate_error(mData->mCodec->setInputSurface(
824 aMediaPersistentSurface->mPersistentSurface));
825}
826
Praveen Chavanf373e842017-02-01 11:50:15 -0800827EXPORT
828media_status_t AMediaCodec_setParameters(
829 AMediaCodec *mData, const AMediaFormat* params) {
830 if (params == NULL || mData == NULL) {
831 return AMEDIA_ERROR_INVALID_PARAMETER;
832 }
833 sp<AMessage> nativeParams;
834 AMediaFormat_getFormat(params, &nativeParams);
835 ALOGV("setParameters: %s", nativeParams->debugString(0).c_str());
836
837 return translate_error(mData->mCodec->setParameters(nativeParams));
838}
839
Robert Shihaf42d3f2017-03-20 16:45:37 -0700840EXPORT
841media_status_t AMediaCodec_signalEndOfInputStream(AMediaCodec *mData) {
842
843 if (mData == NULL) {
844 return AMEDIA_ERROR_INVALID_PARAMETER;
845 }
846
847 status_t err = mData->mCodec->signalEndOfInputStream();
848 if (err == INVALID_OPERATION) {
849 return AMEDIA_ERROR_INVALID_OPERATION;
850 }
851
852 return translate_error(err);
853
854}
855
Marco Nelissene22a64b2014-05-23 15:49:49 -0700856//EXPORT
Glenn Kastenb187de12014-12-30 08:18:15 -0800857media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback,
858 void *userdata) {
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700859 mData->mCallback = callback;
860 mData->mCallbackUserData = userdata;
Marco Nelissene419d7c2014-05-15 14:17:25 -0700861 return AMEDIA_OK;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700862}
863
Marco Nelissen050eb322014-05-09 15:10:23 -0700864typedef struct AMediaCodecCryptoInfo {
865 int numsubsamples;
866 uint8_t key[16];
867 uint8_t iv[16];
Marco Nelissen79e2b622014-05-16 08:07:28 -0700868 cryptoinfo_mode_t mode;
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800869 cryptoinfo_pattern_t pattern;
Marco Nelissen050eb322014-05-09 15:10:23 -0700870 size_t *clearbytes;
871 size_t *encryptedbytes;
872} AMediaCodecCryptoInfo;
873
Marco Nelissen3425fd52014-05-14 11:12:46 -0700874EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700875media_status_t AMediaCodec_queueSecureInputBuffer(
Marco Nelissen050eb322014-05-09 15:10:23 -0700876 AMediaCodec* codec,
877 size_t idx,
878 off_t offset,
879 AMediaCodecCryptoInfo* crypto,
880 uint64_t time,
881 uint32_t flags) {
882
883 CryptoPlugin::SubSample *subSamples = new CryptoPlugin::SubSample[crypto->numsubsamples];
884 for (int i = 0; i < crypto->numsubsamples; i++) {
885 subSamples[i].mNumBytesOfClearData = crypto->clearbytes[i];
886 subSamples[i].mNumBytesOfEncryptedData = crypto->encryptedbytes[i];
887 }
888
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800889 CryptoPlugin::Pattern pattern;
890 pattern.mEncryptBlocks = crypto->pattern.encryptBlocks;
891 pattern.mSkipBlocks = crypto->pattern.skipBlocks;
892
Marco Nelissen050eb322014-05-09 15:10:23 -0700893 AString errormsg;
894 status_t err = codec->mCodec->queueSecureInputBuffer(idx,
895 offset,
896 subSamples,
897 crypto->numsubsamples,
898 crypto->key,
899 crypto->iv,
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800900 (CryptoPlugin::Mode)crypto->mode,
901 pattern,
Marco Nelissen050eb322014-05-09 15:10:23 -0700902 time,
903 flags,
904 &errormsg);
905 if (err != 0) {
906 ALOGE("queSecureInputBuffer: %s", errormsg.c_str());
907 }
Marco Nelissen829e0972014-05-13 16:22:19 -0700908 delete [] subSamples;
Marco Nelissen050eb322014-05-09 15:10:23 -0700909 return translate_error(err);
910}
911
Wei Jia00cc9922017-11-23 08:00:34 -0800912EXPORT
913bool AMediaCodecActionCode_isRecoverable(int32_t actionCode) {
914 return (actionCode == ACTION_CODE_RECOVERABLE);
915}
916
917EXPORT
918bool AMediaCodecActionCode_isTransient(int32_t actionCode) {
919 return (actionCode == ACTION_CODE_TRANSIENT);
920}
921
Marco Nelissen050eb322014-05-09 15:10:23 -0700922
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800923EXPORT
924void AMediaCodecCryptoInfo_setPattern(AMediaCodecCryptoInfo *info,
925 cryptoinfo_pattern_t *pattern) {
926 info->pattern.encryptBlocks = pattern->encryptBlocks;
927 info->pattern.skipBlocks = pattern->skipBlocks;
928}
Marco Nelissen050eb322014-05-09 15:10:23 -0700929
Marco Nelissen3425fd52014-05-14 11:12:46 -0700930EXPORT
Marco Nelissen050eb322014-05-09 15:10:23 -0700931AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new(
932 int numsubsamples,
933 uint8_t key[16],
934 uint8_t iv[16],
Marco Nelissen79e2b622014-05-16 08:07:28 -0700935 cryptoinfo_mode_t mode,
Marco Nelissen050eb322014-05-09 15:10:23 -0700936 size_t *clearbytes,
937 size_t *encryptedbytes) {
938
939 // size needed to store all the crypto data
Marco Nelissend1fd0272018-07-31 15:12:51 -0700940 size_t cryptosize;
941 // = sizeof(AMediaCodecCryptoInfo) + sizeof(size_t) * numsubsamples * 2;
942 if (__builtin_mul_overflow(sizeof(size_t) * 2, numsubsamples, &cryptosize) ||
943 __builtin_add_overflow(cryptosize, sizeof(AMediaCodecCryptoInfo), &cryptosize)) {
944 ALOGE("crypto size overflow");
945 return NULL;
946 }
Marco Nelissen050eb322014-05-09 15:10:23 -0700947 AMediaCodecCryptoInfo *ret = (AMediaCodecCryptoInfo*) malloc(cryptosize);
948 if (!ret) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700949 ALOGE("couldn't allocate %zu bytes", cryptosize);
Marco Nelissen050eb322014-05-09 15:10:23 -0700950 return NULL;
951 }
952 ret->numsubsamples = numsubsamples;
953 memcpy(ret->key, key, 16);
954 memcpy(ret->iv, iv, 16);
955 ret->mode = mode;
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800956 ret->pattern.encryptBlocks = 0;
957 ret->pattern.skipBlocks = 0;
Marco Nelissen050eb322014-05-09 15:10:23 -0700958
959 // clearbytes and encryptedbytes point at the actual data, which follows
Marco Nelissen829e0972014-05-13 16:22:19 -0700960 ret->clearbytes = (size_t*) (ret + 1); // point immediately after the struct
961 ret->encryptedbytes = ret->clearbytes + numsubsamples; // point after the clear sizes
Marco Nelissen050eb322014-05-09 15:10:23 -0700962
Marco Nelissen829e0972014-05-13 16:22:19 -0700963 memcpy(ret->clearbytes, clearbytes, numsubsamples * sizeof(size_t));
964 memcpy(ret->encryptedbytes, encryptedbytes, numsubsamples * sizeof(size_t));
Marco Nelissen050eb322014-05-09 15:10:23 -0700965
966 return ret;
967}
968
969
Marco Nelissen3425fd52014-05-14 11:12:46 -0700970EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700971media_status_t AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo* info) {
Marco Nelissen050eb322014-05-09 15:10:23 -0700972 free(info);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700973 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700974}
975
Marco Nelissen3425fd52014-05-14 11:12:46 -0700976EXPORT
Marco Nelissen050eb322014-05-09 15:10:23 -0700977size_t AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo* ci) {
978 return ci->numsubsamples;
979}
980
Marco Nelissen3425fd52014-05-14 11:12:46 -0700981EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700982media_status_t AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
983 if (!ci) {
984 return AMEDIA_ERROR_INVALID_OBJECT;
985 }
986 if (!dst) {
987 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700988 }
989 memcpy(dst, ci->key, 16);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700990 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700991}
992
Marco Nelissen3425fd52014-05-14 11:12:46 -0700993EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700994media_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
995 if (!ci) {
996 return AMEDIA_ERROR_INVALID_OBJECT;
997 }
998 if (!dst) {
999 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -07001000 }
1001 memcpy(dst, ci->iv, 16);
Marco Nelissene419d7c2014-05-15 14:17:25 -07001002 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -07001003}
1004
Marco Nelissen3425fd52014-05-14 11:12:46 -07001005EXPORT
Marco Nelissen79e2b622014-05-16 08:07:28 -07001006cryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo* ci) {
Marco Nelissen050eb322014-05-09 15:10:23 -07001007 if (!ci) {
Marco Nelissen79e2b622014-05-16 08:07:28 -07001008 return (cryptoinfo_mode_t) AMEDIA_ERROR_INVALID_OBJECT;
Marco Nelissen050eb322014-05-09 15:10:23 -07001009 }
1010 return ci->mode;
1011}
1012
Marco Nelissen3425fd52014-05-14 11:12:46 -07001013EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -07001014media_status_t AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
1015 if (!ci) {
1016 return AMEDIA_ERROR_INVALID_OBJECT;
1017 }
1018 if (!dst) {
1019 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -07001020 }
1021 memcpy(dst, ci->clearbytes, sizeof(size_t) * ci->numsubsamples);
Marco Nelissene419d7c2014-05-15 14:17:25 -07001022 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -07001023}
1024
Marco Nelissen3425fd52014-05-14 11:12:46 -07001025EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -07001026media_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
1027 if (!ci) {
1028 return AMEDIA_ERROR_INVALID_OBJECT;
1029 }
1030 if (!dst) {
1031 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -07001032 }
1033 memcpy(dst, ci->encryptedbytes, sizeof(size_t) * ci->numsubsamples);
Marco Nelissene419d7c2014-05-15 14:17:25 -07001034 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -07001035}
Marco Nelissencdb42cd2014-05-08 14:46:05 -07001036
Ray Essickef058462021-01-24 14:50:08 -08001037EXPORT const char* AMEDIACODEC_KEY_HDR10_PLUS_INFO = AMEDIAFORMAT_KEY_HDR10_PLUS_INFO;
1038EXPORT const char* AMEDIACODEC_KEY_LOW_LATENCY = AMEDIAFORMAT_KEY_LOW_LATENCY;
1039EXPORT const char* AMEDIACODEC_KEY_OFFSET_TIME = "time-offset-us";
1040EXPORT const char* AMEDIACODEC_KEY_REQUEST_SYNC_FRAME = "request-sync";
1041EXPORT const char* AMEDIACODEC_KEY_SUSPEND = "drop-input-frames";
1042EXPORT const char* AMEDIACODEC_KEY_SUSPEND_TIME = "drop-start-time-us";
1043EXPORT const char* AMEDIACODEC_KEY_VIDEO_BITRATE = "video-bitrate";
1044
Marco Nelissen0c3be872014-05-01 10:14:44 -07001045} // extern "C"
1046