blob: 354971ac1843d80f2eec7ba43f931d50c1cb866e [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>
18
Marco Nelissenc7a11b22014-05-30 10:13:25 -070019//#define LOG_NDEBUG 0
Marco Nelissen0c3be872014-05-01 10:14:44 -070020#define LOG_TAG "NdkMediaCodec"
21
Chong Zhangefd1c5c2020-11-18 10:33:13 -080022#include <media/NdkMediaCodecPlatform.h>
Colin Cross7e8d4ba2017-05-04 16:17:42 -070023#include <media/NdkMediaError.h>
Marco Nelissen98603d82018-07-17 11:06:55 -070024#include <media/NdkMediaFormatPriv.h>
Marco Nelissen050eb322014-05-09 15:10:23 -070025#include "NdkMediaCryptoPriv.h"
Marco Nelissen0c3be872014-05-01 10:14:44 -070026
27#include <utils/Log.h>
28#include <utils/StrongPointer.h>
29#include <gui/Surface.h>
30
Marco Nelissen0c3be872014-05-01 10:14:44 -070031#include <media/stagefright/foundation/ALooper.h>
Jin Heo2665ce82021-09-10 17:20:00 +090032#include <media/stagefright/foundation/ABuffer.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070033#include <media/stagefright/foundation/AMessage.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070034
Praveen Chavan85a53632017-01-31 12:21:33 -080035#include <media/stagefright/PersistentSurface.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070036#include <media/stagefright/MediaCodec.h>
37#include <media/stagefright/MediaErrors.h>
Wonsik Kim7e34bf52016-08-23 00:09:18 +090038#include <media/MediaCodecBuffer.h>
Praveen Chavan19431582017-01-16 11:56:18 -080039#include <android/native_window.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070040
41using namespace android;
42
43
Marco Nelissene419d7c2014-05-15 14:17:25 -070044static media_status_t translate_error(status_t err) {
Marco Nelissen0c3be872014-05-01 10:14:44 -070045 if (err == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -070046 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -070047 } else if (err == -EAGAIN) {
Marco Nelissene419d7c2014-05-15 14:17:25 -070048 return (media_status_t) AMEDIACODEC_INFO_TRY_AGAIN_LATER;
Chong Zhangeb9aca62020-09-16 12:49:41 -070049 } else if (err == NO_MEMORY) {
50 return AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE;
51 } else if (err == DEAD_OBJECT) {
52 return AMEDIACODEC_ERROR_RECLAIMED;
Marco Nelissen0c3be872014-05-01 10:14:44 -070053 }
54 ALOGE("sf error code: %d", err);
Marco Nelissene419d7c2014-05-15 14:17:25 -070055 return AMEDIA_ERROR_UNKNOWN;
Marco Nelissen0c3be872014-05-01 10:14:44 -070056}
57
Marco Nelissencdb42cd2014-05-08 14:46:05 -070058enum {
59 kWhatActivityNotify,
Wei Jia00cc9922017-11-23 08:00:34 -080060 kWhatAsyncNotify,
Marco Nelissencdb42cd2014-05-08 14:46:05 -070061 kWhatRequestActivityNotifications,
62 kWhatStopActivityNotifications,
Jin Heo2665ce82021-09-10 17:20:00 +090063 kWhatFrameRenderedNotify,
Marco Nelissen0c3be872014-05-01 10:14:44 -070064};
65
Praveen Chavan85a53632017-01-31 12:21:33 -080066struct AMediaCodecPersistentSurface : public Surface {
67 sp<PersistentSurface> mPersistentSurface;
68 AMediaCodecPersistentSurface(
69 const sp<IGraphicBufferProducer>& igbp,
70 const sp<PersistentSurface>& ps)
71 : Surface(igbp) {
72 mPersistentSurface = ps;
73 }
74 virtual ~AMediaCodecPersistentSurface() {
75 //mPersistentSurface ref will be let go off here
76 }
77};
Marco Nelissen0c3be872014-05-01 10:14:44 -070078
Marco Nelissencdb42cd2014-05-08 14:46:05 -070079class CodecHandler: public AHandler {
80private:
81 AMediaCodec* mCodec;
82public:
Chih-Hung Hsieh090ef602016-04-27 10:39:54 -070083 explicit CodecHandler(AMediaCodec *codec);
Marco Nelissencdb42cd2014-05-08 14:46:05 -070084 virtual void onMessageReceived(const sp<AMessage> &msg);
85};
Marco Nelissen0c3be872014-05-01 10:14:44 -070086
Marco Nelissene22a64b2014-05-23 15:49:49 -070087typedef void (*OnCodecEvent)(AMediaCodec *codec, void *userdata);
88
Marco Nelissen0c3be872014-05-01 10:14:44 -070089struct AMediaCodec {
90 sp<android::MediaCodec> mCodec;
91 sp<ALooper> mLooper;
92 sp<CodecHandler> mHandler;
Marco Nelissencdb42cd2014-05-08 14:46:05 -070093 sp<AMessage> mActivityNotification;
94 int32_t mGeneration;
95 bool mRequestedActivityNotification;
96 OnCodecEvent mCallback;
97 void *mCallbackUserData;
Wei Jia00cc9922017-11-23 08:00:34 -080098
99 sp<AMessage> mAsyncNotify;
100 mutable Mutex mAsyncCallbackLock;
101 AMediaCodecOnAsyncNotifyCallback mAsyncCallback;
102 void *mAsyncCallbackUserData;
Jin Heo2665ce82021-09-10 17:20:00 +0900103
104 sp<AMessage> mFrameRenderedNotify;
105 mutable Mutex mFrameRenderedCallbackLock;
106 AMediaCodecOnFrameRendered mFrameRenderedCallback;
107 void *mFrameRenderedCallbackUserData;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700108};
109
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700110CodecHandler::CodecHandler(AMediaCodec *codec) {
111 mCodec = codec;
112}
113
114void CodecHandler::onMessageReceived(const sp<AMessage> &msg) {
115
116 switch (msg->what()) {
117 case kWhatRequestActivityNotifications:
118 {
119 if (mCodec->mRequestedActivityNotification) {
120 break;
121 }
122
123 mCodec->mCodec->requestActivityNotification(mCodec->mActivityNotification);
124 mCodec->mRequestedActivityNotification = true;
125 break;
126 }
127
128 case kWhatActivityNotify:
129 {
130 {
131 int32_t generation;
132 msg->findInt32("generation", &generation);
133
134 if (generation != mCodec->mGeneration) {
135 // stale
136 break;
137 }
138
139 mCodec->mRequestedActivityNotification = false;
140 }
141
142 if (mCodec->mCallback) {
143 mCodec->mCallback(mCodec, mCodec->mCallbackUserData);
144 }
145 break;
146 }
147
Wei Jia00cc9922017-11-23 08:00:34 -0800148 case kWhatAsyncNotify:
149 {
150 int32_t cbID;
151 if (!msg->findInt32("callbackID", &cbID)) {
152 ALOGE("kWhatAsyncNotify: callbackID is expected.");
153 break;
154 }
155
156 ALOGV("kWhatAsyncNotify: cbID = %d", cbID);
157
158 switch (cbID) {
159 case MediaCodec::CB_INPUT_AVAILABLE:
160 {
161 int32_t index;
162 if (!msg->findInt32("index", &index)) {
163 ALOGE("CB_INPUT_AVAILABLE: index is expected.");
164 break;
165 }
166
167 Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700168 if (mCodec->mAsyncCallback.onAsyncInputAvailable != NULL) {
Wei Jia00cc9922017-11-23 08:00:34 -0800169 mCodec->mAsyncCallback.onAsyncInputAvailable(
170 mCodec,
171 mCodec->mAsyncCallbackUserData,
172 index);
173 }
174
175 break;
176 }
177
178 case MediaCodec::CB_OUTPUT_AVAILABLE:
179 {
180 int32_t index;
181 size_t offset;
182 size_t size;
183 int64_t timeUs;
184 int32_t flags;
185
186 if (!msg->findInt32("index", &index)) {
187 ALOGE("CB_OUTPUT_AVAILABLE: index is expected.");
188 break;
189 }
190 if (!msg->findSize("offset", &offset)) {
191 ALOGE("CB_OUTPUT_AVAILABLE: offset is expected.");
192 break;
193 }
194 if (!msg->findSize("size", &size)) {
195 ALOGE("CB_OUTPUT_AVAILABLE: size is expected.");
196 break;
197 }
198 if (!msg->findInt64("timeUs", &timeUs)) {
199 ALOGE("CB_OUTPUT_AVAILABLE: timeUs is expected.");
200 break;
201 }
202 if (!msg->findInt32("flags", &flags)) {
203 ALOGE("CB_OUTPUT_AVAILABLE: flags is expected.");
204 break;
205 }
206
207 AMediaCodecBufferInfo bufferInfo = {
208 (int32_t)offset,
209 (int32_t)size,
210 timeUs,
211 (uint32_t)flags};
212
213 Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700214 if (mCodec->mAsyncCallback.onAsyncOutputAvailable != NULL) {
Wei Jia00cc9922017-11-23 08:00:34 -0800215 mCodec->mAsyncCallback.onAsyncOutputAvailable(
216 mCodec,
217 mCodec->mAsyncCallbackUserData,
218 index,
219 &bufferInfo);
220 }
221
222 break;
223 }
224
225 case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
226 {
227 sp<AMessage> format;
228 if (!msg->findMessage("format", &format)) {
229 ALOGE("CB_OUTPUT_FORMAT_CHANGED: format is expected.");
230 break;
231 }
232
Chong Zhang1fa26862019-09-16 16:15:00 -0700233 // Here format is MediaCodec's internal copy of output format.
234 // Make a copy since the client might modify it.
235 sp<AMessage> copy;
236 if (format != nullptr) {
237 copy = format->dup();
238 }
239 AMediaFormat *aMediaFormat = AMediaFormat_fromMsg(&copy);
Wei Jia00cc9922017-11-23 08:00:34 -0800240
241 Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700242 if (mCodec->mAsyncCallback.onAsyncFormatChanged != NULL) {
Wei Jia00cc9922017-11-23 08:00:34 -0800243 mCodec->mAsyncCallback.onAsyncFormatChanged(
244 mCodec,
245 mCodec->mAsyncCallbackUserData,
246 aMediaFormat);
247 }
248
249 break;
250 }
251
252 case MediaCodec::CB_ERROR:
253 {
254 status_t err;
255 int32_t actionCode;
256 AString detail;
257 if (!msg->findInt32("err", &err)) {
258 ALOGE("CB_ERROR: err is expected.");
259 break;
260 }
Rakesh Kumard5ea3f32019-09-20 17:08:07 +0530261 if (!msg->findInt32("actionCode", &actionCode)) {
262 ALOGE("CB_ERROR: actionCode is expected.");
Wei Jia00cc9922017-11-23 08:00:34 -0800263 break;
264 }
265 msg->findString("detail", &detail);
Chong Zhangeb9aca62020-09-16 12:49:41 -0700266 ALOGE("Codec reported error(0x%x), actionCode(%d), detail(%s)",
Wei Jia00cc9922017-11-23 08:00:34 -0800267 err, actionCode, detail.c_str());
268
269 Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700270 if (mCodec->mAsyncCallback.onAsyncError != NULL) {
Wei Jia00cc9922017-11-23 08:00:34 -0800271 mCodec->mAsyncCallback.onAsyncError(
272 mCodec,
273 mCodec->mAsyncCallbackUserData,
274 translate_error(err),
275 actionCode,
276 detail.c_str());
277 }
278
279 break;
280 }
281
282 default:
283 {
284 ALOGE("kWhatAsyncNotify: callbackID(%d) is unexpected.", cbID);
285 break;
286 }
287 }
288 break;
289 }
290
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700291 case kWhatStopActivityNotifications:
292 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800293 sp<AReplyToken> replyID;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700294 msg->senderAwaitsResponse(&replyID);
295
296 mCodec->mGeneration++;
297 mCodec->mRequestedActivityNotification = false;
298
299 sp<AMessage> response = new AMessage;
300 response->postReply(replyID);
301 break;
302 }
303
Jin Heo2665ce82021-09-10 17:20:00 +0900304 case kWhatFrameRenderedNotify:
305 {
306 sp<AMessage> data;
307 if (!msg->findMessage("data", &data)) {
308 ALOGE("kWhatFrameRenderedNotify: data is expected.");
309 break;
310 }
311
312 AMessage::Type type;
313 int64_t mediaTimeUs, systemNano;
314 size_t index = 0;
315
316 // TODO. This code has dependency with MediaCodec::CreateFramesRenderedMessage.
317 for (size_t ix = 0; ix < data->countEntries(); ix++) {
318 AString name = data->getEntryNameAt(ix, &type);
319 if (name.startsWith(AStringPrintf("%zu-media-time-us", index).c_str())) {
320 AMessage::ItemData data = msg->getEntryAt(index);
321 data.find(&mediaTimeUs);
322 } else if (name.startsWith(AStringPrintf("%zu-system-nano", index).c_str())) {
323 AMessage::ItemData data = msg->getEntryAt(index);
324 data.find(&systemNano);
325
326 Mutex::Autolock _l(mCodec->mFrameRenderedCallbackLock);
327 if (mCodec->mFrameRenderedCallback != NULL) {
328 mCodec->mFrameRenderedCallback(
329 mCodec,
330 mCodec->mFrameRenderedCallbackUserData,
331 mediaTimeUs,
332 systemNano);
333 }
334
335 index++;
336 }
337 }
338 break;
339 }
340
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700341 default:
342 ALOGE("shouldn't be here");
343 break;
344 }
345
346}
347
348
349static void requestActivityNotification(AMediaCodec *codec) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800350 (new AMessage(kWhatRequestActivityNotifications, codec->mHandler))->post();
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700351}
352
Marco Nelissen0c3be872014-05-01 10:14:44 -0700353extern "C" {
354
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800355static AMediaCodec * createAMediaCodec(const char *name,
356 bool name_is_type,
357 bool encoder,
358 pid_t pid = android::MediaCodec::kNoPid,
359 uid_t uid = android::MediaCodec::kNoUid) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700360 AMediaCodec *mData = new AMediaCodec();
361 mData->mLooper = new ALooper;
362 mData->mLooper->setName("NDK MediaCodec_looper");
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800363 size_t res = mData->mLooper->start(
Marco Nelissen0c3be872014-05-01 10:14:44 -0700364 false, // runOnCallingThread
365 true, // canCallJava XXX
Wei Jia00cc9922017-11-23 08:00:34 -0800366 PRIORITY_AUDIO);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800367 if (res != OK) {
368 ALOGE("Failed to start the looper");
Greg Kaiser4e147802016-03-14 14:44:20 -0700369 AMediaCodec_delete(mData);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800370 return NULL;
371 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700372 if (name_is_type) {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800373 mData->mCodec = android::MediaCodec::CreateByType(
374 mData->mLooper,
375 name,
376 encoder,
377 nullptr /* err */,
378 pid,
379 uid);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700380 } else {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800381 mData->mCodec = android::MediaCodec::CreateByComponentName(
382 mData->mLooper,
383 name,
384 nullptr /* err */,
385 pid,
386 uid);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700387 }
Andy Hung6bb63ad2015-04-28 19:05:08 -0700388 if (mData->mCodec == NULL) { // failed to create codec
389 AMediaCodec_delete(mData);
390 return NULL;
391 }
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700392 mData->mHandler = new CodecHandler(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700393 mData->mLooper->registerHandler(mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700394 mData->mGeneration = 1;
395 mData->mRequestedActivityNotification = false;
396 mData->mCallback = NULL;
397
Wei Jia00cc9922017-11-23 08:00:34 -0800398 mData->mAsyncCallback = {};
399 mData->mAsyncCallbackUserData = NULL;
400
Marco Nelissen0c3be872014-05-01 10:14:44 -0700401 return mData;
402}
403
Marco Nelissen3425fd52014-05-14 11:12:46 -0700404EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700405AMediaCodec* AMediaCodec_createCodecByName(const char *name) {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800406 return createAMediaCodec(name, false /* name_is_type */, false /* encoder */);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700407}
408
Marco Nelissen3425fd52014-05-14 11:12:46 -0700409EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700410AMediaCodec* AMediaCodec_createDecoderByType(const char *mime_type) {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800411 return createAMediaCodec(mime_type, true /* name_is_type */, false /* encoder */);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700412}
413
Marco Nelissen3425fd52014-05-14 11:12:46 -0700414EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700415AMediaCodec* AMediaCodec_createEncoderByType(const char *name) {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800416 return createAMediaCodec(name, true /* name_is_type */, true /* encoder */);
417}
418
419EXPORT
420AMediaCodec* AMediaCodec_createCodecByNameForClient(const char *name,
421 pid_t pid,
422 uid_t uid) {
423 return createAMediaCodec(name, false /* name_is_type */, false /* encoder */, pid, uid);
424}
425
426EXPORT
427AMediaCodec* AMediaCodec_createDecoderByTypeForClient(const char *mime_type,
428 pid_t pid,
429 uid_t uid) {
430 return createAMediaCodec(mime_type, true /* name_is_type */, false /* encoder */, pid, uid);
431}
432
433EXPORT
434AMediaCodec* AMediaCodec_createEncoderByTypeForClient(const char *name,
435 pid_t pid,
436 uid_t uid) {
437 return createAMediaCodec(name, true /* name_is_type */, true /* encoder */, pid, uid);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700438}
439
Marco Nelissen3425fd52014-05-14 11:12:46 -0700440EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700441media_status_t AMediaCodec_delete(AMediaCodec *mData) {
Andy Hung6bb63ad2015-04-28 19:05:08 -0700442 if (mData != NULL) {
443 if (mData->mCodec != NULL) {
444 mData->mCodec->release();
445 mData->mCodec.clear();
446 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700447
Andy Hung6bb63ad2015-04-28 19:05:08 -0700448 if (mData->mLooper != NULL) {
449 if (mData->mHandler != NULL) {
450 mData->mLooper->unregisterHandler(mData->mHandler->id());
451 }
452 mData->mLooper->stop();
453 mData->mLooper.clear();
454 }
455 delete mData;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700456 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700457 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700458}
459
Marco Nelissen3425fd52014-05-14 11:12:46 -0700460EXPORT
Wei Jia00cc9922017-11-23 08:00:34 -0800461media_status_t AMediaCodec_getName(
462 AMediaCodec *mData,
463 char** out_name) {
464 if (out_name == NULL) {
465 return AMEDIA_ERROR_INVALID_PARAMETER;
466 }
467
468 AString compName;
469 status_t err = mData->mCodec->getName(&compName);
470 if (err != OK) {
471 return translate_error(err);
472 }
473 *out_name = strdup(compName.c_str());
474 return AMEDIA_OK;
475}
476
477EXPORT
478void AMediaCodec_releaseName(
479 AMediaCodec * /* mData */,
480 char* name) {
481 if (name != NULL) {
482 free(name);
483 }
484}
485
486EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700487media_status_t AMediaCodec_configure(
Marco Nelissen050eb322014-05-09 15:10:23 -0700488 AMediaCodec *mData,
489 const AMediaFormat* format,
490 ANativeWindow* window,
491 AMediaCrypto *crypto,
492 uint32_t flags) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700493 sp<AMessage> nativeFormat;
494 AMediaFormat_getFormat(format, &nativeFormat);
Manisha Jajoob821e1d2021-08-09 15:09:53 +0530495 // create our shallow copy, so we aren't victim to any later changes.
496 sp<AMessage> dupNativeFormat = nativeFormat->dup();
497 ALOGV("configure with format: %s", dupNativeFormat->debugString(0).c_str());
Marco Nelissen0c3be872014-05-01 10:14:44 -0700498 sp<Surface> surface = NULL;
499 if (window != NULL) {
500 surface = (Surface*) window;
501 }
502
Manisha Jajoob821e1d2021-08-09 15:09:53 +0530503 status_t err = mData->mCodec->configure(dupNativeFormat, surface,
Wei Jia00cc9922017-11-23 08:00:34 -0800504 crypto ? crypto->mCrypto : NULL, flags);
505 if (err != OK) {
506 ALOGE("configure: err(%d), failed with format: %s",
Manisha Jajoob821e1d2021-08-09 15:09:53 +0530507 err, dupNativeFormat->debugString(0).c_str());
Wei Jia00cc9922017-11-23 08:00:34 -0800508 }
509 return translate_error(err);
510}
511
512EXPORT
513media_status_t AMediaCodec_setAsyncNotifyCallback(
514 AMediaCodec *mData,
515 AMediaCodecOnAsyncNotifyCallback callback,
516 void *userdata) {
Wei Jia00cc9922017-11-23 08:00:34 -0800517
518 Mutex::Autolock _l(mData->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700519
520 if (mData->mAsyncNotify == NULL) {
521 mData->mAsyncNotify = new AMessage(kWhatAsyncNotify, mData->mHandler);
522 }
523
524 // always call, codec may have been reset/re-configured since last call.
525 status_t err = mData->mCodec->setCallback(mData->mAsyncNotify);
526 if (err != OK) {
527 ALOGE("setAsyncNotifyCallback: err(%d), failed to set async callback", err);
528 return translate_error(err);
529 }
530
Wei Jia00cc9922017-11-23 08:00:34 -0800531 mData->mAsyncCallback = callback;
532 mData->mAsyncCallbackUserData = userdata;
533
534 return AMEDIA_OK;
535}
536
Jin Heo2665ce82021-09-10 17:20:00 +0900537EXPORT
538media_status_t AMediaCodec_setOnFrameRenderedCallback(
539 AMediaCodec *mData,
540 AMediaCodecOnFrameRendered callback,
541 void *userdata) {
542 Mutex::Autolock _l(mData->mFrameRenderedCallbackLock);
543 if (mData->mFrameRenderedNotify == NULL) {
544 mData->mFrameRenderedNotify = new AMessage(kWhatFrameRenderedNotify, mData->mHandler);
545 }
546 status_t err = mData->mCodec->setOnFrameRenderedNotification(mData->mFrameRenderedNotify);
547 if (err != OK) {
548 ALOGE("setOnFrameRenderedNotifyCallback: err(%d), failed to set callback", err);
549 return translate_error(err);
550 }
551
552 mData->mFrameRenderedCallback = callback;
553 mData->mFrameRenderedCallbackUserData = userdata;
554
555 return AMEDIA_OK;
556}
Wei Jia00cc9922017-11-23 08:00:34 -0800557
558EXPORT
559media_status_t AMediaCodec_releaseCrypto(AMediaCodec *mData) {
560 return translate_error(mData->mCodec->releaseCrypto());
Marco Nelissen0c3be872014-05-01 10:14:44 -0700561}
562
Marco Nelissen3425fd52014-05-14 11:12:46 -0700563EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700564media_status_t AMediaCodec_start(AMediaCodec *mData) {
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700565 status_t ret = mData->mCodec->start();
566 if (ret != OK) {
567 return translate_error(ret);
568 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800569 mData->mActivityNotification = new AMessage(kWhatActivityNotify, mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700570 mData->mActivityNotification->setInt32("generation", mData->mGeneration);
571 requestActivityNotification(mData);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700572 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700573}
574
Marco Nelissen3425fd52014-05-14 11:12:46 -0700575EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700576media_status_t AMediaCodec_stop(AMediaCodec *mData) {
577 media_status_t ret = translate_error(mData->mCodec->stop());
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700578
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800579 sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700580 sp<AMessage> response;
581 msg->postAndAwaitResponse(&response);
582 mData->mActivityNotification.clear();
583
584 return ret;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700585}
586
Marco Nelissen3425fd52014-05-14 11:12:46 -0700587EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700588media_status_t AMediaCodec_flush(AMediaCodec *mData) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700589 return translate_error(mData->mCodec->flush());
590}
591
Marco Nelissen3425fd52014-05-14 11:12:46 -0700592EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700593ssize_t AMediaCodec_dequeueInputBuffer(AMediaCodec *mData, int64_t timeoutUs) {
594 size_t idx;
595 status_t ret = mData->mCodec->dequeueInputBuffer(&idx, timeoutUs);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700596 requestActivityNotification(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700597 if (ret == OK) {
598 return idx;
599 }
600 return translate_error(ret);
601}
602
Marco Nelissen3425fd52014-05-14 11:12:46 -0700603EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700604uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
Wei Jia00cc9922017-11-23 08:00:34 -0800605 if (mData->mAsyncNotify != NULL) {
606 // Asynchronous mode
607 sp<MediaCodecBuffer> abuf;
608 if (mData->mCodec->getInputBuffer(idx, &abuf) != 0) {
609 return NULL;
610 }
611
612 if (out_size != NULL) {
613 *out_size = abuf->capacity();
614 }
615 return abuf->data();
616 }
617
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900618 android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700619 if (mData->mCodec->getInputBuffers(&abufs) == 0) {
620 size_t n = abufs.size();
621 if (idx >= n) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700622 ALOGE("buffer index %zu out of range", idx);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700623 return NULL;
624 }
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900625 if (abufs[idx] == NULL) {
626 ALOGE("buffer index %zu is NULL", idx);
627 return NULL;
628 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700629 if (out_size != NULL) {
630 *out_size = abufs[idx]->capacity();
631 }
632 return abufs[idx]->data();
633 }
634 ALOGE("couldn't get input buffers");
635 return NULL;
636}
637
Marco Nelissen3425fd52014-05-14 11:12:46 -0700638EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700639uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
Wei Jia00cc9922017-11-23 08:00:34 -0800640 if (mData->mAsyncNotify != NULL) {
641 // Asynchronous mode
642 sp<MediaCodecBuffer> abuf;
643 if (mData->mCodec->getOutputBuffer(idx, &abuf) != 0) {
644 return NULL;
645 }
646
647 if (out_size != NULL) {
648 *out_size = abuf->capacity();
649 }
650 return abuf->data();
651 }
652
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900653 android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700654 if (mData->mCodec->getOutputBuffers(&abufs) == 0) {
655 size_t n = abufs.size();
656 if (idx >= n) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700657 ALOGE("buffer index %zu out of range", idx);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700658 return NULL;
659 }
660 if (out_size != NULL) {
661 *out_size = abufs[idx]->capacity();
662 }
663 return abufs[idx]->data();
664 }
665 ALOGE("couldn't get output buffers");
666 return NULL;
667}
668
Marco Nelissen3425fd52014-05-14 11:12:46 -0700669EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700670media_status_t AMediaCodec_queueInputBuffer(AMediaCodec *mData,
Marco Nelissen0c3be872014-05-01 10:14:44 -0700671 size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags) {
672
673 AString errorMsg;
674 status_t ret = mData->mCodec->queueInputBuffer(idx, offset, size, time, flags, &errorMsg);
675 return translate_error(ret);
676}
677
Marco Nelissen3425fd52014-05-14 11:12:46 -0700678EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700679ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec *mData,
680 AMediaCodecBufferInfo *info, int64_t timeoutUs) {
681 size_t idx;
682 size_t offset;
683 size_t size;
684 uint32_t flags;
685 int64_t presentationTimeUs;
686 status_t ret = mData->mCodec->dequeueOutputBuffer(&idx, &offset, &size, &presentationTimeUs,
687 &flags, timeoutUs);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700688 requestActivityNotification(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700689 switch (ret) {
690 case OK:
691 info->offset = offset;
692 info->size = size;
693 info->flags = flags;
694 info->presentationTimeUs = presentationTimeUs;
695 return idx;
696 case -EAGAIN:
697 return AMEDIACODEC_INFO_TRY_AGAIN_LATER;
698 case android::INFO_FORMAT_CHANGED:
699 return AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED;
700 case INFO_OUTPUT_BUFFERS_CHANGED:
701 return AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED;
702 default:
703 break;
704 }
705 return translate_error(ret);
706}
707
Marco Nelissen3425fd52014-05-14 11:12:46 -0700708EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700709AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec *mData) {
710 sp<AMessage> format;
711 mData->mCodec->getOutputFormat(&format);
712 return AMediaFormat_fromMsg(&format);
713}
714
Marco Nelissen3425fd52014-05-14 11:12:46 -0700715EXPORT
Wei Jia00cc9922017-11-23 08:00:34 -0800716AMediaFormat* AMediaCodec_getInputFormat(AMediaCodec *mData) {
717 sp<AMessage> format;
718 mData->mCodec->getInputFormat(&format);
719 return AMediaFormat_fromMsg(&format);
720}
721
722EXPORT
Manikanta Kanamarlapudi2c32f4d2017-07-07 16:24:31 +0530723AMediaFormat* AMediaCodec_getBufferFormat(AMediaCodec *mData, size_t index) {
724 sp<AMessage> format;
725 mData->mCodec->getOutputFormat(index, &format);
726 return AMediaFormat_fromMsg(&format);
727}
728
729EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700730media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec *mData, size_t idx, bool render) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700731 if (render) {
732 return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx));
733 } else {
734 return translate_error(mData->mCodec->releaseOutputBuffer(idx));
735 }
736}
737
Marco Nelissen3425fd52014-05-14 11:12:46 -0700738EXPORT
Marco Nelissen79e2b622014-05-16 08:07:28 -0700739media_status_t AMediaCodec_releaseOutputBufferAtTime(
740 AMediaCodec *mData, size_t idx, int64_t timestampNs) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700741 ALOGV("render @ %" PRId64, timestampNs);
Marco Nelissen79e2b622014-05-16 08:07:28 -0700742 return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx, timestampNs));
743}
744
Vineeta Srivastava8c35da52016-01-08 17:33:09 -0800745EXPORT
746media_status_t AMediaCodec_setOutputSurface(AMediaCodec *mData, ANativeWindow* window) {
747 sp<Surface> surface = NULL;
748 if (window != NULL) {
749 surface = (Surface*) window;
750 }
751 return translate_error(mData->mCodec->setSurface(surface));
752}
753
Praveen Chavan19431582017-01-16 11:56:18 -0800754EXPORT
755media_status_t AMediaCodec_createInputSurface(AMediaCodec *mData, ANativeWindow **surface) {
756 if (surface == NULL || mData == NULL) {
757 return AMEDIA_ERROR_INVALID_PARAMETER;
758 }
759 *surface = NULL;
760
761 sp<IGraphicBufferProducer> igbp = NULL;
762 status_t err = mData->mCodec->createInputSurface(&igbp);
763 if (err != NO_ERROR) {
764 return translate_error(err);
765 }
766
767 *surface = new Surface(igbp);
768 ANativeWindow_acquire(*surface);
769 return AMEDIA_OK;
770}
771
Praveen Chavan85a53632017-01-31 12:21:33 -0800772EXPORT
773media_status_t AMediaCodec_createPersistentInputSurface(ANativeWindow **surface) {
774 if (surface == NULL) {
775 return AMEDIA_ERROR_INVALID_PARAMETER;
776 }
777 *surface = NULL;
778
779 sp<PersistentSurface> ps = MediaCodec::CreatePersistentInputSurface();
780 if (ps == NULL) {
781 return AMEDIA_ERROR_UNKNOWN;
782 }
783
784 sp<IGraphicBufferProducer> igbp = ps->getBufferProducer();
785 if (igbp == NULL) {
786 return AMEDIA_ERROR_UNKNOWN;
787 }
788
789 *surface = new AMediaCodecPersistentSurface(igbp, ps);
790 ANativeWindow_acquire(*surface);
791
792 return AMEDIA_OK;
793}
794
795EXPORT
796media_status_t AMediaCodec_setInputSurface(
797 AMediaCodec *mData, ANativeWindow *surface) {
798
799 if (surface == NULL || mData == NULL) {
800 return AMEDIA_ERROR_INVALID_PARAMETER;
801 }
802
803 AMediaCodecPersistentSurface *aMediaPersistentSurface =
804 static_cast<AMediaCodecPersistentSurface *>(surface);
805 if (aMediaPersistentSurface->mPersistentSurface == NULL) {
806 return AMEDIA_ERROR_INVALID_PARAMETER;
807 }
808
809 return translate_error(mData->mCodec->setInputSurface(
810 aMediaPersistentSurface->mPersistentSurface));
811}
812
Praveen Chavanf373e842017-02-01 11:50:15 -0800813EXPORT
814media_status_t AMediaCodec_setParameters(
815 AMediaCodec *mData, const AMediaFormat* params) {
816 if (params == NULL || mData == NULL) {
817 return AMEDIA_ERROR_INVALID_PARAMETER;
818 }
819 sp<AMessage> nativeParams;
820 AMediaFormat_getFormat(params, &nativeParams);
821 ALOGV("setParameters: %s", nativeParams->debugString(0).c_str());
822
823 return translate_error(mData->mCodec->setParameters(nativeParams));
824}
825
Robert Shihaf42d3f2017-03-20 16:45:37 -0700826EXPORT
827media_status_t AMediaCodec_signalEndOfInputStream(AMediaCodec *mData) {
828
829 if (mData == NULL) {
830 return AMEDIA_ERROR_INVALID_PARAMETER;
831 }
832
833 status_t err = mData->mCodec->signalEndOfInputStream();
834 if (err == INVALID_OPERATION) {
835 return AMEDIA_ERROR_INVALID_OPERATION;
836 }
837
838 return translate_error(err);
839
840}
841
Marco Nelissene22a64b2014-05-23 15:49:49 -0700842//EXPORT
Glenn Kastenb187de12014-12-30 08:18:15 -0800843media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback,
844 void *userdata) {
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700845 mData->mCallback = callback;
846 mData->mCallbackUserData = userdata;
Marco Nelissene419d7c2014-05-15 14:17:25 -0700847 return AMEDIA_OK;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700848}
849
Marco Nelissen050eb322014-05-09 15:10:23 -0700850typedef struct AMediaCodecCryptoInfo {
851 int numsubsamples;
852 uint8_t key[16];
853 uint8_t iv[16];
Marco Nelissen79e2b622014-05-16 08:07:28 -0700854 cryptoinfo_mode_t mode;
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800855 cryptoinfo_pattern_t pattern;
Marco Nelissen050eb322014-05-09 15:10:23 -0700856 size_t *clearbytes;
857 size_t *encryptedbytes;
858} AMediaCodecCryptoInfo;
859
Marco Nelissen3425fd52014-05-14 11:12:46 -0700860EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700861media_status_t AMediaCodec_queueSecureInputBuffer(
Marco Nelissen050eb322014-05-09 15:10:23 -0700862 AMediaCodec* codec,
863 size_t idx,
864 off_t offset,
865 AMediaCodecCryptoInfo* crypto,
866 uint64_t time,
867 uint32_t flags) {
868
869 CryptoPlugin::SubSample *subSamples = new CryptoPlugin::SubSample[crypto->numsubsamples];
870 for (int i = 0; i < crypto->numsubsamples; i++) {
871 subSamples[i].mNumBytesOfClearData = crypto->clearbytes[i];
872 subSamples[i].mNumBytesOfEncryptedData = crypto->encryptedbytes[i];
873 }
874
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800875 CryptoPlugin::Pattern pattern;
876 pattern.mEncryptBlocks = crypto->pattern.encryptBlocks;
877 pattern.mSkipBlocks = crypto->pattern.skipBlocks;
878
Marco Nelissen050eb322014-05-09 15:10:23 -0700879 AString errormsg;
880 status_t err = codec->mCodec->queueSecureInputBuffer(idx,
881 offset,
882 subSamples,
883 crypto->numsubsamples,
884 crypto->key,
885 crypto->iv,
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800886 (CryptoPlugin::Mode)crypto->mode,
887 pattern,
Marco Nelissen050eb322014-05-09 15:10:23 -0700888 time,
889 flags,
890 &errormsg);
891 if (err != 0) {
892 ALOGE("queSecureInputBuffer: %s", errormsg.c_str());
893 }
Marco Nelissen829e0972014-05-13 16:22:19 -0700894 delete [] subSamples;
Marco Nelissen050eb322014-05-09 15:10:23 -0700895 return translate_error(err);
896}
897
Wei Jia00cc9922017-11-23 08:00:34 -0800898EXPORT
899bool AMediaCodecActionCode_isRecoverable(int32_t actionCode) {
900 return (actionCode == ACTION_CODE_RECOVERABLE);
901}
902
903EXPORT
904bool AMediaCodecActionCode_isTransient(int32_t actionCode) {
905 return (actionCode == ACTION_CODE_TRANSIENT);
906}
907
Marco Nelissen050eb322014-05-09 15:10:23 -0700908
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800909EXPORT
910void AMediaCodecCryptoInfo_setPattern(AMediaCodecCryptoInfo *info,
911 cryptoinfo_pattern_t *pattern) {
912 info->pattern.encryptBlocks = pattern->encryptBlocks;
913 info->pattern.skipBlocks = pattern->skipBlocks;
914}
Marco Nelissen050eb322014-05-09 15:10:23 -0700915
Marco Nelissen3425fd52014-05-14 11:12:46 -0700916EXPORT
Marco Nelissen050eb322014-05-09 15:10:23 -0700917AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new(
918 int numsubsamples,
919 uint8_t key[16],
920 uint8_t iv[16],
Marco Nelissen79e2b622014-05-16 08:07:28 -0700921 cryptoinfo_mode_t mode,
Marco Nelissen050eb322014-05-09 15:10:23 -0700922 size_t *clearbytes,
923 size_t *encryptedbytes) {
924
925 // size needed to store all the crypto data
Marco Nelissend1fd0272018-07-31 15:12:51 -0700926 size_t cryptosize;
927 // = sizeof(AMediaCodecCryptoInfo) + sizeof(size_t) * numsubsamples * 2;
928 if (__builtin_mul_overflow(sizeof(size_t) * 2, numsubsamples, &cryptosize) ||
929 __builtin_add_overflow(cryptosize, sizeof(AMediaCodecCryptoInfo), &cryptosize)) {
930 ALOGE("crypto size overflow");
931 return NULL;
932 }
Marco Nelissen050eb322014-05-09 15:10:23 -0700933 AMediaCodecCryptoInfo *ret = (AMediaCodecCryptoInfo*) malloc(cryptosize);
934 if (!ret) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700935 ALOGE("couldn't allocate %zu bytes", cryptosize);
Marco Nelissen050eb322014-05-09 15:10:23 -0700936 return NULL;
937 }
938 ret->numsubsamples = numsubsamples;
939 memcpy(ret->key, key, 16);
940 memcpy(ret->iv, iv, 16);
941 ret->mode = mode;
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800942 ret->pattern.encryptBlocks = 0;
943 ret->pattern.skipBlocks = 0;
Marco Nelissen050eb322014-05-09 15:10:23 -0700944
945 // clearbytes and encryptedbytes point at the actual data, which follows
Marco Nelissen829e0972014-05-13 16:22:19 -0700946 ret->clearbytes = (size_t*) (ret + 1); // point immediately after the struct
947 ret->encryptedbytes = ret->clearbytes + numsubsamples; // point after the clear sizes
Marco Nelissen050eb322014-05-09 15:10:23 -0700948
Marco Nelissen829e0972014-05-13 16:22:19 -0700949 memcpy(ret->clearbytes, clearbytes, numsubsamples * sizeof(size_t));
950 memcpy(ret->encryptedbytes, encryptedbytes, numsubsamples * sizeof(size_t));
Marco Nelissen050eb322014-05-09 15:10:23 -0700951
952 return ret;
953}
954
955
Marco Nelissen3425fd52014-05-14 11:12:46 -0700956EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700957media_status_t AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo* info) {
Marco Nelissen050eb322014-05-09 15:10:23 -0700958 free(info);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700959 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700960}
961
Marco Nelissen3425fd52014-05-14 11:12:46 -0700962EXPORT
Marco Nelissen050eb322014-05-09 15:10:23 -0700963size_t AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo* ci) {
964 return ci->numsubsamples;
965}
966
Marco Nelissen3425fd52014-05-14 11:12:46 -0700967EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700968media_status_t AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
969 if (!ci) {
970 return AMEDIA_ERROR_INVALID_OBJECT;
971 }
972 if (!dst) {
973 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700974 }
975 memcpy(dst, ci->key, 16);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700976 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700977}
978
Marco Nelissen3425fd52014-05-14 11:12:46 -0700979EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700980media_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
981 if (!ci) {
982 return AMEDIA_ERROR_INVALID_OBJECT;
983 }
984 if (!dst) {
985 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700986 }
987 memcpy(dst, ci->iv, 16);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700988 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700989}
990
Marco Nelissen3425fd52014-05-14 11:12:46 -0700991EXPORT
Marco Nelissen79e2b622014-05-16 08:07:28 -0700992cryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo* ci) {
Marco Nelissen050eb322014-05-09 15:10:23 -0700993 if (!ci) {
Marco Nelissen79e2b622014-05-16 08:07:28 -0700994 return (cryptoinfo_mode_t) AMEDIA_ERROR_INVALID_OBJECT;
Marco Nelissen050eb322014-05-09 15:10:23 -0700995 }
996 return ci->mode;
997}
998
Marco Nelissen3425fd52014-05-14 11:12:46 -0700999EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -07001000media_status_t AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
1001 if (!ci) {
1002 return AMEDIA_ERROR_INVALID_OBJECT;
1003 }
1004 if (!dst) {
1005 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -07001006 }
1007 memcpy(dst, ci->clearbytes, sizeof(size_t) * ci->numsubsamples);
Marco Nelissene419d7c2014-05-15 14:17:25 -07001008 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -07001009}
1010
Marco Nelissen3425fd52014-05-14 11:12:46 -07001011EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -07001012media_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
1013 if (!ci) {
1014 return AMEDIA_ERROR_INVALID_OBJECT;
1015 }
1016 if (!dst) {
1017 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -07001018 }
1019 memcpy(dst, ci->encryptedbytes, sizeof(size_t) * ci->numsubsamples);
Marco Nelissene419d7c2014-05-15 14:17:25 -07001020 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -07001021}
Marco Nelissencdb42cd2014-05-08 14:46:05 -07001022
Ray Essickef058462021-01-24 14:50:08 -08001023EXPORT const char* AMEDIACODEC_KEY_HDR10_PLUS_INFO = AMEDIAFORMAT_KEY_HDR10_PLUS_INFO;
1024EXPORT const char* AMEDIACODEC_KEY_LOW_LATENCY = AMEDIAFORMAT_KEY_LOW_LATENCY;
1025EXPORT const char* AMEDIACODEC_KEY_OFFSET_TIME = "time-offset-us";
1026EXPORT const char* AMEDIACODEC_KEY_REQUEST_SYNC_FRAME = "request-sync";
1027EXPORT const char* AMEDIACODEC_KEY_SUSPEND = "drop-input-frames";
1028EXPORT const char* AMEDIACODEC_KEY_SUSPEND_TIME = "drop-start-time-us";
1029EXPORT const char* AMEDIACODEC_KEY_VIDEO_BITRATE = "video-bitrate";
1030
Marco Nelissen0c3be872014-05-01 10:14:44 -07001031} // extern "C"
1032