blob: 805ebc52c64f75f4f4cf406eb63d95ac6e89a503 [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
Jin Heoe15572c2022-06-14 14:43:11 +090017#include <charconv>
Mark Salyzyn98f28cd2014-06-18 16:32:50 -070018#include <inttypes.h>
Ray Essicka49482a2022-03-12 13:52:24 -080019#include <mutex>
20#include <set>
Mark Salyzyn98f28cd2014-06-18 16:32:50 -070021
Marco Nelissenc7a11b22014-05-30 10:13:25 -070022//#define LOG_NDEBUG 0
Marco Nelissen0c3be872014-05-01 10:14:44 -070023#define LOG_TAG "NdkMediaCodec"
24
Chong Zhangefd1c5c2020-11-18 10:33:13 -080025#include <media/NdkMediaCodecPlatform.h>
Colin Cross7e8d4ba2017-05-04 16:17:42 -070026#include <media/NdkMediaError.h>
Marco Nelissen98603d82018-07-17 11:06:55 -070027#include <media/NdkMediaFormatPriv.h>
Marco Nelissen050eb322014-05-09 15:10:23 -070028#include "NdkMediaCryptoPriv.h"
Marco Nelissen0c3be872014-05-01 10:14:44 -070029
30#include <utils/Log.h>
31#include <utils/StrongPointer.h>
32#include <gui/Surface.h>
33
Marco Nelissen0c3be872014-05-01 10:14:44 -070034#include <media/stagefright/foundation/ALooper.h>
Jin Heo2665ce82021-09-10 17:20:00 +090035#include <media/stagefright/foundation/ABuffer.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070036#include <media/stagefright/foundation/AMessage.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070037
Praveen Chavan85a53632017-01-31 12:21:33 -080038#include <media/stagefright/PersistentSurface.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070039#include <media/stagefright/MediaCodec.h>
40#include <media/stagefright/MediaErrors.h>
Wonsik Kim7e34bf52016-08-23 00:09:18 +090041#include <media/MediaCodecBuffer.h>
Praveen Chavan19431582017-01-16 11:56:18 -080042#include <android/native_window.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070043
44using namespace android;
45
46
Marco Nelissene419d7c2014-05-15 14:17:25 -070047static media_status_t translate_error(status_t err) {
Ray Essicka49482a2022-03-12 13:52:24 -080048
Marco Nelissen0c3be872014-05-01 10:14:44 -070049 if (err == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -070050 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -070051 } else if (err == -EAGAIN) {
Marco Nelissene419d7c2014-05-15 14:17:25 -070052 return (media_status_t) AMEDIACODEC_INFO_TRY_AGAIN_LATER;
Chong Zhangeb9aca62020-09-16 12:49:41 -070053 } else if (err == NO_MEMORY) {
54 return AMEDIACODEC_ERROR_INSUFFICIENT_RESOURCE;
55 } else if (err == DEAD_OBJECT) {
56 return AMEDIACODEC_ERROR_RECLAIMED;
Marco Nelissen0c3be872014-05-01 10:14:44 -070057 }
Ray Essicka49482a2022-03-12 13:52:24 -080058
59 {
60 // minimize log flooding. Some CTS behavior made this noisy and apps could do the same.
61 static std::set<status_t> untranslated;
62 static std::mutex mutex;
63 std::lock_guard lg(mutex);
64
65 if (untranslated.find(err) == untranslated.end()) {
66 ALOGE("untranslated sf error code: %d", err);
67 untranslated.insert(err);
68 }
69 }
Marco Nelissene419d7c2014-05-15 14:17:25 -070070 return AMEDIA_ERROR_UNKNOWN;
Marco Nelissen0c3be872014-05-01 10:14:44 -070071}
72
Marco Nelissencdb42cd2014-05-08 14:46:05 -070073enum {
74 kWhatActivityNotify,
Wei Jia00cc9922017-11-23 08:00:34 -080075 kWhatAsyncNotify,
Marco Nelissencdb42cd2014-05-08 14:46:05 -070076 kWhatRequestActivityNotifications,
77 kWhatStopActivityNotifications,
Jin Heo2665ce82021-09-10 17:20:00 +090078 kWhatFrameRenderedNotify,
Marco Nelissen0c3be872014-05-01 10:14:44 -070079};
80
Praveen Chavan85a53632017-01-31 12:21:33 -080081struct AMediaCodecPersistentSurface : public Surface {
82 sp<PersistentSurface> mPersistentSurface;
83 AMediaCodecPersistentSurface(
84 const sp<IGraphicBufferProducer>& igbp,
85 const sp<PersistentSurface>& ps)
86 : Surface(igbp) {
87 mPersistentSurface = ps;
88 }
89 virtual ~AMediaCodecPersistentSurface() {
90 //mPersistentSurface ref will be let go off here
91 }
92};
Marco Nelissen0c3be872014-05-01 10:14:44 -070093
Marco Nelissencdb42cd2014-05-08 14:46:05 -070094class CodecHandler: public AHandler {
95private:
96 AMediaCodec* mCodec;
97public:
Chih-Hung Hsieh090ef602016-04-27 10:39:54 -070098 explicit CodecHandler(AMediaCodec *codec);
Marco Nelissencdb42cd2014-05-08 14:46:05 -070099 virtual void onMessageReceived(const sp<AMessage> &msg);
100};
Marco Nelissen0c3be872014-05-01 10:14:44 -0700101
Marco Nelissene22a64b2014-05-23 15:49:49 -0700102typedef void (*OnCodecEvent)(AMediaCodec *codec, void *userdata);
103
Marco Nelissen0c3be872014-05-01 10:14:44 -0700104struct AMediaCodec {
105 sp<android::MediaCodec> mCodec;
106 sp<ALooper> mLooper;
107 sp<CodecHandler> mHandler;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700108 sp<AMessage> mActivityNotification;
109 int32_t mGeneration;
110 bool mRequestedActivityNotification;
111 OnCodecEvent mCallback;
112 void *mCallbackUserData;
Wei Jia00cc9922017-11-23 08:00:34 -0800113
114 sp<AMessage> mAsyncNotify;
115 mutable Mutex mAsyncCallbackLock;
116 AMediaCodecOnAsyncNotifyCallback mAsyncCallback;
117 void *mAsyncCallbackUserData;
Jin Heo2665ce82021-09-10 17:20:00 +0900118
119 sp<AMessage> mFrameRenderedNotify;
120 mutable Mutex mFrameRenderedCallbackLock;
121 AMediaCodecOnFrameRendered mFrameRenderedCallback;
122 void *mFrameRenderedCallbackUserData;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700123};
124
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700125CodecHandler::CodecHandler(AMediaCodec *codec) {
126 mCodec = codec;
127}
128
129void CodecHandler::onMessageReceived(const sp<AMessage> &msg) {
130
131 switch (msg->what()) {
132 case kWhatRequestActivityNotifications:
133 {
134 if (mCodec->mRequestedActivityNotification) {
135 break;
136 }
137
138 mCodec->mCodec->requestActivityNotification(mCodec->mActivityNotification);
139 mCodec->mRequestedActivityNotification = true;
140 break;
141 }
142
143 case kWhatActivityNotify:
144 {
145 {
146 int32_t generation;
147 msg->findInt32("generation", &generation);
148
149 if (generation != mCodec->mGeneration) {
150 // stale
151 break;
152 }
153
154 mCodec->mRequestedActivityNotification = false;
155 }
156
157 if (mCodec->mCallback) {
158 mCodec->mCallback(mCodec, mCodec->mCallbackUserData);
159 }
160 break;
161 }
162
Wei Jia00cc9922017-11-23 08:00:34 -0800163 case kWhatAsyncNotify:
164 {
165 int32_t cbID;
166 if (!msg->findInt32("callbackID", &cbID)) {
167 ALOGE("kWhatAsyncNotify: callbackID is expected.");
168 break;
169 }
170
171 ALOGV("kWhatAsyncNotify: cbID = %d", cbID);
172
173 switch (cbID) {
174 case MediaCodec::CB_INPUT_AVAILABLE:
175 {
176 int32_t index;
177 if (!msg->findInt32("index", &index)) {
178 ALOGE("CB_INPUT_AVAILABLE: index is expected.");
179 break;
180 }
181
182 Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700183 if (mCodec->mAsyncCallback.onAsyncInputAvailable != NULL) {
Wei Jia00cc9922017-11-23 08:00:34 -0800184 mCodec->mAsyncCallback.onAsyncInputAvailable(
185 mCodec,
186 mCodec->mAsyncCallbackUserData,
187 index);
188 }
189
190 break;
191 }
192
193 case MediaCodec::CB_OUTPUT_AVAILABLE:
194 {
195 int32_t index;
196 size_t offset;
197 size_t size;
198 int64_t timeUs;
199 int32_t flags;
200
201 if (!msg->findInt32("index", &index)) {
202 ALOGE("CB_OUTPUT_AVAILABLE: index is expected.");
203 break;
204 }
205 if (!msg->findSize("offset", &offset)) {
206 ALOGE("CB_OUTPUT_AVAILABLE: offset is expected.");
207 break;
208 }
209 if (!msg->findSize("size", &size)) {
210 ALOGE("CB_OUTPUT_AVAILABLE: size is expected.");
211 break;
212 }
213 if (!msg->findInt64("timeUs", &timeUs)) {
214 ALOGE("CB_OUTPUT_AVAILABLE: timeUs is expected.");
215 break;
216 }
217 if (!msg->findInt32("flags", &flags)) {
218 ALOGE("CB_OUTPUT_AVAILABLE: flags is expected.");
219 break;
220 }
221
222 AMediaCodecBufferInfo bufferInfo = {
223 (int32_t)offset,
224 (int32_t)size,
225 timeUs,
226 (uint32_t)flags};
227
228 Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700229 if (mCodec->mAsyncCallback.onAsyncOutputAvailable != NULL) {
Wei Jia00cc9922017-11-23 08:00:34 -0800230 mCodec->mAsyncCallback.onAsyncOutputAvailable(
231 mCodec,
232 mCodec->mAsyncCallbackUserData,
233 index,
234 &bufferInfo);
235 }
236
237 break;
238 }
239
240 case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
241 {
242 sp<AMessage> format;
243 if (!msg->findMessage("format", &format)) {
244 ALOGE("CB_OUTPUT_FORMAT_CHANGED: format is expected.");
245 break;
246 }
247
Chong Zhang1fa26862019-09-16 16:15:00 -0700248 // Here format is MediaCodec's internal copy of output format.
249 // Make a copy since the client might modify it.
250 sp<AMessage> copy;
251 if (format != nullptr) {
252 copy = format->dup();
253 }
254 AMediaFormat *aMediaFormat = AMediaFormat_fromMsg(&copy);
Wei Jia00cc9922017-11-23 08:00:34 -0800255
256 Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700257 if (mCodec->mAsyncCallback.onAsyncFormatChanged != NULL) {
Wei Jia00cc9922017-11-23 08:00:34 -0800258 mCodec->mAsyncCallback.onAsyncFormatChanged(
259 mCodec,
260 mCodec->mAsyncCallbackUserData,
261 aMediaFormat);
262 }
263
264 break;
265 }
266
267 case MediaCodec::CB_ERROR:
268 {
269 status_t err;
270 int32_t actionCode;
271 AString detail;
272 if (!msg->findInt32("err", &err)) {
273 ALOGE("CB_ERROR: err is expected.");
274 break;
275 }
Rakesh Kumard5ea3f32019-09-20 17:08:07 +0530276 if (!msg->findInt32("actionCode", &actionCode)) {
277 ALOGE("CB_ERROR: actionCode is expected.");
Wei Jia00cc9922017-11-23 08:00:34 -0800278 break;
279 }
280 msg->findString("detail", &detail);
Arun Johnsondc1e59e2022-04-13 23:26:54 +0000281 ALOGE("Codec reported error(0x%x/%s), actionCode(%d), detail(%s)",
282 err, StrMediaError(err).c_str(), actionCode, detail.c_str());
Wei Jia00cc9922017-11-23 08:00:34 -0800283
284 Mutex::Autolock _l(mCodec->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700285 if (mCodec->mAsyncCallback.onAsyncError != NULL) {
Wei Jia00cc9922017-11-23 08:00:34 -0800286 mCodec->mAsyncCallback.onAsyncError(
287 mCodec,
288 mCodec->mAsyncCallbackUserData,
289 translate_error(err),
290 actionCode,
291 detail.c_str());
292 }
293
294 break;
295 }
296
297 default:
298 {
299 ALOGE("kWhatAsyncNotify: callbackID(%d) is unexpected.", cbID);
300 break;
301 }
302 }
303 break;
304 }
305
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700306 case kWhatStopActivityNotifications:
307 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800308 sp<AReplyToken> replyID;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700309 msg->senderAwaitsResponse(&replyID);
310
311 mCodec->mGeneration++;
312 mCodec->mRequestedActivityNotification = false;
313
314 sp<AMessage> response = new AMessage;
315 response->postReply(replyID);
316 break;
317 }
318
Jin Heo2665ce82021-09-10 17:20:00 +0900319 case kWhatFrameRenderedNotify:
320 {
321 sp<AMessage> data;
322 if (!msg->findMessage("data", &data)) {
323 ALOGE("kWhatFrameRenderedNotify: data is expected.");
324 break;
325 }
326
327 AMessage::Type type;
Jin Heoe15572c2022-06-14 14:43:11 +0900328 size_t n = data->countEntries();
Jin Heo2665ce82021-09-10 17:20:00 +0900329
Jin Heoe15572c2022-06-14 14:43:11 +0900330 thread_local std::vector<std::optional<int64_t>> mediaTimesInUs;
331 thread_local std::vector<std::optional<int64_t>> systemTimesInNs;
332 mediaTimesInUs.resize(n);
333 systemTimesInNs.resize(n);
334 std::fill_n(mediaTimesInUs.begin(), n, std::nullopt);
335 std::fill_n(systemTimesInNs.begin(), n, std::nullopt);
336 for (size_t i = 0; i < n; i++) {
337 AString name = data->getEntryNameAt(i, &type);
338 if (name.endsWith("-media-time-us")) {
339 int64_t mediaTimeUs;
340 AMessage::ItemData itemData = data->getEntryAt(i);
341 itemData.find(&mediaTimeUs);
Jin Heo2665ce82021-09-10 17:20:00 +0900342
Jin Heoe15572c2022-06-14 14:43:11 +0900343 int index = -1;
344 std::from_chars_result result = std::from_chars(
345 name.c_str(), name.c_str() + name.find("-"), index);
346 if (result.ec == std::errc() && 0 <= index && index < n) {
347 mediaTimesInUs[index] = mediaTimeUs;
348 } else {
349 std::error_code ec = std::make_error_code(result.ec);
350 ALOGE("Unexpected media time index: #%d with value %lldus (err=%d %s)",
351 index, (long long)mediaTimeUs, ec.value(), ec.message().c_str());
352 }
353 } else if (name.endsWith("-system-nano")) {
354 int64_t systemNano;
355 AMessage::ItemData itemData = data->getEntryAt(i);
356 itemData.find(&systemNano);
357
358 int index = -1;
359 std::from_chars_result result = std::from_chars(
360 name.c_str(), name.c_str() + name.find("-"), index);
361 if (result.ec == std::errc() && 0 <= index && index < n) {
362 systemTimesInNs[index] = systemNano;
363 } else {
364 std::error_code ec = std::make_error_code(result.ec);
365 ALOGE("Unexpected system time index: #%d with value %lldns (err=%d %s)",
366 index, (long long)systemNano, ec.value(), ec.message().c_str());
367 }
368 }
369 }
370
371 Mutex::Autolock _l(mCodec->mFrameRenderedCallbackLock);
372 if (mCodec->mFrameRenderedCallback != NULL) {
373 for (size_t i = 0; i < n; ++i) {
374 if (mediaTimesInUs[i] && systemTimesInNs[i]) {
Jin Heo2665ce82021-09-10 17:20:00 +0900375 mCodec->mFrameRenderedCallback(
376 mCodec,
377 mCodec->mFrameRenderedCallbackUserData,
Jin Heoe15572c2022-06-14 14:43:11 +0900378 mediaTimesInUs[i].value(),
379 systemTimesInNs[i].value());
380 } else {
381 break;
Jin Heo2665ce82021-09-10 17:20:00 +0900382 }
Jin Heo2665ce82021-09-10 17:20:00 +0900383 }
384 }
385 break;
386 }
387
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700388 default:
389 ALOGE("shouldn't be here");
390 break;
391 }
392
393}
394
395
396static void requestActivityNotification(AMediaCodec *codec) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800397 (new AMessage(kWhatRequestActivityNotifications, codec->mHandler))->post();
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700398}
399
Marco Nelissen0c3be872014-05-01 10:14:44 -0700400extern "C" {
401
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800402static AMediaCodec * createAMediaCodec(const char *name,
403 bool name_is_type,
404 bool encoder,
405 pid_t pid = android::MediaCodec::kNoPid,
406 uid_t uid = android::MediaCodec::kNoUid) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700407 AMediaCodec *mData = new AMediaCodec();
408 mData->mLooper = new ALooper;
409 mData->mLooper->setName("NDK MediaCodec_looper");
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800410 size_t res = mData->mLooper->start(
Marco Nelissen0c3be872014-05-01 10:14:44 -0700411 false, // runOnCallingThread
412 true, // canCallJava XXX
Wei Jia00cc9922017-11-23 08:00:34 -0800413 PRIORITY_AUDIO);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800414 if (res != OK) {
415 ALOGE("Failed to start the looper");
Greg Kaiser4e147802016-03-14 14:44:20 -0700416 AMediaCodec_delete(mData);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800417 return NULL;
418 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700419 if (name_is_type) {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800420 mData->mCodec = android::MediaCodec::CreateByType(
421 mData->mLooper,
422 name,
423 encoder,
424 nullptr /* err */,
425 pid,
426 uid);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700427 } else {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800428 mData->mCodec = android::MediaCodec::CreateByComponentName(
429 mData->mLooper,
430 name,
431 nullptr /* err */,
432 pid,
433 uid);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700434 }
Andy Hung6bb63ad2015-04-28 19:05:08 -0700435 if (mData->mCodec == NULL) { // failed to create codec
436 AMediaCodec_delete(mData);
437 return NULL;
438 }
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700439 mData->mHandler = new CodecHandler(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700440 mData->mLooper->registerHandler(mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700441 mData->mGeneration = 1;
442 mData->mRequestedActivityNotification = false;
443 mData->mCallback = NULL;
444
Wei Jia00cc9922017-11-23 08:00:34 -0800445 mData->mAsyncCallback = {};
446 mData->mAsyncCallbackUserData = NULL;
447
Marco Nelissen0c3be872014-05-01 10:14:44 -0700448 return mData;
449}
450
Marco Nelissen3425fd52014-05-14 11:12:46 -0700451EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700452AMediaCodec* AMediaCodec_createCodecByName(const char *name) {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800453 return createAMediaCodec(name, false /* name_is_type */, false /* encoder */);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700454}
455
Marco Nelissen3425fd52014-05-14 11:12:46 -0700456EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700457AMediaCodec* AMediaCodec_createDecoderByType(const char *mime_type) {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800458 return createAMediaCodec(mime_type, true /* name_is_type */, false /* encoder */);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700459}
460
Marco Nelissen3425fd52014-05-14 11:12:46 -0700461EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700462AMediaCodec* AMediaCodec_createEncoderByType(const char *name) {
Chong Zhangefd1c5c2020-11-18 10:33:13 -0800463 return createAMediaCodec(name, true /* name_is_type */, true /* encoder */);
464}
465
466EXPORT
467AMediaCodec* AMediaCodec_createCodecByNameForClient(const char *name,
468 pid_t pid,
469 uid_t uid) {
470 return createAMediaCodec(name, false /* name_is_type */, false /* encoder */, pid, uid);
471}
472
473EXPORT
474AMediaCodec* AMediaCodec_createDecoderByTypeForClient(const char *mime_type,
475 pid_t pid,
476 uid_t uid) {
477 return createAMediaCodec(mime_type, true /* name_is_type */, false /* encoder */, pid, uid);
478}
479
480EXPORT
481AMediaCodec* AMediaCodec_createEncoderByTypeForClient(const char *name,
482 pid_t pid,
483 uid_t uid) {
484 return createAMediaCodec(name, true /* name_is_type */, true /* encoder */, pid, uid);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700485}
486
Marco Nelissen3425fd52014-05-14 11:12:46 -0700487EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700488media_status_t AMediaCodec_delete(AMediaCodec *mData) {
Andy Hung6bb63ad2015-04-28 19:05:08 -0700489 if (mData != NULL) {
490 if (mData->mCodec != NULL) {
491 mData->mCodec->release();
492 mData->mCodec.clear();
493 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700494
Andy Hung6bb63ad2015-04-28 19:05:08 -0700495 if (mData->mLooper != NULL) {
496 if (mData->mHandler != NULL) {
497 mData->mLooper->unregisterHandler(mData->mHandler->id());
498 }
499 mData->mLooper->stop();
500 mData->mLooper.clear();
501 }
502 delete mData;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700503 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700504 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700505}
506
Marco Nelissen3425fd52014-05-14 11:12:46 -0700507EXPORT
Wei Jia00cc9922017-11-23 08:00:34 -0800508media_status_t AMediaCodec_getName(
509 AMediaCodec *mData,
510 char** out_name) {
511 if (out_name == NULL) {
512 return AMEDIA_ERROR_INVALID_PARAMETER;
513 }
514
515 AString compName;
516 status_t err = mData->mCodec->getName(&compName);
517 if (err != OK) {
518 return translate_error(err);
519 }
520 *out_name = strdup(compName.c_str());
521 return AMEDIA_OK;
522}
523
524EXPORT
525void AMediaCodec_releaseName(
526 AMediaCodec * /* mData */,
527 char* name) {
528 if (name != NULL) {
529 free(name);
530 }
531}
532
533EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700534media_status_t AMediaCodec_configure(
Marco Nelissen050eb322014-05-09 15:10:23 -0700535 AMediaCodec *mData,
536 const AMediaFormat* format,
537 ANativeWindow* window,
538 AMediaCrypto *crypto,
539 uint32_t flags) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700540 sp<AMessage> nativeFormat;
541 AMediaFormat_getFormat(format, &nativeFormat);
Manisha Jajoob821e1d2021-08-09 15:09:53 +0530542 // create our shallow copy, so we aren't victim to any later changes.
543 sp<AMessage> dupNativeFormat = nativeFormat->dup();
544 ALOGV("configure with format: %s", dupNativeFormat->debugString(0).c_str());
Marco Nelissen0c3be872014-05-01 10:14:44 -0700545 sp<Surface> surface = NULL;
546 if (window != NULL) {
547 surface = (Surface*) window;
548 }
549
Manisha Jajoob821e1d2021-08-09 15:09:53 +0530550 status_t err = mData->mCodec->configure(dupNativeFormat, surface,
Wei Jia00cc9922017-11-23 08:00:34 -0800551 crypto ? crypto->mCrypto : NULL, flags);
552 if (err != OK) {
553 ALOGE("configure: err(%d), failed with format: %s",
Manisha Jajoob821e1d2021-08-09 15:09:53 +0530554 err, dupNativeFormat->debugString(0).c_str());
Wei Jia00cc9922017-11-23 08:00:34 -0800555 }
556 return translate_error(err);
557}
558
559EXPORT
560media_status_t AMediaCodec_setAsyncNotifyCallback(
561 AMediaCodec *mData,
562 AMediaCodecOnAsyncNotifyCallback callback,
563 void *userdata) {
Wei Jia00cc9922017-11-23 08:00:34 -0800564
565 Mutex::Autolock _l(mData->mAsyncCallbackLock);
Ray Essick4e5af242021-11-05 14:20:22 -0700566
567 if (mData->mAsyncNotify == NULL) {
568 mData->mAsyncNotify = new AMessage(kWhatAsyncNotify, mData->mHandler);
569 }
570
571 // always call, codec may have been reset/re-configured since last call.
572 status_t err = mData->mCodec->setCallback(mData->mAsyncNotify);
573 if (err != OK) {
574 ALOGE("setAsyncNotifyCallback: err(%d), failed to set async callback", err);
575 return translate_error(err);
576 }
577
Wei Jia00cc9922017-11-23 08:00:34 -0800578 mData->mAsyncCallback = callback;
579 mData->mAsyncCallbackUserData = userdata;
580
581 return AMEDIA_OK;
582}
583
Jin Heo2665ce82021-09-10 17:20:00 +0900584EXPORT
585media_status_t AMediaCodec_setOnFrameRenderedCallback(
586 AMediaCodec *mData,
587 AMediaCodecOnFrameRendered callback,
588 void *userdata) {
589 Mutex::Autolock _l(mData->mFrameRenderedCallbackLock);
590 if (mData->mFrameRenderedNotify == NULL) {
591 mData->mFrameRenderedNotify = new AMessage(kWhatFrameRenderedNotify, mData->mHandler);
592 }
593 status_t err = mData->mCodec->setOnFrameRenderedNotification(mData->mFrameRenderedNotify);
594 if (err != OK) {
595 ALOGE("setOnFrameRenderedNotifyCallback: err(%d), failed to set callback", err);
596 return translate_error(err);
597 }
598
599 mData->mFrameRenderedCallback = callback;
600 mData->mFrameRenderedCallbackUserData = userdata;
601
602 return AMEDIA_OK;
603}
Wei Jia00cc9922017-11-23 08:00:34 -0800604
605EXPORT
606media_status_t AMediaCodec_releaseCrypto(AMediaCodec *mData) {
607 return translate_error(mData->mCodec->releaseCrypto());
Marco Nelissen0c3be872014-05-01 10:14:44 -0700608}
609
Marco Nelissen3425fd52014-05-14 11:12:46 -0700610EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700611media_status_t AMediaCodec_start(AMediaCodec *mData) {
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700612 status_t ret = mData->mCodec->start();
613 if (ret != OK) {
614 return translate_error(ret);
615 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800616 mData->mActivityNotification = new AMessage(kWhatActivityNotify, mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700617 mData->mActivityNotification->setInt32("generation", mData->mGeneration);
618 requestActivityNotification(mData);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700619 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700620}
621
Marco Nelissen3425fd52014-05-14 11:12:46 -0700622EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700623media_status_t AMediaCodec_stop(AMediaCodec *mData) {
624 media_status_t ret = translate_error(mData->mCodec->stop());
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700625
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800626 sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700627 sp<AMessage> response;
628 msg->postAndAwaitResponse(&response);
629 mData->mActivityNotification.clear();
630
631 return ret;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700632}
633
Marco Nelissen3425fd52014-05-14 11:12:46 -0700634EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700635media_status_t AMediaCodec_flush(AMediaCodec *mData) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700636 return translate_error(mData->mCodec->flush());
637}
638
Marco Nelissen3425fd52014-05-14 11:12:46 -0700639EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700640ssize_t AMediaCodec_dequeueInputBuffer(AMediaCodec *mData, int64_t timeoutUs) {
641 size_t idx;
642 status_t ret = mData->mCodec->dequeueInputBuffer(&idx, timeoutUs);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700643 requestActivityNotification(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700644 if (ret == OK) {
645 return idx;
646 }
647 return translate_error(ret);
648}
649
Marco Nelissen3425fd52014-05-14 11:12:46 -0700650EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700651uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
Wei Jia00cc9922017-11-23 08:00:34 -0800652 if (mData->mAsyncNotify != NULL) {
653 // Asynchronous mode
654 sp<MediaCodecBuffer> abuf;
655 if (mData->mCodec->getInputBuffer(idx, &abuf) != 0) {
656 return NULL;
657 }
658
659 if (out_size != NULL) {
660 *out_size = abuf->capacity();
661 }
662 return abuf->data();
663 }
664
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900665 android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700666 if (mData->mCodec->getInputBuffers(&abufs) == 0) {
667 size_t n = abufs.size();
668 if (idx >= n) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700669 ALOGE("buffer index %zu out of range", idx);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700670 return NULL;
671 }
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900672 if (abufs[idx] == NULL) {
673 ALOGE("buffer index %zu is NULL", idx);
674 return NULL;
675 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700676 if (out_size != NULL) {
677 *out_size = abufs[idx]->capacity();
678 }
679 return abufs[idx]->data();
680 }
681 ALOGE("couldn't get input buffers");
682 return NULL;
683}
684
Marco Nelissen3425fd52014-05-14 11:12:46 -0700685EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700686uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
Wei Jia00cc9922017-11-23 08:00:34 -0800687 if (mData->mAsyncNotify != NULL) {
688 // Asynchronous mode
689 sp<MediaCodecBuffer> abuf;
690 if (mData->mCodec->getOutputBuffer(idx, &abuf) != 0) {
691 return NULL;
692 }
693
694 if (out_size != NULL) {
695 *out_size = abuf->capacity();
696 }
697 return abuf->data();
698 }
699
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900700 android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700701 if (mData->mCodec->getOutputBuffers(&abufs) == 0) {
702 size_t n = abufs.size();
703 if (idx >= n) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700704 ALOGE("buffer index %zu out of range", idx);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700705 return NULL;
706 }
707 if (out_size != NULL) {
708 *out_size = abufs[idx]->capacity();
709 }
710 return abufs[idx]->data();
711 }
712 ALOGE("couldn't get output buffers");
713 return NULL;
714}
715
Marco Nelissen3425fd52014-05-14 11:12:46 -0700716EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700717media_status_t AMediaCodec_queueInputBuffer(AMediaCodec *mData,
Marco Nelissen0c3be872014-05-01 10:14:44 -0700718 size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags) {
719
720 AString errorMsg;
721 status_t ret = mData->mCodec->queueInputBuffer(idx, offset, size, time, flags, &errorMsg);
722 return translate_error(ret);
723}
724
Marco Nelissen3425fd52014-05-14 11:12:46 -0700725EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700726ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec *mData,
727 AMediaCodecBufferInfo *info, int64_t timeoutUs) {
728 size_t idx;
729 size_t offset;
730 size_t size;
731 uint32_t flags;
732 int64_t presentationTimeUs;
733 status_t ret = mData->mCodec->dequeueOutputBuffer(&idx, &offset, &size, &presentationTimeUs,
734 &flags, timeoutUs);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700735 requestActivityNotification(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700736 switch (ret) {
737 case OK:
738 info->offset = offset;
739 info->size = size;
740 info->flags = flags;
741 info->presentationTimeUs = presentationTimeUs;
742 return idx;
743 case -EAGAIN:
744 return AMEDIACODEC_INFO_TRY_AGAIN_LATER;
745 case android::INFO_FORMAT_CHANGED:
746 return AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED;
747 case INFO_OUTPUT_BUFFERS_CHANGED:
748 return AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED;
749 default:
750 break;
751 }
752 return translate_error(ret);
753}
754
Marco Nelissen3425fd52014-05-14 11:12:46 -0700755EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700756AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec *mData) {
757 sp<AMessage> format;
758 mData->mCodec->getOutputFormat(&format);
759 return AMediaFormat_fromMsg(&format);
760}
761
Marco Nelissen3425fd52014-05-14 11:12:46 -0700762EXPORT
Wei Jia00cc9922017-11-23 08:00:34 -0800763AMediaFormat* AMediaCodec_getInputFormat(AMediaCodec *mData) {
764 sp<AMessage> format;
765 mData->mCodec->getInputFormat(&format);
766 return AMediaFormat_fromMsg(&format);
767}
768
769EXPORT
Manikanta Kanamarlapudi2c32f4d2017-07-07 16:24:31 +0530770AMediaFormat* AMediaCodec_getBufferFormat(AMediaCodec *mData, size_t index) {
771 sp<AMessage> format;
772 mData->mCodec->getOutputFormat(index, &format);
773 return AMediaFormat_fromMsg(&format);
774}
775
776EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700777media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec *mData, size_t idx, bool render) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700778 if (render) {
779 return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx));
780 } else {
781 return translate_error(mData->mCodec->releaseOutputBuffer(idx));
782 }
783}
784
Marco Nelissen3425fd52014-05-14 11:12:46 -0700785EXPORT
Marco Nelissen79e2b622014-05-16 08:07:28 -0700786media_status_t AMediaCodec_releaseOutputBufferAtTime(
787 AMediaCodec *mData, size_t idx, int64_t timestampNs) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700788 ALOGV("render @ %" PRId64, timestampNs);
Marco Nelissen79e2b622014-05-16 08:07:28 -0700789 return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx, timestampNs));
790}
791
Vineeta Srivastava8c35da52016-01-08 17:33:09 -0800792EXPORT
793media_status_t AMediaCodec_setOutputSurface(AMediaCodec *mData, ANativeWindow* window) {
794 sp<Surface> surface = NULL;
795 if (window != NULL) {
796 surface = (Surface*) window;
797 }
798 return translate_error(mData->mCodec->setSurface(surface));
799}
800
Praveen Chavan19431582017-01-16 11:56:18 -0800801EXPORT
802media_status_t AMediaCodec_createInputSurface(AMediaCodec *mData, ANativeWindow **surface) {
803 if (surface == NULL || mData == NULL) {
804 return AMEDIA_ERROR_INVALID_PARAMETER;
805 }
806 *surface = NULL;
807
808 sp<IGraphicBufferProducer> igbp = NULL;
809 status_t err = mData->mCodec->createInputSurface(&igbp);
810 if (err != NO_ERROR) {
811 return translate_error(err);
812 }
813
814 *surface = new Surface(igbp);
815 ANativeWindow_acquire(*surface);
816 return AMEDIA_OK;
817}
818
Praveen Chavan85a53632017-01-31 12:21:33 -0800819EXPORT
820media_status_t AMediaCodec_createPersistentInputSurface(ANativeWindow **surface) {
821 if (surface == NULL) {
822 return AMEDIA_ERROR_INVALID_PARAMETER;
823 }
824 *surface = NULL;
825
826 sp<PersistentSurface> ps = MediaCodec::CreatePersistentInputSurface();
827 if (ps == NULL) {
828 return AMEDIA_ERROR_UNKNOWN;
829 }
830
831 sp<IGraphicBufferProducer> igbp = ps->getBufferProducer();
832 if (igbp == NULL) {
833 return AMEDIA_ERROR_UNKNOWN;
834 }
835
836 *surface = new AMediaCodecPersistentSurface(igbp, ps);
837 ANativeWindow_acquire(*surface);
838
839 return AMEDIA_OK;
840}
841
842EXPORT
843media_status_t AMediaCodec_setInputSurface(
844 AMediaCodec *mData, ANativeWindow *surface) {
845
846 if (surface == NULL || mData == NULL) {
847 return AMEDIA_ERROR_INVALID_PARAMETER;
848 }
849
850 AMediaCodecPersistentSurface *aMediaPersistentSurface =
851 static_cast<AMediaCodecPersistentSurface *>(surface);
852 if (aMediaPersistentSurface->mPersistentSurface == NULL) {
853 return AMEDIA_ERROR_INVALID_PARAMETER;
854 }
855
856 return translate_error(mData->mCodec->setInputSurface(
857 aMediaPersistentSurface->mPersistentSurface));
858}
859
Praveen Chavanf373e842017-02-01 11:50:15 -0800860EXPORT
861media_status_t AMediaCodec_setParameters(
862 AMediaCodec *mData, const AMediaFormat* params) {
863 if (params == NULL || mData == NULL) {
864 return AMEDIA_ERROR_INVALID_PARAMETER;
865 }
866 sp<AMessage> nativeParams;
867 AMediaFormat_getFormat(params, &nativeParams);
868 ALOGV("setParameters: %s", nativeParams->debugString(0).c_str());
869
870 return translate_error(mData->mCodec->setParameters(nativeParams));
871}
872
Robert Shihaf42d3f2017-03-20 16:45:37 -0700873EXPORT
874media_status_t AMediaCodec_signalEndOfInputStream(AMediaCodec *mData) {
875
876 if (mData == NULL) {
877 return AMEDIA_ERROR_INVALID_PARAMETER;
878 }
879
880 status_t err = mData->mCodec->signalEndOfInputStream();
881 if (err == INVALID_OPERATION) {
882 return AMEDIA_ERROR_INVALID_OPERATION;
883 }
884
885 return translate_error(err);
886
887}
888
Marco Nelissene22a64b2014-05-23 15:49:49 -0700889//EXPORT
Glenn Kastenb187de12014-12-30 08:18:15 -0800890media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback,
891 void *userdata) {
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700892 mData->mCallback = callback;
893 mData->mCallbackUserData = userdata;
Marco Nelissene419d7c2014-05-15 14:17:25 -0700894 return AMEDIA_OK;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700895}
896
Marco Nelissen050eb322014-05-09 15:10:23 -0700897typedef struct AMediaCodecCryptoInfo {
898 int numsubsamples;
899 uint8_t key[16];
900 uint8_t iv[16];
Marco Nelissen79e2b622014-05-16 08:07:28 -0700901 cryptoinfo_mode_t mode;
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800902 cryptoinfo_pattern_t pattern;
Marco Nelissen050eb322014-05-09 15:10:23 -0700903 size_t *clearbytes;
904 size_t *encryptedbytes;
905} AMediaCodecCryptoInfo;
906
Marco Nelissen3425fd52014-05-14 11:12:46 -0700907EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700908media_status_t AMediaCodec_queueSecureInputBuffer(
Marco Nelissen050eb322014-05-09 15:10:23 -0700909 AMediaCodec* codec,
910 size_t idx,
911 off_t offset,
912 AMediaCodecCryptoInfo* crypto,
913 uint64_t time,
914 uint32_t flags) {
915
916 CryptoPlugin::SubSample *subSamples = new CryptoPlugin::SubSample[crypto->numsubsamples];
917 for (int i = 0; i < crypto->numsubsamples; i++) {
918 subSamples[i].mNumBytesOfClearData = crypto->clearbytes[i];
919 subSamples[i].mNumBytesOfEncryptedData = crypto->encryptedbytes[i];
920 }
921
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800922 CryptoPlugin::Pattern pattern;
923 pattern.mEncryptBlocks = crypto->pattern.encryptBlocks;
924 pattern.mSkipBlocks = crypto->pattern.skipBlocks;
925
Marco Nelissen050eb322014-05-09 15:10:23 -0700926 AString errormsg;
927 status_t err = codec->mCodec->queueSecureInputBuffer(idx,
928 offset,
929 subSamples,
930 crypto->numsubsamples,
931 crypto->key,
932 crypto->iv,
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800933 (CryptoPlugin::Mode)crypto->mode,
934 pattern,
Marco Nelissen050eb322014-05-09 15:10:23 -0700935 time,
936 flags,
937 &errormsg);
938 if (err != 0) {
939 ALOGE("queSecureInputBuffer: %s", errormsg.c_str());
940 }
Marco Nelissen829e0972014-05-13 16:22:19 -0700941 delete [] subSamples;
Marco Nelissen050eb322014-05-09 15:10:23 -0700942 return translate_error(err);
943}
944
Wei Jia00cc9922017-11-23 08:00:34 -0800945EXPORT
946bool AMediaCodecActionCode_isRecoverable(int32_t actionCode) {
947 return (actionCode == ACTION_CODE_RECOVERABLE);
948}
949
950EXPORT
951bool AMediaCodecActionCode_isTransient(int32_t actionCode) {
952 return (actionCode == ACTION_CODE_TRANSIENT);
953}
954
Marco Nelissen050eb322014-05-09 15:10:23 -0700955
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800956EXPORT
957void AMediaCodecCryptoInfo_setPattern(AMediaCodecCryptoInfo *info,
958 cryptoinfo_pattern_t *pattern) {
959 info->pattern.encryptBlocks = pattern->encryptBlocks;
960 info->pattern.skipBlocks = pattern->skipBlocks;
961}
Marco Nelissen050eb322014-05-09 15:10:23 -0700962
Marco Nelissen3425fd52014-05-14 11:12:46 -0700963EXPORT
Marco Nelissen050eb322014-05-09 15:10:23 -0700964AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new(
965 int numsubsamples,
966 uint8_t key[16],
967 uint8_t iv[16],
Marco Nelissen79e2b622014-05-16 08:07:28 -0700968 cryptoinfo_mode_t mode,
Marco Nelissen050eb322014-05-09 15:10:23 -0700969 size_t *clearbytes,
970 size_t *encryptedbytes) {
971
972 // size needed to store all the crypto data
Marco Nelissend1fd0272018-07-31 15:12:51 -0700973 size_t cryptosize;
974 // = sizeof(AMediaCodecCryptoInfo) + sizeof(size_t) * numsubsamples * 2;
975 if (__builtin_mul_overflow(sizeof(size_t) * 2, numsubsamples, &cryptosize) ||
976 __builtin_add_overflow(cryptosize, sizeof(AMediaCodecCryptoInfo), &cryptosize)) {
977 ALOGE("crypto size overflow");
978 return NULL;
979 }
Marco Nelissen050eb322014-05-09 15:10:23 -0700980 AMediaCodecCryptoInfo *ret = (AMediaCodecCryptoInfo*) malloc(cryptosize);
981 if (!ret) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700982 ALOGE("couldn't allocate %zu bytes", cryptosize);
Marco Nelissen050eb322014-05-09 15:10:23 -0700983 return NULL;
984 }
985 ret->numsubsamples = numsubsamples;
986 memcpy(ret->key, key, 16);
987 memcpy(ret->iv, iv, 16);
988 ret->mode = mode;
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800989 ret->pattern.encryptBlocks = 0;
990 ret->pattern.skipBlocks = 0;
Marco Nelissen050eb322014-05-09 15:10:23 -0700991
992 // clearbytes and encryptedbytes point at the actual data, which follows
Marco Nelissen829e0972014-05-13 16:22:19 -0700993 ret->clearbytes = (size_t*) (ret + 1); // point immediately after the struct
994 ret->encryptedbytes = ret->clearbytes + numsubsamples; // point after the clear sizes
Marco Nelissen050eb322014-05-09 15:10:23 -0700995
Marco Nelissen829e0972014-05-13 16:22:19 -0700996 memcpy(ret->clearbytes, clearbytes, numsubsamples * sizeof(size_t));
997 memcpy(ret->encryptedbytes, encryptedbytes, numsubsamples * sizeof(size_t));
Marco Nelissen050eb322014-05-09 15:10:23 -0700998
999 return ret;
1000}
1001
1002
Marco Nelissen3425fd52014-05-14 11:12:46 -07001003EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -07001004media_status_t AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo* info) {
Marco Nelissen050eb322014-05-09 15:10:23 -07001005 free(info);
Marco Nelissene419d7c2014-05-15 14:17:25 -07001006 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -07001007}
1008
Marco Nelissen3425fd52014-05-14 11:12:46 -07001009EXPORT
Marco Nelissen050eb322014-05-09 15:10:23 -07001010size_t AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo* ci) {
1011 return ci->numsubsamples;
1012}
1013
Marco Nelissen3425fd52014-05-14 11:12:46 -07001014EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -07001015media_status_t AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
1016 if (!ci) {
1017 return AMEDIA_ERROR_INVALID_OBJECT;
1018 }
1019 if (!dst) {
1020 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -07001021 }
1022 memcpy(dst, ci->key, 16);
Marco Nelissene419d7c2014-05-15 14:17:25 -07001023 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -07001024}
1025
Marco Nelissen3425fd52014-05-14 11:12:46 -07001026EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -07001027media_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
1028 if (!ci) {
1029 return AMEDIA_ERROR_INVALID_OBJECT;
1030 }
1031 if (!dst) {
1032 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -07001033 }
1034 memcpy(dst, ci->iv, 16);
Marco Nelissene419d7c2014-05-15 14:17:25 -07001035 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -07001036}
1037
Marco Nelissen3425fd52014-05-14 11:12:46 -07001038EXPORT
Marco Nelissen79e2b622014-05-16 08:07:28 -07001039cryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo* ci) {
Marco Nelissen050eb322014-05-09 15:10:23 -07001040 if (!ci) {
Marco Nelissen79e2b622014-05-16 08:07:28 -07001041 return (cryptoinfo_mode_t) AMEDIA_ERROR_INVALID_OBJECT;
Marco Nelissen050eb322014-05-09 15:10:23 -07001042 }
1043 return ci->mode;
1044}
1045
Marco Nelissen3425fd52014-05-14 11:12:46 -07001046EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -07001047media_status_t AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
1048 if (!ci) {
1049 return AMEDIA_ERROR_INVALID_OBJECT;
1050 }
1051 if (!dst) {
1052 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -07001053 }
1054 memcpy(dst, ci->clearbytes, sizeof(size_t) * ci->numsubsamples);
Marco Nelissene419d7c2014-05-15 14:17:25 -07001055 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -07001056}
1057
Marco Nelissen3425fd52014-05-14 11:12:46 -07001058EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -07001059media_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
1060 if (!ci) {
1061 return AMEDIA_ERROR_INVALID_OBJECT;
1062 }
1063 if (!dst) {
1064 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -07001065 }
1066 memcpy(dst, ci->encryptedbytes, sizeof(size_t) * ci->numsubsamples);
Marco Nelissene419d7c2014-05-15 14:17:25 -07001067 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -07001068}
Marco Nelissencdb42cd2014-05-08 14:46:05 -07001069
Ray Essickef058462021-01-24 14:50:08 -08001070EXPORT const char* AMEDIACODEC_KEY_HDR10_PLUS_INFO = AMEDIAFORMAT_KEY_HDR10_PLUS_INFO;
1071EXPORT const char* AMEDIACODEC_KEY_LOW_LATENCY = AMEDIAFORMAT_KEY_LOW_LATENCY;
1072EXPORT const char* AMEDIACODEC_KEY_OFFSET_TIME = "time-offset-us";
1073EXPORT const char* AMEDIACODEC_KEY_REQUEST_SYNC_FRAME = "request-sync";
1074EXPORT const char* AMEDIACODEC_KEY_SUSPEND = "drop-input-frames";
1075EXPORT const char* AMEDIACODEC_KEY_SUSPEND_TIME = "drop-start-time-us";
1076EXPORT const char* AMEDIACODEC_KEY_VIDEO_BITRATE = "video-bitrate";
1077
Marco Nelissen0c3be872014-05-01 10:14:44 -07001078} // extern "C"
1079