blob: 0d89c0f2ae632833b5fe4c44d4be4625caf38b92 [file] [log] [blame]
Andreas Huber57788222012-02-21 11:47:18 -08001/*
2 * Copyright 2012, 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
17//#define LOG_NDEBUG 0
18#define LOG_TAG "MediaCodec"
19#include <utils/Log.h>
20
21#include <media/stagefright/MediaCodec.h>
22
23#include "include/SoftwareRenderer.h"
24
Mathias Agopianb1e7cd12013-02-14 17:11:27 -080025#include <gui/Surface.h>
Andreas Hubered3e3e02012-03-26 11:13:27 -070026#include <media/ICrypto.h>
Andreas Huber57788222012-02-21 11:47:18 -080027#include <media/stagefright/foundation/ABuffer.h>
28#include <media/stagefright/foundation/ADebug.h>
29#include <media/stagefright/foundation/AMessage.h>
Andreas Huber5b8987e2012-04-19 12:52:20 -070030#include <media/stagefright/foundation/AString.h>
Andreas Hubered3e3e02012-03-26 11:13:27 -070031#include <media/stagefright/foundation/hexdump.h>
Andreas Huber57788222012-02-21 11:47:18 -080032#include <media/stagefright/ACodec.h>
Andy McFaddenf779bb52013-02-19 07:28:30 -080033#include <media/stagefright/BufferProducerWrapper.h>
Andreas Huber57788222012-02-21 11:47:18 -080034#include <media/stagefright/MediaErrors.h>
35#include <media/stagefright/MetaData.h>
36#include <media/stagefright/NativeWindowWrapper.h>
37
38namespace android {
39
40// static
41sp<MediaCodec> MediaCodec::CreateByType(
42 const sp<ALooper> &looper, const char *mime, bool encoder) {
43 sp<MediaCodec> codec = new MediaCodec(looper);
44 if (codec->init(mime, true /* nameIsType */, encoder) != OK) {
45 return NULL;
46 }
47
48 return codec;
49}
50
51// static
52sp<MediaCodec> MediaCodec::CreateByComponentName(
53 const sp<ALooper> &looper, const char *name) {
54 sp<MediaCodec> codec = new MediaCodec(looper);
55 if (codec->init(name, false /* nameIsType */, false /* encoder */) != OK) {
56 return NULL;
57 }
58
59 return codec;
60}
61
62MediaCodec::MediaCodec(const sp<ALooper> &looper)
63 : mState(UNINITIALIZED),
64 mLooper(looper),
65 mCodec(new ACodec),
Andy McFaddenf779bb52013-02-19 07:28:30 -080066 mReplyID(0),
Andreas Huber57788222012-02-21 11:47:18 -080067 mFlags(0),
68 mSoftRenderer(NULL),
69 mDequeueInputTimeoutGeneration(0),
70 mDequeueInputReplyID(0),
71 mDequeueOutputTimeoutGeneration(0),
Andy McFaddenba6218e2013-03-05 14:31:02 -080072 mDequeueOutputReplyID(0),
73 mHaveInputSurface(false) {
Andreas Huber57788222012-02-21 11:47:18 -080074}
75
76MediaCodec::~MediaCodec() {
77 CHECK_EQ(mState, UNINITIALIZED);
78}
79
80// static
81status_t MediaCodec::PostAndAwaitResponse(
82 const sp<AMessage> &msg, sp<AMessage> *response) {
83 status_t err = msg->postAndAwaitResponse(response);
84
85 if (err != OK) {
86 return err;
87 }
88
89 if (!(*response)->findInt32("err", &err)) {
90 err = OK;
91 }
92
93 return err;
94}
95
96status_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) {
97 // Current video decoders do not return from OMX_FillThisBuffer
98 // quickly, violating the OpenMAX specs, until that is remedied
99 // we need to invest in an extra looper to free the main event
100 // queue.
101 bool needDedicatedLooper = false;
102 if (nameIsType && !strncasecmp(name, "video/", 6)) {
103 needDedicatedLooper = true;
104 } else if (!nameIsType && !strncmp(name, "OMX.TI.DUCATI1.VIDEO.", 21)) {
105 needDedicatedLooper = true;
106 }
107
108 if (needDedicatedLooper) {
109 if (mCodecLooper == NULL) {
110 mCodecLooper = new ALooper;
111 mCodecLooper->setName("CodecLooper");
112 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
113 }
114
115 mCodecLooper->registerHandler(mCodec);
116 } else {
117 mLooper->registerHandler(mCodec);
118 }
119
120 mLooper->registerHandler(this);
121
122 mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id()));
123
124 sp<AMessage> msg = new AMessage(kWhatInit, id());
125 msg->setString("name", name);
126 msg->setInt32("nameIsType", nameIsType);
127
128 if (nameIsType) {
129 msg->setInt32("encoder", encoder);
130 }
131
132 sp<AMessage> response;
133 return PostAndAwaitResponse(msg, &response);
134}
135
136status_t MediaCodec::configure(
137 const sp<AMessage> &format,
Mathias Agopianb1e7cd12013-02-14 17:11:27 -0800138 const sp<Surface> &nativeWindow,
Andreas Huber1bd139a2012-04-03 14:19:20 -0700139 const sp<ICrypto> &crypto,
Andreas Huber57788222012-02-21 11:47:18 -0800140 uint32_t flags) {
141 sp<AMessage> msg = new AMessage(kWhatConfigure, id());
142
143 msg->setMessage("format", format);
144 msg->setInt32("flags", flags);
145
146 if (nativeWindow != NULL) {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700147 msg->setObject(
148 "native-window",
149 new NativeWindowWrapper(nativeWindow));
150 }
151
152 if (crypto != NULL) {
153 msg->setPointer("crypto", crypto.get());
Andreas Huber57788222012-02-21 11:47:18 -0800154 }
155
156 sp<AMessage> response;
157 return PostAndAwaitResponse(msg, &response);
158}
159
Andy McFaddenf779bb52013-02-19 07:28:30 -0800160status_t MediaCodec::createInputSurface(
161 sp<IGraphicBufferProducer>* bufferProducer) {
162 sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, id());
163
Andy McFaddenf779bb52013-02-19 07:28:30 -0800164 sp<AMessage> response;
165 status_t err = PostAndAwaitResponse(msg, &response);
166 if (err == NO_ERROR) {
167 // unwrap the sp<IGraphicBufferProducer>
168 sp<RefBase> obj;
169 bool found = response->findObject("input-surface", &obj);
170 CHECK(found);
171 sp<BufferProducerWrapper> wrapper(
172 static_cast<BufferProducerWrapper*>(obj.get()));
173 *bufferProducer = wrapper->getBufferProducer();
174 } else {
175 ALOGW("createInputSurface failed, err=%d", err);
176 }
177 return err;
178}
179
Andreas Huber57788222012-02-21 11:47:18 -0800180status_t MediaCodec::start() {
181 sp<AMessage> msg = new AMessage(kWhatStart, id());
182
183 sp<AMessage> response;
184 return PostAndAwaitResponse(msg, &response);
185}
186
187status_t MediaCodec::stop() {
188 sp<AMessage> msg = new AMessage(kWhatStop, id());
189
190 sp<AMessage> response;
191 return PostAndAwaitResponse(msg, &response);
192}
193
Andreas Huberc95c2dd2012-02-28 15:54:51 -0800194status_t MediaCodec::release() {
195 sp<AMessage> msg = new AMessage(kWhatRelease, id());
196
197 sp<AMessage> response;
198 return PostAndAwaitResponse(msg, &response);
199}
200
Andreas Huber57788222012-02-21 11:47:18 -0800201status_t MediaCodec::queueInputBuffer(
202 size_t index,
203 size_t offset,
204 size_t size,
205 int64_t presentationTimeUs,
Andreas Huber5b8987e2012-04-19 12:52:20 -0700206 uint32_t flags,
207 AString *errorDetailMsg) {
208 if (errorDetailMsg != NULL) {
209 errorDetailMsg->clear();
210 }
211
Andreas Huber57788222012-02-21 11:47:18 -0800212 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
213 msg->setSize("index", index);
214 msg->setSize("offset", offset);
215 msg->setSize("size", size);
216 msg->setInt64("timeUs", presentationTimeUs);
217 msg->setInt32("flags", flags);
Andreas Huber5b8987e2012-04-19 12:52:20 -0700218 msg->setPointer("errorDetailMsg", errorDetailMsg);
Andreas Huber57788222012-02-21 11:47:18 -0800219
220 sp<AMessage> response;
221 return PostAndAwaitResponse(msg, &response);
222}
223
Andreas Huber4b75a9c2012-04-06 11:06:28 -0700224status_t MediaCodec::queueSecureInputBuffer(
225 size_t index,
226 size_t offset,
227 const CryptoPlugin::SubSample *subSamples,
228 size_t numSubSamples,
229 const uint8_t key[16],
230 const uint8_t iv[16],
231 CryptoPlugin::Mode mode,
232 int64_t presentationTimeUs,
Andreas Huber5b8987e2012-04-19 12:52:20 -0700233 uint32_t flags,
234 AString *errorDetailMsg) {
235 if (errorDetailMsg != NULL) {
236 errorDetailMsg->clear();
237 }
238
Andreas Huber4b75a9c2012-04-06 11:06:28 -0700239 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
240 msg->setSize("index", index);
241 msg->setSize("offset", offset);
242 msg->setPointer("subSamples", (void *)subSamples);
243 msg->setSize("numSubSamples", numSubSamples);
244 msg->setPointer("key", (void *)key);
245 msg->setPointer("iv", (void *)iv);
246 msg->setInt32("mode", mode);
247 msg->setInt64("timeUs", presentationTimeUs);
248 msg->setInt32("flags", flags);
Andreas Huber5b8987e2012-04-19 12:52:20 -0700249 msg->setPointer("errorDetailMsg", errorDetailMsg);
Andreas Huber4b75a9c2012-04-06 11:06:28 -0700250
251 sp<AMessage> response;
Andreas Huber5b8987e2012-04-19 12:52:20 -0700252 status_t err = PostAndAwaitResponse(msg, &response);
253
254 return err;
Andreas Huber4b75a9c2012-04-06 11:06:28 -0700255}
256
Andreas Huber57788222012-02-21 11:47:18 -0800257status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
258 sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id());
259 msg->setInt64("timeoutUs", timeoutUs);
260
261 sp<AMessage> response;
262 status_t err;
263 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
264 return err;
265 }
266
267 CHECK(response->findSize("index", index));
268
269 return OK;
270}
271
272status_t MediaCodec::dequeueOutputBuffer(
273 size_t *index,
274 size_t *offset,
275 size_t *size,
276 int64_t *presentationTimeUs,
277 uint32_t *flags,
278 int64_t timeoutUs) {
279 sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id());
280 msg->setInt64("timeoutUs", timeoutUs);
281
282 sp<AMessage> response;
283 status_t err;
284 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
285 return err;
286 }
287
288 CHECK(response->findSize("index", index));
289 CHECK(response->findSize("offset", offset));
290 CHECK(response->findSize("size", size));
291 CHECK(response->findInt64("timeUs", presentationTimeUs));
292 CHECK(response->findInt32("flags", (int32_t *)flags));
293
294 return OK;
295}
296
297status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
298 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
299 msg->setSize("index", index);
300 msg->setInt32("render", true);
301
302 sp<AMessage> response;
303 return PostAndAwaitResponse(msg, &response);
304}
305
306status_t MediaCodec::releaseOutputBuffer(size_t index) {
307 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
308 msg->setSize("index", index);
309
310 sp<AMessage> response;
311 return PostAndAwaitResponse(msg, &response);
312}
313
Andy McFaddenf779bb52013-02-19 07:28:30 -0800314status_t MediaCodec::signalEndOfInputStream() {
315 sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, id());
316
317 sp<AMessage> response;
318 return PostAndAwaitResponse(msg, &response);
319}
320
Andreas Huber57788222012-02-21 11:47:18 -0800321status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
322 sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id());
323
324 sp<AMessage> response;
325 status_t err;
326 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
327 return err;
328 }
329
330 CHECK(response->findMessage("format", format));
331
332 return OK;
333}
334
Martin Storsjo8601efe2012-09-25 11:43:02 +0300335status_t MediaCodec::getName(AString *name) const {
336 sp<AMessage> msg = new AMessage(kWhatGetName, id());
337
338 sp<AMessage> response;
339 status_t err;
340 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
341 return err;
342 }
343
344 CHECK(response->findString("name", name));
345
346 return OK;
347}
348
Andreas Huber57788222012-02-21 11:47:18 -0800349status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
350 sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
351 msg->setInt32("portIndex", kPortIndexInput);
352 msg->setPointer("buffers", buffers);
353
354 sp<AMessage> response;
355 return PostAndAwaitResponse(msg, &response);
356}
357
358status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
359 sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
360 msg->setInt32("portIndex", kPortIndexOutput);
361 msg->setPointer("buffers", buffers);
362
363 sp<AMessage> response;
364 return PostAndAwaitResponse(msg, &response);
365}
366
367status_t MediaCodec::flush() {
368 sp<AMessage> msg = new AMessage(kWhatFlush, id());
369
370 sp<AMessage> response;
371 return PostAndAwaitResponse(msg, &response);
372}
373
Andreas Huber03e2ffa2012-09-13 16:43:51 -0700374status_t MediaCodec::requestIDRFrame() {
375 (new AMessage(kWhatRequestIDRFrame, id()))->post();
376
377 return OK;
378}
379
Andreas Huber72c66862012-10-03 10:16:58 -0700380void MediaCodec::requestActivityNotification(const sp<AMessage> &notify) {
381 sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, id());
382 msg->setMessage("notify", notify);
383 msg->post();
384}
385
Andreas Huber57788222012-02-21 11:47:18 -0800386////////////////////////////////////////////////////////////////////////////////
387
388void MediaCodec::cancelPendingDequeueOperations() {
389 if (mFlags & kFlagDequeueInputPending) {
390 sp<AMessage> response = new AMessage;
391 response->setInt32("err", INVALID_OPERATION);
392 response->postReply(mDequeueInputReplyID);
393
394 ++mDequeueInputTimeoutGeneration;
395 mDequeueInputReplyID = 0;
396 mFlags &= ~kFlagDequeueInputPending;
397 }
398
399 if (mFlags & kFlagDequeueOutputPending) {
400 sp<AMessage> response = new AMessage;
401 response->setInt32("err", INVALID_OPERATION);
402 response->postReply(mDequeueOutputReplyID);
403
404 ++mDequeueOutputTimeoutGeneration;
405 mDequeueOutputReplyID = 0;
406 mFlags &= ~kFlagDequeueOutputPending;
407 }
408}
409
410bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) {
411 if (mState != STARTED
412 || (mFlags & kFlagStickyError)
413 || (newRequest && (mFlags & kFlagDequeueInputPending))) {
414 sp<AMessage> response = new AMessage;
415 response->setInt32("err", INVALID_OPERATION);
416
417 response->postReply(replyID);
418
419 return true;
420 }
421
422 ssize_t index = dequeuePortBuffer(kPortIndexInput);
423
424 if (index < 0) {
425 CHECK_EQ(index, -EAGAIN);
426 return false;
427 }
428
429 sp<AMessage> response = new AMessage;
430 response->setSize("index", index);
431 response->postReply(replyID);
432
433 return true;
434}
435
436bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) {
437 sp<AMessage> response = new AMessage;
438
439 if (mState != STARTED
440 || (mFlags & kFlagStickyError)
441 || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
442 response->setInt32("err", INVALID_OPERATION);
443 } else if (mFlags & kFlagOutputBuffersChanged) {
444 response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED);
445 mFlags &= ~kFlagOutputBuffersChanged;
446 } else if (mFlags & kFlagOutputFormatChanged) {
447 response->setInt32("err", INFO_FORMAT_CHANGED);
448 mFlags &= ~kFlagOutputFormatChanged;
449 } else {
450 ssize_t index = dequeuePortBuffer(kPortIndexOutput);
451
452 if (index < 0) {
453 CHECK_EQ(index, -EAGAIN);
454 return false;
455 }
456
457 const sp<ABuffer> &buffer =
458 mPortBuffers[kPortIndexOutput].itemAt(index).mData;
459
460 response->setSize("index", index);
461 response->setSize("offset", buffer->offset());
462 response->setSize("size", buffer->size());
463
464 int64_t timeUs;
465 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
466
467 response->setInt64("timeUs", timeUs);
468
469 int32_t omxFlags;
470 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
471
472 uint32_t flags = 0;
473 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
474 flags |= BUFFER_FLAG_SYNCFRAME;
475 }
476 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
477 flags |= BUFFER_FLAG_CODECCONFIG;
478 }
479 if (omxFlags & OMX_BUFFERFLAG_EOS) {
480 flags |= BUFFER_FLAG_EOS;
481 }
482
483 response->setInt32("flags", flags);
484 }
485
486 response->postReply(replyID);
487
488 return true;
489}
490
491void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
492 switch (msg->what()) {
493 case kWhatCodecNotify:
494 {
495 int32_t what;
496 CHECK(msg->findInt32("what", &what));
497
498 switch (what) {
499 case ACodec::kWhatError:
500 {
501 int32_t omxError, internalError;
502 CHECK(msg->findInt32("omx-error", &omxError));
503 CHECK(msg->findInt32("err", &internalError));
504
505 ALOGE("Codec reported an error. "
506 "(omx error 0x%08x, internalError %d)",
507 omxError, internalError);
508
509 bool sendErrorReponse = true;
510
511 switch (mState) {
512 case INITIALIZING:
513 {
514 setState(UNINITIALIZED);
515 break;
516 }
517
518 case CONFIGURING:
519 {
520 setState(INITIALIZED);
521 break;
522 }
523
524 case STARTING:
525 {
526 setState(CONFIGURED);
527 break;
528 }
529
530 case STOPPING:
Andreas Huberc95c2dd2012-02-28 15:54:51 -0800531 case RELEASING:
Andreas Huber57788222012-02-21 11:47:18 -0800532 {
533 // Ignore the error, assuming we'll still get
534 // the shutdown complete notification.
535
536 sendErrorReponse = false;
537 break;
538 }
539
540 case FLUSHING:
541 {
542 setState(STARTED);
543 break;
544 }
545
546 case STARTED:
547 {
548 sendErrorReponse = false;
549
550 mFlags |= kFlagStickyError;
Andreas Huber72c66862012-10-03 10:16:58 -0700551 postActivityNotificationIfPossible();
Andreas Huber57788222012-02-21 11:47:18 -0800552
553 cancelPendingDequeueOperations();
554 break;
555 }
556
557 default:
558 {
559 sendErrorReponse = false;
560
561 mFlags |= kFlagStickyError;
Andreas Huber72c66862012-10-03 10:16:58 -0700562 postActivityNotificationIfPossible();
Andreas Huber57788222012-02-21 11:47:18 -0800563 break;
564 }
565 }
566
567 if (sendErrorReponse) {
568 sp<AMessage> response = new AMessage;
569 response->setInt32("err", UNKNOWN_ERROR);
570
571 response->postReply(mReplyID);
572 }
573 break;
574 }
575
576 case ACodec::kWhatComponentAllocated:
577 {
578 CHECK_EQ(mState, INITIALIZING);
579 setState(INITIALIZED);
580
Martin Storsjo8601efe2012-09-25 11:43:02 +0300581 CHECK(msg->findString("componentName", &mComponentName));
Andreas Huber57788222012-02-21 11:47:18 -0800582
Martin Storsjo8601efe2012-09-25 11:43:02 +0300583 if (mComponentName.startsWith("OMX.google.")) {
Andreas Huber57788222012-02-21 11:47:18 -0800584 mFlags |= kFlagIsSoftwareCodec;
585 } else {
586 mFlags &= ~kFlagIsSoftwareCodec;
587 }
588
Martin Storsjo8601efe2012-09-25 11:43:02 +0300589 if (mComponentName.endsWith(".secure")) {
Andreas Huber1bd139a2012-04-03 14:19:20 -0700590 mFlags |= kFlagIsSecure;
591 } else {
592 mFlags &= ~kFlagIsSecure;
593 }
594
Andreas Huber57788222012-02-21 11:47:18 -0800595 (new AMessage)->postReply(mReplyID);
596 break;
597 }
598
599 case ACodec::kWhatComponentConfigured:
600 {
601 CHECK_EQ(mState, CONFIGURING);
602 setState(CONFIGURED);
603
Andy McFaddenba6218e2013-03-05 14:31:02 -0800604 // reset input surface flag
605 mHaveInputSurface = false;
606
Andreas Huber57788222012-02-21 11:47:18 -0800607 (new AMessage)->postReply(mReplyID);
608 break;
609 }
610
Andy McFaddenf779bb52013-02-19 07:28:30 -0800611 case ACodec::kWhatInputSurfaceCreated:
612 {
613 // response to ACodec::kWhatCreateInputSurface
614 status_t err = NO_ERROR;
615 sp<AMessage> response = new AMessage();
616 if (!msg->findInt32("err", &err)) {
617 sp<RefBase> obj;
618 msg->findObject("input-surface", &obj);
619 CHECK(obj != NULL);
620 response->setObject("input-surface", obj);
Andy McFaddenba6218e2013-03-05 14:31:02 -0800621 mHaveInputSurface = true;
Andy McFaddenf779bb52013-02-19 07:28:30 -0800622 } else {
623 response->setInt32("err", err);
624 }
625 response->postReply(mReplyID);
626 break;
627 }
628
629 case ACodec::kWhatSignaledInputEOS:
630 {
631 // response to ACodec::kWhatSignalEndOfInputStream
632 sp<AMessage> response = new AMessage();
633 status_t err;
634 if (msg->findInt32("err", &err)) {
635 response->setInt32("err", err);
636 }
637 response->postReply(mReplyID);
638 break;
639 }
640
641
Andreas Huber57788222012-02-21 11:47:18 -0800642 case ACodec::kWhatBuffersAllocated:
643 {
644 int32_t portIndex;
645 CHECK(msg->findInt32("portIndex", &portIndex));
646
647 ALOGV("%s buffers allocated",
648 portIndex == kPortIndexInput ? "input" : "output");
649
650 CHECK(portIndex == kPortIndexInput
651 || portIndex == kPortIndexOutput);
652
653 mPortBuffers[portIndex].clear();
654
655 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
Andreas Huber57788222012-02-21 11:47:18 -0800656
Andreas Hubereb614312012-05-10 16:43:19 -0700657 sp<RefBase> obj;
658 CHECK(msg->findObject("portDesc", &obj));
Andreas Huber57788222012-02-21 11:47:18 -0800659
Andreas Hubereb614312012-05-10 16:43:19 -0700660 sp<ACodec::PortDescription> portDesc =
661 static_cast<ACodec::PortDescription *>(obj.get());
Andreas Huber57788222012-02-21 11:47:18 -0800662
Andreas Hubereb614312012-05-10 16:43:19 -0700663 size_t numBuffers = portDesc->countBuffers();
664
665 for (size_t i = 0; i < numBuffers; ++i) {
Andreas Huber57788222012-02-21 11:47:18 -0800666 BufferInfo info;
Andreas Hubereb614312012-05-10 16:43:19 -0700667 info.mBufferID = portDesc->bufferIDAt(i);
Andreas Huber57788222012-02-21 11:47:18 -0800668 info.mOwnedByClient = false;
Andreas Hubereb614312012-05-10 16:43:19 -0700669 info.mData = portDesc->bufferAt(i);
Andreas Huber57788222012-02-21 11:47:18 -0800670
Andreas Huber1bd139a2012-04-03 14:19:20 -0700671 if (portIndex == kPortIndexInput && mCrypto != NULL) {
Andreas Hubered3e3e02012-03-26 11:13:27 -0700672 info.mEncryptedData =
673 new ABuffer(info.mData->capacity());
674 }
675
Andreas Huber57788222012-02-21 11:47:18 -0800676 buffers->push_back(info);
677 }
678
679 if (portIndex == kPortIndexOutput) {
680 if (mState == STARTING) {
681 // We're always allocating output buffers after
682 // allocating input buffers, so this is a good
683 // indication that now all buffers are allocated.
684 setState(STARTED);
685 (new AMessage)->postReply(mReplyID);
686 } else {
687 mFlags |= kFlagOutputBuffersChanged;
Andreas Huber72c66862012-10-03 10:16:58 -0700688 postActivityNotificationIfPossible();
Andreas Huber57788222012-02-21 11:47:18 -0800689 }
690 }
691 break;
692 }
693
694 case ACodec::kWhatOutputFormatChanged:
695 {
696 ALOGV("codec output format changed");
697
698 if ((mFlags & kFlagIsSoftwareCodec)
699 && mNativeWindow != NULL) {
700 AString mime;
701 CHECK(msg->findString("mime", &mime));
702
703 if (!strncasecmp("video/", mime.c_str(), 6)) {
704 delete mSoftRenderer;
705 mSoftRenderer = NULL;
706
707 int32_t width, height;
708 CHECK(msg->findInt32("width", &width));
709 CHECK(msg->findInt32("height", &height));
710
711 int32_t colorFormat;
712 CHECK(msg->findInt32(
713 "color-format", &colorFormat));
714
715 sp<MetaData> meta = new MetaData;
716 meta->setInt32(kKeyWidth, width);
717 meta->setInt32(kKeyHeight, height);
718 meta->setInt32(kKeyColorFormat, colorFormat);
719
720 mSoftRenderer =
721 new SoftwareRenderer(mNativeWindow, meta);
722 }
723 }
724
725 mOutputFormat = msg;
726 mFlags |= kFlagOutputFormatChanged;
Andreas Huber72c66862012-10-03 10:16:58 -0700727 postActivityNotificationIfPossible();
Andreas Huber57788222012-02-21 11:47:18 -0800728 break;
729 }
730
731 case ACodec::kWhatFillThisBuffer:
732 {
733 /* size_t index = */updateBuffers(kPortIndexInput, msg);
734
Andreas Huberc95c2dd2012-02-28 15:54:51 -0800735 if (mState == FLUSHING
736 || mState == STOPPING
737 || mState == RELEASING) {
Andreas Huber57788222012-02-21 11:47:18 -0800738 returnBuffersToCodecOnPort(kPortIndexInput);
739 break;
740 }
741
Andreas Huber8ee516a2012-05-08 11:21:26 -0700742 if (!mCSD.empty()) {
743 ssize_t index = dequeuePortBuffer(kPortIndexInput);
744 CHECK_GE(index, 0);
745
746 // If codec specific data had been specified as
747 // part of the format in the call to configure and
748 // if there's more csd left, we submit it here
749 // clients only get access to input buffers once
750 // this data has been exhausted.
751
752 status_t err = queueCSDInputBuffer(index);
753
754 if (err != OK) {
755 ALOGE("queueCSDInputBuffer failed w/ error %d",
756 err);
757
758 mFlags |= kFlagStickyError;
Andreas Huber72c66862012-10-03 10:16:58 -0700759 postActivityNotificationIfPossible();
760
Andreas Huber8ee516a2012-05-08 11:21:26 -0700761 cancelPendingDequeueOperations();
762 }
763 break;
764 }
765
Andreas Huber57788222012-02-21 11:47:18 -0800766 if (mFlags & kFlagDequeueInputPending) {
767 CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
768
769 ++mDequeueInputTimeoutGeneration;
770 mFlags &= ~kFlagDequeueInputPending;
771 mDequeueInputReplyID = 0;
Andreas Huber72c66862012-10-03 10:16:58 -0700772 } else {
773 postActivityNotificationIfPossible();
Andreas Huber57788222012-02-21 11:47:18 -0800774 }
775 break;
776 }
777
778 case ACodec::kWhatDrainThisBuffer:
779 {
780 /* size_t index = */updateBuffers(kPortIndexOutput, msg);
781
Andreas Huberc95c2dd2012-02-28 15:54:51 -0800782 if (mState == FLUSHING
783 || mState == STOPPING
784 || mState == RELEASING) {
Andreas Huber57788222012-02-21 11:47:18 -0800785 returnBuffersToCodecOnPort(kPortIndexOutput);
786 break;
787 }
788
Andreas Huber2d8bedd2012-02-21 14:38:23 -0800789 sp<ABuffer> buffer;
790 CHECK(msg->findBuffer("buffer", &buffer));
Andreas Huber57788222012-02-21 11:47:18 -0800791
792 int32_t omxFlags;
793 CHECK(msg->findInt32("flags", &omxFlags));
794
795 buffer->meta()->setInt32("omxFlags", omxFlags);
796
797 if (mFlags & kFlagDequeueOutputPending) {
798 CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
799
800 ++mDequeueOutputTimeoutGeneration;
801 mFlags &= ~kFlagDequeueOutputPending;
802 mDequeueOutputReplyID = 0;
Andreas Huber72c66862012-10-03 10:16:58 -0700803 } else {
804 postActivityNotificationIfPossible();
Andreas Huber57788222012-02-21 11:47:18 -0800805 }
Andreas Huber72c66862012-10-03 10:16:58 -0700806
Andreas Huber57788222012-02-21 11:47:18 -0800807 break;
808 }
809
810 case ACodec::kWhatEOS:
811 {
812 // We already notify the client of this by using the
813 // corresponding flag in "onOutputBufferReady".
814 break;
815 }
816
817 case ACodec::kWhatShutdownCompleted:
818 {
Andreas Huberc95c2dd2012-02-28 15:54:51 -0800819 if (mState == STOPPING) {
820 setState(INITIALIZED);
821 } else {
822 CHECK_EQ(mState, RELEASING);
823 setState(UNINITIALIZED);
824 }
Andreas Huber57788222012-02-21 11:47:18 -0800825
826 (new AMessage)->postReply(mReplyID);
827 break;
828 }
829
830 case ACodec::kWhatFlushCompleted:
831 {
832 CHECK_EQ(mState, FLUSHING);
833 setState(STARTED);
834
835 mCodec->signalResume();
836
837 (new AMessage)->postReply(mReplyID);
838 break;
839 }
840
841 default:
842 TRESPASS();
843 }
844 break;
845 }
846
847 case kWhatInit:
848 {
849 uint32_t replyID;
850 CHECK(msg->senderAwaitsResponse(&replyID));
851
852 if (mState != UNINITIALIZED) {
853 sp<AMessage> response = new AMessage;
854 response->setInt32("err", INVALID_OPERATION);
855
856 response->postReply(replyID);
857 break;
858 }
859
860 mReplyID = replyID;
861 setState(INITIALIZING);
862
863 AString name;
864 CHECK(msg->findString("name", &name));
865
866 int32_t nameIsType;
867 int32_t encoder = false;
Andreas Huber0db28012012-02-24 08:41:46 -0800868 CHECK(msg->findInt32("nameIsType", &nameIsType));
869 if (nameIsType) {
Andreas Huber57788222012-02-21 11:47:18 -0800870 CHECK(msg->findInt32("encoder", &encoder));
871 }
872
873 sp<AMessage> format = new AMessage;
874
875 if (nameIsType) {
876 format->setString("mime", name.c_str());
877 format->setInt32("encoder", encoder);
878 } else {
879 format->setString("componentName", name.c_str());
880 }
881
882 mCodec->initiateAllocateComponent(format);
883 break;
884 }
885
886 case kWhatConfigure:
887 {
888 uint32_t replyID;
889 CHECK(msg->senderAwaitsResponse(&replyID));
890
891 if (mState != INITIALIZED) {
892 sp<AMessage> response = new AMessage;
893 response->setInt32("err", INVALID_OPERATION);
894
895 response->postReply(replyID);
896 break;
897 }
898
Andreas Huber57788222012-02-21 11:47:18 -0800899 sp<RefBase> obj;
900 if (!msg->findObject("native-window", &obj)) {
901 obj.clear();
902 }
903
904 sp<AMessage> format;
905 CHECK(msg->findMessage("format", &format));
906
907 if (obj != NULL) {
908 format->setObject("native-window", obj);
Andreas Huber1bd139a2012-04-03 14:19:20 -0700909
Andreas Huber7541ff52012-05-10 10:54:15 -0700910 status_t err = setNativeWindow(
911 static_cast<NativeWindowWrapper *>(obj.get())
912 ->getSurfaceTextureClient());
913
914 if (err != OK) {
915 sp<AMessage> response = new AMessage;
916 response->setInt32("err", err);
917
918 response->postReply(replyID);
919 break;
Andreas Huber1bd139a2012-04-03 14:19:20 -0700920 }
921 } else {
Andreas Huber7541ff52012-05-10 10:54:15 -0700922 setNativeWindow(NULL);
Andreas Huber57788222012-02-21 11:47:18 -0800923 }
924
Andreas Huber7541ff52012-05-10 10:54:15 -0700925 mReplyID = replyID;
926 setState(CONFIGURING);
927
Andreas Huber1bd139a2012-04-03 14:19:20 -0700928 void *crypto;
929 if (!msg->findPointer("crypto", &crypto)) {
930 crypto = NULL;
931 }
932
933 mCrypto = static_cast<ICrypto *>(crypto);
934
Andreas Huber57788222012-02-21 11:47:18 -0800935 uint32_t flags;
936 CHECK(msg->findInt32("flags", (int32_t *)&flags));
937
938 if (flags & CONFIGURE_FLAG_ENCODE) {
939 format->setInt32("encoder", true);
940 }
941
Andreas Huber8ee516a2012-05-08 11:21:26 -0700942 extractCSD(format);
943
Andreas Huber57788222012-02-21 11:47:18 -0800944 mCodec->initiateConfigureComponent(format);
945 break;
946 }
947
Andy McFaddenf779bb52013-02-19 07:28:30 -0800948 case kWhatCreateInputSurface:
949 {
950 uint32_t replyID;
951 CHECK(msg->senderAwaitsResponse(&replyID));
952
953 // Must be configured, but can't have been started yet.
954 if (mState != CONFIGURED) {
955 sp<AMessage> response = new AMessage;
956 response->setInt32("err", INVALID_OPERATION);
957
958 response->postReply(replyID);
959 break;
960 }
961
962 mReplyID = replyID;
963 mCodec->initiateCreateInputSurface();
964 break;
965 }
966
Andreas Huber57788222012-02-21 11:47:18 -0800967 case kWhatStart:
968 {
969 uint32_t replyID;
970 CHECK(msg->senderAwaitsResponse(&replyID));
971
972 if (mState != CONFIGURED) {
973 sp<AMessage> response = new AMessage;
974 response->setInt32("err", INVALID_OPERATION);
975
976 response->postReply(replyID);
977 break;
978 }
979
980 mReplyID = replyID;
981 setState(STARTING);
982
983 mCodec->initiateStart();
984 break;
985 }
986
987 case kWhatStop:
988 {
989 uint32_t replyID;
990 CHECK(msg->senderAwaitsResponse(&replyID));
991
992 if (mState != INITIALIZED
993 && mState != CONFIGURED && mState != STARTED) {
994 sp<AMessage> response = new AMessage;
995 response->setInt32("err", INVALID_OPERATION);
996
997 response->postReply(replyID);
998 break;
999 }
1000
1001 mReplyID = replyID;
1002 setState(STOPPING);
1003
Andreas Huberc95c2dd2012-02-28 15:54:51 -08001004 mCodec->initiateShutdown(true /* keepComponentAllocated */);
1005 returnBuffersToCodec();
1006 break;
1007 }
1008
1009 case kWhatRelease:
1010 {
1011 uint32_t replyID;
1012 CHECK(msg->senderAwaitsResponse(&replyID));
1013
1014 if (mState != INITIALIZED
1015 && mState != CONFIGURED && mState != STARTED) {
1016 sp<AMessage> response = new AMessage;
1017 response->setInt32("err", INVALID_OPERATION);
1018
1019 response->postReply(replyID);
1020 break;
1021 }
1022
1023 mReplyID = replyID;
1024 setState(RELEASING);
1025
Andreas Huber57788222012-02-21 11:47:18 -08001026 mCodec->initiateShutdown();
1027 returnBuffersToCodec();
1028 break;
1029 }
1030
1031 case kWhatDequeueInputBuffer:
1032 {
1033 uint32_t replyID;
1034 CHECK(msg->senderAwaitsResponse(&replyID));
1035
Andy McFaddenba6218e2013-03-05 14:31:02 -08001036 if (mHaveInputSurface) {
1037 ALOGE("dequeueInputBuffer can't be used with input surface");
1038 sp<AMessage> response = new AMessage;
1039 response->setInt32("err", INVALID_OPERATION);
1040 response->postReply(replyID);
1041 break;
1042 }
1043
Andreas Huber57788222012-02-21 11:47:18 -08001044 if (handleDequeueInputBuffer(replyID, true /* new request */)) {
1045 break;
1046 }
1047
1048 int64_t timeoutUs;
1049 CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1050
1051 if (timeoutUs == 0ll) {
1052 sp<AMessage> response = new AMessage;
1053 response->setInt32("err", -EAGAIN);
1054 response->postReply(replyID);
1055 break;
1056 }
1057
1058 mFlags |= kFlagDequeueInputPending;
1059 mDequeueInputReplyID = replyID;
1060
1061 if (timeoutUs > 0ll) {
1062 sp<AMessage> timeoutMsg =
1063 new AMessage(kWhatDequeueInputTimedOut, id());
1064 timeoutMsg->setInt32(
1065 "generation", ++mDequeueInputTimeoutGeneration);
1066 timeoutMsg->post(timeoutUs);
1067 }
1068 break;
1069 }
1070
1071 case kWhatDequeueInputTimedOut:
1072 {
1073 int32_t generation;
1074 CHECK(msg->findInt32("generation", &generation));
1075
1076 if (generation != mDequeueInputTimeoutGeneration) {
1077 // Obsolete
1078 break;
1079 }
1080
1081 CHECK(mFlags & kFlagDequeueInputPending);
1082
1083 sp<AMessage> response = new AMessage;
1084 response->setInt32("err", -EAGAIN);
1085 response->postReply(mDequeueInputReplyID);
1086
1087 mFlags &= ~kFlagDequeueInputPending;
1088 mDequeueInputReplyID = 0;
1089 break;
1090 }
1091
1092 case kWhatQueueInputBuffer:
1093 {
1094 uint32_t replyID;
1095 CHECK(msg->senderAwaitsResponse(&replyID));
1096
1097 if (mState != STARTED || (mFlags & kFlagStickyError)) {
1098 sp<AMessage> response = new AMessage;
1099 response->setInt32("err", INVALID_OPERATION);
1100
1101 response->postReply(replyID);
1102 break;
1103 }
1104
1105 status_t err = onQueueInputBuffer(msg);
1106
1107 sp<AMessage> response = new AMessage;
1108 response->setInt32("err", err);
1109 response->postReply(replyID);
1110 break;
1111 }
1112
1113 case kWhatDequeueOutputBuffer:
1114 {
1115 uint32_t replyID;
1116 CHECK(msg->senderAwaitsResponse(&replyID));
1117
1118 if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
1119 break;
1120 }
1121
1122 int64_t timeoutUs;
1123 CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1124
1125 if (timeoutUs == 0ll) {
1126 sp<AMessage> response = new AMessage;
1127 response->setInt32("err", -EAGAIN);
1128 response->postReply(replyID);
1129 break;
1130 }
1131
1132 mFlags |= kFlagDequeueOutputPending;
1133 mDequeueOutputReplyID = replyID;
1134
1135 if (timeoutUs > 0ll) {
1136 sp<AMessage> timeoutMsg =
1137 new AMessage(kWhatDequeueOutputTimedOut, id());
1138 timeoutMsg->setInt32(
1139 "generation", ++mDequeueOutputTimeoutGeneration);
1140 timeoutMsg->post(timeoutUs);
1141 }
1142 break;
1143 }
1144
1145 case kWhatDequeueOutputTimedOut:
1146 {
1147 int32_t generation;
1148 CHECK(msg->findInt32("generation", &generation));
1149
1150 if (generation != mDequeueOutputTimeoutGeneration) {
1151 // Obsolete
1152 break;
1153 }
1154
1155 CHECK(mFlags & kFlagDequeueOutputPending);
1156
1157 sp<AMessage> response = new AMessage;
1158 response->setInt32("err", -EAGAIN);
1159 response->postReply(mDequeueOutputReplyID);
1160
1161 mFlags &= ~kFlagDequeueOutputPending;
1162 mDequeueOutputReplyID = 0;
1163 break;
1164 }
1165
1166 case kWhatReleaseOutputBuffer:
1167 {
1168 uint32_t replyID;
1169 CHECK(msg->senderAwaitsResponse(&replyID));
1170
1171 if (mState != STARTED || (mFlags & kFlagStickyError)) {
1172 sp<AMessage> response = new AMessage;
1173 response->setInt32("err", INVALID_OPERATION);
1174
1175 response->postReply(replyID);
1176 break;
1177 }
1178
1179 status_t err = onReleaseOutputBuffer(msg);
1180
1181 sp<AMessage> response = new AMessage;
1182 response->setInt32("err", err);
1183 response->postReply(replyID);
1184 break;
1185 }
1186
Andy McFaddenf779bb52013-02-19 07:28:30 -08001187 case kWhatSignalEndOfInputStream:
1188 {
1189 uint32_t replyID;
1190 CHECK(msg->senderAwaitsResponse(&replyID));
1191
1192 if (mState != STARTED || (mFlags & kFlagStickyError)) {
1193 sp<AMessage> response = new AMessage;
1194 response->setInt32("err", INVALID_OPERATION);
1195
1196 response->postReply(replyID);
1197 break;
1198 }
1199
1200 mReplyID = replyID;
1201 mCodec->signalEndOfInputStream();
1202 break;
1203 }
1204
Andreas Huber57788222012-02-21 11:47:18 -08001205 case kWhatGetBuffers:
1206 {
1207 uint32_t replyID;
1208 CHECK(msg->senderAwaitsResponse(&replyID));
1209
1210 if (mState != STARTED || (mFlags & kFlagStickyError)) {
1211 sp<AMessage> response = new AMessage;
1212 response->setInt32("err", INVALID_OPERATION);
1213
1214 response->postReply(replyID);
1215 break;
1216 }
1217
1218 int32_t portIndex;
1219 CHECK(msg->findInt32("portIndex", &portIndex));
1220
1221 Vector<sp<ABuffer> > *dstBuffers;
1222 CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
1223
1224 dstBuffers->clear();
1225 const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
1226
1227 for (size_t i = 0; i < srcBuffers.size(); ++i) {
1228 const BufferInfo &info = srcBuffers.itemAt(i);
1229
Andreas Hubered3e3e02012-03-26 11:13:27 -07001230 dstBuffers->push_back(
Andreas Huber1bd139a2012-04-03 14:19:20 -07001231 (portIndex == kPortIndexInput && mCrypto != NULL)
Andreas Hubered3e3e02012-03-26 11:13:27 -07001232 ? info.mEncryptedData : info.mData);
Andreas Huber57788222012-02-21 11:47:18 -08001233 }
1234
1235 (new AMessage)->postReply(replyID);
1236 break;
1237 }
1238
1239 case kWhatFlush:
1240 {
1241 uint32_t replyID;
1242 CHECK(msg->senderAwaitsResponse(&replyID));
1243
1244 if (mState != STARTED || (mFlags & kFlagStickyError)) {
1245 sp<AMessage> response = new AMessage;
1246 response->setInt32("err", INVALID_OPERATION);
1247
1248 response->postReply(replyID);
1249 break;
1250 }
1251
1252 mReplyID = replyID;
1253 setState(FLUSHING);
1254
1255 mCodec->signalFlush();
1256 returnBuffersToCodec();
1257 break;
1258 }
1259
1260 case kWhatGetOutputFormat:
1261 {
1262 uint32_t replyID;
1263 CHECK(msg->senderAwaitsResponse(&replyID));
1264
1265 if ((mState != STARTED && mState != FLUSHING)
Martin Storsjo972f2322012-07-13 12:48:19 +03001266 || (mFlags & kFlagStickyError)
1267 || mOutputFormat == NULL) {
Andreas Huber57788222012-02-21 11:47:18 -08001268 sp<AMessage> response = new AMessage;
1269 response->setInt32("err", INVALID_OPERATION);
1270
1271 response->postReply(replyID);
1272 break;
1273 }
1274
1275 sp<AMessage> response = new AMessage;
1276 response->setMessage("format", mOutputFormat);
1277 response->postReply(replyID);
1278 break;
1279 }
1280
Andreas Huber03e2ffa2012-09-13 16:43:51 -07001281 case kWhatRequestIDRFrame:
1282 {
1283 mCodec->signalRequestIDRFrame();
1284 break;
1285 }
1286
Andreas Huber72c66862012-10-03 10:16:58 -07001287 case kWhatRequestActivityNotification:
1288 {
1289 CHECK(mActivityNotify == NULL);
1290 CHECK(msg->findMessage("notify", &mActivityNotify));
1291
1292 postActivityNotificationIfPossible();
1293 break;
1294 }
1295
Martin Storsjo8601efe2012-09-25 11:43:02 +03001296 case kWhatGetName:
1297 {
1298 uint32_t replyID;
1299 CHECK(msg->senderAwaitsResponse(&replyID));
1300
1301 if (mComponentName.empty()) {
1302 sp<AMessage> response = new AMessage;
1303 response->setInt32("err", INVALID_OPERATION);
1304
1305 response->postReply(replyID);
1306 break;
1307 }
1308
1309 sp<AMessage> response = new AMessage;
1310 response->setString("name", mComponentName.c_str());
1311 response->postReply(replyID);
1312 break;
1313 }
1314
Andreas Huberc71601c2013-02-07 10:56:14 -08001315 case kWhatSetParameters:
1316 {
1317 uint32_t replyID;
1318 CHECK(msg->senderAwaitsResponse(&replyID));
1319
1320 sp<AMessage> params;
1321 CHECK(msg->findMessage("params", &params));
1322
1323 status_t err = onSetParameters(params);
1324
1325 sp<AMessage> response = new AMessage;
1326 response->setInt32("err", err);
1327
1328 response->postReply(replyID);
1329 break;
1330 }
1331
Andreas Huber57788222012-02-21 11:47:18 -08001332 default:
1333 TRESPASS();
1334 }
1335}
1336
Andreas Huber8ee516a2012-05-08 11:21:26 -07001337void MediaCodec::extractCSD(const sp<AMessage> &format) {
1338 mCSD.clear();
1339
1340 size_t i = 0;
1341 for (;;) {
1342 sp<ABuffer> csd;
1343 if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) {
1344 break;
1345 }
1346
1347 mCSD.push_back(csd);
1348 ++i;
1349 }
1350
1351 ALOGV("Found %u pieces of codec specific data.", mCSD.size());
1352}
1353
1354status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
1355 CHECK(!mCSD.empty());
1356
1357 BufferInfo *info =
1358 &mPortBuffers[kPortIndexInput].editItemAt(bufferIndex);
1359
1360 sp<ABuffer> csd = *mCSD.begin();
1361 mCSD.erase(mCSD.begin());
1362
1363 const sp<ABuffer> &codecInputData =
1364 (mCrypto != NULL) ? info->mEncryptedData : info->mData;
1365
1366 if (csd->size() > codecInputData->capacity()) {
1367 return -EINVAL;
1368 }
1369
1370 memcpy(codecInputData->data(), csd->data(), csd->size());
1371
1372 AString errorDetailMsg;
1373
1374 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
1375 msg->setSize("index", bufferIndex);
1376 msg->setSize("offset", 0);
1377 msg->setSize("size", csd->size());
1378 msg->setInt64("timeUs", 0ll);
1379 msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
1380 msg->setPointer("errorDetailMsg", &errorDetailMsg);
1381
1382 return onQueueInputBuffer(msg);
1383}
1384
Andreas Huber57788222012-02-21 11:47:18 -08001385void MediaCodec::setState(State newState) {
Andreas Huber7541ff52012-05-10 10:54:15 -07001386 if (newState == INITIALIZED || newState == UNINITIALIZED) {
Andreas Huber57788222012-02-21 11:47:18 -08001387 delete mSoftRenderer;
1388 mSoftRenderer = NULL;
1389
Andreas Huber1bd139a2012-04-03 14:19:20 -07001390 mCrypto.clear();
Andreas Huber7541ff52012-05-10 10:54:15 -07001391 setNativeWindow(NULL);
Andreas Huber57788222012-02-21 11:47:18 -08001392
1393 mOutputFormat.clear();
1394 mFlags &= ~kFlagOutputFormatChanged;
1395 mFlags &= ~kFlagOutputBuffersChanged;
1396 mFlags &= ~kFlagStickyError;
Andreas Huber72c66862012-10-03 10:16:58 -07001397
1398 mActivityNotify.clear();
Andreas Huber57788222012-02-21 11:47:18 -08001399 }
1400
Martin Storsjo8601efe2012-09-25 11:43:02 +03001401 if (newState == UNINITIALIZED) {
1402 mComponentName.clear();
1403 }
1404
Andreas Huber57788222012-02-21 11:47:18 -08001405 mState = newState;
1406
1407 cancelPendingDequeueOperations();
1408}
1409
1410void MediaCodec::returnBuffersToCodec() {
1411 returnBuffersToCodecOnPort(kPortIndexInput);
1412 returnBuffersToCodecOnPort(kPortIndexOutput);
1413}
1414
1415void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
1416 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1417
1418 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1419
1420 for (size_t i = 0; i < buffers->size(); ++i) {
1421 BufferInfo *info = &buffers->editItemAt(i);
1422
1423 if (info->mNotify != NULL) {
1424 sp<AMessage> msg = info->mNotify;
1425 info->mNotify = NULL;
1426 info->mOwnedByClient = false;
1427
1428 if (portIndex == kPortIndexInput) {
1429 msg->setInt32("err", ERROR_END_OF_STREAM);
1430 }
1431 msg->post();
1432 }
1433 }
1434
1435 mAvailPortBuffers[portIndex].clear();
1436}
1437
1438size_t MediaCodec::updateBuffers(
1439 int32_t portIndex, const sp<AMessage> &msg) {
1440 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1441
1442 void *bufferID;
1443 CHECK(msg->findPointer("buffer-id", &bufferID));
1444
1445 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1446
1447 for (size_t i = 0; i < buffers->size(); ++i) {
1448 BufferInfo *info = &buffers->editItemAt(i);
1449
1450 if (info->mBufferID == bufferID) {
1451 CHECK(info->mNotify == NULL);
1452 CHECK(msg->findMessage("reply", &info->mNotify));
1453
1454 mAvailPortBuffers[portIndex].push_back(i);
1455
1456 return i;
1457 }
1458 }
1459
1460 TRESPASS();
1461
1462 return 0;
1463}
1464
1465status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
1466 size_t index;
1467 size_t offset;
1468 size_t size;
1469 int64_t timeUs;
1470 uint32_t flags;
1471 CHECK(msg->findSize("index", &index));
1472 CHECK(msg->findSize("offset", &offset));
Andreas Huber57788222012-02-21 11:47:18 -08001473 CHECK(msg->findInt64("timeUs", &timeUs));
1474 CHECK(msg->findInt32("flags", (int32_t *)&flags));
1475
Andreas Huber4b75a9c2012-04-06 11:06:28 -07001476 const CryptoPlugin::SubSample *subSamples;
1477 size_t numSubSamples;
1478 const uint8_t *key;
1479 const uint8_t *iv;
1480 CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
1481
1482 // We allow the simpler queueInputBuffer API to be used even in
1483 // secure mode, by fabricating a single unencrypted subSample.
1484 CryptoPlugin::SubSample ss;
1485
1486 if (msg->findSize("size", &size)) {
1487 if (mCrypto != NULL) {
1488 ss.mNumBytesOfClearData = size;
1489 ss.mNumBytesOfEncryptedData = 0;
1490
1491 subSamples = &ss;
1492 numSubSamples = 1;
1493 key = NULL;
1494 iv = NULL;
1495 }
1496 } else {
1497 if (mCrypto == NULL) {
1498 return -EINVAL;
1499 }
1500
1501 CHECK(msg->findPointer("subSamples", (void **)&subSamples));
1502 CHECK(msg->findSize("numSubSamples", &numSubSamples));
1503 CHECK(msg->findPointer("key", (void **)&key));
1504 CHECK(msg->findPointer("iv", (void **)&iv));
1505
1506 int32_t tmp;
1507 CHECK(msg->findInt32("mode", &tmp));
1508
1509 mode = (CryptoPlugin::Mode)tmp;
1510
1511 size = 0;
1512 for (size_t i = 0; i < numSubSamples; ++i) {
1513 size += subSamples[i].mNumBytesOfClearData;
1514 size += subSamples[i].mNumBytesOfEncryptedData;
1515 }
1516 }
1517
Andreas Huber57788222012-02-21 11:47:18 -08001518 if (index >= mPortBuffers[kPortIndexInput].size()) {
1519 return -ERANGE;
1520 }
1521
1522 BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
1523
1524 if (info->mNotify == NULL || !info->mOwnedByClient) {
1525 return -EACCES;
1526 }
1527
1528 if (offset + size > info->mData->capacity()) {
1529 return -EINVAL;
1530 }
1531
1532 sp<AMessage> reply = info->mNotify;
Andreas Huber57788222012-02-21 11:47:18 -08001533 info->mData->setRange(offset, size);
1534 info->mData->meta()->setInt64("timeUs", timeUs);
1535
1536 if (flags & BUFFER_FLAG_EOS) {
1537 info->mData->meta()->setInt32("eos", true);
1538 }
1539
1540 if (flags & BUFFER_FLAG_CODECCONFIG) {
1541 info->mData->meta()->setInt32("csd", true);
1542 }
1543
Andreas Huber1bd139a2012-04-03 14:19:20 -07001544 if (mCrypto != NULL) {
1545 if (size > info->mEncryptedData->capacity()) {
Andreas Hubered3e3e02012-03-26 11:13:27 -07001546 return -ERANGE;
1547 }
1548
Andreas Huber5b8987e2012-04-19 12:52:20 -07001549 AString *errorDetailMsg;
1550 CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
1551
Edwin Wongfa2b8f22012-07-10 20:01:13 -07001552 ssize_t result = mCrypto->decrypt(
Andreas Huber1bd139a2012-04-03 14:19:20 -07001553 (mFlags & kFlagIsSecure) != 0,
1554 key,
1555 iv,
1556 mode,
1557 info->mEncryptedData->base() + offset,
Andreas Huber4b75a9c2012-04-06 11:06:28 -07001558 subSamples,
1559 numSubSamples,
Andreas Huber5b8987e2012-04-19 12:52:20 -07001560 info->mData->base(),
1561 errorDetailMsg);
Andreas Huber1bd139a2012-04-03 14:19:20 -07001562
Edwin Wongfa2b8f22012-07-10 20:01:13 -07001563 if (result < 0) {
1564 return result;
Andreas Huber1bd139a2012-04-03 14:19:20 -07001565 }
1566
Edwin Wongfa2b8f22012-07-10 20:01:13 -07001567 info->mData->setRange(0, result);
Andreas Hubered3e3e02012-03-26 11:13:27 -07001568 }
1569
Andreas Huber2d8bedd2012-02-21 14:38:23 -08001570 reply->setBuffer("buffer", info->mData);
Andreas Huber57788222012-02-21 11:47:18 -08001571 reply->post();
1572
Andreas Huber5b8987e2012-04-19 12:52:20 -07001573 info->mNotify = NULL;
1574 info->mOwnedByClient = false;
1575
Andreas Huber57788222012-02-21 11:47:18 -08001576 return OK;
1577}
1578
1579status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
1580 size_t index;
1581 CHECK(msg->findSize("index", &index));
1582
1583 int32_t render;
1584 if (!msg->findInt32("render", &render)) {
1585 render = 0;
1586 }
1587
1588 if (mState != STARTED) {
1589 return -EINVAL;
1590 }
1591
1592 if (index >= mPortBuffers[kPortIndexOutput].size()) {
1593 return -ERANGE;
1594 }
1595
1596 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1597
1598 if (info->mNotify == NULL || !info->mOwnedByClient) {
1599 return -EACCES;
1600 }
1601
1602 if (render) {
1603 info->mNotify->setInt32("render", true);
1604
1605 if (mSoftRenderer != NULL) {
1606 mSoftRenderer->render(
1607 info->mData->data(), info->mData->size(), NULL);
1608 }
1609 }
1610
1611 info->mNotify->post();
1612 info->mNotify = NULL;
1613 info->mOwnedByClient = false;
1614
1615 return OK;
1616}
1617
1618ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
1619 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1620
1621 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
1622
1623 if (availBuffers->empty()) {
1624 return -EAGAIN;
1625 }
1626
1627 size_t index = *availBuffers->begin();
1628 availBuffers->erase(availBuffers->begin());
1629
1630 BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
1631 CHECK(!info->mOwnedByClient);
1632 info->mOwnedByClient = true;
1633
1634 return index;
1635}
1636
Andreas Huber7541ff52012-05-10 10:54:15 -07001637status_t MediaCodec::setNativeWindow(
Mathias Agopianb1e7cd12013-02-14 17:11:27 -08001638 const sp<Surface> &surfaceTextureClient) {
Andreas Huber7541ff52012-05-10 10:54:15 -07001639 status_t err;
1640
1641 if (mNativeWindow != NULL) {
1642 err = native_window_api_disconnect(
1643 mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
1644
1645 if (err != OK) {
1646 ALOGW("native_window_api_disconnect returned an error: %s (%d)",
1647 strerror(-err), err);
1648 }
1649
1650 mNativeWindow.clear();
1651 }
1652
1653 if (surfaceTextureClient != NULL) {
1654 err = native_window_api_connect(
1655 surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA);
1656
1657 if (err != OK) {
1658 ALOGE("native_window_api_connect returned an error: %s (%d)",
1659 strerror(-err), err);
1660
1661 return err;
1662 }
1663
1664 mNativeWindow = surfaceTextureClient;
1665 }
1666
1667 return OK;
1668}
1669
Andreas Huber72c66862012-10-03 10:16:58 -07001670void MediaCodec::postActivityNotificationIfPossible() {
1671 if (mActivityNotify == NULL) {
1672 return;
1673 }
1674
1675 if ((mFlags & (kFlagStickyError
1676 | kFlagOutputBuffersChanged
1677 | kFlagOutputFormatChanged))
1678 || !mAvailPortBuffers[kPortIndexInput].empty()
1679 || !mAvailPortBuffers[kPortIndexOutput].empty()) {
1680 mActivityNotify->post();
1681 mActivityNotify.clear();
1682 }
1683}
1684
Andreas Huberc71601c2013-02-07 10:56:14 -08001685status_t MediaCodec::setParameters(const sp<AMessage> &params) {
1686 sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
1687 msg->setMessage("params", params);
1688
1689 sp<AMessage> response;
1690 return PostAndAwaitResponse(msg, &response);
1691}
1692
1693status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
1694 mCodec->signalSetParameters(params);
1695
1696 return OK;
1697}
1698
Andreas Huber57788222012-02-21 11:47:18 -08001699} // namespace android