blob: c5d88589430b96f643c10898bed9e2fcf08934d3 [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
Marco Nelissenc7a11b22014-05-30 10:13:25 -070017//#define LOG_NDEBUG 0
Marco Nelissen0c3be872014-05-01 10:14:44 -070018#define LOG_TAG "NdkMediaCodec"
19
20#include "NdkMediaCodec.h"
Marco Nelissen050eb322014-05-09 15:10:23 -070021#include "NdkMediaError.h"
22#include "NdkMediaCryptoPriv.h"
Marco Nelissen0c3be872014-05-01 10:14:44 -070023#include "NdkMediaFormatPriv.h"
24
25#include <utils/Log.h>
26#include <utils/StrongPointer.h>
27#include <gui/Surface.h>
28
Marco Nelissen0c3be872014-05-01 10:14:44 -070029#include <media/stagefright/foundation/ALooper.h>
30#include <media/stagefright/foundation/AMessage.h>
31#include <media/stagefright/foundation/ABuffer.h>
32
33#include <media/stagefright/MediaCodec.h>
34#include <media/stagefright/MediaErrors.h>
35
36using namespace android;
37
38
Marco Nelissene419d7c2014-05-15 14:17:25 -070039static media_status_t translate_error(status_t err) {
Marco Nelissen0c3be872014-05-01 10:14:44 -070040 if (err == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -070041 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -070042 } else if (err == -EAGAIN) {
Marco Nelissene419d7c2014-05-15 14:17:25 -070043 return (media_status_t) AMEDIACODEC_INFO_TRY_AGAIN_LATER;
Marco Nelissen0c3be872014-05-01 10:14:44 -070044 }
45 ALOGE("sf error code: %d", err);
Marco Nelissene419d7c2014-05-15 14:17:25 -070046 return AMEDIA_ERROR_UNKNOWN;
Marco Nelissen0c3be872014-05-01 10:14:44 -070047}
48
Marco Nelissencdb42cd2014-05-08 14:46:05 -070049enum {
50 kWhatActivityNotify,
51 kWhatRequestActivityNotifications,
52 kWhatStopActivityNotifications,
Marco Nelissen0c3be872014-05-01 10:14:44 -070053};
54
Marco Nelissen0c3be872014-05-01 10:14:44 -070055
Marco Nelissencdb42cd2014-05-08 14:46:05 -070056class CodecHandler: public AHandler {
57private:
58 AMediaCodec* mCodec;
59public:
60 CodecHandler(AMediaCodec *codec);
61 virtual void onMessageReceived(const sp<AMessage> &msg);
62};
Marco Nelissen0c3be872014-05-01 10:14:44 -070063
Marco Nelissene22a64b2014-05-23 15:49:49 -070064typedef void (*OnCodecEvent)(AMediaCodec *codec, void *userdata);
65
Marco Nelissen0c3be872014-05-01 10:14:44 -070066struct AMediaCodec {
67 sp<android::MediaCodec> mCodec;
68 sp<ALooper> mLooper;
69 sp<CodecHandler> mHandler;
Marco Nelissencdb42cd2014-05-08 14:46:05 -070070 sp<AMessage> mActivityNotification;
71 int32_t mGeneration;
72 bool mRequestedActivityNotification;
73 OnCodecEvent mCallback;
74 void *mCallbackUserData;
Marco Nelissen0c3be872014-05-01 10:14:44 -070075};
76
Marco Nelissencdb42cd2014-05-08 14:46:05 -070077CodecHandler::CodecHandler(AMediaCodec *codec) {
78 mCodec = codec;
79}
80
81void CodecHandler::onMessageReceived(const sp<AMessage> &msg) {
82
83 switch (msg->what()) {
84 case kWhatRequestActivityNotifications:
85 {
86 if (mCodec->mRequestedActivityNotification) {
87 break;
88 }
89
90 mCodec->mCodec->requestActivityNotification(mCodec->mActivityNotification);
91 mCodec->mRequestedActivityNotification = true;
92 break;
93 }
94
95 case kWhatActivityNotify:
96 {
97 {
98 int32_t generation;
99 msg->findInt32("generation", &generation);
100
101 if (generation != mCodec->mGeneration) {
102 // stale
103 break;
104 }
105
106 mCodec->mRequestedActivityNotification = false;
107 }
108
109 if (mCodec->mCallback) {
110 mCodec->mCallback(mCodec, mCodec->mCallbackUserData);
111 }
112 break;
113 }
114
115 case kWhatStopActivityNotifications:
116 {
117 uint32_t replyID;
118 msg->senderAwaitsResponse(&replyID);
119
120 mCodec->mGeneration++;
121 mCodec->mRequestedActivityNotification = false;
122
123 sp<AMessage> response = new AMessage;
124 response->postReply(replyID);
125 break;
126 }
127
128 default:
129 ALOGE("shouldn't be here");
130 break;
131 }
132
133}
134
135
136static void requestActivityNotification(AMediaCodec *codec) {
137 (new AMessage(kWhatRequestActivityNotifications, codec->mHandler->id()))->post();
138}
139
Marco Nelissen0c3be872014-05-01 10:14:44 -0700140extern "C" {
141
142static AMediaCodec * createAMediaCodec(const char *name, bool name_is_type, bool encoder) {
143 AMediaCodec *mData = new AMediaCodec();
144 mData->mLooper = new ALooper;
145 mData->mLooper->setName("NDK MediaCodec_looper");
146 status_t ret = mData->mLooper->start(
147 false, // runOnCallingThread
148 true, // canCallJava XXX
149 PRIORITY_FOREGROUND);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700150 if (name_is_type) {
151 mData->mCodec = android::MediaCodec::CreateByType(mData->mLooper, name, encoder);
152 } else {
153 mData->mCodec = android::MediaCodec::CreateByComponentName(mData->mLooper, name);
154 }
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700155 mData->mHandler = new CodecHandler(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700156 mData->mLooper->registerHandler(mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700157 mData->mGeneration = 1;
158 mData->mRequestedActivityNotification = false;
159 mData->mCallback = NULL;
160
Marco Nelissen0c3be872014-05-01 10:14:44 -0700161 return mData;
162}
163
Marco Nelissen3425fd52014-05-14 11:12:46 -0700164EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700165AMediaCodec* AMediaCodec_createCodecByName(const char *name) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700166 return createAMediaCodec(name, false, false);
167}
168
Marco Nelissen3425fd52014-05-14 11:12:46 -0700169EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700170AMediaCodec* AMediaCodec_createDecoderByType(const char *mime_type) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700171 return createAMediaCodec(mime_type, true, false);
172}
173
Marco Nelissen3425fd52014-05-14 11:12:46 -0700174EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700175AMediaCodec* AMediaCodec_createEncoderByType(const char *name) {
176 return createAMediaCodec(name, true, true);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700177}
178
Marco Nelissen3425fd52014-05-14 11:12:46 -0700179EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700180media_status_t AMediaCodec_delete(AMediaCodec *mData) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700181 if (mData->mCodec != NULL) {
182 mData->mCodec->release();
183 mData->mCodec.clear();
184 }
185
186 if (mData->mLooper != NULL) {
187 mData->mLooper->unregisterHandler(mData->mHandler->id());
188 mData->mLooper->stop();
189 mData->mLooper.clear();
190 }
191 delete mData;
Marco Nelissene419d7c2014-05-15 14:17:25 -0700192 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700193}
194
Marco Nelissen3425fd52014-05-14 11:12:46 -0700195EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700196media_status_t AMediaCodec_configure(
Marco Nelissen050eb322014-05-09 15:10:23 -0700197 AMediaCodec *mData,
198 const AMediaFormat* format,
199 ANativeWindow* window,
200 AMediaCrypto *crypto,
201 uint32_t flags) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700202 sp<AMessage> nativeFormat;
203 AMediaFormat_getFormat(format, &nativeFormat);
204 ALOGV("configure with format: %s", nativeFormat->debugString(0).c_str());
205 sp<Surface> surface = NULL;
206 if (window != NULL) {
207 surface = (Surface*) window;
208 }
209
Marco Nelissen050eb322014-05-09 15:10:23 -0700210 return translate_error(mData->mCodec->configure(nativeFormat, surface,
211 crypto ? crypto->mCrypto : NULL, flags));
Marco Nelissen0c3be872014-05-01 10:14:44 -0700212}
213
Marco Nelissen3425fd52014-05-14 11:12:46 -0700214EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700215media_status_t AMediaCodec_start(AMediaCodec *mData) {
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700216 status_t ret = mData->mCodec->start();
217 if (ret != OK) {
218 return translate_error(ret);
219 }
220 mData->mActivityNotification = new AMessage(kWhatActivityNotify, mData->mHandler->id());
221 mData->mActivityNotification->setInt32("generation", mData->mGeneration);
222 requestActivityNotification(mData);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700223 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700224}
225
Marco Nelissen3425fd52014-05-14 11:12:46 -0700226EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700227media_status_t AMediaCodec_stop(AMediaCodec *mData) {
228 media_status_t ret = translate_error(mData->mCodec->stop());
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700229
230 sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, mData->mHandler->id());
231 sp<AMessage> response;
232 msg->postAndAwaitResponse(&response);
233 mData->mActivityNotification.clear();
234
235 return ret;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700236}
237
Marco Nelissen3425fd52014-05-14 11:12:46 -0700238EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700239media_status_t AMediaCodec_flush(AMediaCodec *mData) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700240 return translate_error(mData->mCodec->flush());
241}
242
Marco Nelissen3425fd52014-05-14 11:12:46 -0700243EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700244ssize_t AMediaCodec_dequeueInputBuffer(AMediaCodec *mData, int64_t timeoutUs) {
245 size_t idx;
246 status_t ret = mData->mCodec->dequeueInputBuffer(&idx, timeoutUs);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700247 requestActivityNotification(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700248 if (ret == OK) {
249 return idx;
250 }
251 return translate_error(ret);
252}
253
Marco Nelissen3425fd52014-05-14 11:12:46 -0700254EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700255uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
256 android::Vector<android::sp<android::ABuffer> > abufs;
257 if (mData->mCodec->getInputBuffers(&abufs) == 0) {
258 size_t n = abufs.size();
259 if (idx >= n) {
260 ALOGE("buffer index %d out of range", idx);
261 return NULL;
262 }
263 if (out_size != NULL) {
264 *out_size = abufs[idx]->capacity();
265 }
266 return abufs[idx]->data();
267 }
268 ALOGE("couldn't get input buffers");
269 return NULL;
270}
271
Marco Nelissen3425fd52014-05-14 11:12:46 -0700272EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700273uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
274 android::Vector<android::sp<android::ABuffer> > abufs;
275 if (mData->mCodec->getOutputBuffers(&abufs) == 0) {
276 size_t n = abufs.size();
277 if (idx >= n) {
278 ALOGE("buffer index %d out of range", idx);
279 return NULL;
280 }
281 if (out_size != NULL) {
282 *out_size = abufs[idx]->capacity();
283 }
284 return abufs[idx]->data();
285 }
286 ALOGE("couldn't get output buffers");
287 return NULL;
288}
289
Marco Nelissen3425fd52014-05-14 11:12:46 -0700290EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700291media_status_t AMediaCodec_queueInputBuffer(AMediaCodec *mData,
Marco Nelissen0c3be872014-05-01 10:14:44 -0700292 size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags) {
293
294 AString errorMsg;
295 status_t ret = mData->mCodec->queueInputBuffer(idx, offset, size, time, flags, &errorMsg);
296 return translate_error(ret);
297}
298
Marco Nelissen3425fd52014-05-14 11:12:46 -0700299EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700300ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec *mData,
301 AMediaCodecBufferInfo *info, int64_t timeoutUs) {
302 size_t idx;
303 size_t offset;
304 size_t size;
305 uint32_t flags;
306 int64_t presentationTimeUs;
307 status_t ret = mData->mCodec->dequeueOutputBuffer(&idx, &offset, &size, &presentationTimeUs,
308 &flags, timeoutUs);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700309 requestActivityNotification(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700310 switch (ret) {
311 case OK:
312 info->offset = offset;
313 info->size = size;
314 info->flags = flags;
315 info->presentationTimeUs = presentationTimeUs;
316 return idx;
317 case -EAGAIN:
318 return AMEDIACODEC_INFO_TRY_AGAIN_LATER;
319 case android::INFO_FORMAT_CHANGED:
320 return AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED;
321 case INFO_OUTPUT_BUFFERS_CHANGED:
322 return AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED;
323 default:
324 break;
325 }
326 return translate_error(ret);
327}
328
Marco Nelissen3425fd52014-05-14 11:12:46 -0700329EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700330AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec *mData) {
331 sp<AMessage> format;
332 mData->mCodec->getOutputFormat(&format);
333 return AMediaFormat_fromMsg(&format);
334}
335
Marco Nelissen3425fd52014-05-14 11:12:46 -0700336EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700337media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec *mData, size_t idx, bool render) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700338 if (render) {
339 return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx));
340 } else {
341 return translate_error(mData->mCodec->releaseOutputBuffer(idx));
342 }
343}
344
Marco Nelissen3425fd52014-05-14 11:12:46 -0700345EXPORT
Marco Nelissen79e2b622014-05-16 08:07:28 -0700346media_status_t AMediaCodec_releaseOutputBufferAtTime(
347 AMediaCodec *mData, size_t idx, int64_t timestampNs) {
348 ALOGV("render @ %lld", timestampNs);
349 return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx, timestampNs));
350}
351
Marco Nelissene22a64b2014-05-23 15:49:49 -0700352//EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700353media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback, void *userdata) {
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700354 mData->mCallback = callback;
355 mData->mCallbackUserData = userdata;
Marco Nelissene419d7c2014-05-15 14:17:25 -0700356 return AMEDIA_OK;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700357}
358
Marco Nelissen050eb322014-05-09 15:10:23 -0700359typedef struct AMediaCodecCryptoInfo {
360 int numsubsamples;
361 uint8_t key[16];
362 uint8_t iv[16];
Marco Nelissen79e2b622014-05-16 08:07:28 -0700363 cryptoinfo_mode_t mode;
Marco Nelissen050eb322014-05-09 15:10:23 -0700364 size_t *clearbytes;
365 size_t *encryptedbytes;
366} AMediaCodecCryptoInfo;
367
Marco Nelissen3425fd52014-05-14 11:12:46 -0700368EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700369media_status_t AMediaCodec_queueSecureInputBuffer(
Marco Nelissen050eb322014-05-09 15:10:23 -0700370 AMediaCodec* codec,
371 size_t idx,
372 off_t offset,
373 AMediaCodecCryptoInfo* crypto,
374 uint64_t time,
375 uint32_t flags) {
376
377 CryptoPlugin::SubSample *subSamples = new CryptoPlugin::SubSample[crypto->numsubsamples];
378 for (int i = 0; i < crypto->numsubsamples; i++) {
379 subSamples[i].mNumBytesOfClearData = crypto->clearbytes[i];
380 subSamples[i].mNumBytesOfEncryptedData = crypto->encryptedbytes[i];
381 }
382
383 AString errormsg;
384 status_t err = codec->mCodec->queueSecureInputBuffer(idx,
385 offset,
386 subSamples,
387 crypto->numsubsamples,
388 crypto->key,
389 crypto->iv,
390 (CryptoPlugin::Mode) crypto->mode,
391 time,
392 flags,
393 &errormsg);
394 if (err != 0) {
395 ALOGE("queSecureInputBuffer: %s", errormsg.c_str());
396 }
Marco Nelissen829e0972014-05-13 16:22:19 -0700397 delete [] subSamples;
Marco Nelissen050eb322014-05-09 15:10:23 -0700398 return translate_error(err);
399}
400
401
402
Marco Nelissen3425fd52014-05-14 11:12:46 -0700403EXPORT
Marco Nelissen050eb322014-05-09 15:10:23 -0700404AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new(
405 int numsubsamples,
406 uint8_t key[16],
407 uint8_t iv[16],
Marco Nelissen79e2b622014-05-16 08:07:28 -0700408 cryptoinfo_mode_t mode,
Marco Nelissen050eb322014-05-09 15:10:23 -0700409 size_t *clearbytes,
410 size_t *encryptedbytes) {
411
412 // size needed to store all the crypto data
413 size_t cryptosize = sizeof(AMediaCodecCryptoInfo) + sizeof(size_t) * numsubsamples * 2;
414 AMediaCodecCryptoInfo *ret = (AMediaCodecCryptoInfo*) malloc(cryptosize);
415 if (!ret) {
416 ALOGE("couldn't allocate %d bytes", cryptosize);
417 return NULL;
418 }
419 ret->numsubsamples = numsubsamples;
420 memcpy(ret->key, key, 16);
421 memcpy(ret->iv, iv, 16);
422 ret->mode = mode;
423
424 // clearbytes and encryptedbytes point at the actual data, which follows
Marco Nelissen829e0972014-05-13 16:22:19 -0700425 ret->clearbytes = (size_t*) (ret + 1); // point immediately after the struct
426 ret->encryptedbytes = ret->clearbytes + numsubsamples; // point after the clear sizes
Marco Nelissen050eb322014-05-09 15:10:23 -0700427
Marco Nelissen829e0972014-05-13 16:22:19 -0700428 memcpy(ret->clearbytes, clearbytes, numsubsamples * sizeof(size_t));
429 memcpy(ret->encryptedbytes, encryptedbytes, numsubsamples * sizeof(size_t));
Marco Nelissen050eb322014-05-09 15:10:23 -0700430
431 return ret;
432}
433
434
Marco Nelissen3425fd52014-05-14 11:12:46 -0700435EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700436media_status_t AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo* info) {
Marco Nelissen050eb322014-05-09 15:10:23 -0700437 free(info);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700438 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700439}
440
Marco Nelissen3425fd52014-05-14 11:12:46 -0700441EXPORT
Marco Nelissen050eb322014-05-09 15:10:23 -0700442size_t AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo* ci) {
443 return ci->numsubsamples;
444}
445
Marco Nelissen3425fd52014-05-14 11:12:46 -0700446EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700447media_status_t AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
448 if (!ci) {
449 return AMEDIA_ERROR_INVALID_OBJECT;
450 }
451 if (!dst) {
452 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700453 }
454 memcpy(dst, ci->key, 16);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700455 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700456}
457
Marco Nelissen3425fd52014-05-14 11:12:46 -0700458EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700459media_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
460 if (!ci) {
461 return AMEDIA_ERROR_INVALID_OBJECT;
462 }
463 if (!dst) {
464 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700465 }
466 memcpy(dst, ci->iv, 16);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700467 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700468}
469
Marco Nelissen3425fd52014-05-14 11:12:46 -0700470EXPORT
Marco Nelissen79e2b622014-05-16 08:07:28 -0700471cryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo* ci) {
Marco Nelissen050eb322014-05-09 15:10:23 -0700472 if (!ci) {
Marco Nelissen79e2b622014-05-16 08:07:28 -0700473 return (cryptoinfo_mode_t) AMEDIA_ERROR_INVALID_OBJECT;
Marco Nelissen050eb322014-05-09 15:10:23 -0700474 }
475 return ci->mode;
476}
477
Marco Nelissen3425fd52014-05-14 11:12:46 -0700478EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700479media_status_t AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
480 if (!ci) {
481 return AMEDIA_ERROR_INVALID_OBJECT;
482 }
483 if (!dst) {
484 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700485 }
486 memcpy(dst, ci->clearbytes, sizeof(size_t) * ci->numsubsamples);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700487 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700488}
489
Marco Nelissen3425fd52014-05-14 11:12:46 -0700490EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700491media_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
492 if (!ci) {
493 return AMEDIA_ERROR_INVALID_OBJECT;
494 }
495 if (!dst) {
496 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700497 }
498 memcpy(dst, ci->encryptedbytes, sizeof(size_t) * ci->numsubsamples);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700499 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700500}
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700501
Marco Nelissen0c3be872014-05-01 10:14:44 -0700502} // extern "C"
503