blob: ecbdc2ec721b2635e9521987535ef7029fd828f2 [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
22#include "NdkMediaCodec.h"
Marco Nelissen050eb322014-05-09 15:10:23 -070023#include "NdkMediaError.h"
24#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
34#include <media/stagefright/MediaCodec.h>
35#include <media/stagefright/MediaErrors.h>
Wonsik Kim7e34bf52016-08-23 00:09:18 +090036#include <media/MediaCodecBuffer.h>
Praveen Chavan19431582017-01-16 11:56:18 -080037#include <android/native_window.h>
Marco Nelissen0c3be872014-05-01 10:14:44 -070038
39using namespace android;
40
41
Marco Nelissene419d7c2014-05-15 14:17:25 -070042static media_status_t translate_error(status_t err) {
Marco Nelissen0c3be872014-05-01 10:14:44 -070043 if (err == OK) {
Marco Nelissene419d7c2014-05-15 14:17:25 -070044 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -070045 } else if (err == -EAGAIN) {
Marco Nelissene419d7c2014-05-15 14:17:25 -070046 return (media_status_t) AMEDIACODEC_INFO_TRY_AGAIN_LATER;
Marco Nelissen0c3be872014-05-01 10:14:44 -070047 }
48 ALOGE("sf error code: %d", err);
Marco Nelissene419d7c2014-05-15 14:17:25 -070049 return AMEDIA_ERROR_UNKNOWN;
Marco Nelissen0c3be872014-05-01 10:14:44 -070050}
51
Marco Nelissencdb42cd2014-05-08 14:46:05 -070052enum {
53 kWhatActivityNotify,
54 kWhatRequestActivityNotifications,
55 kWhatStopActivityNotifications,
Marco Nelissen0c3be872014-05-01 10:14:44 -070056};
57
Marco Nelissen0c3be872014-05-01 10:14:44 -070058
Marco Nelissencdb42cd2014-05-08 14:46:05 -070059class CodecHandler: public AHandler {
60private:
61 AMediaCodec* mCodec;
62public:
Chih-Hung Hsieh090ef602016-04-27 10:39:54 -070063 explicit CodecHandler(AMediaCodec *codec);
Marco Nelissencdb42cd2014-05-08 14:46:05 -070064 virtual void onMessageReceived(const sp<AMessage> &msg);
65};
Marco Nelissen0c3be872014-05-01 10:14:44 -070066
Marco Nelissene22a64b2014-05-23 15:49:49 -070067typedef void (*OnCodecEvent)(AMediaCodec *codec, void *userdata);
68
Marco Nelissen0c3be872014-05-01 10:14:44 -070069struct AMediaCodec {
70 sp<android::MediaCodec> mCodec;
71 sp<ALooper> mLooper;
72 sp<CodecHandler> mHandler;
Marco Nelissencdb42cd2014-05-08 14:46:05 -070073 sp<AMessage> mActivityNotification;
74 int32_t mGeneration;
75 bool mRequestedActivityNotification;
76 OnCodecEvent mCallback;
77 void *mCallbackUserData;
Marco Nelissen0c3be872014-05-01 10:14:44 -070078};
79
Marco Nelissencdb42cd2014-05-08 14:46:05 -070080CodecHandler::CodecHandler(AMediaCodec *codec) {
81 mCodec = codec;
82}
83
84void CodecHandler::onMessageReceived(const sp<AMessage> &msg) {
85
86 switch (msg->what()) {
87 case kWhatRequestActivityNotifications:
88 {
89 if (mCodec->mRequestedActivityNotification) {
90 break;
91 }
92
93 mCodec->mCodec->requestActivityNotification(mCodec->mActivityNotification);
94 mCodec->mRequestedActivityNotification = true;
95 break;
96 }
97
98 case kWhatActivityNotify:
99 {
100 {
101 int32_t generation;
102 msg->findInt32("generation", &generation);
103
104 if (generation != mCodec->mGeneration) {
105 // stale
106 break;
107 }
108
109 mCodec->mRequestedActivityNotification = false;
110 }
111
112 if (mCodec->mCallback) {
113 mCodec->mCallback(mCodec, mCodec->mCallbackUserData);
114 }
115 break;
116 }
117
118 case kWhatStopActivityNotifications:
119 {
Lajos Molnar3f274362015-03-05 14:35:41 -0800120 sp<AReplyToken> replyID;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700121 msg->senderAwaitsResponse(&replyID);
122
123 mCodec->mGeneration++;
124 mCodec->mRequestedActivityNotification = false;
125
126 sp<AMessage> response = new AMessage;
127 response->postReply(replyID);
128 break;
129 }
130
131 default:
132 ALOGE("shouldn't be here");
133 break;
134 }
135
136}
137
138
139static void requestActivityNotification(AMediaCodec *codec) {
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800140 (new AMessage(kWhatRequestActivityNotifications, codec->mHandler))->post();
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700141}
142
Marco Nelissen0c3be872014-05-01 10:14:44 -0700143extern "C" {
144
145static AMediaCodec * createAMediaCodec(const char *name, bool name_is_type, bool encoder) {
146 AMediaCodec *mData = new AMediaCodec();
147 mData->mLooper = new ALooper;
148 mData->mLooper->setName("NDK MediaCodec_looper");
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800149 size_t res = mData->mLooper->start(
Marco Nelissen0c3be872014-05-01 10:14:44 -0700150 false, // runOnCallingThread
151 true, // canCallJava XXX
152 PRIORITY_FOREGROUND);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800153 if (res != OK) {
154 ALOGE("Failed to start the looper");
Greg Kaiser4e147802016-03-14 14:44:20 -0700155 AMediaCodec_delete(mData);
Aurimas Liutikas214c8332016-02-19 14:48:23 -0800156 return NULL;
157 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700158 if (name_is_type) {
159 mData->mCodec = android::MediaCodec::CreateByType(mData->mLooper, name, encoder);
160 } else {
161 mData->mCodec = android::MediaCodec::CreateByComponentName(mData->mLooper, name);
162 }
Andy Hung6bb63ad2015-04-28 19:05:08 -0700163 if (mData->mCodec == NULL) { // failed to create codec
164 AMediaCodec_delete(mData);
165 return NULL;
166 }
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700167 mData->mHandler = new CodecHandler(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700168 mData->mLooper->registerHandler(mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700169 mData->mGeneration = 1;
170 mData->mRequestedActivityNotification = false;
171 mData->mCallback = NULL;
172
Marco Nelissen0c3be872014-05-01 10:14:44 -0700173 return mData;
174}
175
Marco Nelissen3425fd52014-05-14 11:12:46 -0700176EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700177AMediaCodec* AMediaCodec_createCodecByName(const char *name) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700178 return createAMediaCodec(name, false, false);
179}
180
Marco Nelissen3425fd52014-05-14 11:12:46 -0700181EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700182AMediaCodec* AMediaCodec_createDecoderByType(const char *mime_type) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700183 return createAMediaCodec(mime_type, true, false);
184}
185
Marco Nelissen3425fd52014-05-14 11:12:46 -0700186EXPORT
Marco Nelissen86aa02c2014-05-07 16:03:54 -0700187AMediaCodec* AMediaCodec_createEncoderByType(const char *name) {
188 return createAMediaCodec(name, true, true);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700189}
190
Marco Nelissen3425fd52014-05-14 11:12:46 -0700191EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700192media_status_t AMediaCodec_delete(AMediaCodec *mData) {
Andy Hung6bb63ad2015-04-28 19:05:08 -0700193 if (mData != NULL) {
194 if (mData->mCodec != NULL) {
195 mData->mCodec->release();
196 mData->mCodec.clear();
197 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700198
Andy Hung6bb63ad2015-04-28 19:05:08 -0700199 if (mData->mLooper != NULL) {
200 if (mData->mHandler != NULL) {
201 mData->mLooper->unregisterHandler(mData->mHandler->id());
202 }
203 mData->mLooper->stop();
204 mData->mLooper.clear();
205 }
206 delete mData;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700207 }
Marco Nelissene419d7c2014-05-15 14:17:25 -0700208 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700209}
210
Marco Nelissen3425fd52014-05-14 11:12:46 -0700211EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700212media_status_t AMediaCodec_configure(
Marco Nelissen050eb322014-05-09 15:10:23 -0700213 AMediaCodec *mData,
214 const AMediaFormat* format,
215 ANativeWindow* window,
216 AMediaCrypto *crypto,
217 uint32_t flags) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700218 sp<AMessage> nativeFormat;
219 AMediaFormat_getFormat(format, &nativeFormat);
220 ALOGV("configure with format: %s", nativeFormat->debugString(0).c_str());
221 sp<Surface> surface = NULL;
222 if (window != NULL) {
223 surface = (Surface*) window;
224 }
225
Marco Nelissen050eb322014-05-09 15:10:23 -0700226 return translate_error(mData->mCodec->configure(nativeFormat, surface,
227 crypto ? crypto->mCrypto : NULL, flags));
Marco Nelissen0c3be872014-05-01 10:14:44 -0700228}
229
Marco Nelissen3425fd52014-05-14 11:12:46 -0700230EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700231media_status_t AMediaCodec_start(AMediaCodec *mData) {
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700232 status_t ret = mData->mCodec->start();
233 if (ret != OK) {
234 return translate_error(ret);
235 }
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800236 mData->mActivityNotification = new AMessage(kWhatActivityNotify, mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700237 mData->mActivityNotification->setInt32("generation", mData->mGeneration);
238 requestActivityNotification(mData);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700239 return AMEDIA_OK;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700240}
241
Marco Nelissen3425fd52014-05-14 11:12:46 -0700242EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700243media_status_t AMediaCodec_stop(AMediaCodec *mData) {
244 media_status_t ret = translate_error(mData->mCodec->stop());
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700245
Lajos Molnar1d15ab52015-03-04 16:46:34 -0800246 sp<AMessage> msg = new AMessage(kWhatStopActivityNotifications, mData->mHandler);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700247 sp<AMessage> response;
248 msg->postAndAwaitResponse(&response);
249 mData->mActivityNotification.clear();
250
251 return ret;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700252}
253
Marco Nelissen3425fd52014-05-14 11:12:46 -0700254EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700255media_status_t AMediaCodec_flush(AMediaCodec *mData) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700256 return translate_error(mData->mCodec->flush());
257}
258
Marco Nelissen3425fd52014-05-14 11:12:46 -0700259EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700260ssize_t AMediaCodec_dequeueInputBuffer(AMediaCodec *mData, int64_t timeoutUs) {
261 size_t idx;
262 status_t ret = mData->mCodec->dequeueInputBuffer(&idx, timeoutUs);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700263 requestActivityNotification(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700264 if (ret == OK) {
265 return idx;
266 }
267 return translate_error(ret);
268}
269
Marco Nelissen3425fd52014-05-14 11:12:46 -0700270EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700271uint8_t* AMediaCodec_getInputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900272 android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700273 if (mData->mCodec->getInputBuffers(&abufs) == 0) {
274 size_t n = abufs.size();
275 if (idx >= n) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700276 ALOGE("buffer index %zu out of range", idx);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700277 return NULL;
278 }
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900279 if (abufs[idx] == NULL) {
280 ALOGE("buffer index %zu is NULL", idx);
281 return NULL;
282 }
Marco Nelissen0c3be872014-05-01 10:14:44 -0700283 if (out_size != NULL) {
284 *out_size = abufs[idx]->capacity();
285 }
286 return abufs[idx]->data();
287 }
288 ALOGE("couldn't get input buffers");
289 return NULL;
290}
291
Marco Nelissen3425fd52014-05-14 11:12:46 -0700292EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700293uint8_t* AMediaCodec_getOutputBuffer(AMediaCodec *mData, size_t idx, size_t *out_size) {
Wonsik Kim7e34bf52016-08-23 00:09:18 +0900294 android::Vector<android::sp<android::MediaCodecBuffer> > abufs;
Marco Nelissen0c3be872014-05-01 10:14:44 -0700295 if (mData->mCodec->getOutputBuffers(&abufs) == 0) {
296 size_t n = abufs.size();
297 if (idx >= n) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700298 ALOGE("buffer index %zu out of range", idx);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700299 return NULL;
300 }
301 if (out_size != NULL) {
302 *out_size = abufs[idx]->capacity();
303 }
304 return abufs[idx]->data();
305 }
306 ALOGE("couldn't get output buffers");
307 return NULL;
308}
309
Marco Nelissen3425fd52014-05-14 11:12:46 -0700310EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700311media_status_t AMediaCodec_queueInputBuffer(AMediaCodec *mData,
Marco Nelissen0c3be872014-05-01 10:14:44 -0700312 size_t idx, off_t offset, size_t size, uint64_t time, uint32_t flags) {
313
314 AString errorMsg;
315 status_t ret = mData->mCodec->queueInputBuffer(idx, offset, size, time, flags, &errorMsg);
316 return translate_error(ret);
317}
318
Marco Nelissen3425fd52014-05-14 11:12:46 -0700319EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700320ssize_t AMediaCodec_dequeueOutputBuffer(AMediaCodec *mData,
321 AMediaCodecBufferInfo *info, int64_t timeoutUs) {
322 size_t idx;
323 size_t offset;
324 size_t size;
325 uint32_t flags;
326 int64_t presentationTimeUs;
327 status_t ret = mData->mCodec->dequeueOutputBuffer(&idx, &offset, &size, &presentationTimeUs,
328 &flags, timeoutUs);
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700329 requestActivityNotification(mData);
Marco Nelissen0c3be872014-05-01 10:14:44 -0700330 switch (ret) {
331 case OK:
332 info->offset = offset;
333 info->size = size;
334 info->flags = flags;
335 info->presentationTimeUs = presentationTimeUs;
336 return idx;
337 case -EAGAIN:
338 return AMEDIACODEC_INFO_TRY_AGAIN_LATER;
339 case android::INFO_FORMAT_CHANGED:
340 return AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED;
341 case INFO_OUTPUT_BUFFERS_CHANGED:
342 return AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED;
343 default:
344 break;
345 }
346 return translate_error(ret);
347}
348
Marco Nelissen3425fd52014-05-14 11:12:46 -0700349EXPORT
Marco Nelissen0c3be872014-05-01 10:14:44 -0700350AMediaFormat* AMediaCodec_getOutputFormat(AMediaCodec *mData) {
351 sp<AMessage> format;
352 mData->mCodec->getOutputFormat(&format);
353 return AMediaFormat_fromMsg(&format);
354}
355
Marco Nelissen3425fd52014-05-14 11:12:46 -0700356EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700357media_status_t AMediaCodec_releaseOutputBuffer(AMediaCodec *mData, size_t idx, bool render) {
Marco Nelissen0c3be872014-05-01 10:14:44 -0700358 if (render) {
359 return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx));
360 } else {
361 return translate_error(mData->mCodec->releaseOutputBuffer(idx));
362 }
363}
364
Marco Nelissen3425fd52014-05-14 11:12:46 -0700365EXPORT
Marco Nelissen79e2b622014-05-16 08:07:28 -0700366media_status_t AMediaCodec_releaseOutputBufferAtTime(
367 AMediaCodec *mData, size_t idx, int64_t timestampNs) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700368 ALOGV("render @ %" PRId64, timestampNs);
Marco Nelissen79e2b622014-05-16 08:07:28 -0700369 return translate_error(mData->mCodec->renderOutputBufferAndRelease(idx, timestampNs));
370}
371
Vineeta Srivastava8c35da52016-01-08 17:33:09 -0800372EXPORT
373media_status_t AMediaCodec_setOutputSurface(AMediaCodec *mData, ANativeWindow* window) {
374 sp<Surface> surface = NULL;
375 if (window != NULL) {
376 surface = (Surface*) window;
377 }
378 return translate_error(mData->mCodec->setSurface(surface));
379}
380
Praveen Chavan19431582017-01-16 11:56:18 -0800381EXPORT
382media_status_t AMediaCodec_createInputSurface(AMediaCodec *mData, ANativeWindow **surface) {
383 if (surface == NULL || mData == NULL) {
384 return AMEDIA_ERROR_INVALID_PARAMETER;
385 }
386 *surface = NULL;
387
388 sp<IGraphicBufferProducer> igbp = NULL;
389 status_t err = mData->mCodec->createInputSurface(&igbp);
390 if (err != NO_ERROR) {
391 return translate_error(err);
392 }
393
394 *surface = new Surface(igbp);
395 ANativeWindow_acquire(*surface);
396 return AMEDIA_OK;
397}
398
Marco Nelissene22a64b2014-05-23 15:49:49 -0700399//EXPORT
Glenn Kastenb187de12014-12-30 08:18:15 -0800400media_status_t AMediaCodec_setNotificationCallback(AMediaCodec *mData, OnCodecEvent callback,
401 void *userdata) {
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700402 mData->mCallback = callback;
403 mData->mCallbackUserData = userdata;
Marco Nelissene419d7c2014-05-15 14:17:25 -0700404 return AMEDIA_OK;
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700405}
406
Marco Nelissen050eb322014-05-09 15:10:23 -0700407typedef struct AMediaCodecCryptoInfo {
408 int numsubsamples;
409 uint8_t key[16];
410 uint8_t iv[16];
Marco Nelissen79e2b622014-05-16 08:07:28 -0700411 cryptoinfo_mode_t mode;
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800412 cryptoinfo_pattern_t pattern;
Marco Nelissen050eb322014-05-09 15:10:23 -0700413 size_t *clearbytes;
414 size_t *encryptedbytes;
415} AMediaCodecCryptoInfo;
416
Marco Nelissen3425fd52014-05-14 11:12:46 -0700417EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700418media_status_t AMediaCodec_queueSecureInputBuffer(
Marco Nelissen050eb322014-05-09 15:10:23 -0700419 AMediaCodec* codec,
420 size_t idx,
421 off_t offset,
422 AMediaCodecCryptoInfo* crypto,
423 uint64_t time,
424 uint32_t flags) {
425
426 CryptoPlugin::SubSample *subSamples = new CryptoPlugin::SubSample[crypto->numsubsamples];
427 for (int i = 0; i < crypto->numsubsamples; i++) {
428 subSamples[i].mNumBytesOfClearData = crypto->clearbytes[i];
429 subSamples[i].mNumBytesOfEncryptedData = crypto->encryptedbytes[i];
430 }
431
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800432 CryptoPlugin::Pattern pattern;
433 pattern.mEncryptBlocks = crypto->pattern.encryptBlocks;
434 pattern.mSkipBlocks = crypto->pattern.skipBlocks;
435
Marco Nelissen050eb322014-05-09 15:10:23 -0700436 AString errormsg;
437 status_t err = codec->mCodec->queueSecureInputBuffer(idx,
438 offset,
439 subSamples,
440 crypto->numsubsamples,
441 crypto->key,
442 crypto->iv,
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800443 (CryptoPlugin::Mode)crypto->mode,
444 pattern,
Marco Nelissen050eb322014-05-09 15:10:23 -0700445 time,
446 flags,
447 &errormsg);
448 if (err != 0) {
449 ALOGE("queSecureInputBuffer: %s", errormsg.c_str());
450 }
Marco Nelissen829e0972014-05-13 16:22:19 -0700451 delete [] subSamples;
Marco Nelissen050eb322014-05-09 15:10:23 -0700452 return translate_error(err);
453}
454
455
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800456EXPORT
457void AMediaCodecCryptoInfo_setPattern(AMediaCodecCryptoInfo *info,
458 cryptoinfo_pattern_t *pattern) {
459 info->pattern.encryptBlocks = pattern->encryptBlocks;
460 info->pattern.skipBlocks = pattern->skipBlocks;
461}
Marco Nelissen050eb322014-05-09 15:10:23 -0700462
Marco Nelissen3425fd52014-05-14 11:12:46 -0700463EXPORT
Marco Nelissen050eb322014-05-09 15:10:23 -0700464AMediaCodecCryptoInfo *AMediaCodecCryptoInfo_new(
465 int numsubsamples,
466 uint8_t key[16],
467 uint8_t iv[16],
Marco Nelissen79e2b622014-05-16 08:07:28 -0700468 cryptoinfo_mode_t mode,
Marco Nelissen050eb322014-05-09 15:10:23 -0700469 size_t *clearbytes,
470 size_t *encryptedbytes) {
471
472 // size needed to store all the crypto data
473 size_t cryptosize = sizeof(AMediaCodecCryptoInfo) + sizeof(size_t) * numsubsamples * 2;
474 AMediaCodecCryptoInfo *ret = (AMediaCodecCryptoInfo*) malloc(cryptosize);
475 if (!ret) {
Mark Salyzyn98f28cd2014-06-18 16:32:50 -0700476 ALOGE("couldn't allocate %zu bytes", cryptosize);
Marco Nelissen050eb322014-05-09 15:10:23 -0700477 return NULL;
478 }
479 ret->numsubsamples = numsubsamples;
480 memcpy(ret->key, key, 16);
481 memcpy(ret->iv, iv, 16);
482 ret->mode = mode;
Jeff Tinker18cb1ec2015-12-18 11:55:22 -0800483 ret->pattern.encryptBlocks = 0;
484 ret->pattern.skipBlocks = 0;
Marco Nelissen050eb322014-05-09 15:10:23 -0700485
486 // clearbytes and encryptedbytes point at the actual data, which follows
Marco Nelissen829e0972014-05-13 16:22:19 -0700487 ret->clearbytes = (size_t*) (ret + 1); // point immediately after the struct
488 ret->encryptedbytes = ret->clearbytes + numsubsamples; // point after the clear sizes
Marco Nelissen050eb322014-05-09 15:10:23 -0700489
Marco Nelissen829e0972014-05-13 16:22:19 -0700490 memcpy(ret->clearbytes, clearbytes, numsubsamples * sizeof(size_t));
491 memcpy(ret->encryptedbytes, encryptedbytes, numsubsamples * sizeof(size_t));
Marco Nelissen050eb322014-05-09 15:10:23 -0700492
493 return ret;
494}
495
496
Marco Nelissen3425fd52014-05-14 11:12:46 -0700497EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700498media_status_t AMediaCodecCryptoInfo_delete(AMediaCodecCryptoInfo* info) {
Marco Nelissen050eb322014-05-09 15:10:23 -0700499 free(info);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700500 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700501}
502
Marco Nelissen3425fd52014-05-14 11:12:46 -0700503EXPORT
Marco Nelissen050eb322014-05-09 15:10:23 -0700504size_t AMediaCodecCryptoInfo_getNumSubSamples(AMediaCodecCryptoInfo* ci) {
505 return ci->numsubsamples;
506}
507
Marco Nelissen3425fd52014-05-14 11:12:46 -0700508EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700509media_status_t AMediaCodecCryptoInfo_getKey(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
510 if (!ci) {
511 return AMEDIA_ERROR_INVALID_OBJECT;
512 }
513 if (!dst) {
514 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700515 }
516 memcpy(dst, ci->key, 16);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700517 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700518}
519
Marco Nelissen3425fd52014-05-14 11:12:46 -0700520EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700521media_status_t AMediaCodecCryptoInfo_getIV(AMediaCodecCryptoInfo* ci, uint8_t *dst) {
522 if (!ci) {
523 return AMEDIA_ERROR_INVALID_OBJECT;
524 }
525 if (!dst) {
526 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700527 }
528 memcpy(dst, ci->iv, 16);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700529 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700530}
531
Marco Nelissen3425fd52014-05-14 11:12:46 -0700532EXPORT
Marco Nelissen79e2b622014-05-16 08:07:28 -0700533cryptoinfo_mode_t AMediaCodecCryptoInfo_getMode(AMediaCodecCryptoInfo* ci) {
Marco Nelissen050eb322014-05-09 15:10:23 -0700534 if (!ci) {
Marco Nelissen79e2b622014-05-16 08:07:28 -0700535 return (cryptoinfo_mode_t) AMEDIA_ERROR_INVALID_OBJECT;
Marco Nelissen050eb322014-05-09 15:10:23 -0700536 }
537 return ci->mode;
538}
539
Marco Nelissen3425fd52014-05-14 11:12:46 -0700540EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700541media_status_t AMediaCodecCryptoInfo_getClearBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
542 if (!ci) {
543 return AMEDIA_ERROR_INVALID_OBJECT;
544 }
545 if (!dst) {
546 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700547 }
548 memcpy(dst, ci->clearbytes, sizeof(size_t) * ci->numsubsamples);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700549 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700550}
551
Marco Nelissen3425fd52014-05-14 11:12:46 -0700552EXPORT
Marco Nelissene419d7c2014-05-15 14:17:25 -0700553media_status_t AMediaCodecCryptoInfo_getEncryptedBytes(AMediaCodecCryptoInfo* ci, size_t *dst) {
554 if (!ci) {
555 return AMEDIA_ERROR_INVALID_OBJECT;
556 }
557 if (!dst) {
558 return AMEDIA_ERROR_INVALID_PARAMETER;
Marco Nelissen050eb322014-05-09 15:10:23 -0700559 }
560 memcpy(dst, ci->encryptedbytes, sizeof(size_t) * ci->numsubsamples);
Marco Nelissene419d7c2014-05-15 14:17:25 -0700561 return AMEDIA_OK;
Marco Nelissen050eb322014-05-09 15:10:23 -0700562}
Marco Nelissencdb42cd2014-05-08 14:46:05 -0700563
Marco Nelissen0c3be872014-05-01 10:14:44 -0700564} // extern "C"
565