blob: 11dedbb7309137eda87c271d99dbf607c80ddd32 [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
Colin Cross7e8d4ba2017-05-04 16:17:42 -070022#include <media/NdkMediaCodec.h>
23#include <media/NdkMediaError.h>
Marco Nelissen050eb322014-05-09 15:10:23 -070024#include "NdkMediaCryptoPriv.h"
Marco Nelissen0c3be872014-05-01 10:14:44 -070025#include "NdkMediaFormatPriv.h"
26
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>
32#include <media/stagefright/foundation/AMessage.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070033
Praveen Chavan85a53632017-01-31 12:21:33 -080034#include <media/stagefright/PersistentSurface.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070035#include <media/stagefright/MediaCodec.h>
36#include <media/stagefright/MediaErrors.h>
Wonsik Kim7e34bf52016-08-23 00:09:18 +090037#include <media/MediaCodecBuffer.h>
Praveen Chavan19431582017-01-16 11:56:18 -080038#include <android/native_window.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070039
40using namespace android;
41
42
Marco Nelissene419d7c2014-05-15 14:17:25 -070043static media_status_t translate_error(status_t err) {
Marco Nelissen0c3be872014-05-01 10:14:44 -070044 if (err == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -070045 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -070046 } else if (err == -EAGAIN) {
Marco Nelissene419d7c2014-05-15 14:17:25 -070047 return (media_status_t) AMEDIACODEC_INFO_TRY_AGAIN_LATER;
Marco Nelissen0c3be872014-05-01 10:14:44 -070048 }
49 ALOGE("sf error code: %d", err);
Marco Nelissene419d7c2014-05-15 14:17:25 -070050 return AMEDIA_ERROR_UNKNOWN;
Marco Nelissen0c3be872014-05-01 10:14:44 -070051}
52
Marco Nelissencdb42cd2014-05-08 14:46:05 -070053enum {
54 kWhatActivityNotify,
55 kWhatRequestActivityNotifications,
56 kWhatStopActivityNotifications,
Marco Nelissen0c3be872014-05-01 10:14:44 -070057};
58
Praveen Chavan85a53632017-01-31 12:21:33 -080059struct AMediaCodecPersistentSurface : public Surface {
60 sp<PersistentSurface> mPersistentSurface;
61 AMediaCodecPersistentSurface(
62 const sp<IGraphicBufferProducer>& igbp,
63 const sp<PersistentSurface>& ps)
64 : Surface(igbp) {
65 mPersistentSurface = ps;
66 }
67 virtual ~AMediaCodecPersistentSurface() {
68 //mPersistentSurface ref will be let go off here
69 }
70};
Marco Nelissen0c3be872014-05-01 10:14:44 -070071
Marco Nelissencdb42cd2014-05-08 14:46:05 -070072class CodecHandler: public AHandler {
73private:
74 AMediaCodec* mCodec;
75public:
Chih-Hung Hsieh090ef602016-04-27 10:39:54 -070076 explicit CodecHandler(AMediaCodec *codec);
Marco Nelissencdb42cd2014-05-08 14:46:05 -070077 virtual void onMessageReceived(const sp<AMessage> &msg);
78};
Marco Nelissen0c3be872014-05-01 10:14:44 -070079
Marco Nelissene22a64b2014-05-23 15:49:49 -070080typedef void (*OnCodecEvent)(AMediaCodec *codec, void *userdata);
81
Marco Nelissen0c3be872014-05-01 10:14:44 -070082struct AMediaCodec {
83 sp<android::MediaCodec> mCodec;
84 sp<ALooper> mLooper;
85 sp<CodecHandler> mHandler;
Marco Nelissencdb42cd2014-05-08 14:46:05 -070086 sp<AMessage> mActivityNotification;
87 int32_t mGeneration;
88 bool mRequestedActivityNotification;
89 OnCodecEvent mCallback;
90 void *mCallbackUserData;
Marco Nelissen0c3be872014-05-01 10:14:44 -070091};
92
Marco Nelissencdb42cd2014-05-08 14:46:05 -070093CodecHandler::CodecHandler(AMediaCodec *codec) {
94 mCodec = codec;
95}
96
97void CodecHandler::onMessageReceived(const sp<AMessage> &msg) {
98
99 switch (msg->what()) {
100 case kWhatRequestActivityNotifications:
101 {
102 if (mCodec->mRequestedActivityNotification) {
103 break;
104 }
105
106 mCodec->mCodec->requestActivityNotification(mCodec->mActivityNotification);
107 mCodec->mRequestedActivityNotification = true;
108 break;
109 }
110
111 case kWhatActivityNotify:
112 {
113 {
114 int32_t generation;
115 msg->findInt32("generation", &generation);
116
117 if (generation != mCodec->mGeneration) {
118 // stale
119 break;
120 }
121
122 mCodec->mRequestedActivityNotification = false;
123 }
124
125 if (mCodec->mCallback) {
126 mCodec->mCallback(mCodec, mCodec->mCallbackUserData);
127 }
128 break;
129 }
130
131 case kWhatStopActivityNotifications:
132 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800133 sp<AReplyToken> replyID;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700134 msg->senderAwaitsResponse(&replyID);
135
136 mCodec->mGeneration++;
137 mCodec->mRequestedActivityNotification = false;
138
139 sp<AMessage> response = new AMessage;
140 response->postReply(replyID);
141 break;
142 }
143
144 default:
145 ALOGE("shouldn't be here");
146 break;
147 }
148
149}
150
151
152static void requestActivityNotification(AMediaCodec *codec) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800153 (new AMessage(kWhatRequestActivityNotifications, codec->mHandler))->post();
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700154}
155
Marco Nelissen0c3be872014-05-01 10:14:44 -0700156extern "C" {
157
158static AMediaCodec * createAMediaCodec(const char *name, bool name_is_type, bool encoder) {
159 AMediaCodec *mData = new AMediaCodec();
160 mData->mLooper = new ALooper;
161 mData->mLooper->setName("NDK MediaCodec_looper");
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800162 size_t res = mData->mLooper->start(
Marco Nelissen0c3be872014-05-01 10:14:44 -0700163 false, // runOnCallingThread
164 true, // canCallJava XXX
165 PRIORITY_FOREGROUND);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800166 if (res != OK) {
167 ALOGE("Failed to start the looper");
Greg Kaiser4e147802016-03-14 14:44:20 -0700168 AMediaCodec_delete(mData);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800169 return NULL;
170 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700171 if (name_is_type) {
172 mData->mCodec = android::MediaCodec::CreateByType(mData->mLooper, name, encoder);
173 } else {
174 mData->mCodec = android::MediaCodec::CreateByComponentName(mData->mLooper, name);
175 }
Andy Hung6bb63ad2015-04-28 19:05:08 -0700176 if (mData->mCodec == NULL) { // failed to create codec
177 AMediaCodec_delete(mData);
178 return NULL;
179 }
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700180 mData->mHandler = new CodecHandler(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700181 mData->mLooper->registerHandler(mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700182 mData->mGeneration = 1;
183 mData->mRequestedActivityNotification = false;
184 mData->mCallback = NULL;
185
Marco Nelissen0c3be872014-05-01 10:14:44 -0700186 return mData;
187}
188
Marco Nelissen3425fd52014-05-14 11:12:46 -0700189EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700190AMediaCodec* AMediaCodec_createCodecByName(const char *name) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700191 return createAMediaCodec(name, false, false);
192}
193
Marco Nelissen3425fd52014-05-14 11:12:46 -0700194EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700195AMediaCodec* AMediaCodec_createDecoderByType(const char *mime_type) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700196 return createAMediaCodec(mime_type, true, false);
197}
198
Marco Nelissen3425fd52014-05-14 11:12:46 -0700199EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700200AMediaCodec* AMediaCodec_createEncoderByType(const char *name) {
201 return createAMediaCodec(name, true, true);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700202}
203
Marco Nelissen3425fd52014-05-14 11:12:46 -0700204EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700205media_status_t AMediaCodec_delete(AMediaCodec *mData) {
Andy Hung6bb63ad2015-04-28 19:05:08 -0700206 if (mData != NULL) {
207 if (mData->mCodec != NULL) {
208 mData->mCodec->release();
209 mData->mCodec.clear();
210 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700211
Andy Hung6bb63ad2015-04-28 19:05:08 -0700212 if (mData->mLooper != NULL) {
213 if (mData->mHandler != NULL) {
214 mData->mLooper->unregisterHandler(mData->mHandler->id());
215 }
216 mData->mLooper->stop();
217 mData->mLooper.clear();
218 }
219 delete mData;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700220 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700221 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700222}
223
Marco Nelissen3425fd52014-05-14 11:12:46 -0700224EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700225media_status_t AMediaCodec_configure(
Marco Nelissen050eb322014-05-09 15:10:23 -0700226 AMediaCodec *mData,
227 const AMediaFormat* format,
228 ANativeWindow* window,
229 AMediaCrypto *crypto,
230 uint32_t flags) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700231 sp<AMessage> nativeFormat;
232 AMediaFormat_getFormat(format, &nativeFormat);
233 ALOGV("configure with format: %s", nativeFormat->debugString(0).c_str());
234 sp<Surface> surface = NULL;
235 if (window != NULL) {
236 surface = (Surface*) window;
237 }
238
Marco Nelissen050eb322014-05-09 15:10:23 -0700239 return translate_error(mData->mCodec->configure(nativeFormat, surface,
240 crypto ? crypto->mCrypto : NULL, flags));
Marco Nelissen0c3be872014-05-01 10:14:44 -0700241}
242
Marco Nelissen3425fd52014-05-14 11:12:46 -0700243EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700244media_status_t AMediaCodec_start(AMediaCodec *mData) {
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700245 status_t ret = mData->mCodec->start();
246 if (ret != OK) {
247 return translate_error(ret);
248 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800249 mData->mActivityNotification = new AMessage(kWhatActivityNotify, mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700250 mData->mActivityNotification->setInt32("generation", mData->mGeneration);
251 requestActivityNotification(mData);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700252 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700253}
254
Marco Nelissen3425fd52014-05-14 11:12:46 -0700255EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700256media_status_t AMediaCodec_stop(AMediaCodec *mData) {
257 media_status_t ret = translate_error(mData->mCodec->stop());
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700258
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800259 sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700260 sp<AMessage> response;
261 msg->postAndAwaitResponse(&response);
262 mData->mActivityNotification.clear();
263
264 return ret;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700265}
266
Marco Nelissen3425fd52014-05-14 11:12:46 -0700267EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700268media_status_t AMediaCodec_flush(AMediaCodec *mData) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700269 return translate_error(mData->mCodec->flush());
270}
271
Marco Nelissen3425fd52014-05-14 11:12:46 -0700272EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700273ssize_t AMediaCodec_dequeueInputBuffer(AMediaCodec *mData, int64_t timeoutUs) {
274 size_t idx;
275 status_t ret = mData->mCodec->dequeueInputBuffer(&idx, timeoutUs);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700276 requestActivityNotification(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700277 if (ret == OK) {
278 return idx;
279 }
280 return translate_error(ret);
281}
282
Marco Nelissen3425fd52014-05-14 11:12:46 -0700283EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700284uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900285 android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700286 if (mData->mCodec->getInputBuffers(&abufs) == 0) {
287 size_t n = abufs.size();
288 if (idx >= n) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700289 ALOGE("buffer index %zu out of range", idx);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700290 return NULL;
291 }
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900292 if (abufs[idx] == NULL) {
293 ALOGE("buffer index %zu is NULL", idx);
294 return NULL;
295 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700296 if (out_size != NULL) {
297 *out_size = abufs[idx]->capacity();
298 }
299 return abufs[idx]->data();
300 }
301 ALOGE("couldn't get input buffers");
302 return NULL;
303}
304
Marco Nelissen3425fd52014-05-14 11:12:46 -0700305EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700306uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900307 android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700308 if (mData->mCodec->getOutputBuffers(&abufs) == 0) {
309 size_t n = abufs.size();
310 if (idx >= n) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700311 ALOGE("buffer index %zu out of range", idx);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700312 return NULL;
313 }
314 if (out_size != NULL) {
315 *out_size = abufs[idx]->capacity();
316 }
317 return abufs[idx]->data();
318 }
319 ALOGE("couldn't get output buffers");
320 return NULL;
321}
322
Marco Nelissen3425fd52014-05-14 11:12:46 -0700323EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700324media_status_t AMediaCodec_queueInputBuffer(AMediaCodec *mData,
Marco Nelissen0c3be872014-05-01 10:14:44 -0700325 size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags) {
326
327 AString errorMsg;
328 status_t ret = mData->mCodec->queueInputBuffer(idx, offset, size, time, flags, &errorMsg);
329 return translate_error(ret);
330}
331
Marco Nelissen3425fd52014-05-14 11:12:46 -0700332EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700333ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec *mData,
334 AMediaCodecBufferInfo *info, int64_t timeoutUs) {
335 size_t idx;
336 size_t offset;
337 size_t size;
338 uint32_t flags;
339 int64_t presentationTimeUs;
340 status_t ret = mData->mCodec->dequeueOutputBuffer(&idx, &offset, &size, &presentationTimeUs,
341 &flags, timeoutUs);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700342 requestActivityNotification(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700343 switch (ret) {
344 case OK:
345 info->offset = offset;
346 info->size = size;
347 info->flags = flags;
348 info->presentationTimeUs = presentationTimeUs;
349 return idx;
350 case -EAGAIN:
351 return AMEDIACODEC_INFO_TRY_AGAIN_LATER;
352 case android::INFO_FORMAT_CHANGED:
353 return AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED;
354 case INFO_OUTPUT_BUFFERS_CHANGED:
355 return AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED;
356 default:
357 break;
358 }
359 return translate_error(ret);
360}
361
Marco Nelissen3425fd52014-05-14 11:12:46 -0700362EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700363AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec *mData) {
364 sp<AMessage> format;
365 mData->mCodec->getOutputFormat(&format);
366 return AMediaFormat_fromMsg(&format);
367}
368
Marco Nelissen3425fd52014-05-14 11:12:46 -0700369EXPORT
Manikanta Kanamarlapudi2c32f4d2017-07-07 16:24:31 +0530370AMediaFormat* AMediaCodec_getBufferFormat(AMediaCodec *mData, size_t index) {
371 sp<AMessage> format;
372 mData->mCodec->getOutputFormat(index, &format);
373 return AMediaFormat_fromMsg(&format);
374}
375
376EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700377media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec *mData, size_t idx, bool render) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700378 if (render) {
379 return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx));
380 } else {
381 return translate_error(mData->mCodec->releaseOutputBuffer(idx));
382 }
383}
384
Marco Nelissen3425fd52014-05-14 11:12:46 -0700385EXPORT
Marco Nelissen79e2b622014-05-16 08:07:28 -0700386media_status_t AMediaCodec_releaseOutputBufferAtTime(
387 AMediaCodec *mData, size_t idx, int64_t timestampNs) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700388 ALOGV("render @ %" PRId64, timestampNs);
Marco Nelissen79e2b622014-05-16 08:07:28 -0700389 return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx, timestampNs));
390}
391
Vineeta Srivastava8c35da52016-01-08 17:33:09 -0800392EXPORT
393media_status_t AMediaCodec_setOutputSurface(AMediaCodec *mData, ANativeWindow* window) {
394 sp<Surface> surface = NULL;
395 if (window != NULL) {
396 surface = (Surface*) window;
397 }
398 return translate_error(mData->mCodec->setSurface(surface));
399}
400
Praveen Chavan19431582017-01-16 11:56:18 -0800401EXPORT
402media_status_t AMediaCodec_createInputSurface(AMediaCodec *mData, ANativeWindow **surface) {
403 if (surface == NULL || mData == NULL) {
404 return AMEDIA_ERROR_INVALID_PARAMETER;
405 }
406 *surface = NULL;
407
408 sp<IGraphicBufferProducer> igbp = NULL;
409 status_t err = mData->mCodec->createInputSurface(&igbp);
410 if (err != NO_ERROR) {
411 return translate_error(err);
412 }
413
414 *surface = new Surface(igbp);
415 ANativeWindow_acquire(*surface);
416 return AMEDIA_OK;
417}
418
Praveen Chavan85a53632017-01-31 12:21:33 -0800419EXPORT
420media_status_t AMediaCodec_createPersistentInputSurface(ANativeWindow **surface) {
421 if (surface == NULL) {
422 return AMEDIA_ERROR_INVALID_PARAMETER;
423 }
424 *surface = NULL;
425
426 sp<PersistentSurface> ps = MediaCodec::CreatePersistentInputSurface();
427 if (ps == NULL) {
428 return AMEDIA_ERROR_UNKNOWN;
429 }
430
431 sp<IGraphicBufferProducer> igbp = ps->getBufferProducer();
432 if (igbp == NULL) {
433 return AMEDIA_ERROR_UNKNOWN;
434 }
435
436 *surface = new AMediaCodecPersistentSurface(igbp, ps);
437 ANativeWindow_acquire(*surface);
438
439 return AMEDIA_OK;
440}
441
442EXPORT
443media_status_t AMediaCodec_setInputSurface(
444 AMediaCodec *mData, ANativeWindow *surface) {
445
446 if (surface == NULL || mData == NULL) {
447 return AMEDIA_ERROR_INVALID_PARAMETER;
448 }
449
450 AMediaCodecPersistentSurface *aMediaPersistentSurface =
451 static_cast<AMediaCodecPersistentSurface *>(surface);
452 if (aMediaPersistentSurface->mPersistentSurface == NULL) {
453 return AMEDIA_ERROR_INVALID_PARAMETER;
454 }
455
456 return translate_error(mData->mCodec->setInputSurface(
457 aMediaPersistentSurface->mPersistentSurface));
458}
459
Praveen Chavanf373e842017-02-01 11:50:15 -0800460EXPORT
461media_status_t AMediaCodec_setParameters(
462 AMediaCodec *mData, const AMediaFormat* params) {
463 if (params == NULL || mData == NULL) {
464 return AMEDIA_ERROR_INVALID_PARAMETER;
465 }
466 sp<AMessage> nativeParams;
467 AMediaFormat_getFormat(params, &nativeParams);
468 ALOGV("setParameters: %s", nativeParams->debugString(0).c_str());
469
470 return translate_error(mData->mCodec->setParameters(nativeParams));
471}
472
Robert Shihaf42d3f2017-03-20 16:45:37 -0700473EXPORT
474media_status_t AMediaCodec_signalEndOfInputStream(AMediaCodec *mData) {
475
476 if (mData == NULL) {
477 return AMEDIA_ERROR_INVALID_PARAMETER;
478 }
479
480 status_t err = mData->mCodec->signalEndOfInputStream();
481 if (err == INVALID_OPERATION) {
482 return AMEDIA_ERROR_INVALID_OPERATION;
483 }
484
485 return translate_error(err);
486
487}
488
Marco Nelissene22a64b2014-05-23 15:49:49 -0700489//EXPORT
Glenn Kastenb187de12014-12-30 08:18:15 -0800490media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback,
491 void *userdata) {
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700492 mData->mCallback = callback;
493 mData->mCallbackUserData = userdata;
Marco Nelissene419d7c2014-05-15 14:17:25 -0700494 return AMEDIA_OK;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700495}
496
Marco Nelissen050eb322014-05-09 15:10:23 -0700497typedef struct AMediaCodecCryptoInfo {
498 int numsubsamples;
499 uint8_t key[16];
500 uint8_t iv[16];
Marco Nelissen79e2b622014-05-16 08:07:28 -0700501 cryptoinfo_mode_t mode;
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800502 cryptoinfo_pattern_t pattern;
Marco Nelissen050eb322014-05-09 15:10:23 -0700503 size_t *clearbytes;
504 size_t *encryptedbytes;
505} AMediaCodecCryptoInfo;
506
Marco Nelissen3425fd52014-05-14 11:12:46 -0700507EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700508media_status_t AMediaCodec_queueSecureInputBuffer(
Marco Nelissen050eb322014-05-09 15:10:23 -0700509 AMediaCodec* codec,
510 size_t idx,
511 off_t offset,
512 AMediaCodecCryptoInfo* crypto,
513 uint64_t time,
514 uint32_t flags) {
515
516 CryptoPlugin::SubSample *subSamples = new CryptoPlugin::SubSample[crypto->numsubsamples];
517 for (int i = 0; i < crypto->numsubsamples; i++) {
518 subSamples[i].mNumBytesOfClearData = crypto->clearbytes[i];
519 subSamples[i].mNumBytesOfEncryptedData = crypto->encryptedbytes[i];
520 }
521
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800522 CryptoPlugin::Pattern pattern;
523 pattern.mEncryptBlocks = crypto->pattern.encryptBlocks;
524 pattern.mSkipBlocks = crypto->pattern.skipBlocks;
525
Marco Nelissen050eb322014-05-09 15:10:23 -0700526 AString errormsg;
527 status_t err = codec->mCodec->queueSecureInputBuffer(idx,
528 offset,
529 subSamples,
530 crypto->numsubsamples,
531 crypto->key,
532 crypto->iv,
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800533 (CryptoPlugin::Mode)crypto->mode,
534 pattern,
Marco Nelissen050eb322014-05-09 15:10:23 -0700535 time,
536 flags,
537 &errormsg);
538 if (err != 0) {
539 ALOGE("queSecureInputBuffer: %s", errormsg.c_str());
540 }
Marco Nelissen829e0972014-05-13 16:22:19 -0700541 delete [] subSamples;
Marco Nelissen050eb322014-05-09 15:10:23 -0700542 return translate_error(err);
543}
544
545
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800546EXPORT
547void AMediaCodecCryptoInfo_setPattern(AMediaCodecCryptoInfo *info,
548 cryptoinfo_pattern_t *pattern) {
549 info->pattern.encryptBlocks = pattern->encryptBlocks;
550 info->pattern.skipBlocks = pattern->skipBlocks;
551}
Marco Nelissen050eb322014-05-09 15:10:23 -0700552
Marco Nelissen3425fd52014-05-14 11:12:46 -0700553EXPORT
Marco Nelissen050eb322014-05-09 15:10:23 -0700554AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new(
555 int numsubsamples,
556 uint8_t key[16],
557 uint8_t iv[16],
Marco Nelissen79e2b622014-05-16 08:07:28 -0700558 cryptoinfo_mode_t mode,
Marco Nelissen050eb322014-05-09 15:10:23 -0700559 size_t *clearbytes,
560 size_t *encryptedbytes) {
561
562 // size needed to store all the crypto data
563 size_t cryptosize = sizeof(AMediaCodecCryptoInfo) + sizeof(size_t) * numsubsamples * 2;
564 AMediaCodecCryptoInfo *ret = (AMediaCodecCryptoInfo*) malloc(cryptosize);
565 if (!ret) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700566 ALOGE("couldn't allocate %zu bytes", cryptosize);
Marco Nelissen050eb322014-05-09 15:10:23 -0700567 return NULL;
568 }
569 ret->numsubsamples = numsubsamples;
570 memcpy(ret->key, key, 16);
571 memcpy(ret->iv, iv, 16);
572 ret->mode = mode;
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800573 ret->pattern.encryptBlocks = 0;
574 ret->pattern.skipBlocks = 0;
Marco Nelissen050eb322014-05-09 15:10:23 -0700575
576 // clearbytes and encryptedbytes point at the actual data, which follows
Marco Nelissen829e0972014-05-13 16:22:19 -0700577 ret->clearbytes = (size_t*) (ret + 1); // point immediately after the struct
578 ret->encryptedbytes = ret->clearbytes + numsubsamples; // point after the clear sizes
Marco Nelissen050eb322014-05-09 15:10:23 -0700579
Marco Nelissen829e0972014-05-13 16:22:19 -0700580 memcpy(ret->clearbytes, clearbytes, numsubsamples * sizeof(size_t));
581 memcpy(ret->encryptedbytes, encryptedbytes, numsubsamples * sizeof(size_t));
Marco Nelissen050eb322014-05-09 15:10:23 -0700582
583 return ret;
584}
585
586
Marco Nelissen3425fd52014-05-14 11:12:46 -0700587EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700588media_status_t AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo* info) {
Marco Nelissen050eb322014-05-09 15:10:23 -0700589 free(info);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700590 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700591}
592
Marco Nelissen3425fd52014-05-14 11:12:46 -0700593EXPORT
Marco Nelissen050eb322014-05-09 15:10:23 -0700594size_t AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo* ci) {
595 return ci->numsubsamples;
596}
597
Marco Nelissen3425fd52014-05-14 11:12:46 -0700598EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700599media_status_t AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
600 if (!ci) {
601 return AMEDIA_ERROR_INVALID_OBJECT;
602 }
603 if (!dst) {
604 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700605 }
606 memcpy(dst, ci->key, 16);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700607 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700608}
609
Marco Nelissen3425fd52014-05-14 11:12:46 -0700610EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700611media_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
612 if (!ci) {
613 return AMEDIA_ERROR_INVALID_OBJECT;
614 }
615 if (!dst) {
616 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700617 }
618 memcpy(dst, ci->iv, 16);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700619 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700620}
621
Marco Nelissen3425fd52014-05-14 11:12:46 -0700622EXPORT
Marco Nelissen79e2b622014-05-16 08:07:28 -0700623cryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo* ci) {
Marco Nelissen050eb322014-05-09 15:10:23 -0700624 if (!ci) {
Marco Nelissen79e2b622014-05-16 08:07:28 -0700625 return (cryptoinfo_mode_t) AMEDIA_ERROR_INVALID_OBJECT;
Marco Nelissen050eb322014-05-09 15:10:23 -0700626 }
627 return ci->mode;
628}
629
Marco Nelissen3425fd52014-05-14 11:12:46 -0700630EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700631media_status_t AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
632 if (!ci) {
633 return AMEDIA_ERROR_INVALID_OBJECT;
634 }
635 if (!dst) {
636 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700637 }
638 memcpy(dst, ci->clearbytes, sizeof(size_t) * ci->numsubsamples);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700639 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700640}
641
Marco Nelissen3425fd52014-05-14 11:12:46 -0700642EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700643media_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
644 if (!ci) {
645 return AMEDIA_ERROR_INVALID_OBJECT;
646 }
647 if (!dst) {
648 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700649 }
650 memcpy(dst, ci->encryptedbytes, sizeof(size_t) * ci->numsubsamples);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700651 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700652}
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700653
Marco Nelissen0c3be872014-05-01 10:14:44 -0700654} // extern "C"
655