1 /*
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 <inttypes.h>
20
21 #include "include/avc_utils.h"
22 #include "include/SoftwareRenderer.h"
23
24 #include <binder/IBatteryStats.h>
25 #include <binder/IServiceManager.h>
26 #include <gui/Surface.h>
27 #include <media/ICrypto.h>
28 #include <media/stagefright/foundation/ABuffer.h>
29 #include <media/stagefright/foundation/ADebug.h>
30 #include <media/stagefright/foundation/AMessage.h>
31 #include <media/stagefright/foundation/AString.h>
32 #include <media/stagefright/foundation/hexdump.h>
33 #include <media/stagefright/ACodec.h>
34 #include <media/stagefright/BufferProducerWrapper.h>
35 #include <media/stagefright/MediaCodec.h>
36 #include <media/stagefright/MediaCodecList.h>
37 #include <media/stagefright/MediaDefs.h>
38 #include <media/stagefright/MediaErrors.h>
39 #include <media/stagefright/MetaData.h>
40 #include <media/stagefright/NativeWindowWrapper.h>
41 #include <private/android_filesystem_config.h>
42 #include <utils/Log.h>
43 #include <utils/Singleton.h>
44
45 namespace android {
46
47 struct MediaCodec::BatteryNotifier : public Singleton<BatteryNotifier> {
48 BatteryNotifier();
49
50 void noteStartVideo();
51 void noteStopVideo();
52 void noteStartAudio();
53 void noteStopAudio();
54
55 private:
56 int32_t mVideoRefCount;
57 int32_t mAudioRefCount;
58 sp<IBatteryStats> mBatteryStatService;
59 };
60
ANDROID_SINGLETON_STATIC_INSTANCE(MediaCodec::BatteryNotifier)61 ANDROID_SINGLETON_STATIC_INSTANCE(MediaCodec::BatteryNotifier)
62
63 MediaCodec::BatteryNotifier::BatteryNotifier() :
64 mVideoRefCount(0),
65 mAudioRefCount(0) {
66 // get battery service
67 const sp<IServiceManager> sm(defaultServiceManager());
68 if (sm != NULL) {
69 const String16 name("batterystats");
70 mBatteryStatService = interface_cast<IBatteryStats>(sm->getService(name));
71 if (mBatteryStatService == NULL) {
72 ALOGE("batterystats service unavailable!");
73 }
74 }
75 }
76
noteStartVideo()77 void MediaCodec::BatteryNotifier::noteStartVideo() {
78 if (mVideoRefCount == 0 && mBatteryStatService != NULL) {
79 mBatteryStatService->noteStartVideo(AID_MEDIA);
80 }
81 mVideoRefCount++;
82 }
83
noteStopVideo()84 void MediaCodec::BatteryNotifier::noteStopVideo() {
85 if (mVideoRefCount == 0) {
86 ALOGW("BatteryNotifier::noteStop(): video refcount is broken!");
87 return;
88 }
89
90 mVideoRefCount--;
91 if (mVideoRefCount == 0 && mBatteryStatService != NULL) {
92 mBatteryStatService->noteStopVideo(AID_MEDIA);
93 }
94 }
95
noteStartAudio()96 void MediaCodec::BatteryNotifier::noteStartAudio() {
97 if (mAudioRefCount == 0 && mBatteryStatService != NULL) {
98 mBatteryStatService->noteStartAudio(AID_MEDIA);
99 }
100 mAudioRefCount++;
101 }
102
noteStopAudio()103 void MediaCodec::BatteryNotifier::noteStopAudio() {
104 if (mAudioRefCount == 0) {
105 ALOGW("BatteryNotifier::noteStop(): audio refcount is broken!");
106 return;
107 }
108
109 mAudioRefCount--;
110 if (mAudioRefCount == 0 && mBatteryStatService != NULL) {
111 mBatteryStatService->noteStopAudio(AID_MEDIA);
112 }
113 }
114 // static
CreateByType(const sp<ALooper> & looper,const char * mime,bool encoder,status_t * err)115 sp<MediaCodec> MediaCodec::CreateByType(
116 const sp<ALooper> &looper, const char *mime, bool encoder, status_t *err) {
117 sp<MediaCodec> codec = new MediaCodec(looper);
118
119 const status_t ret = codec->init(mime, true /* nameIsType */, encoder);
120 if (err != NULL) {
121 *err = ret;
122 }
123 return ret == OK ? codec : NULL; // NULL deallocates codec.
124 }
125
126 // static
CreateByComponentName(const sp<ALooper> & looper,const char * name,status_t * err)127 sp<MediaCodec> MediaCodec::CreateByComponentName(
128 const sp<ALooper> &looper, const char *name, status_t *err) {
129 sp<MediaCodec> codec = new MediaCodec(looper);
130
131 const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */);
132 if (err != NULL) {
133 *err = ret;
134 }
135 return ret == OK ? codec : NULL; // NULL deallocates codec.
136 }
137
MediaCodec(const sp<ALooper> & looper)138 MediaCodec::MediaCodec(const sp<ALooper> &looper)
139 : mState(UNINITIALIZED),
140 mLooper(looper),
141 mCodec(NULL),
142 mReplyID(0),
143 mFlags(0),
144 mStickyError(OK),
145 mSoftRenderer(NULL),
146 mBatteryStatNotified(false),
147 mIsVideo(false),
148 mDequeueInputTimeoutGeneration(0),
149 mDequeueInputReplyID(0),
150 mDequeueOutputTimeoutGeneration(0),
151 mDequeueOutputReplyID(0),
152 mHaveInputSurface(false) {
153 }
154
~MediaCodec()155 MediaCodec::~MediaCodec() {
156 CHECK_EQ(mState, UNINITIALIZED);
157 }
158
159 // static
PostAndAwaitResponse(const sp<AMessage> & msg,sp<AMessage> * response)160 status_t MediaCodec::PostAndAwaitResponse(
161 const sp<AMessage> &msg, sp<AMessage> *response) {
162 status_t err = msg->postAndAwaitResponse(response);
163
164 if (err != OK) {
165 return err;
166 }
167
168 if (!(*response)->findInt32("err", &err)) {
169 err = OK;
170 }
171
172 return err;
173 }
174
175 // static
PostReplyWithError(int32_t replyID,int32_t err)176 void MediaCodec::PostReplyWithError(int32_t replyID, int32_t err) {
177 sp<AMessage> response = new AMessage;
178 response->setInt32("err", err);
179 response->postReply(replyID);
180 }
181
init(const AString & name,bool nameIsType,bool encoder)182 status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) {
183 // save init parameters for reset
184 mInitName = name;
185 mInitNameIsType = nameIsType;
186 mInitIsEncoder = encoder;
187
188 // Current video decoders do not return from OMX_FillThisBuffer
189 // quickly, violating the OpenMAX specs, until that is remedied
190 // we need to invest in an extra looper to free the main event
191 // queue.
192 mCodec = new ACodec;
193 bool needDedicatedLooper = false;
194 if (nameIsType && !strncasecmp(name.c_str(), "video/", 6)) {
195 needDedicatedLooper = true;
196 } else {
197 AString tmp = name;
198 if (tmp.endsWith(".secure")) {
199 tmp.erase(tmp.size() - 7, 7);
200 }
201 const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
202 ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
203 if (codecIdx >= 0) {
204 const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
205 Vector<AString> mimes;
206 info->getSupportedMimes(&mimes);
207 for (size_t i = 0; i < mimes.size(); i++) {
208 if (mimes[i].startsWith("video/")) {
209 needDedicatedLooper = true;
210 break;
211 }
212 }
213 }
214 }
215
216 if (needDedicatedLooper) {
217 if (mCodecLooper == NULL) {
218 mCodecLooper = new ALooper;
219 mCodecLooper->setName("CodecLooper");
220 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
221 }
222
223 mCodecLooper->registerHandler(mCodec);
224 } else {
225 mLooper->registerHandler(mCodec);
226 }
227
228 mLooper->registerHandler(this);
229
230 mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id()));
231
232 sp<AMessage> msg = new AMessage(kWhatInit, id());
233 msg->setString("name", name);
234 msg->setInt32("nameIsType", nameIsType);
235
236 if (nameIsType) {
237 msg->setInt32("encoder", encoder);
238 }
239
240 sp<AMessage> response;
241 return PostAndAwaitResponse(msg, &response);
242 }
243
setCallback(const sp<AMessage> & callback)244 status_t MediaCodec::setCallback(const sp<AMessage> &callback) {
245 sp<AMessage> msg = new AMessage(kWhatSetCallback, id());
246 msg->setMessage("callback", callback);
247
248 sp<AMessage> response;
249 return PostAndAwaitResponse(msg, &response);
250 }
251
configure(const sp<AMessage> & format,const sp<Surface> & nativeWindow,const sp<ICrypto> & crypto,uint32_t flags)252 status_t MediaCodec::configure(
253 const sp<AMessage> &format,
254 const sp<Surface> &nativeWindow,
255 const sp<ICrypto> &crypto,
256 uint32_t flags) {
257 sp<AMessage> msg = new AMessage(kWhatConfigure, id());
258
259 msg->setMessage("format", format);
260 msg->setInt32("flags", flags);
261
262 if (nativeWindow != NULL) {
263 msg->setObject(
264 "native-window",
265 new NativeWindowWrapper(nativeWindow));
266 }
267
268 if (crypto != NULL) {
269 msg->setPointer("crypto", crypto.get());
270 }
271
272 sp<AMessage> response;
273 status_t err = PostAndAwaitResponse(msg, &response);
274
275 if (err != OK && err != INVALID_OPERATION) {
276 // MediaCodec now set state to UNINITIALIZED upon any fatal error.
277 // To maintain backward-compatibility, do a reset() to put codec
278 // back into INITIALIZED state.
279 // But don't reset if the err is INVALID_OPERATION, which means
280 // the configure failure is due to wrong state.
281
282 ALOGE("configure failed with err 0x%08x, resetting...", err);
283 reset();
284 }
285
286 return err;
287 }
288
createInputSurface(sp<IGraphicBufferProducer> * bufferProducer)289 status_t MediaCodec::createInputSurface(
290 sp<IGraphicBufferProducer>* bufferProducer) {
291 sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, id());
292
293 sp<AMessage> response;
294 status_t err = PostAndAwaitResponse(msg, &response);
295 if (err == NO_ERROR) {
296 // unwrap the sp<IGraphicBufferProducer>
297 sp<RefBase> obj;
298 bool found = response->findObject("input-surface", &obj);
299 CHECK(found);
300 sp<BufferProducerWrapper> wrapper(
301 static_cast<BufferProducerWrapper*>(obj.get()));
302 *bufferProducer = wrapper->getBufferProducer();
303 } else {
304 ALOGW("createInputSurface failed, err=%d", err);
305 }
306 return err;
307 }
308
start()309 status_t MediaCodec::start() {
310 sp<AMessage> msg = new AMessage(kWhatStart, id());
311
312 sp<AMessage> response;
313 return PostAndAwaitResponse(msg, &response);
314 }
315
stop()316 status_t MediaCodec::stop() {
317 sp<AMessage> msg = new AMessage(kWhatStop, id());
318
319 sp<AMessage> response;
320 return PostAndAwaitResponse(msg, &response);
321 }
322
release()323 status_t MediaCodec::release() {
324 sp<AMessage> msg = new AMessage(kWhatRelease, id());
325
326 sp<AMessage> response;
327 return PostAndAwaitResponse(msg, &response);
328 }
329
reset()330 status_t MediaCodec::reset() {
331 /* When external-facing MediaCodec object is created,
332 it is already initialized. Thus, reset is essentially
333 release() followed by init(), plus clearing the state */
334
335 status_t err = release();
336
337 // unregister handlers
338 if (mCodec != NULL) {
339 if (mCodecLooper != NULL) {
340 mCodecLooper->unregisterHandler(mCodec->id());
341 } else {
342 mLooper->unregisterHandler(mCodec->id());
343 }
344 mCodec = NULL;
345 }
346 mLooper->unregisterHandler(id());
347
348 mFlags = 0; // clear all flags
349 mStickyError = OK;
350
351 // reset state not reset by setState(UNINITIALIZED)
352 mReplyID = 0;
353 mDequeueInputReplyID = 0;
354 mDequeueOutputReplyID = 0;
355 mDequeueInputTimeoutGeneration = 0;
356 mDequeueOutputTimeoutGeneration = 0;
357 mHaveInputSurface = false;
358
359 if (err == OK) {
360 err = init(mInitName, mInitNameIsType, mInitIsEncoder);
361 }
362 return err;
363 }
364
queueInputBuffer(size_t index,size_t offset,size_t size,int64_t presentationTimeUs,uint32_t flags,AString * errorDetailMsg)365 status_t MediaCodec::queueInputBuffer(
366 size_t index,
367 size_t offset,
368 size_t size,
369 int64_t presentationTimeUs,
370 uint32_t flags,
371 AString *errorDetailMsg) {
372 if (errorDetailMsg != NULL) {
373 errorDetailMsg->clear();
374 }
375
376 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
377 msg->setSize("index", index);
378 msg->setSize("offset", offset);
379 msg->setSize("size", size);
380 msg->setInt64("timeUs", presentationTimeUs);
381 msg->setInt32("flags", flags);
382 msg->setPointer("errorDetailMsg", errorDetailMsg);
383
384 sp<AMessage> response;
385 return PostAndAwaitResponse(msg, &response);
386 }
387
queueSecureInputBuffer(size_t index,size_t offset,const CryptoPlugin::SubSample * subSamples,size_t numSubSamples,const uint8_t key[16],const uint8_t iv[16],CryptoPlugin::Mode mode,int64_t presentationTimeUs,uint32_t flags,AString * errorDetailMsg)388 status_t MediaCodec::queueSecureInputBuffer(
389 size_t index,
390 size_t offset,
391 const CryptoPlugin::SubSample *subSamples,
392 size_t numSubSamples,
393 const uint8_t key[16],
394 const uint8_t iv[16],
395 CryptoPlugin::Mode mode,
396 int64_t presentationTimeUs,
397 uint32_t flags,
398 AString *errorDetailMsg) {
399 if (errorDetailMsg != NULL) {
400 errorDetailMsg->clear();
401 }
402
403 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
404 msg->setSize("index", index);
405 msg->setSize("offset", offset);
406 msg->setPointer("subSamples", (void *)subSamples);
407 msg->setSize("numSubSamples", numSubSamples);
408 msg->setPointer("key", (void *)key);
409 msg->setPointer("iv", (void *)iv);
410 msg->setInt32("mode", mode);
411 msg->setInt64("timeUs", presentationTimeUs);
412 msg->setInt32("flags", flags);
413 msg->setPointer("errorDetailMsg", errorDetailMsg);
414
415 sp<AMessage> response;
416 status_t err = PostAndAwaitResponse(msg, &response);
417
418 return err;
419 }
420
dequeueInputBuffer(size_t * index,int64_t timeoutUs)421 status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
422 sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id());
423 msg->setInt64("timeoutUs", timeoutUs);
424
425 sp<AMessage> response;
426 status_t err;
427 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
428 return err;
429 }
430
431 CHECK(response->findSize("index", index));
432
433 return OK;
434 }
435
dequeueOutputBuffer(size_t * index,size_t * offset,size_t * size,int64_t * presentationTimeUs,uint32_t * flags,int64_t timeoutUs)436 status_t MediaCodec::dequeueOutputBuffer(
437 size_t *index,
438 size_t *offset,
439 size_t *size,
440 int64_t *presentationTimeUs,
441 uint32_t *flags,
442 int64_t timeoutUs) {
443 sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id());
444 msg->setInt64("timeoutUs", timeoutUs);
445
446 sp<AMessage> response;
447 status_t err;
448 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
449 return err;
450 }
451
452 CHECK(response->findSize("index", index));
453 CHECK(response->findSize("offset", offset));
454 CHECK(response->findSize("size", size));
455 CHECK(response->findInt64("timeUs", presentationTimeUs));
456 CHECK(response->findInt32("flags", (int32_t *)flags));
457
458 return OK;
459 }
460
renderOutputBufferAndRelease(size_t index)461 status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
462 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
463 msg->setSize("index", index);
464 msg->setInt32("render", true);
465
466 sp<AMessage> response;
467 return PostAndAwaitResponse(msg, &response);
468 }
469
renderOutputBufferAndRelease(size_t index,int64_t timestampNs)470 status_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) {
471 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
472 msg->setSize("index", index);
473 msg->setInt32("render", true);
474 msg->setInt64("timestampNs", timestampNs);
475
476 sp<AMessage> response;
477 return PostAndAwaitResponse(msg, &response);
478 }
479
releaseOutputBuffer(size_t index)480 status_t MediaCodec::releaseOutputBuffer(size_t index) {
481 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
482 msg->setSize("index", index);
483
484 sp<AMessage> response;
485 return PostAndAwaitResponse(msg, &response);
486 }
487
signalEndOfInputStream()488 status_t MediaCodec::signalEndOfInputStream() {
489 sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, id());
490
491 sp<AMessage> response;
492 return PostAndAwaitResponse(msg, &response);
493 }
494
getOutputFormat(sp<AMessage> * format) const495 status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
496 sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id());
497
498 sp<AMessage> response;
499 status_t err;
500 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
501 return err;
502 }
503
504 CHECK(response->findMessage("format", format));
505
506 return OK;
507 }
508
getInputFormat(sp<AMessage> * format) const509 status_t MediaCodec::getInputFormat(sp<AMessage> *format) const {
510 sp<AMessage> msg = new AMessage(kWhatGetInputFormat, id());
511
512 sp<AMessage> response;
513 status_t err;
514 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
515 return err;
516 }
517
518 CHECK(response->findMessage("format", format));
519
520 return OK;
521 }
522
getName(AString * name) const523 status_t MediaCodec::getName(AString *name) const {
524 sp<AMessage> msg = new AMessage(kWhatGetName, id());
525
526 sp<AMessage> response;
527 status_t err;
528 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
529 return err;
530 }
531
532 CHECK(response->findString("name", name));
533
534 return OK;
535 }
536
getInputBuffers(Vector<sp<ABuffer>> * buffers) const537 status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
538 sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
539 msg->setInt32("portIndex", kPortIndexInput);
540 msg->setPointer("buffers", buffers);
541
542 sp<AMessage> response;
543 return PostAndAwaitResponse(msg, &response);
544 }
545
getOutputBuffers(Vector<sp<ABuffer>> * buffers) const546 status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
547 sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
548 msg->setInt32("portIndex", kPortIndexOutput);
549 msg->setPointer("buffers", buffers);
550
551 sp<AMessage> response;
552 return PostAndAwaitResponse(msg, &response);
553 }
554
getOutputBuffer(size_t index,sp<ABuffer> * buffer)555 status_t MediaCodec::getOutputBuffer(size_t index, sp<ABuffer> *buffer) {
556 sp<AMessage> format;
557 return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
558 }
559
getOutputFormat(size_t index,sp<AMessage> * format)560 status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
561 sp<ABuffer> buffer;
562 return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
563 }
564
getInputBuffer(size_t index,sp<ABuffer> * buffer)565 status_t MediaCodec::getInputBuffer(size_t index, sp<ABuffer> *buffer) {
566 sp<AMessage> format;
567 return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
568 }
569
isExecuting() const570 bool MediaCodec::isExecuting() const {
571 return mState == STARTED || mState == FLUSHED;
572 }
573
getBufferAndFormat(size_t portIndex,size_t index,sp<ABuffer> * buffer,sp<AMessage> * format)574 status_t MediaCodec::getBufferAndFormat(
575 size_t portIndex, size_t index,
576 sp<ABuffer> *buffer, sp<AMessage> *format) {
577 // use mutex instead of a context switch
578
579 buffer->clear();
580 format->clear();
581 if (!isExecuting()) {
582 return INVALID_OPERATION;
583 }
584
585 // we do not want mPortBuffers to change during this section
586 // we also don't want mOwnedByClient to change during this
587 Mutex::Autolock al(mBufferLock);
588 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
589 if (index < buffers->size()) {
590 const BufferInfo &info = buffers->itemAt(index);
591 if (info.mOwnedByClient) {
592 // by the time buffers array is initialized, crypto is set
593 if (portIndex == kPortIndexInput && mCrypto != NULL) {
594 *buffer = info.mEncryptedData;
595 } else {
596 *buffer = info.mData;
597 }
598 *format = info.mFormat;
599 }
600 }
601 return OK;
602 }
603
flush()604 status_t MediaCodec::flush() {
605 sp<AMessage> msg = new AMessage(kWhatFlush, id());
606
607 sp<AMessage> response;
608 return PostAndAwaitResponse(msg, &response);
609 }
610
requestIDRFrame()611 status_t MediaCodec::requestIDRFrame() {
612 (new AMessage(kWhatRequestIDRFrame, id()))->post();
613
614 return OK;
615 }
616
requestActivityNotification(const sp<AMessage> & notify)617 void MediaCodec::requestActivityNotification(const sp<AMessage> ¬ify) {
618 sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, id());
619 msg->setMessage("notify", notify);
620 msg->post();
621 }
622
623 ////////////////////////////////////////////////////////////////////////////////
624
cancelPendingDequeueOperations()625 void MediaCodec::cancelPendingDequeueOperations() {
626 if (mFlags & kFlagDequeueInputPending) {
627 PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
628
629 ++mDequeueInputTimeoutGeneration;
630 mDequeueInputReplyID = 0;
631 mFlags &= ~kFlagDequeueInputPending;
632 }
633
634 if (mFlags & kFlagDequeueOutputPending) {
635 PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
636
637 ++mDequeueOutputTimeoutGeneration;
638 mDequeueOutputReplyID = 0;
639 mFlags &= ~kFlagDequeueOutputPending;
640 }
641 }
642
handleDequeueInputBuffer(uint32_t replyID,bool newRequest)643 bool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) {
644 if (!isExecuting() || (mFlags & kFlagIsAsync)
645 || (newRequest && (mFlags & kFlagDequeueInputPending))) {
646 PostReplyWithError(replyID, INVALID_OPERATION);
647 return true;
648 } else if (mFlags & kFlagStickyError) {
649 PostReplyWithError(replyID, getStickyError());
650 return true;
651 }
652
653 ssize_t index = dequeuePortBuffer(kPortIndexInput);
654
655 if (index < 0) {
656 CHECK_EQ(index, -EAGAIN);
657 return false;
658 }
659
660 sp<AMessage> response = new AMessage;
661 response->setSize("index", index);
662 response->postReply(replyID);
663
664 return true;
665 }
666
handleDequeueOutputBuffer(uint32_t replyID,bool newRequest)667 bool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) {
668 sp<AMessage> response = new AMessage;
669
670 if (!isExecuting() || (mFlags & kFlagIsAsync)
671 || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
672 response->setInt32("err", INVALID_OPERATION);
673 } else if (mFlags & kFlagStickyError) {
674 response->setInt32("err", getStickyError());
675 } else if (mFlags & kFlagOutputBuffersChanged) {
676 response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED);
677 mFlags &= ~kFlagOutputBuffersChanged;
678 } else if (mFlags & kFlagOutputFormatChanged) {
679 response->setInt32("err", INFO_FORMAT_CHANGED);
680 mFlags &= ~kFlagOutputFormatChanged;
681 } else {
682 ssize_t index = dequeuePortBuffer(kPortIndexOutput);
683
684 if (index < 0) {
685 CHECK_EQ(index, -EAGAIN);
686 return false;
687 }
688
689 const sp<ABuffer> &buffer =
690 mPortBuffers[kPortIndexOutput].itemAt(index).mData;
691
692 response->setSize("index", index);
693 response->setSize("offset", buffer->offset());
694 response->setSize("size", buffer->size());
695
696 int64_t timeUs;
697 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
698
699 response->setInt64("timeUs", timeUs);
700
701 int32_t omxFlags;
702 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
703
704 uint32_t flags = 0;
705 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
706 flags |= BUFFER_FLAG_SYNCFRAME;
707 }
708 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
709 flags |= BUFFER_FLAG_CODECCONFIG;
710 }
711 if (omxFlags & OMX_BUFFERFLAG_EOS) {
712 flags |= BUFFER_FLAG_EOS;
713 }
714
715 response->setInt32("flags", flags);
716 }
717
718 response->postReply(replyID);
719
720 return true;
721 }
722
onMessageReceived(const sp<AMessage> & msg)723 void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
724 switch (msg->what()) {
725 case kWhatCodecNotify:
726 {
727 int32_t what;
728 CHECK(msg->findInt32("what", &what));
729
730 switch (what) {
731 case CodecBase::kWhatError:
732 {
733 int32_t err, actionCode;
734 CHECK(msg->findInt32("err", &err));
735 CHECK(msg->findInt32("actionCode", &actionCode));
736
737 ALOGE("Codec reported err %#x, actionCode %d, while in state %d",
738 err, actionCode, mState);
739 if (err == DEAD_OBJECT) {
740 mFlags |= kFlagSawMediaServerDie;
741 mFlags &= ~kFlagIsComponentAllocated;
742 }
743
744 bool sendErrorResponse = true;
745
746 switch (mState) {
747 case INITIALIZING:
748 {
749 setState(UNINITIALIZED);
750 break;
751 }
752
753 case CONFIGURING:
754 {
755 setState(actionCode == ACTION_CODE_FATAL ?
756 UNINITIALIZED : INITIALIZED);
757 break;
758 }
759
760 case STARTING:
761 {
762 setState(actionCode == ACTION_CODE_FATAL ?
763 UNINITIALIZED : CONFIGURED);
764 break;
765 }
766
767 case STOPPING:
768 case RELEASING:
769 {
770 // Ignore the error, assuming we'll still get
771 // the shutdown complete notification.
772
773 sendErrorResponse = false;
774
775 if (mFlags & kFlagSawMediaServerDie) {
776 // MediaServer died, there definitely won't
777 // be a shutdown complete notification after
778 // all.
779
780 // note that we're directly going from
781 // STOPPING->UNINITIALIZED, instead of the
782 // usual STOPPING->INITIALIZED state.
783 setState(UNINITIALIZED);
784 if (mState == RELEASING) {
785 mComponentName.clear();
786 }
787 (new AMessage)->postReply(mReplyID);
788 }
789 break;
790 }
791
792 case FLUSHING:
793 {
794 if (actionCode == ACTION_CODE_FATAL) {
795 setState(UNINITIALIZED);
796 } else {
797 setState(
798 (mFlags & kFlagIsAsync) ? FLUSHED : STARTED);
799 }
800 break;
801 }
802
803 case FLUSHED:
804 case STARTED:
805 {
806 sendErrorResponse = false;
807
808 setStickyError(err);
809 postActivityNotificationIfPossible();
810
811 cancelPendingDequeueOperations();
812
813 if (mFlags & kFlagIsAsync) {
814 onError(err, actionCode);
815 }
816 switch (actionCode) {
817 case ACTION_CODE_TRANSIENT:
818 break;
819 case ACTION_CODE_RECOVERABLE:
820 setState(INITIALIZED);
821 break;
822 default:
823 setState(UNINITIALIZED);
824 break;
825 }
826 break;
827 }
828
829 default:
830 {
831 sendErrorResponse = false;
832
833 setStickyError(err);
834 postActivityNotificationIfPossible();
835
836 // actionCode in an uninitialized state is always fatal.
837 if (mState == UNINITIALIZED) {
838 actionCode = ACTION_CODE_FATAL;
839 }
840 if (mFlags & kFlagIsAsync) {
841 onError(err, actionCode);
842 }
843 switch (actionCode) {
844 case ACTION_CODE_TRANSIENT:
845 break;
846 case ACTION_CODE_RECOVERABLE:
847 setState(INITIALIZED);
848 break;
849 default:
850 setState(UNINITIALIZED);
851 break;
852 }
853 break;
854 }
855 }
856
857 if (sendErrorResponse) {
858 PostReplyWithError(mReplyID, err);
859 }
860 break;
861 }
862
863 case CodecBase::kWhatComponentAllocated:
864 {
865 CHECK_EQ(mState, INITIALIZING);
866 setState(INITIALIZED);
867 mFlags |= kFlagIsComponentAllocated;
868
869 CHECK(msg->findString("componentName", &mComponentName));
870
871 if (mComponentName.startsWith("OMX.google.")) {
872 mFlags |= kFlagUsesSoftwareRenderer;
873 } else {
874 mFlags &= ~kFlagUsesSoftwareRenderer;
875 }
876
877 if (mComponentName.endsWith(".secure")) {
878 mFlags |= kFlagIsSecure;
879 } else {
880 mFlags &= ~kFlagIsSecure;
881 }
882
883 (new AMessage)->postReply(mReplyID);
884 break;
885 }
886
887 case CodecBase::kWhatComponentConfigured:
888 {
889 CHECK_EQ(mState, CONFIGURING);
890
891 // reset input surface flag
892 mHaveInputSurface = false;
893
894 CHECK(msg->findMessage("input-format", &mInputFormat));
895 CHECK(msg->findMessage("output-format", &mOutputFormat));
896
897 int32_t usingSwRenderer;
898 if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer)
899 && usingSwRenderer) {
900 mFlags |= kFlagUsesSoftwareRenderer;
901 }
902 setState(CONFIGURED);
903 (new AMessage)->postReply(mReplyID);
904 break;
905 }
906
907 case CodecBase::kWhatInputSurfaceCreated:
908 {
909 // response to initiateCreateInputSurface()
910 status_t err = NO_ERROR;
911 sp<AMessage> response = new AMessage();
912 if (!msg->findInt32("err", &err)) {
913 sp<RefBase> obj;
914 msg->findObject("input-surface", &obj);
915 CHECK(obj != NULL);
916 response->setObject("input-surface", obj);
917 mHaveInputSurface = true;
918 } else {
919 response->setInt32("err", err);
920 }
921 response->postReply(mReplyID);
922 break;
923 }
924
925 case CodecBase::kWhatSignaledInputEOS:
926 {
927 // response to signalEndOfInputStream()
928 sp<AMessage> response = new AMessage();
929 status_t err;
930 if (msg->findInt32("err", &err)) {
931 response->setInt32("err", err);
932 }
933 response->postReply(mReplyID);
934 break;
935 }
936
937
938 case CodecBase::kWhatBuffersAllocated:
939 {
940 Mutex::Autolock al(mBufferLock);
941 int32_t portIndex;
942 CHECK(msg->findInt32("portIndex", &portIndex));
943
944 ALOGV("%s buffers allocated",
945 portIndex == kPortIndexInput ? "input" : "output");
946
947 CHECK(portIndex == kPortIndexInput
948 || portIndex == kPortIndexOutput);
949
950 mPortBuffers[portIndex].clear();
951
952 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
953
954 sp<RefBase> obj;
955 CHECK(msg->findObject("portDesc", &obj));
956
957 sp<CodecBase::PortDescription> portDesc =
958 static_cast<CodecBase::PortDescription *>(obj.get());
959
960 size_t numBuffers = portDesc->countBuffers();
961
962 for (size_t i = 0; i < numBuffers; ++i) {
963 BufferInfo info;
964 info.mBufferID = portDesc->bufferIDAt(i);
965 info.mOwnedByClient = false;
966 info.mData = portDesc->bufferAt(i);
967
968 if (portIndex == kPortIndexInput && mCrypto != NULL) {
969 info.mEncryptedData =
970 new ABuffer(info.mData->capacity());
971 }
972
973 buffers->push_back(info);
974 }
975
976 if (portIndex == kPortIndexOutput) {
977 if (mState == STARTING) {
978 // We're always allocating output buffers after
979 // allocating input buffers, so this is a good
980 // indication that now all buffers are allocated.
981 setState(STARTED);
982 (new AMessage)->postReply(mReplyID);
983 } else {
984 mFlags |= kFlagOutputBuffersChanged;
985 postActivityNotificationIfPossible();
986 }
987 }
988 break;
989 }
990
991 case CodecBase::kWhatOutputFormatChanged:
992 {
993 ALOGV("codec output format changed");
994
995 if (mSoftRenderer == NULL &&
996 mNativeWindow != NULL &&
997 (mFlags & kFlagUsesSoftwareRenderer)) {
998 AString mime;
999 CHECK(msg->findString("mime", &mime));
1000
1001 if (mime.startsWithIgnoreCase("video/")) {
1002 mSoftRenderer = new SoftwareRenderer(mNativeWindow);
1003 }
1004 }
1005
1006 mOutputFormat = msg;
1007
1008 if (mFlags & kFlagIsEncoder) {
1009 // Before we announce the format change we should
1010 // collect codec specific data and amend the output
1011 // format as necessary.
1012 mFlags |= kFlagGatherCodecSpecificData;
1013 } else if (mFlags & kFlagIsAsync) {
1014 onOutputFormatChanged();
1015 } else {
1016 mFlags |= kFlagOutputFormatChanged;
1017 postActivityNotificationIfPossible();
1018 }
1019
1020 // Notify mCrypto of video resolution changes
1021 if (mCrypto != NULL) {
1022 int32_t left, top, right, bottom, width, height;
1023 if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
1024 mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
1025 } else if (mOutputFormat->findInt32("width", &width)
1026 && mOutputFormat->findInt32("height", &height)) {
1027 mCrypto->notifyResolution(width, height);
1028 }
1029 }
1030
1031 break;
1032 }
1033
1034 case CodecBase::kWhatFillThisBuffer:
1035 {
1036 /* size_t index = */updateBuffers(kPortIndexInput, msg);
1037
1038 if (mState == FLUSHING
1039 || mState == STOPPING
1040 || mState == RELEASING) {
1041 returnBuffersToCodecOnPort(kPortIndexInput);
1042 break;
1043 }
1044
1045 if (!mCSD.empty()) {
1046 ssize_t index = dequeuePortBuffer(kPortIndexInput);
1047 CHECK_GE(index, 0);
1048
1049 // If codec specific data had been specified as
1050 // part of the format in the call to configure and
1051 // if there's more csd left, we submit it here
1052 // clients only get access to input buffers once
1053 // this data has been exhausted.
1054
1055 status_t err = queueCSDInputBuffer(index);
1056
1057 if (err != OK) {
1058 ALOGE("queueCSDInputBuffer failed w/ error %d",
1059 err);
1060
1061 setStickyError(err);
1062 postActivityNotificationIfPossible();
1063
1064 cancelPendingDequeueOperations();
1065 }
1066 break;
1067 }
1068
1069 if (mFlags & kFlagIsAsync) {
1070 if (!mHaveInputSurface) {
1071 onInputBufferAvailable();
1072 }
1073 } else if (mFlags & kFlagDequeueInputPending) {
1074 CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
1075
1076 ++mDequeueInputTimeoutGeneration;
1077 mFlags &= ~kFlagDequeueInputPending;
1078 mDequeueInputReplyID = 0;
1079 } else {
1080 postActivityNotificationIfPossible();
1081 }
1082 break;
1083 }
1084
1085 case CodecBase::kWhatDrainThisBuffer:
1086 {
1087 /* size_t index = */updateBuffers(kPortIndexOutput, msg);
1088
1089 if (mState == FLUSHING
1090 || mState == STOPPING
1091 || mState == RELEASING) {
1092 returnBuffersToCodecOnPort(kPortIndexOutput);
1093 break;
1094 }
1095
1096 sp<ABuffer> buffer;
1097 CHECK(msg->findBuffer("buffer", &buffer));
1098
1099 int32_t omxFlags;
1100 CHECK(msg->findInt32("flags", &omxFlags));
1101
1102 buffer->meta()->setInt32("omxFlags", omxFlags);
1103
1104 if (mFlags & kFlagGatherCodecSpecificData) {
1105 // This is the very first output buffer after a
1106 // format change was signalled, it'll either contain
1107 // the one piece of codec specific data we can expect
1108 // or there won't be codec specific data.
1109 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1110 status_t err =
1111 amendOutputFormatWithCodecSpecificData(buffer);
1112
1113 if (err != OK) {
1114 ALOGE("Codec spit out malformed codec "
1115 "specific data!");
1116 }
1117 }
1118
1119 mFlags &= ~kFlagGatherCodecSpecificData;
1120 if (mFlags & kFlagIsAsync) {
1121 onOutputFormatChanged();
1122 } else {
1123 mFlags |= kFlagOutputFormatChanged;
1124 }
1125 }
1126
1127 if (mFlags & kFlagIsAsync) {
1128 onOutputBufferAvailable();
1129 } else if (mFlags & kFlagDequeueOutputPending) {
1130 CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
1131
1132 ++mDequeueOutputTimeoutGeneration;
1133 mFlags &= ~kFlagDequeueOutputPending;
1134 mDequeueOutputReplyID = 0;
1135 } else {
1136 postActivityNotificationIfPossible();
1137 }
1138
1139 break;
1140 }
1141
1142 case CodecBase::kWhatEOS:
1143 {
1144 // We already notify the client of this by using the
1145 // corresponding flag in "onOutputBufferReady".
1146 break;
1147 }
1148
1149 case CodecBase::kWhatShutdownCompleted:
1150 {
1151 if (mState == STOPPING) {
1152 setState(INITIALIZED);
1153 } else {
1154 CHECK_EQ(mState, RELEASING);
1155 setState(UNINITIALIZED);
1156 mComponentName.clear();
1157 }
1158 mFlags &= ~kFlagIsComponentAllocated;
1159
1160 (new AMessage)->postReply(mReplyID);
1161 break;
1162 }
1163
1164 case CodecBase::kWhatFlushCompleted:
1165 {
1166 if (mState != FLUSHING) {
1167 ALOGW("received FlushCompleted message in state %d",
1168 mState);
1169 break;
1170 }
1171
1172 if (mFlags & kFlagIsAsync) {
1173 setState(FLUSHED);
1174 } else {
1175 setState(STARTED);
1176 mCodec->signalResume();
1177 }
1178
1179 (new AMessage)->postReply(mReplyID);
1180 break;
1181 }
1182
1183 default:
1184 TRESPASS();
1185 }
1186 break;
1187 }
1188
1189 case kWhatInit:
1190 {
1191 uint32_t replyID;
1192 CHECK(msg->senderAwaitsResponse(&replyID));
1193
1194 if (mState != UNINITIALIZED) {
1195 PostReplyWithError(replyID, INVALID_OPERATION);
1196 break;
1197 }
1198
1199 mReplyID = replyID;
1200 setState(INITIALIZING);
1201
1202 AString name;
1203 CHECK(msg->findString("name", &name));
1204
1205 int32_t nameIsType;
1206 int32_t encoder = false;
1207 CHECK(msg->findInt32("nameIsType", &nameIsType));
1208 if (nameIsType) {
1209 CHECK(msg->findInt32("encoder", &encoder));
1210 }
1211
1212 sp<AMessage> format = new AMessage;
1213
1214 if (nameIsType) {
1215 format->setString("mime", name.c_str());
1216 format->setInt32("encoder", encoder);
1217 } else {
1218 format->setString("componentName", name.c_str());
1219 }
1220
1221 mCodec->initiateAllocateComponent(format);
1222 break;
1223 }
1224
1225 case kWhatSetCallback:
1226 {
1227 uint32_t replyID;
1228 CHECK(msg->senderAwaitsResponse(&replyID));
1229
1230 if (mState == UNINITIALIZED
1231 || mState == INITIALIZING
1232 || isExecuting()) {
1233 // callback can't be set after codec is executing,
1234 // or before it's initialized (as the callback
1235 // will be cleared when it goes to INITIALIZED)
1236 PostReplyWithError(replyID, INVALID_OPERATION);
1237 break;
1238 }
1239
1240 sp<AMessage> callback;
1241 CHECK(msg->findMessage("callback", &callback));
1242
1243 mCallback = callback;
1244
1245 if (mCallback != NULL) {
1246 ALOGI("MediaCodec will operate in async mode");
1247 mFlags |= kFlagIsAsync;
1248 } else {
1249 mFlags &= ~kFlagIsAsync;
1250 }
1251
1252 sp<AMessage> response = new AMessage;
1253 response->postReply(replyID);
1254 break;
1255 }
1256
1257 case kWhatConfigure:
1258 {
1259 uint32_t replyID;
1260 CHECK(msg->senderAwaitsResponse(&replyID));
1261
1262 if (mState != INITIALIZED) {
1263 PostReplyWithError(replyID, INVALID_OPERATION);
1264 break;
1265 }
1266
1267 sp<RefBase> obj;
1268 if (!msg->findObject("native-window", &obj)) {
1269 obj.clear();
1270 }
1271
1272 sp<AMessage> format;
1273 CHECK(msg->findMessage("format", &format));
1274
1275 if (obj != NULL) {
1276 format->setObject("native-window", obj);
1277
1278 status_t err = setNativeWindow(
1279 static_cast<NativeWindowWrapper *>(obj.get())
1280 ->getSurfaceTextureClient());
1281
1282 if (err != OK) {
1283 PostReplyWithError(replyID, err);
1284 break;
1285 }
1286 } else {
1287 setNativeWindow(NULL);
1288 }
1289
1290 mReplyID = replyID;
1291 setState(CONFIGURING);
1292
1293 void *crypto;
1294 if (!msg->findPointer("crypto", &crypto)) {
1295 crypto = NULL;
1296 }
1297
1298 mCrypto = static_cast<ICrypto *>(crypto);
1299
1300 uint32_t flags;
1301 CHECK(msg->findInt32("flags", (int32_t *)&flags));
1302
1303 if (flags & CONFIGURE_FLAG_ENCODE) {
1304 format->setInt32("encoder", true);
1305 mFlags |= kFlagIsEncoder;
1306 }
1307
1308 extractCSD(format);
1309
1310 mCodec->initiateConfigureComponent(format);
1311 break;
1312 }
1313
1314 case kWhatCreateInputSurface:
1315 {
1316 uint32_t replyID;
1317 CHECK(msg->senderAwaitsResponse(&replyID));
1318
1319 // Must be configured, but can't have been started yet.
1320 if (mState != CONFIGURED) {
1321 PostReplyWithError(replyID, INVALID_OPERATION);
1322 break;
1323 }
1324
1325 mReplyID = replyID;
1326 mCodec->initiateCreateInputSurface();
1327 break;
1328 }
1329
1330 case kWhatStart:
1331 {
1332 uint32_t replyID;
1333 CHECK(msg->senderAwaitsResponse(&replyID));
1334
1335 if (mState == FLUSHED) {
1336 setState(STARTED);
1337 mCodec->signalResume();
1338 PostReplyWithError(replyID, OK);
1339 break;
1340 } else if (mState != CONFIGURED) {
1341 PostReplyWithError(replyID, INVALID_OPERATION);
1342 break;
1343 }
1344
1345 mReplyID = replyID;
1346 setState(STARTING);
1347
1348 mCodec->initiateStart();
1349 break;
1350 }
1351
1352 case kWhatStop:
1353 case kWhatRelease:
1354 {
1355 State targetState =
1356 (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
1357
1358 uint32_t replyID;
1359 CHECK(msg->senderAwaitsResponse(&replyID));
1360
1361 if (!((mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED) // See 1
1362 && mState != INITIALIZED
1363 && mState != CONFIGURED && !isExecuting()) {
1364 // 1) Permit release to shut down the component if allocated.
1365 //
1366 // 2) We may be in "UNINITIALIZED" state already and
1367 // also shutdown the encoder/decoder without the
1368 // client being aware of this if media server died while
1369 // we were being stopped. The client would assume that
1370 // after stop() returned, it would be safe to call release()
1371 // and it should be in this case, no harm to allow a release()
1372 // if we're already uninitialized.
1373 sp<AMessage> response = new AMessage;
1374 status_t err = mState == targetState ? OK : INVALID_OPERATION;
1375 response->setInt32("err", err);
1376 if (err == OK && targetState == UNINITIALIZED) {
1377 mComponentName.clear();
1378 }
1379 response->postReply(replyID);
1380 break;
1381 }
1382
1383 if (mFlags & kFlagSawMediaServerDie) {
1384 // It's dead, Jim. Don't expect initiateShutdown to yield
1385 // any useful results now...
1386 setState(UNINITIALIZED);
1387 if (targetState == UNINITIALIZED) {
1388 mComponentName.clear();
1389 }
1390 (new AMessage)->postReply(replyID);
1391 break;
1392 }
1393
1394 mReplyID = replyID;
1395 setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
1396
1397 mCodec->initiateShutdown(
1398 msg->what() == kWhatStop /* keepComponentAllocated */);
1399
1400 returnBuffersToCodec();
1401 break;
1402 }
1403
1404 case kWhatDequeueInputBuffer:
1405 {
1406 uint32_t replyID;
1407 CHECK(msg->senderAwaitsResponse(&replyID));
1408
1409 if (mFlags & kFlagIsAsync) {
1410 ALOGE("dequeueOutputBuffer can't be used in async mode");
1411 PostReplyWithError(replyID, INVALID_OPERATION);
1412 break;
1413 }
1414
1415 if (mHaveInputSurface) {
1416 ALOGE("dequeueInputBuffer can't be used with input surface");
1417 PostReplyWithError(replyID, INVALID_OPERATION);
1418 break;
1419 }
1420
1421 if (handleDequeueInputBuffer(replyID, true /* new request */)) {
1422 break;
1423 }
1424
1425 int64_t timeoutUs;
1426 CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1427
1428 if (timeoutUs == 0ll) {
1429 PostReplyWithError(replyID, -EAGAIN);
1430 break;
1431 }
1432
1433 mFlags |= kFlagDequeueInputPending;
1434 mDequeueInputReplyID = replyID;
1435
1436 if (timeoutUs > 0ll) {
1437 sp<AMessage> timeoutMsg =
1438 new AMessage(kWhatDequeueInputTimedOut, id());
1439 timeoutMsg->setInt32(
1440 "generation", ++mDequeueInputTimeoutGeneration);
1441 timeoutMsg->post(timeoutUs);
1442 }
1443 break;
1444 }
1445
1446 case kWhatDequeueInputTimedOut:
1447 {
1448 int32_t generation;
1449 CHECK(msg->findInt32("generation", &generation));
1450
1451 if (generation != mDequeueInputTimeoutGeneration) {
1452 // Obsolete
1453 break;
1454 }
1455
1456 CHECK(mFlags & kFlagDequeueInputPending);
1457
1458 PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
1459
1460 mFlags &= ~kFlagDequeueInputPending;
1461 mDequeueInputReplyID = 0;
1462 break;
1463 }
1464
1465 case kWhatQueueInputBuffer:
1466 {
1467 uint32_t replyID;
1468 CHECK(msg->senderAwaitsResponse(&replyID));
1469
1470 if (!isExecuting()) {
1471 PostReplyWithError(replyID, INVALID_OPERATION);
1472 break;
1473 } else if (mFlags & kFlagStickyError) {
1474 PostReplyWithError(replyID, getStickyError());
1475 break;
1476 }
1477
1478 status_t err = onQueueInputBuffer(msg);
1479
1480 PostReplyWithError(replyID, err);
1481 break;
1482 }
1483
1484 case kWhatDequeueOutputBuffer:
1485 {
1486 uint32_t replyID;
1487 CHECK(msg->senderAwaitsResponse(&replyID));
1488
1489 if (mFlags & kFlagIsAsync) {
1490 ALOGE("dequeueOutputBuffer can't be used in async mode");
1491 PostReplyWithError(replyID, INVALID_OPERATION);
1492 break;
1493 }
1494
1495 if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
1496 break;
1497 }
1498
1499 int64_t timeoutUs;
1500 CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1501
1502 if (timeoutUs == 0ll) {
1503 PostReplyWithError(replyID, -EAGAIN);
1504 break;
1505 }
1506
1507 mFlags |= kFlagDequeueOutputPending;
1508 mDequeueOutputReplyID = replyID;
1509
1510 if (timeoutUs > 0ll) {
1511 sp<AMessage> timeoutMsg =
1512 new AMessage(kWhatDequeueOutputTimedOut, id());
1513 timeoutMsg->setInt32(
1514 "generation", ++mDequeueOutputTimeoutGeneration);
1515 timeoutMsg->post(timeoutUs);
1516 }
1517 break;
1518 }
1519
1520 case kWhatDequeueOutputTimedOut:
1521 {
1522 int32_t generation;
1523 CHECK(msg->findInt32("generation", &generation));
1524
1525 if (generation != mDequeueOutputTimeoutGeneration) {
1526 // Obsolete
1527 break;
1528 }
1529
1530 CHECK(mFlags & kFlagDequeueOutputPending);
1531
1532 PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
1533
1534 mFlags &= ~kFlagDequeueOutputPending;
1535 mDequeueOutputReplyID = 0;
1536 break;
1537 }
1538
1539 case kWhatReleaseOutputBuffer:
1540 {
1541 uint32_t replyID;
1542 CHECK(msg->senderAwaitsResponse(&replyID));
1543
1544 if (!isExecuting()) {
1545 PostReplyWithError(replyID, INVALID_OPERATION);
1546 break;
1547 } else if (mFlags & kFlagStickyError) {
1548 PostReplyWithError(replyID, getStickyError());
1549 break;
1550 }
1551
1552 status_t err = onReleaseOutputBuffer(msg);
1553
1554 PostReplyWithError(replyID, err);
1555 break;
1556 }
1557
1558 case kWhatSignalEndOfInputStream:
1559 {
1560 uint32_t replyID;
1561 CHECK(msg->senderAwaitsResponse(&replyID));
1562
1563 if (!isExecuting()) {
1564 PostReplyWithError(replyID, INVALID_OPERATION);
1565 break;
1566 } else if (mFlags & kFlagStickyError) {
1567 PostReplyWithError(replyID, getStickyError());
1568 break;
1569 }
1570
1571 mReplyID = replyID;
1572 mCodec->signalEndOfInputStream();
1573 break;
1574 }
1575
1576 case kWhatGetBuffers:
1577 {
1578 uint32_t replyID;
1579 CHECK(msg->senderAwaitsResponse(&replyID));
1580
1581 if (!isExecuting() || (mFlags & kFlagIsAsync)) {
1582 PostReplyWithError(replyID, INVALID_OPERATION);
1583 break;
1584 } else if (mFlags & kFlagStickyError) {
1585 PostReplyWithError(replyID, getStickyError());
1586 break;
1587 }
1588
1589 int32_t portIndex;
1590 CHECK(msg->findInt32("portIndex", &portIndex));
1591
1592 Vector<sp<ABuffer> > *dstBuffers;
1593 CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
1594
1595 dstBuffers->clear();
1596 const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
1597
1598 for (size_t i = 0; i < srcBuffers.size(); ++i) {
1599 const BufferInfo &info = srcBuffers.itemAt(i);
1600
1601 dstBuffers->push_back(
1602 (portIndex == kPortIndexInput && mCrypto != NULL)
1603 ? info.mEncryptedData : info.mData);
1604 }
1605
1606 (new AMessage)->postReply(replyID);
1607 break;
1608 }
1609
1610 case kWhatFlush:
1611 {
1612 uint32_t replyID;
1613 CHECK(msg->senderAwaitsResponse(&replyID));
1614
1615 if (!isExecuting()) {
1616 PostReplyWithError(replyID, INVALID_OPERATION);
1617 break;
1618 } else if (mFlags & kFlagStickyError) {
1619 PostReplyWithError(replyID, getStickyError());
1620 break;
1621 }
1622
1623 mReplyID = replyID;
1624 // TODO: skip flushing if already FLUSHED
1625 setState(FLUSHING);
1626
1627 mCodec->signalFlush();
1628 returnBuffersToCodec();
1629 break;
1630 }
1631
1632 case kWhatGetInputFormat:
1633 case kWhatGetOutputFormat:
1634 {
1635 sp<AMessage> format =
1636 (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
1637
1638 uint32_t replyID;
1639 CHECK(msg->senderAwaitsResponse(&replyID));
1640
1641 if ((mState != CONFIGURED && mState != STARTING &&
1642 mState != STARTED && mState != FLUSHING &&
1643 mState != FLUSHED)
1644 || format == NULL) {
1645 PostReplyWithError(replyID, INVALID_OPERATION);
1646 break;
1647 } else if (mFlags & kFlagStickyError) {
1648 PostReplyWithError(replyID, getStickyError());
1649 break;
1650 }
1651
1652 sp<AMessage> response = new AMessage;
1653 response->setMessage("format", format);
1654 response->postReply(replyID);
1655 break;
1656 }
1657
1658 case kWhatRequestIDRFrame:
1659 {
1660 mCodec->signalRequestIDRFrame();
1661 break;
1662 }
1663
1664 case kWhatRequestActivityNotification:
1665 {
1666 CHECK(mActivityNotify == NULL);
1667 CHECK(msg->findMessage("notify", &mActivityNotify));
1668
1669 postActivityNotificationIfPossible();
1670 break;
1671 }
1672
1673 case kWhatGetName:
1674 {
1675 uint32_t replyID;
1676 CHECK(msg->senderAwaitsResponse(&replyID));
1677
1678 if (mComponentName.empty()) {
1679 PostReplyWithError(replyID, INVALID_OPERATION);
1680 break;
1681 }
1682
1683 sp<AMessage> response = new AMessage;
1684 response->setString("name", mComponentName.c_str());
1685 response->postReply(replyID);
1686 break;
1687 }
1688
1689 case kWhatSetParameters:
1690 {
1691 uint32_t replyID;
1692 CHECK(msg->senderAwaitsResponse(&replyID));
1693
1694 sp<AMessage> params;
1695 CHECK(msg->findMessage("params", ¶ms));
1696
1697 status_t err = onSetParameters(params);
1698
1699 PostReplyWithError(replyID, err);
1700 break;
1701 }
1702
1703 default:
1704 TRESPASS();
1705 }
1706 }
1707
extractCSD(const sp<AMessage> & format)1708 void MediaCodec::extractCSD(const sp<AMessage> &format) {
1709 mCSD.clear();
1710
1711 size_t i = 0;
1712 for (;;) {
1713 sp<ABuffer> csd;
1714 if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) {
1715 break;
1716 }
1717
1718 mCSD.push_back(csd);
1719 ++i;
1720 }
1721
1722 ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
1723 }
1724
queueCSDInputBuffer(size_t bufferIndex)1725 status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
1726 CHECK(!mCSD.empty());
1727
1728 const BufferInfo *info =
1729 &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
1730
1731 sp<ABuffer> csd = *mCSD.begin();
1732 mCSD.erase(mCSD.begin());
1733
1734 const sp<ABuffer> &codecInputData =
1735 (mCrypto != NULL) ? info->mEncryptedData : info->mData;
1736
1737 if (csd->size() > codecInputData->capacity()) {
1738 return -EINVAL;
1739 }
1740
1741 memcpy(codecInputData->data(), csd->data(), csd->size());
1742
1743 AString errorDetailMsg;
1744
1745 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
1746 msg->setSize("index", bufferIndex);
1747 msg->setSize("offset", 0);
1748 msg->setSize("size", csd->size());
1749 msg->setInt64("timeUs", 0ll);
1750 msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
1751 msg->setPointer("errorDetailMsg", &errorDetailMsg);
1752
1753 return onQueueInputBuffer(msg);
1754 }
1755
setState(State newState)1756 void MediaCodec::setState(State newState) {
1757 if (newState == INITIALIZED || newState == UNINITIALIZED) {
1758 delete mSoftRenderer;
1759 mSoftRenderer = NULL;
1760
1761 mCrypto.clear();
1762 setNativeWindow(NULL);
1763
1764 mInputFormat.clear();
1765 mOutputFormat.clear();
1766 mFlags &= ~kFlagOutputFormatChanged;
1767 mFlags &= ~kFlagOutputBuffersChanged;
1768 mFlags &= ~kFlagStickyError;
1769 mFlags &= ~kFlagIsEncoder;
1770 mFlags &= ~kFlagGatherCodecSpecificData;
1771 mFlags &= ~kFlagIsAsync;
1772 mStickyError = OK;
1773
1774 mActivityNotify.clear();
1775 mCallback.clear();
1776 }
1777
1778 if (newState == UNINITIALIZED) {
1779 // return any straggling buffers, e.g. if we got here on an error
1780 returnBuffersToCodec();
1781
1782 // The component is gone, mediaserver's probably back up already
1783 // but should definitely be back up should we try to instantiate
1784 // another component.. and the cycle continues.
1785 mFlags &= ~kFlagSawMediaServerDie;
1786 }
1787
1788 mState = newState;
1789
1790 cancelPendingDequeueOperations();
1791
1792 updateBatteryStat();
1793 }
1794
returnBuffersToCodec()1795 void MediaCodec::returnBuffersToCodec() {
1796 returnBuffersToCodecOnPort(kPortIndexInput);
1797 returnBuffersToCodecOnPort(kPortIndexOutput);
1798 }
1799
returnBuffersToCodecOnPort(int32_t portIndex)1800 void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
1801 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1802 Mutex::Autolock al(mBufferLock);
1803
1804 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1805
1806 for (size_t i = 0; i < buffers->size(); ++i) {
1807 BufferInfo *info = &buffers->editItemAt(i);
1808
1809 if (info->mNotify != NULL) {
1810 sp<AMessage> msg = info->mNotify;
1811 info->mNotify = NULL;
1812 info->mOwnedByClient = false;
1813
1814 if (portIndex == kPortIndexInput) {
1815 /* no error, just returning buffers */
1816 msg->setInt32("err", OK);
1817 }
1818 msg->post();
1819 }
1820 }
1821
1822 mAvailPortBuffers[portIndex].clear();
1823 }
1824
updateBuffers(int32_t portIndex,const sp<AMessage> & msg)1825 size_t MediaCodec::updateBuffers(
1826 int32_t portIndex, const sp<AMessage> &msg) {
1827 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1828
1829 uint32_t bufferID;
1830 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
1831
1832 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1833
1834 for (size_t i = 0; i < buffers->size(); ++i) {
1835 BufferInfo *info = &buffers->editItemAt(i);
1836
1837 if (info->mBufferID == bufferID) {
1838 CHECK(info->mNotify == NULL);
1839 CHECK(msg->findMessage("reply", &info->mNotify));
1840
1841 info->mFormat =
1842 (portIndex == kPortIndexInput) ? mInputFormat : mOutputFormat;
1843 mAvailPortBuffers[portIndex].push_back(i);
1844
1845 return i;
1846 }
1847 }
1848
1849 TRESPASS();
1850
1851 return 0;
1852 }
1853
onQueueInputBuffer(const sp<AMessage> & msg)1854 status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
1855 size_t index;
1856 size_t offset;
1857 size_t size;
1858 int64_t timeUs;
1859 uint32_t flags;
1860 CHECK(msg->findSize("index", &index));
1861 CHECK(msg->findSize("offset", &offset));
1862 CHECK(msg->findInt64("timeUs", &timeUs));
1863 CHECK(msg->findInt32("flags", (int32_t *)&flags));
1864
1865 const CryptoPlugin::SubSample *subSamples;
1866 size_t numSubSamples;
1867 const uint8_t *key;
1868 const uint8_t *iv;
1869 CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
1870
1871 // We allow the simpler queueInputBuffer API to be used even in
1872 // secure mode, by fabricating a single unencrypted subSample.
1873 CryptoPlugin::SubSample ss;
1874
1875 if (msg->findSize("size", &size)) {
1876 if (mCrypto != NULL) {
1877 ss.mNumBytesOfClearData = size;
1878 ss.mNumBytesOfEncryptedData = 0;
1879
1880 subSamples = &ss;
1881 numSubSamples = 1;
1882 key = NULL;
1883 iv = NULL;
1884 }
1885 } else {
1886 if (mCrypto == NULL) {
1887 return -EINVAL;
1888 }
1889
1890 CHECK(msg->findPointer("subSamples", (void **)&subSamples));
1891 CHECK(msg->findSize("numSubSamples", &numSubSamples));
1892 CHECK(msg->findPointer("key", (void **)&key));
1893 CHECK(msg->findPointer("iv", (void **)&iv));
1894
1895 int32_t tmp;
1896 CHECK(msg->findInt32("mode", &tmp));
1897
1898 mode = (CryptoPlugin::Mode)tmp;
1899
1900 size = 0;
1901 for (size_t i = 0; i < numSubSamples; ++i) {
1902 size += subSamples[i].mNumBytesOfClearData;
1903 size += subSamples[i].mNumBytesOfEncryptedData;
1904 }
1905 }
1906
1907 if (index >= mPortBuffers[kPortIndexInput].size()) {
1908 return -ERANGE;
1909 }
1910
1911 BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
1912
1913 if (info->mNotify == NULL || !info->mOwnedByClient) {
1914 return -EACCES;
1915 }
1916
1917 if (offset + size > info->mData->capacity()) {
1918 return -EINVAL;
1919 }
1920
1921 sp<AMessage> reply = info->mNotify;
1922 info->mData->setRange(offset, size);
1923 info->mData->meta()->setInt64("timeUs", timeUs);
1924
1925 if (flags & BUFFER_FLAG_EOS) {
1926 info->mData->meta()->setInt32("eos", true);
1927 }
1928
1929 if (flags & BUFFER_FLAG_CODECCONFIG) {
1930 info->mData->meta()->setInt32("csd", true);
1931 }
1932
1933 if (mCrypto != NULL) {
1934 if (size > info->mEncryptedData->capacity()) {
1935 return -ERANGE;
1936 }
1937
1938 AString *errorDetailMsg;
1939 CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
1940
1941 ssize_t result = mCrypto->decrypt(
1942 (mFlags & kFlagIsSecure) != 0,
1943 key,
1944 iv,
1945 mode,
1946 info->mEncryptedData->base() + offset,
1947 subSamples,
1948 numSubSamples,
1949 info->mData->base(),
1950 errorDetailMsg);
1951
1952 if (result < 0) {
1953 return result;
1954 }
1955
1956 info->mData->setRange(0, result);
1957 }
1958
1959 // synchronization boundary for getBufferAndFormat
1960 {
1961 Mutex::Autolock al(mBufferLock);
1962 info->mOwnedByClient = false;
1963 }
1964 reply->setBuffer("buffer", info->mData);
1965 reply->post();
1966
1967 info->mNotify = NULL;
1968
1969 return OK;
1970 }
1971
onReleaseOutputBuffer(const sp<AMessage> & msg)1972 status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
1973 size_t index;
1974 CHECK(msg->findSize("index", &index));
1975
1976 int32_t render;
1977 if (!msg->findInt32("render", &render)) {
1978 render = 0;
1979 }
1980
1981 if (!isExecuting()) {
1982 return -EINVAL;
1983 }
1984
1985 if (index >= mPortBuffers[kPortIndexOutput].size()) {
1986 return -ERANGE;
1987 }
1988
1989 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1990
1991 if (info->mNotify == NULL || !info->mOwnedByClient) {
1992 return -EACCES;
1993 }
1994
1995 // synchronization boundary for getBufferAndFormat
1996 {
1997 Mutex::Autolock al(mBufferLock);
1998 info->mOwnedByClient = false;
1999 }
2000
2001 if (render && info->mData != NULL && info->mData->size() != 0) {
2002 info->mNotify->setInt32("render", true);
2003
2004 int64_t timestampNs = 0;
2005 if (msg->findInt64("timestampNs", ×tampNs)) {
2006 info->mNotify->setInt64("timestampNs", timestampNs);
2007 } else {
2008 // TODO: it seems like we should use the timestamp
2009 // in the (media)buffer as it potentially came from
2010 // an input surface, but we did not propagate it prior to
2011 // API 20. Perhaps check for target SDK version.
2012 #if 0
2013 if (info->mData->meta()->findInt64("timeUs", ×tampNs)) {
2014 ALOGV("using buffer PTS of %" PRId64, timestampNs);
2015 timestampNs *= 1000;
2016 }
2017 #endif
2018 }
2019
2020 if (mSoftRenderer != NULL) {
2021 mSoftRenderer->render(
2022 info->mData->data(), info->mData->size(),
2023 timestampNs, NULL, info->mFormat);
2024 }
2025 }
2026
2027 info->mNotify->post();
2028 info->mNotify = NULL;
2029
2030 return OK;
2031 }
2032
dequeuePortBuffer(int32_t portIndex)2033 ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
2034 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2035
2036 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
2037
2038 if (availBuffers->empty()) {
2039 return -EAGAIN;
2040 }
2041
2042 size_t index = *availBuffers->begin();
2043 availBuffers->erase(availBuffers->begin());
2044
2045 BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
2046 CHECK(!info->mOwnedByClient);
2047 {
2048 Mutex::Autolock al(mBufferLock);
2049 info->mOwnedByClient = true;
2050
2051 // set image-data
2052 if (info->mFormat != NULL) {
2053 sp<ABuffer> imageData;
2054 if (info->mFormat->findBuffer("image-data", &imageData)) {
2055 info->mData->meta()->setBuffer("image-data", imageData);
2056 }
2057 int32_t left, top, right, bottom;
2058 if (info->mFormat->findRect("crop", &left, &top, &right, &bottom)) {
2059 info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
2060 }
2061 }
2062 }
2063
2064 return index;
2065 }
2066
setNativeWindow(const sp<Surface> & surfaceTextureClient)2067 status_t MediaCodec::setNativeWindow(
2068 const sp<Surface> &surfaceTextureClient) {
2069 status_t err;
2070
2071 if (mNativeWindow != NULL) {
2072 err = native_window_api_disconnect(
2073 mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
2074
2075 if (err != OK) {
2076 ALOGW("native_window_api_disconnect returned an error: %s (%d)",
2077 strerror(-err), err);
2078 }
2079
2080 mNativeWindow.clear();
2081 }
2082
2083 if (surfaceTextureClient != NULL) {
2084 err = native_window_api_connect(
2085 surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA);
2086
2087 if (err != OK) {
2088 ALOGE("native_window_api_connect returned an error: %s (%d)",
2089 strerror(-err), err);
2090
2091 return err;
2092 }
2093
2094 mNativeWindow = surfaceTextureClient;
2095 }
2096
2097 return OK;
2098 }
2099
onInputBufferAvailable()2100 void MediaCodec::onInputBufferAvailable() {
2101 int32_t index;
2102 while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
2103 sp<AMessage> msg = mCallback->dup();
2104 msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
2105 msg->setInt32("index", index);
2106 msg->post();
2107 }
2108 }
2109
onOutputBufferAvailable()2110 void MediaCodec::onOutputBufferAvailable() {
2111 int32_t index;
2112 while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
2113 const sp<ABuffer> &buffer =
2114 mPortBuffers[kPortIndexOutput].itemAt(index).mData;
2115 sp<AMessage> msg = mCallback->dup();
2116 msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
2117 msg->setInt32("index", index);
2118 msg->setSize("offset", buffer->offset());
2119 msg->setSize("size", buffer->size());
2120
2121 int64_t timeUs;
2122 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2123
2124 msg->setInt64("timeUs", timeUs);
2125
2126 int32_t omxFlags;
2127 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
2128
2129 uint32_t flags = 0;
2130 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
2131 flags |= BUFFER_FLAG_SYNCFRAME;
2132 }
2133 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
2134 flags |= BUFFER_FLAG_CODECCONFIG;
2135 }
2136 if (omxFlags & OMX_BUFFERFLAG_EOS) {
2137 flags |= BUFFER_FLAG_EOS;
2138 }
2139
2140 msg->setInt32("flags", flags);
2141
2142 msg->post();
2143 }
2144 }
2145
onError(status_t err,int32_t actionCode,const char * detail)2146 void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
2147 if (mCallback != NULL) {
2148 sp<AMessage> msg = mCallback->dup();
2149 msg->setInt32("callbackID", CB_ERROR);
2150 msg->setInt32("err", err);
2151 msg->setInt32("actionCode", actionCode);
2152
2153 if (detail != NULL) {
2154 msg->setString("detail", detail);
2155 }
2156
2157 msg->post();
2158 }
2159 }
2160
onOutputFormatChanged()2161 void MediaCodec::onOutputFormatChanged() {
2162 if (mCallback != NULL) {
2163 sp<AMessage> msg = mCallback->dup();
2164 msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
2165 msg->setMessage("format", mOutputFormat);
2166 msg->post();
2167 }
2168 }
2169
2170
postActivityNotificationIfPossible()2171 void MediaCodec::postActivityNotificationIfPossible() {
2172 if (mActivityNotify == NULL) {
2173 return;
2174 }
2175
2176 bool isErrorOrOutputChanged =
2177 (mFlags & (kFlagStickyError
2178 | kFlagOutputBuffersChanged
2179 | kFlagOutputFormatChanged));
2180
2181 if (isErrorOrOutputChanged
2182 || !mAvailPortBuffers[kPortIndexInput].empty()
2183 || !mAvailPortBuffers[kPortIndexOutput].empty()) {
2184 mActivityNotify->setInt32("input-buffers",
2185 mAvailPortBuffers[kPortIndexInput].size());
2186
2187 if (isErrorOrOutputChanged) {
2188 // we want consumer to dequeue as many times as it can
2189 mActivityNotify->setInt32("output-buffers", INT32_MAX);
2190 } else {
2191 mActivityNotify->setInt32("output-buffers",
2192 mAvailPortBuffers[kPortIndexOutput].size());
2193 }
2194 mActivityNotify->post();
2195 mActivityNotify.clear();
2196 }
2197 }
2198
setParameters(const sp<AMessage> & params)2199 status_t MediaCodec::setParameters(const sp<AMessage> ¶ms) {
2200 sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
2201 msg->setMessage("params", params);
2202
2203 sp<AMessage> response;
2204 return PostAndAwaitResponse(msg, &response);
2205 }
2206
onSetParameters(const sp<AMessage> & params)2207 status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) {
2208 mCodec->signalSetParameters(params);
2209
2210 return OK;
2211 }
2212
amendOutputFormatWithCodecSpecificData(const sp<ABuffer> & buffer)2213 status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
2214 const sp<ABuffer> &buffer) {
2215 AString mime;
2216 CHECK(mOutputFormat->findString("mime", &mime));
2217
2218 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
2219 // Codec specific data should be SPS and PPS in a single buffer,
2220 // each prefixed by a startcode (0x00 0x00 0x00 0x01).
2221 // We separate the two and put them into the output format
2222 // under the keys "csd-0" and "csd-1".
2223
2224 unsigned csdIndex = 0;
2225
2226 const uint8_t *data = buffer->data();
2227 size_t size = buffer->size();
2228
2229 const uint8_t *nalStart;
2230 size_t nalSize;
2231 while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
2232 sp<ABuffer> csd = new ABuffer(nalSize + 4);
2233 memcpy(csd->data(), "\x00\x00\x00\x01", 4);
2234 memcpy(csd->data() + 4, nalStart, nalSize);
2235
2236 mOutputFormat->setBuffer(
2237 StringPrintf("csd-%u", csdIndex).c_str(), csd);
2238
2239 ++csdIndex;
2240 }
2241
2242 if (csdIndex != 2) {
2243 return ERROR_MALFORMED;
2244 }
2245 } else {
2246 // For everything else we just stash the codec specific data into
2247 // the output format as a single piece of csd under "csd-0".
2248 mOutputFormat->setBuffer("csd-0", buffer);
2249 }
2250
2251 return OK;
2252 }
2253
updateBatteryStat()2254 void MediaCodec::updateBatteryStat() {
2255 if (mState == CONFIGURED && !mBatteryStatNotified) {
2256 AString mime;
2257 CHECK(mOutputFormat != NULL &&
2258 mOutputFormat->findString("mime", &mime));
2259
2260 mIsVideo = mime.startsWithIgnoreCase("video/");
2261
2262 BatteryNotifier& notifier(BatteryNotifier::getInstance());
2263
2264 if (mIsVideo) {
2265 notifier.noteStartVideo();
2266 } else {
2267 notifier.noteStartAudio();
2268 }
2269
2270 mBatteryStatNotified = true;
2271 } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
2272 BatteryNotifier& notifier(BatteryNotifier::getInstance());
2273
2274 if (mIsVideo) {
2275 notifier.noteStopVideo();
2276 } else {
2277 notifier.noteStopAudio();
2278 }
2279
2280 mBatteryStatNotified = false;
2281 }
2282 }
2283
2284 } // namespace android
2285