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/IMemory.h>
25 #include <binder/IPCThreadState.h>
26 #include <binder/IServiceManager.h>
27 #include <binder/MemoryDealer.h>
28 #include <gui/BufferQueue.h>
29 #include <gui/Surface.h>
30 #include <media/ICrypto.h>
31 #include <media/IOMX.h>
32 #include <media/IResourceManagerService.h>
33 #include <media/stagefright/foundation/ABuffer.h>
34 #include <media/stagefright/foundation/ADebug.h>
35 #include <media/stagefright/foundation/AMessage.h>
36 #include <media/stagefright/foundation/AString.h>
37 #include <media/stagefright/foundation/hexdump.h>
38 #include <media/stagefright/ACodec.h>
39 #include <media/stagefright/BufferProducerWrapper.h>
40 #include <media/stagefright/MediaCodec.h>
41 #include <media/stagefright/MediaCodecList.h>
42 #include <media/stagefright/MediaDefs.h>
43 #include <media/stagefright/MediaErrors.h>
44 #include <media/stagefright/MediaFilter.h>
45 #include <media/stagefright/MetaData.h>
46 #include <media/stagefright/OMXClient.h>
47 #include <media/stagefright/OMXCodec.h>
48 #include <media/stagefright/PersistentSurface.h>
49 #include <media/stagefright/SurfaceUtils.h>
50 #include <mediautils/BatteryNotifier.h>
51 #include <private/android_filesystem_config.h>
52 #include <utils/Log.h>
53 #include <utils/Singleton.h>
54
55 namespace android {
56
getId(sp<IResourceManagerClient> client)57 static int64_t getId(sp<IResourceManagerClient> client) {
58 return (int64_t) client.get();
59 }
60
isResourceError(status_t err)61 static bool isResourceError(status_t err) {
62 return (err == NO_MEMORY);
63 }
64
65 static const int kMaxRetry = 2;
66 static const int kMaxReclaimWaitTimeInUs = 500000; // 0.5s
67
68 struct ResourceManagerClient : public BnResourceManagerClient {
ResourceManagerClientandroid::ResourceManagerClient69 ResourceManagerClient(MediaCodec* codec) : mMediaCodec(codec) {}
70
reclaimResourceandroid::ResourceManagerClient71 virtual bool reclaimResource() {
72 sp<MediaCodec> codec = mMediaCodec.promote();
73 if (codec == NULL) {
74 // codec is already gone.
75 return true;
76 }
77 status_t err = codec->reclaim();
78 if (err == WOULD_BLOCK) {
79 ALOGD("Wait for the client to release codec.");
80 usleep(kMaxReclaimWaitTimeInUs);
81 ALOGD("Try to reclaim again.");
82 err = codec->reclaim(true /* force */);
83 }
84 if (err != OK) {
85 ALOGW("ResourceManagerClient failed to release codec with err %d", err);
86 }
87 return (err == OK);
88 }
89
getNameandroid::ResourceManagerClient90 virtual String8 getName() {
91 String8 ret;
92 sp<MediaCodec> codec = mMediaCodec.promote();
93 if (codec == NULL) {
94 // codec is already gone.
95 return ret;
96 }
97
98 AString name;
99 if (codec->getName(&name) == OK) {
100 ret.setTo(name.c_str());
101 }
102 return ret;
103 }
104
105 protected:
~ResourceManagerClientandroid::ResourceManagerClient106 virtual ~ResourceManagerClient() {}
107
108 private:
109 wp<MediaCodec> mMediaCodec;
110
111 DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient);
112 };
113
ResourceManagerServiceProxy(pid_t pid)114 MediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy(pid_t pid)
115 : mPid(pid) {
116 if (mPid == MediaCodec::kNoPid) {
117 mPid = IPCThreadState::self()->getCallingPid();
118 }
119 }
120
~ResourceManagerServiceProxy()121 MediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() {
122 if (mService != NULL) {
123 IInterface::asBinder(mService)->unlinkToDeath(this);
124 }
125 }
126
init()127 void MediaCodec::ResourceManagerServiceProxy::init() {
128 sp<IServiceManager> sm = defaultServiceManager();
129 sp<IBinder> binder = sm->getService(String16("media.resource_manager"));
130 mService = interface_cast<IResourceManagerService>(binder);
131 if (mService == NULL) {
132 ALOGE("Failed to get ResourceManagerService");
133 return;
134 }
135 IInterface::asBinder(mService)->linkToDeath(this);
136 }
137
binderDied(const wp<IBinder> &)138 void MediaCodec::ResourceManagerServiceProxy::binderDied(const wp<IBinder>& /*who*/) {
139 ALOGW("ResourceManagerService died.");
140 Mutex::Autolock _l(mLock);
141 mService.clear();
142 }
143
addResource(int64_t clientId,const sp<IResourceManagerClient> client,const Vector<MediaResource> & resources)144 void MediaCodec::ResourceManagerServiceProxy::addResource(
145 int64_t clientId,
146 const sp<IResourceManagerClient> client,
147 const Vector<MediaResource> &resources) {
148 Mutex::Autolock _l(mLock);
149 if (mService == NULL) {
150 return;
151 }
152 mService->addResource(mPid, clientId, client, resources);
153 }
154
removeResource(int64_t clientId)155 void MediaCodec::ResourceManagerServiceProxy::removeResource(int64_t clientId) {
156 Mutex::Autolock _l(mLock);
157 if (mService == NULL) {
158 return;
159 }
160 mService->removeResource(mPid, clientId);
161 }
162
reclaimResource(const Vector<MediaResource> & resources)163 bool MediaCodec::ResourceManagerServiceProxy::reclaimResource(
164 const Vector<MediaResource> &resources) {
165 Mutex::Autolock _l(mLock);
166 if (mService == NULL) {
167 return false;
168 }
169 return mService->reclaimResource(mPid, resources);
170 }
171
172 // static
CreateByType(const sp<ALooper> & looper,const char * mime,bool encoder,status_t * err,pid_t pid)173 sp<MediaCodec> MediaCodec::CreateByType(
174 const sp<ALooper> &looper, const char *mime, bool encoder, status_t *err, pid_t pid) {
175 sp<MediaCodec> codec = new MediaCodec(looper, pid);
176
177 const status_t ret = codec->init(mime, true /* nameIsType */, encoder);
178 if (err != NULL) {
179 *err = ret;
180 }
181 return ret == OK ? codec : NULL; // NULL deallocates codec.
182 }
183
184 // static
CreateByComponentName(const sp<ALooper> & looper,const char * name,status_t * err,pid_t pid)185 sp<MediaCodec> MediaCodec::CreateByComponentName(
186 const sp<ALooper> &looper, const char *name, status_t *err, pid_t pid) {
187 sp<MediaCodec> codec = new MediaCodec(looper, pid);
188
189 const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */);
190 if (err != NULL) {
191 *err = ret;
192 }
193 return ret == OK ? codec : NULL; // NULL deallocates codec.
194 }
195
196 // static
CreatePersistentInputSurface()197 sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() {
198 OMXClient client;
199 CHECK_EQ(client.connect(), (status_t)OK);
200 sp<IOMX> omx = client.interface();
201
202 const sp<IMediaCodecList> mediaCodecList = MediaCodecList::getInstance();
203 if (mediaCodecList == NULL) {
204 ALOGE("Failed to obtain MediaCodecList!");
205 return NULL; // if called from Java should raise IOException
206 }
207
208 AString tmp;
209 sp<AMessage> globalSettings = mediaCodecList->getGlobalSettings();
210 if (globalSettings == NULL || !globalSettings->findString(
211 kMaxEncoderInputBuffers, &tmp)) {
212 ALOGE("Failed to get encoder input buffer count!");
213 return NULL;
214 }
215
216 int32_t bufferCount = strtol(tmp.c_str(), NULL, 10);
217 if (bufferCount <= 0
218 || bufferCount > BufferQueue::MAX_MAX_ACQUIRED_BUFFERS) {
219 ALOGE("Encoder input buffer count is invalid!");
220 return NULL;
221 }
222
223 sp<IGraphicBufferProducer> bufferProducer;
224 sp<IGraphicBufferConsumer> bufferConsumer;
225
226 status_t err = omx->createPersistentInputSurface(
227 &bufferProducer, &bufferConsumer);
228
229 if (err != OK) {
230 ALOGE("Failed to create persistent input surface.");
231 return NULL;
232 }
233
234 err = bufferConsumer->setMaxAcquiredBufferCount(bufferCount);
235
236 if (err != NO_ERROR) {
237 ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
238 bufferCount, err);
239 return NULL;
240 }
241
242 return new PersistentSurface(bufferProducer, bufferConsumer);
243 }
244
MediaCodec(const sp<ALooper> & looper,pid_t pid)245 MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid)
246 : mState(UNINITIALIZED),
247 mReleasedByResourceManager(false),
248 mLooper(looper),
249 mCodec(NULL),
250 mReplyID(0),
251 mFlags(0),
252 mStickyError(OK),
253 mSoftRenderer(NULL),
254 mResourceManagerClient(new ResourceManagerClient(this)),
255 mResourceManagerService(new ResourceManagerServiceProxy(pid)),
256 mBatteryStatNotified(false),
257 mIsVideo(false),
258 mVideoWidth(0),
259 mVideoHeight(0),
260 mRotationDegrees(0),
261 mDequeueInputTimeoutGeneration(0),
262 mDequeueInputReplyID(0),
263 mDequeueOutputTimeoutGeneration(0),
264 mDequeueOutputReplyID(0),
265 mHaveInputSurface(false),
266 mHavePendingInputBuffers(false) {
267 }
268
~MediaCodec()269 MediaCodec::~MediaCodec() {
270 CHECK_EQ(mState, UNINITIALIZED);
271 mResourceManagerService->removeResource(getId(mResourceManagerClient));
272 }
273
274 // static
PostAndAwaitResponse(const sp<AMessage> & msg,sp<AMessage> * response)275 status_t MediaCodec::PostAndAwaitResponse(
276 const sp<AMessage> &msg, sp<AMessage> *response) {
277 status_t err = msg->postAndAwaitResponse(response);
278
279 if (err != OK) {
280 return err;
281 }
282
283 if (!(*response)->findInt32("err", &err)) {
284 err = OK;
285 }
286
287 return err;
288 }
289
PostReplyWithError(const sp<AReplyToken> & replyID,int32_t err)290 void MediaCodec::PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err) {
291 int32_t finalErr = err;
292 if (mReleasedByResourceManager) {
293 // override the err code if MediaCodec has been released by ResourceManager.
294 finalErr = DEAD_OBJECT;
295 }
296
297 sp<AMessage> response = new AMessage;
298 response->setInt32("err", finalErr);
299 response->postReply(replyID);
300 }
301
init(const AString & name,bool nameIsType,bool encoder)302 status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) {
303 mResourceManagerService->init();
304
305 // save init parameters for reset
306 mInitName = name;
307 mInitNameIsType = nameIsType;
308 mInitIsEncoder = encoder;
309
310 // Current video decoders do not return from OMX_FillThisBuffer
311 // quickly, violating the OpenMAX specs, until that is remedied
312 // we need to invest in an extra looper to free the main event
313 // queue.
314
315 if (nameIsType || !strncasecmp(name.c_str(), "omx.", 4)) {
316 mCodec = new ACodec;
317 } else if (!nameIsType
318 && !strncasecmp(name.c_str(), "android.filter.", 15)) {
319 mCodec = new MediaFilter;
320 } else {
321 return NAME_NOT_FOUND;
322 }
323
324 bool secureCodec = false;
325 if (nameIsType && !strncasecmp(name.c_str(), "video/", 6)) {
326 mIsVideo = true;
327 } else {
328 AString tmp = name;
329 if (tmp.endsWith(".secure")) {
330 secureCodec = true;
331 tmp.erase(tmp.size() - 7, 7);
332 }
333 const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
334 if (mcl == NULL) {
335 mCodec = NULL; // remove the codec.
336 return NO_INIT; // if called from Java should raise IOException
337 }
338 ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
339 if (codecIdx >= 0) {
340 const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
341 Vector<AString> mimes;
342 info->getSupportedMimes(&mimes);
343 for (size_t i = 0; i < mimes.size(); i++) {
344 if (mimes[i].startsWith("video/")) {
345 mIsVideo = true;
346 break;
347 }
348 }
349 }
350 }
351
352 if (mIsVideo) {
353 // video codec needs dedicated looper
354 if (mCodecLooper == NULL) {
355 mCodecLooper = new ALooper;
356 mCodecLooper->setName("CodecLooper");
357 mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
358 }
359
360 mCodecLooper->registerHandler(mCodec);
361 } else {
362 mLooper->registerHandler(mCodec);
363 }
364
365 mLooper->registerHandler(this);
366
367 mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, this));
368
369 sp<AMessage> msg = new AMessage(kWhatInit, this);
370 msg->setString("name", name);
371 msg->setInt32("nameIsType", nameIsType);
372
373 if (nameIsType) {
374 msg->setInt32("encoder", encoder);
375 }
376
377 status_t err;
378 Vector<MediaResource> resources;
379 const char *type = secureCodec ? kResourceSecureCodec : kResourceNonSecureCodec;
380 const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;
381 resources.push_back(MediaResource(String8(type), String8(subtype), 1));
382 for (int i = 0; i <= kMaxRetry; ++i) {
383 if (i > 0) {
384 // Don't try to reclaim resource for the first time.
385 if (!mResourceManagerService->reclaimResource(resources)) {
386 break;
387 }
388 }
389
390 sp<AMessage> response;
391 err = PostAndAwaitResponse(msg, &response);
392 if (!isResourceError(err)) {
393 break;
394 }
395 }
396 return err;
397 }
398
setCallback(const sp<AMessage> & callback)399 status_t MediaCodec::setCallback(const sp<AMessage> &callback) {
400 sp<AMessage> msg = new AMessage(kWhatSetCallback, this);
401 msg->setMessage("callback", callback);
402
403 sp<AMessage> response;
404 return PostAndAwaitResponse(msg, &response);
405 }
406
setOnFrameRenderedNotification(const sp<AMessage> & notify)407 status_t MediaCodec::setOnFrameRenderedNotification(const sp<AMessage> ¬ify) {
408 sp<AMessage> msg = new AMessage(kWhatSetNotification, this);
409 msg->setMessage("on-frame-rendered", notify);
410 return msg->post();
411 }
412
configure(const sp<AMessage> & format,const sp<Surface> & surface,const sp<ICrypto> & crypto,uint32_t flags)413 status_t MediaCodec::configure(
414 const sp<AMessage> &format,
415 const sp<Surface> &surface,
416 const sp<ICrypto> &crypto,
417 uint32_t flags) {
418 sp<AMessage> msg = new AMessage(kWhatConfigure, this);
419
420 if (mIsVideo) {
421 format->findInt32("width", &mVideoWidth);
422 format->findInt32("height", &mVideoHeight);
423 if (!format->findInt32("rotation-degrees", &mRotationDegrees)) {
424 mRotationDegrees = 0;
425 }
426 }
427
428 msg->setMessage("format", format);
429 msg->setInt32("flags", flags);
430 msg->setObject("surface", surface);
431
432 if (crypto != NULL) {
433 msg->setPointer("crypto", crypto.get());
434 }
435
436 // save msg for reset
437 mConfigureMsg = msg;
438
439 status_t err;
440 Vector<MediaResource> resources;
441 const char *type = (mFlags & kFlagIsSecure) ?
442 kResourceSecureCodec : kResourceNonSecureCodec;
443 const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;
444 resources.push_back(MediaResource(String8(type), String8(subtype), 1));
445 // Don't know the buffer size at this point, but it's fine to use 1 because
446 // the reclaimResource call doesn't consider the requester's buffer size for now.
447 resources.push_back(MediaResource(String8(kResourceGraphicMemory), 1));
448 for (int i = 0; i <= kMaxRetry; ++i) {
449 if (i > 0) {
450 // Don't try to reclaim resource for the first time.
451 if (!mResourceManagerService->reclaimResource(resources)) {
452 break;
453 }
454 }
455
456 sp<AMessage> response;
457 err = PostAndAwaitResponse(msg, &response);
458 if (err != OK && err != INVALID_OPERATION) {
459 // MediaCodec now set state to UNINITIALIZED upon any fatal error.
460 // To maintain backward-compatibility, do a reset() to put codec
461 // back into INITIALIZED state.
462 // But don't reset if the err is INVALID_OPERATION, which means
463 // the configure failure is due to wrong state.
464
465 ALOGE("configure failed with err 0x%08x, resetting...", err);
466 reset();
467 }
468 if (!isResourceError(err)) {
469 break;
470 }
471 }
472 return err;
473 }
474
setInputSurface(const sp<PersistentSurface> & surface)475 status_t MediaCodec::setInputSurface(
476 const sp<PersistentSurface> &surface) {
477 sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
478 msg->setObject("input-surface", surface.get());
479
480 sp<AMessage> response;
481 return PostAndAwaitResponse(msg, &response);
482 }
483
setSurface(const sp<Surface> & surface)484 status_t MediaCodec::setSurface(const sp<Surface> &surface) {
485 sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
486 msg->setObject("surface", surface);
487
488 sp<AMessage> response;
489 return PostAndAwaitResponse(msg, &response);
490 }
491
createInputSurface(sp<IGraphicBufferProducer> * bufferProducer)492 status_t MediaCodec::createInputSurface(
493 sp<IGraphicBufferProducer>* bufferProducer) {
494 sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, this);
495
496 sp<AMessage> response;
497 status_t err = PostAndAwaitResponse(msg, &response);
498 if (err == NO_ERROR) {
499 // unwrap the sp<IGraphicBufferProducer>
500 sp<RefBase> obj;
501 bool found = response->findObject("input-surface", &obj);
502 CHECK(found);
503 sp<BufferProducerWrapper> wrapper(
504 static_cast<BufferProducerWrapper*>(obj.get()));
505 *bufferProducer = wrapper->getBufferProducer();
506 } else {
507 ALOGW("createInputSurface failed, err=%d", err);
508 }
509 return err;
510 }
511
getGraphicBufferSize()512 uint64_t MediaCodec::getGraphicBufferSize() {
513 if (!mIsVideo) {
514 return 0;
515 }
516
517 uint64_t size = 0;
518 size_t portNum = sizeof(mPortBuffers) / sizeof((mPortBuffers)[0]);
519 for (size_t i = 0; i < portNum; ++i) {
520 // TODO: this is just an estimation, we should get the real buffer size from ACodec.
521 size += mPortBuffers[i].size() * mVideoWidth * mVideoHeight * 3 / 2;
522 }
523 return size;
524 }
525
addResource(const String8 & type,const String8 & subtype,uint64_t value)526 void MediaCodec::addResource(const String8 &type, const String8 &subtype, uint64_t value) {
527 Vector<MediaResource> resources;
528 resources.push_back(MediaResource(type, subtype, value));
529 mResourceManagerService->addResource(
530 getId(mResourceManagerClient), mResourceManagerClient, resources);
531 }
532
start()533 status_t MediaCodec::start() {
534 sp<AMessage> msg = new AMessage(kWhatStart, this);
535
536 status_t err;
537 Vector<MediaResource> resources;
538 const char *type = (mFlags & kFlagIsSecure) ?
539 kResourceSecureCodec : kResourceNonSecureCodec;
540 const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;
541 resources.push_back(MediaResource(String8(type), String8(subtype), 1));
542 // Don't know the buffer size at this point, but it's fine to use 1 because
543 // the reclaimResource call doesn't consider the requester's buffer size for now.
544 resources.push_back(MediaResource(String8(kResourceGraphicMemory), 1));
545 for (int i = 0; i <= kMaxRetry; ++i) {
546 if (i > 0) {
547 // Don't try to reclaim resource for the first time.
548 if (!mResourceManagerService->reclaimResource(resources)) {
549 break;
550 }
551 // Recover codec from previous error before retry start.
552 err = reset();
553 if (err != OK) {
554 ALOGE("retrying start: failed to reset codec");
555 break;
556 }
557 sp<AMessage> response;
558 err = PostAndAwaitResponse(mConfigureMsg, &response);
559 if (err != OK) {
560 ALOGE("retrying start: failed to configure codec");
561 break;
562 }
563 }
564
565 sp<AMessage> response;
566 err = PostAndAwaitResponse(msg, &response);
567 if (!isResourceError(err)) {
568 break;
569 }
570 }
571 return err;
572 }
573
stop()574 status_t MediaCodec::stop() {
575 sp<AMessage> msg = new AMessage(kWhatStop, this);
576
577 sp<AMessage> response;
578 return PostAndAwaitResponse(msg, &response);
579 }
580
hasPendingBuffer(int portIndex)581 bool MediaCodec::hasPendingBuffer(int portIndex) {
582 const Vector<BufferInfo> &buffers = mPortBuffers[portIndex];
583 for (size_t i = 0; i < buffers.size(); ++i) {
584 const BufferInfo &info = buffers.itemAt(i);
585 if (info.mOwnedByClient) {
586 return true;
587 }
588 }
589 return false;
590 }
591
hasPendingBuffer()592 bool MediaCodec::hasPendingBuffer() {
593 return hasPendingBuffer(kPortIndexInput) || hasPendingBuffer(kPortIndexOutput);
594 }
595
reclaim(bool force)596 status_t MediaCodec::reclaim(bool force) {
597 ALOGD("MediaCodec::reclaim(%p) %s", this, mInitName.c_str());
598 sp<AMessage> msg = new AMessage(kWhatRelease, this);
599 msg->setInt32("reclaimed", 1);
600 msg->setInt32("force", force ? 1 : 0);
601
602 sp<AMessage> response;
603 status_t ret = PostAndAwaitResponse(msg, &response);
604 if (ret == -ENOENT) {
605 ALOGD("MediaCodec looper is gone, skip reclaim");
606 ret = OK;
607 }
608 return ret;
609 }
610
release()611 status_t MediaCodec::release() {
612 sp<AMessage> msg = new AMessage(kWhatRelease, this);
613
614 sp<AMessage> response;
615 return PostAndAwaitResponse(msg, &response);
616 }
617
reset()618 status_t MediaCodec::reset() {
619 /* When external-facing MediaCodec object is created,
620 it is already initialized. Thus, reset is essentially
621 release() followed by init(), plus clearing the state */
622
623 status_t err = release();
624
625 // unregister handlers
626 if (mCodec != NULL) {
627 if (mCodecLooper != NULL) {
628 mCodecLooper->unregisterHandler(mCodec->id());
629 } else {
630 mLooper->unregisterHandler(mCodec->id());
631 }
632 mCodec = NULL;
633 }
634 mLooper->unregisterHandler(id());
635
636 mFlags = 0; // clear all flags
637 mStickyError = OK;
638
639 // reset state not reset by setState(UNINITIALIZED)
640 mReplyID = 0;
641 mDequeueInputReplyID = 0;
642 mDequeueOutputReplyID = 0;
643 mDequeueInputTimeoutGeneration = 0;
644 mDequeueOutputTimeoutGeneration = 0;
645 mHaveInputSurface = false;
646
647 if (err == OK) {
648 err = init(mInitName, mInitNameIsType, mInitIsEncoder);
649 }
650 return err;
651 }
652
queueInputBuffer(size_t index,size_t offset,size_t size,int64_t presentationTimeUs,uint32_t flags,AString * errorDetailMsg)653 status_t MediaCodec::queueInputBuffer(
654 size_t index,
655 size_t offset,
656 size_t size,
657 int64_t presentationTimeUs,
658 uint32_t flags,
659 AString *errorDetailMsg) {
660 if (errorDetailMsg != NULL) {
661 errorDetailMsg->clear();
662 }
663
664 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
665 msg->setSize("index", index);
666 msg->setSize("offset", offset);
667 msg->setSize("size", size);
668 msg->setInt64("timeUs", presentationTimeUs);
669 msg->setInt32("flags", flags);
670 msg->setPointer("errorDetailMsg", errorDetailMsg);
671
672 sp<AMessage> response;
673 return PostAndAwaitResponse(msg, &response);
674 }
675
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)676 status_t MediaCodec::queueSecureInputBuffer(
677 size_t index,
678 size_t offset,
679 const CryptoPlugin::SubSample *subSamples,
680 size_t numSubSamples,
681 const uint8_t key[16],
682 const uint8_t iv[16],
683 CryptoPlugin::Mode mode,
684 int64_t presentationTimeUs,
685 uint32_t flags,
686 AString *errorDetailMsg) {
687 if (errorDetailMsg != NULL) {
688 errorDetailMsg->clear();
689 }
690
691 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
692 msg->setSize("index", index);
693 msg->setSize("offset", offset);
694 msg->setPointer("subSamples", (void *)subSamples);
695 msg->setSize("numSubSamples", numSubSamples);
696 msg->setPointer("key", (void *)key);
697 msg->setPointer("iv", (void *)iv);
698 msg->setInt32("mode", mode);
699 msg->setInt64("timeUs", presentationTimeUs);
700 msg->setInt32("flags", flags);
701 msg->setPointer("errorDetailMsg", errorDetailMsg);
702
703 sp<AMessage> response;
704 status_t err = PostAndAwaitResponse(msg, &response);
705
706 return err;
707 }
708
dequeueInputBuffer(size_t * index,int64_t timeoutUs)709 status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
710 sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, this);
711 msg->setInt64("timeoutUs", timeoutUs);
712
713 sp<AMessage> response;
714 status_t err;
715 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
716 return err;
717 }
718
719 CHECK(response->findSize("index", index));
720
721 return OK;
722 }
723
dequeueOutputBuffer(size_t * index,size_t * offset,size_t * size,int64_t * presentationTimeUs,uint32_t * flags,int64_t timeoutUs)724 status_t MediaCodec::dequeueOutputBuffer(
725 size_t *index,
726 size_t *offset,
727 size_t *size,
728 int64_t *presentationTimeUs,
729 uint32_t *flags,
730 int64_t timeoutUs) {
731 sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, this);
732 msg->setInt64("timeoutUs", timeoutUs);
733
734 sp<AMessage> response;
735 status_t err;
736 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
737 return err;
738 }
739
740 CHECK(response->findSize("index", index));
741 CHECK(response->findSize("offset", offset));
742 CHECK(response->findSize("size", size));
743 CHECK(response->findInt64("timeUs", presentationTimeUs));
744 CHECK(response->findInt32("flags", (int32_t *)flags));
745
746 return OK;
747 }
748
renderOutputBufferAndRelease(size_t index)749 status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
750 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
751 msg->setSize("index", index);
752 msg->setInt32("render", true);
753
754 sp<AMessage> response;
755 return PostAndAwaitResponse(msg, &response);
756 }
757
renderOutputBufferAndRelease(size_t index,int64_t timestampNs)758 status_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) {
759 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
760 msg->setSize("index", index);
761 msg->setInt32("render", true);
762 msg->setInt64("timestampNs", timestampNs);
763
764 sp<AMessage> response;
765 return PostAndAwaitResponse(msg, &response);
766 }
767
releaseOutputBuffer(size_t index)768 status_t MediaCodec::releaseOutputBuffer(size_t index) {
769 sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
770 msg->setSize("index", index);
771
772 sp<AMessage> response;
773 return PostAndAwaitResponse(msg, &response);
774 }
775
signalEndOfInputStream()776 status_t MediaCodec::signalEndOfInputStream() {
777 sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, this);
778
779 sp<AMessage> response;
780 return PostAndAwaitResponse(msg, &response);
781 }
782
getOutputFormat(sp<AMessage> * format) const783 status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
784 sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, this);
785
786 sp<AMessage> response;
787 status_t err;
788 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
789 return err;
790 }
791
792 CHECK(response->findMessage("format", format));
793
794 return OK;
795 }
796
getInputFormat(sp<AMessage> * format) const797 status_t MediaCodec::getInputFormat(sp<AMessage> *format) const {
798 sp<AMessage> msg = new AMessage(kWhatGetInputFormat, this);
799
800 sp<AMessage> response;
801 status_t err;
802 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
803 return err;
804 }
805
806 CHECK(response->findMessage("format", format));
807
808 return OK;
809 }
810
getName(AString * name) const811 status_t MediaCodec::getName(AString *name) const {
812 sp<AMessage> msg = new AMessage(kWhatGetName, this);
813
814 sp<AMessage> response;
815 status_t err;
816 if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
817 return err;
818 }
819
820 CHECK(response->findString("name", name));
821
822 return OK;
823 }
824
getWidevineLegacyBuffers(Vector<sp<ABuffer>> * buffers) const825 status_t MediaCodec::getWidevineLegacyBuffers(Vector<sp<ABuffer> > *buffers) const {
826 sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
827 msg->setInt32("portIndex", kPortIndexInput);
828 msg->setPointer("buffers", buffers);
829 msg->setInt32("widevine", true);
830
831 sp<AMessage> response;
832 return PostAndAwaitResponse(msg, &response);
833 }
834
getInputBuffers(Vector<sp<ABuffer>> * buffers) const835 status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
836 sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
837 msg->setInt32("portIndex", kPortIndexInput);
838 msg->setPointer("buffers", buffers);
839
840 sp<AMessage> response;
841 return PostAndAwaitResponse(msg, &response);
842 }
843
getOutputBuffers(Vector<sp<ABuffer>> * buffers) const844 status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
845 sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
846 msg->setInt32("portIndex", kPortIndexOutput);
847 msg->setPointer("buffers", buffers);
848
849 sp<AMessage> response;
850 return PostAndAwaitResponse(msg, &response);
851 }
852
getOutputBuffer(size_t index,sp<ABuffer> * buffer)853 status_t MediaCodec::getOutputBuffer(size_t index, sp<ABuffer> *buffer) {
854 sp<AMessage> format;
855 return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
856 }
857
getOutputFormat(size_t index,sp<AMessage> * format)858 status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
859 sp<ABuffer> buffer;
860 return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
861 }
862
getInputBuffer(size_t index,sp<ABuffer> * buffer)863 status_t MediaCodec::getInputBuffer(size_t index, sp<ABuffer> *buffer) {
864 sp<AMessage> format;
865 return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
866 }
867
isExecuting() const868 bool MediaCodec::isExecuting() const {
869 return mState == STARTED || mState == FLUSHED;
870 }
871
getBufferAndFormat(size_t portIndex,size_t index,sp<ABuffer> * buffer,sp<AMessage> * format)872 status_t MediaCodec::getBufferAndFormat(
873 size_t portIndex, size_t index,
874 sp<ABuffer> *buffer, sp<AMessage> *format) {
875 // use mutex instead of a context switch
876
877 if (mReleasedByResourceManager) {
878 return DEAD_OBJECT;
879 }
880
881 buffer->clear();
882 format->clear();
883 if (!isExecuting()) {
884 return INVALID_OPERATION;
885 }
886
887 // we do not want mPortBuffers to change during this section
888 // we also don't want mOwnedByClient to change during this
889 Mutex::Autolock al(mBufferLock);
890 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
891 if (index < buffers->size()) {
892 const BufferInfo &info = buffers->itemAt(index);
893 if (info.mOwnedByClient) {
894 // by the time buffers array is initialized, crypto is set
895 if (portIndex == kPortIndexInput && mCrypto != NULL) {
896 *buffer = info.mEncryptedData;
897 } else {
898 *buffer = info.mData;
899 }
900 *format = info.mFormat;
901 }
902 }
903 return OK;
904 }
905
flush()906 status_t MediaCodec::flush() {
907 sp<AMessage> msg = new AMessage(kWhatFlush, this);
908
909 sp<AMessage> response;
910 return PostAndAwaitResponse(msg, &response);
911 }
912
requestIDRFrame()913 status_t MediaCodec::requestIDRFrame() {
914 (new AMessage(kWhatRequestIDRFrame, this))->post();
915
916 return OK;
917 }
918
requestActivityNotification(const sp<AMessage> & notify)919 void MediaCodec::requestActivityNotification(const sp<AMessage> ¬ify) {
920 sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, this);
921 msg->setMessage("notify", notify);
922 msg->post();
923 }
924
925 ////////////////////////////////////////////////////////////////////////////////
926
cancelPendingDequeueOperations()927 void MediaCodec::cancelPendingDequeueOperations() {
928 if (mFlags & kFlagDequeueInputPending) {
929 PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
930
931 ++mDequeueInputTimeoutGeneration;
932 mDequeueInputReplyID = 0;
933 mFlags &= ~kFlagDequeueInputPending;
934 }
935
936 if (mFlags & kFlagDequeueOutputPending) {
937 PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
938
939 ++mDequeueOutputTimeoutGeneration;
940 mDequeueOutputReplyID = 0;
941 mFlags &= ~kFlagDequeueOutputPending;
942 }
943 }
944
handleDequeueInputBuffer(const sp<AReplyToken> & replyID,bool newRequest)945 bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
946 if (!isExecuting() || (mFlags & kFlagIsAsync)
947 || (newRequest && (mFlags & kFlagDequeueInputPending))) {
948 PostReplyWithError(replyID, INVALID_OPERATION);
949 return true;
950 } else if (mFlags & kFlagStickyError) {
951 PostReplyWithError(replyID, getStickyError());
952 return true;
953 }
954
955 ssize_t index = dequeuePortBuffer(kPortIndexInput);
956
957 if (index < 0) {
958 CHECK_EQ(index, -EAGAIN);
959 return false;
960 }
961
962 sp<AMessage> response = new AMessage;
963 response->setSize("index", index);
964 response->postReply(replyID);
965
966 return true;
967 }
968
handleDequeueOutputBuffer(const sp<AReplyToken> & replyID,bool newRequest)969 bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
970 if (!isExecuting() || (mFlags & kFlagIsAsync)
971 || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
972 PostReplyWithError(replyID, INVALID_OPERATION);
973 } else if (mFlags & kFlagStickyError) {
974 PostReplyWithError(replyID, getStickyError());
975 } else if (mFlags & kFlagOutputBuffersChanged) {
976 PostReplyWithError(replyID, INFO_OUTPUT_BUFFERS_CHANGED);
977 mFlags &= ~kFlagOutputBuffersChanged;
978 } else if (mFlags & kFlagOutputFormatChanged) {
979 PostReplyWithError(replyID, INFO_FORMAT_CHANGED);
980 mFlags &= ~kFlagOutputFormatChanged;
981 } else {
982 sp<AMessage> response = new AMessage;
983 ssize_t index = dequeuePortBuffer(kPortIndexOutput);
984
985 if (index < 0) {
986 CHECK_EQ(index, -EAGAIN);
987 return false;
988 }
989
990 const sp<ABuffer> &buffer =
991 mPortBuffers[kPortIndexOutput].itemAt(index).mData;
992
993 response->setSize("index", index);
994 response->setSize("offset", buffer->offset());
995 response->setSize("size", buffer->size());
996
997 int64_t timeUs;
998 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
999
1000 response->setInt64("timeUs", timeUs);
1001
1002 int32_t omxFlags;
1003 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
1004
1005 uint32_t flags = 0;
1006 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
1007 flags |= BUFFER_FLAG_SYNCFRAME;
1008 }
1009 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1010 flags |= BUFFER_FLAG_CODECCONFIG;
1011 }
1012 if (omxFlags & OMX_BUFFERFLAG_EOS) {
1013 flags |= BUFFER_FLAG_EOS;
1014 }
1015
1016 response->setInt32("flags", flags);
1017 response->postReply(replyID);
1018 }
1019
1020 return true;
1021 }
1022
onMessageReceived(const sp<AMessage> & msg)1023 void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
1024 switch (msg->what()) {
1025 case kWhatCodecNotify:
1026 {
1027 int32_t what;
1028 CHECK(msg->findInt32("what", &what));
1029
1030 switch (what) {
1031 case CodecBase::kWhatError:
1032 {
1033 int32_t err, actionCode;
1034 CHECK(msg->findInt32("err", &err));
1035 CHECK(msg->findInt32("actionCode", &actionCode));
1036
1037 ALOGE("Codec reported err %#x, actionCode %d, while in state %d",
1038 err, actionCode, mState);
1039 if (err == DEAD_OBJECT) {
1040 mFlags |= kFlagSawMediaServerDie;
1041 mFlags &= ~kFlagIsComponentAllocated;
1042 }
1043
1044 bool sendErrorResponse = true;
1045
1046 switch (mState) {
1047 case INITIALIZING:
1048 {
1049 setState(UNINITIALIZED);
1050 break;
1051 }
1052
1053 case CONFIGURING:
1054 {
1055 setState(actionCode == ACTION_CODE_FATAL ?
1056 UNINITIALIZED : INITIALIZED);
1057 break;
1058 }
1059
1060 case STARTING:
1061 {
1062 setState(actionCode == ACTION_CODE_FATAL ?
1063 UNINITIALIZED : CONFIGURED);
1064 break;
1065 }
1066
1067 case STOPPING:
1068 case RELEASING:
1069 {
1070 // Ignore the error, assuming we'll still get
1071 // the shutdown complete notification.
1072
1073 sendErrorResponse = false;
1074
1075 if (mFlags & kFlagSawMediaServerDie) {
1076 // MediaServer died, there definitely won't
1077 // be a shutdown complete notification after
1078 // all.
1079
1080 // note that we're directly going from
1081 // STOPPING->UNINITIALIZED, instead of the
1082 // usual STOPPING->INITIALIZED state.
1083 setState(UNINITIALIZED);
1084 if (mState == RELEASING) {
1085 mComponentName.clear();
1086 }
1087 (new AMessage)->postReply(mReplyID);
1088 }
1089 break;
1090 }
1091
1092 case FLUSHING:
1093 {
1094 if (actionCode == ACTION_CODE_FATAL) {
1095 setState(UNINITIALIZED);
1096 } else {
1097 setState(
1098 (mFlags & kFlagIsAsync) ? FLUSHED : STARTED);
1099 }
1100 break;
1101 }
1102
1103 case FLUSHED:
1104 case STARTED:
1105 {
1106 sendErrorResponse = false;
1107
1108 setStickyError(err);
1109 postActivityNotificationIfPossible();
1110
1111 cancelPendingDequeueOperations();
1112
1113 if (mFlags & kFlagIsAsync) {
1114 onError(err, actionCode);
1115 }
1116 switch (actionCode) {
1117 case ACTION_CODE_TRANSIENT:
1118 break;
1119 case ACTION_CODE_RECOVERABLE:
1120 setState(INITIALIZED);
1121 break;
1122 default:
1123 setState(UNINITIALIZED);
1124 break;
1125 }
1126 break;
1127 }
1128
1129 default:
1130 {
1131 sendErrorResponse = false;
1132
1133 setStickyError(err);
1134 postActivityNotificationIfPossible();
1135
1136 // actionCode in an uninitialized state is always fatal.
1137 if (mState == UNINITIALIZED) {
1138 actionCode = ACTION_CODE_FATAL;
1139 }
1140 if (mFlags & kFlagIsAsync) {
1141 onError(err, actionCode);
1142 }
1143 switch (actionCode) {
1144 case ACTION_CODE_TRANSIENT:
1145 break;
1146 case ACTION_CODE_RECOVERABLE:
1147 setState(INITIALIZED);
1148 break;
1149 default:
1150 setState(UNINITIALIZED);
1151 break;
1152 }
1153 break;
1154 }
1155 }
1156
1157 if (sendErrorResponse) {
1158 PostReplyWithError(mReplyID, err);
1159 }
1160 break;
1161 }
1162
1163 case CodecBase::kWhatComponentAllocated:
1164 {
1165 CHECK_EQ(mState, INITIALIZING);
1166 setState(INITIALIZED);
1167 mFlags |= kFlagIsComponentAllocated;
1168
1169 CHECK(msg->findString("componentName", &mComponentName));
1170
1171 if (mComponentName.startsWith("OMX.google.")) {
1172 mFlags |= kFlagUsesSoftwareRenderer;
1173 } else {
1174 mFlags &= ~kFlagUsesSoftwareRenderer;
1175 }
1176
1177 String8 resourceType;
1178 if (mComponentName.endsWith(".secure")) {
1179 mFlags |= kFlagIsSecure;
1180 resourceType = String8(kResourceSecureCodec);
1181 } else {
1182 mFlags &= ~kFlagIsSecure;
1183 resourceType = String8(kResourceNonSecureCodec);
1184 }
1185
1186 if (mIsVideo) {
1187 // audio codec is currently ignored.
1188 addResource(resourceType, String8(kResourceVideoCodec), 1);
1189 }
1190
1191 (new AMessage)->postReply(mReplyID);
1192 break;
1193 }
1194
1195 case CodecBase::kWhatComponentConfigured:
1196 {
1197 if (mState == UNINITIALIZED || mState == INITIALIZED) {
1198 // In case a kWhatError message came in and replied with error,
1199 // we log a warning and ignore.
1200 ALOGW("configure interrupted by error, current state %d", mState);
1201 break;
1202 }
1203 CHECK_EQ(mState, CONFIGURING);
1204
1205 // reset input surface flag
1206 mHaveInputSurface = false;
1207
1208 CHECK(msg->findMessage("input-format", &mInputFormat));
1209 CHECK(msg->findMessage("output-format", &mOutputFormat));
1210
1211 int32_t usingSwRenderer;
1212 if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer)
1213 && usingSwRenderer) {
1214 mFlags |= kFlagUsesSoftwareRenderer;
1215 }
1216 setState(CONFIGURED);
1217 (new AMessage)->postReply(mReplyID);
1218 break;
1219 }
1220
1221 case CodecBase::kWhatInputSurfaceCreated:
1222 {
1223 // response to initiateCreateInputSurface()
1224 status_t err = NO_ERROR;
1225 sp<AMessage> response = new AMessage;
1226 if (!msg->findInt32("err", &err)) {
1227 sp<RefBase> obj;
1228 msg->findObject("input-surface", &obj);
1229 CHECK(obj != NULL);
1230 response->setObject("input-surface", obj);
1231 mHaveInputSurface = true;
1232 } else {
1233 response->setInt32("err", err);
1234 }
1235 response->postReply(mReplyID);
1236 break;
1237 }
1238
1239 case CodecBase::kWhatInputSurfaceAccepted:
1240 {
1241 // response to initiateSetInputSurface()
1242 status_t err = NO_ERROR;
1243 sp<AMessage> response = new AMessage();
1244 if (!msg->findInt32("err", &err)) {
1245 mHaveInputSurface = true;
1246 } else {
1247 response->setInt32("err", err);
1248 }
1249 response->postReply(mReplyID);
1250 break;
1251 }
1252
1253 case CodecBase::kWhatSignaledInputEOS:
1254 {
1255 // response to signalEndOfInputStream()
1256 sp<AMessage> response = new AMessage;
1257 status_t err;
1258 if (msg->findInt32("err", &err)) {
1259 response->setInt32("err", err);
1260 }
1261 response->postReply(mReplyID);
1262 break;
1263 }
1264
1265
1266 case CodecBase::kWhatBuffersAllocated:
1267 {
1268 Mutex::Autolock al(mBufferLock);
1269 int32_t portIndex;
1270 CHECK(msg->findInt32("portIndex", &portIndex));
1271
1272 ALOGV("%s buffers allocated",
1273 portIndex == kPortIndexInput ? "input" : "output");
1274
1275 CHECK(portIndex == kPortIndexInput
1276 || portIndex == kPortIndexOutput);
1277
1278 mPortBuffers[portIndex].clear();
1279
1280 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1281
1282 sp<RefBase> obj;
1283 CHECK(msg->findObject("portDesc", &obj));
1284
1285 sp<CodecBase::PortDescription> portDesc =
1286 static_cast<CodecBase::PortDescription *>(obj.get());
1287
1288 size_t numBuffers = portDesc->countBuffers();
1289
1290 size_t totalSize = 0;
1291 for (size_t i = 0; i < numBuffers; ++i) {
1292 if (portIndex == kPortIndexInput && mCrypto != NULL) {
1293 totalSize += portDesc->bufferAt(i)->capacity();
1294 }
1295 }
1296
1297 if (totalSize) {
1298 mDealer = new MemoryDealer(totalSize, "MediaCodec");
1299 }
1300
1301 for (size_t i = 0; i < numBuffers; ++i) {
1302 BufferInfo info;
1303 info.mBufferID = portDesc->bufferIDAt(i);
1304 info.mOwnedByClient = false;
1305 info.mData = portDesc->bufferAt(i);
1306
1307 if (portIndex == kPortIndexInput && mCrypto != NULL) {
1308 sp<IMemory> mem = mDealer->allocate(info.mData->capacity());
1309 info.mEncryptedData =
1310 new ABuffer(mem->pointer(), info.mData->capacity());
1311 info.mSharedEncryptedBuffer = mem;
1312 }
1313
1314 buffers->push_back(info);
1315 }
1316
1317 if (portIndex == kPortIndexOutput) {
1318 if (mState == STARTING) {
1319 // We're always allocating output buffers after
1320 // allocating input buffers, so this is a good
1321 // indication that now all buffers are allocated.
1322 if (mIsVideo) {
1323 String8 subtype;
1324 addResource(
1325 String8(kResourceGraphicMemory),
1326 subtype,
1327 getGraphicBufferSize());
1328 }
1329 setState(STARTED);
1330 (new AMessage)->postReply(mReplyID);
1331 } else {
1332 mFlags |= kFlagOutputBuffersChanged;
1333 postActivityNotificationIfPossible();
1334 }
1335 }
1336 break;
1337 }
1338
1339 case CodecBase::kWhatOutputFormatChanged:
1340 {
1341 ALOGV("codec output format changed");
1342
1343 if (mSoftRenderer == NULL &&
1344 mSurface != NULL &&
1345 (mFlags & kFlagUsesSoftwareRenderer)) {
1346 AString mime;
1347 CHECK(msg->findString("mime", &mime));
1348
1349 if (mime.startsWithIgnoreCase("video/")) {
1350 mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees);
1351 }
1352 }
1353
1354 mOutputFormat = msg;
1355
1356 if (mFlags & kFlagIsEncoder) {
1357 // Before we announce the format change we should
1358 // collect codec specific data and amend the output
1359 // format as necessary.
1360 mFlags |= kFlagGatherCodecSpecificData;
1361 } else if (mFlags & kFlagIsAsync) {
1362 onOutputFormatChanged();
1363 } else {
1364 mFlags |= kFlagOutputFormatChanged;
1365 postActivityNotificationIfPossible();
1366 }
1367
1368 // Notify mCrypto of video resolution changes
1369 if (mCrypto != NULL) {
1370 int32_t left, top, right, bottom, width, height;
1371 if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
1372 mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
1373 } else if (mOutputFormat->findInt32("width", &width)
1374 && mOutputFormat->findInt32("height", &height)) {
1375 mCrypto->notifyResolution(width, height);
1376 }
1377 }
1378
1379 break;
1380 }
1381
1382 case CodecBase::kWhatOutputFramesRendered:
1383 {
1384 // ignore these in all states except running, and check that we have a
1385 // notification set
1386 if (mState == STARTED && mOnFrameRenderedNotification != NULL) {
1387 sp<AMessage> notify = mOnFrameRenderedNotification->dup();
1388 notify->setMessage("data", msg);
1389 notify->post();
1390 }
1391 break;
1392 }
1393
1394 case CodecBase::kWhatFillThisBuffer:
1395 {
1396 /* size_t index = */updateBuffers(kPortIndexInput, msg);
1397
1398 if (mState == FLUSHING
1399 || mState == STOPPING
1400 || mState == RELEASING) {
1401 returnBuffersToCodecOnPort(kPortIndexInput);
1402 break;
1403 }
1404
1405 if (!mCSD.empty()) {
1406 ssize_t index = dequeuePortBuffer(kPortIndexInput);
1407 CHECK_GE(index, 0);
1408
1409 // If codec specific data had been specified as
1410 // part of the format in the call to configure and
1411 // if there's more csd left, we submit it here
1412 // clients only get access to input buffers once
1413 // this data has been exhausted.
1414
1415 status_t err = queueCSDInputBuffer(index);
1416
1417 if (err != OK) {
1418 ALOGE("queueCSDInputBuffer failed w/ error %d",
1419 err);
1420
1421 setStickyError(err);
1422 postActivityNotificationIfPossible();
1423
1424 cancelPendingDequeueOperations();
1425 }
1426 break;
1427 }
1428
1429 if (mFlags & kFlagIsAsync) {
1430 if (!mHaveInputSurface) {
1431 if (mState == FLUSHED) {
1432 mHavePendingInputBuffers = true;
1433 } else {
1434 onInputBufferAvailable();
1435 }
1436 }
1437 } else if (mFlags & kFlagDequeueInputPending) {
1438 CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
1439
1440 ++mDequeueInputTimeoutGeneration;
1441 mFlags &= ~kFlagDequeueInputPending;
1442 mDequeueInputReplyID = 0;
1443 } else {
1444 postActivityNotificationIfPossible();
1445 }
1446 break;
1447 }
1448
1449 case CodecBase::kWhatDrainThisBuffer:
1450 {
1451 /* size_t index = */updateBuffers(kPortIndexOutput, msg);
1452
1453 if (mState == FLUSHING
1454 || mState == STOPPING
1455 || mState == RELEASING) {
1456 returnBuffersToCodecOnPort(kPortIndexOutput);
1457 break;
1458 }
1459
1460 sp<ABuffer> buffer;
1461 CHECK(msg->findBuffer("buffer", &buffer));
1462
1463 int32_t omxFlags;
1464 CHECK(msg->findInt32("flags", &omxFlags));
1465
1466 buffer->meta()->setInt32("omxFlags", omxFlags);
1467
1468 if (mFlags & kFlagGatherCodecSpecificData) {
1469 // This is the very first output buffer after a
1470 // format change was signalled, it'll either contain
1471 // the one piece of codec specific data we can expect
1472 // or there won't be codec specific data.
1473 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1474 status_t err =
1475 amendOutputFormatWithCodecSpecificData(buffer);
1476
1477 if (err != OK) {
1478 ALOGE("Codec spit out malformed codec "
1479 "specific data!");
1480 }
1481 }
1482
1483 mFlags &= ~kFlagGatherCodecSpecificData;
1484 if (mFlags & kFlagIsAsync) {
1485 onOutputFormatChanged();
1486 } else {
1487 mFlags |= kFlagOutputFormatChanged;
1488 }
1489 }
1490
1491 if (mFlags & kFlagIsAsync) {
1492 onOutputBufferAvailable();
1493 } else if (mFlags & kFlagDequeueOutputPending) {
1494 CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
1495
1496 ++mDequeueOutputTimeoutGeneration;
1497 mFlags &= ~kFlagDequeueOutputPending;
1498 mDequeueOutputReplyID = 0;
1499 } else {
1500 postActivityNotificationIfPossible();
1501 }
1502
1503 break;
1504 }
1505
1506 case CodecBase::kWhatEOS:
1507 {
1508 // We already notify the client of this by using the
1509 // corresponding flag in "onOutputBufferReady".
1510 break;
1511 }
1512
1513 case CodecBase::kWhatShutdownCompleted:
1514 {
1515 if (mState == STOPPING) {
1516 setState(INITIALIZED);
1517 } else {
1518 CHECK_EQ(mState, RELEASING);
1519 setState(UNINITIALIZED);
1520 mComponentName.clear();
1521 }
1522 mFlags &= ~kFlagIsComponentAllocated;
1523
1524 mResourceManagerService->removeResource(getId(mResourceManagerClient));
1525
1526 (new AMessage)->postReply(mReplyID);
1527 break;
1528 }
1529
1530 case CodecBase::kWhatFlushCompleted:
1531 {
1532 if (mState != FLUSHING) {
1533 ALOGW("received FlushCompleted message in state %d",
1534 mState);
1535 break;
1536 }
1537
1538 if (mFlags & kFlagIsAsync) {
1539 setState(FLUSHED);
1540 } else {
1541 setState(STARTED);
1542 mCodec->signalResume();
1543 }
1544
1545 (new AMessage)->postReply(mReplyID);
1546 break;
1547 }
1548
1549 default:
1550 TRESPASS();
1551 }
1552 break;
1553 }
1554
1555 case kWhatInit:
1556 {
1557 sp<AReplyToken> replyID;
1558 CHECK(msg->senderAwaitsResponse(&replyID));
1559
1560 if (mState != UNINITIALIZED) {
1561 PostReplyWithError(replyID, INVALID_OPERATION);
1562 break;
1563 }
1564
1565 mReplyID = replyID;
1566 setState(INITIALIZING);
1567
1568 AString name;
1569 CHECK(msg->findString("name", &name));
1570
1571 int32_t nameIsType;
1572 int32_t encoder = false;
1573 CHECK(msg->findInt32("nameIsType", &nameIsType));
1574 if (nameIsType) {
1575 CHECK(msg->findInt32("encoder", &encoder));
1576 }
1577
1578 sp<AMessage> format = new AMessage;
1579
1580 if (nameIsType) {
1581 format->setString("mime", name.c_str());
1582 format->setInt32("encoder", encoder);
1583 } else {
1584 format->setString("componentName", name.c_str());
1585 }
1586
1587 mCodec->initiateAllocateComponent(format);
1588 break;
1589 }
1590
1591 case kWhatSetNotification:
1592 {
1593 sp<AMessage> notify;
1594 if (msg->findMessage("on-frame-rendered", ¬ify)) {
1595 mOnFrameRenderedNotification = notify;
1596 }
1597 break;
1598 }
1599
1600 case kWhatSetCallback:
1601 {
1602 sp<AReplyToken> replyID;
1603 CHECK(msg->senderAwaitsResponse(&replyID));
1604
1605 if (mState == UNINITIALIZED
1606 || mState == INITIALIZING
1607 || isExecuting()) {
1608 // callback can't be set after codec is executing,
1609 // or before it's initialized (as the callback
1610 // will be cleared when it goes to INITIALIZED)
1611 PostReplyWithError(replyID, INVALID_OPERATION);
1612 break;
1613 }
1614
1615 sp<AMessage> callback;
1616 CHECK(msg->findMessage("callback", &callback));
1617
1618 mCallback = callback;
1619
1620 if (mCallback != NULL) {
1621 ALOGI("MediaCodec will operate in async mode");
1622 mFlags |= kFlagIsAsync;
1623 } else {
1624 mFlags &= ~kFlagIsAsync;
1625 }
1626
1627 sp<AMessage> response = new AMessage;
1628 response->postReply(replyID);
1629 break;
1630 }
1631
1632 case kWhatConfigure:
1633 {
1634 sp<AReplyToken> replyID;
1635 CHECK(msg->senderAwaitsResponse(&replyID));
1636
1637 if (mState != INITIALIZED) {
1638 PostReplyWithError(replyID, INVALID_OPERATION);
1639 break;
1640 }
1641
1642 sp<RefBase> obj;
1643 CHECK(msg->findObject("surface", &obj));
1644
1645 sp<AMessage> format;
1646 CHECK(msg->findMessage("format", &format));
1647
1648 int32_t push;
1649 if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) {
1650 mFlags |= kFlagPushBlankBuffersOnShutdown;
1651 }
1652
1653 if (obj != NULL) {
1654 format->setObject("native-window", obj);
1655 status_t err = handleSetSurface(static_cast<Surface *>(obj.get()));
1656 if (err != OK) {
1657 PostReplyWithError(replyID, err);
1658 break;
1659 }
1660 } else {
1661 handleSetSurface(NULL);
1662 }
1663
1664 mReplyID = replyID;
1665 setState(CONFIGURING);
1666
1667 void *crypto;
1668 if (!msg->findPointer("crypto", &crypto)) {
1669 crypto = NULL;
1670 }
1671
1672 mCrypto = static_cast<ICrypto *>(crypto);
1673
1674 uint32_t flags;
1675 CHECK(msg->findInt32("flags", (int32_t *)&flags));
1676
1677 if (flags & CONFIGURE_FLAG_ENCODE) {
1678 format->setInt32("encoder", true);
1679 mFlags |= kFlagIsEncoder;
1680 }
1681
1682 extractCSD(format);
1683
1684 mCodec->initiateConfigureComponent(format);
1685 break;
1686 }
1687
1688 case kWhatSetSurface:
1689 {
1690 sp<AReplyToken> replyID;
1691 CHECK(msg->senderAwaitsResponse(&replyID));
1692
1693 status_t err = OK;
1694 sp<Surface> surface;
1695
1696 switch (mState) {
1697 case CONFIGURED:
1698 case STARTED:
1699 case FLUSHED:
1700 {
1701 sp<RefBase> obj;
1702 (void)msg->findObject("surface", &obj);
1703 sp<Surface> surface = static_cast<Surface *>(obj.get());
1704 if (mSurface == NULL) {
1705 // do not support setting surface if it was not set
1706 err = INVALID_OPERATION;
1707 } else if (obj == NULL) {
1708 // do not support unsetting surface
1709 err = BAD_VALUE;
1710 } else {
1711 err = connectToSurface(surface);
1712 if (err == BAD_VALUE) {
1713 // assuming reconnecting to same surface
1714 // TODO: check if it is the same surface
1715 err = OK;
1716 } else {
1717 if (err == OK) {
1718 if (mFlags & kFlagUsesSoftwareRenderer) {
1719 if (mSoftRenderer != NULL
1720 && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1721 pushBlankBuffersToNativeWindow(mSurface.get());
1722 }
1723 mSoftRenderer = new SoftwareRenderer(surface);
1724 // TODO: check if this was successful
1725 } else {
1726 err = mCodec->setSurface(surface);
1727 }
1728 }
1729 if (err == OK) {
1730 (void)disconnectFromSurface();
1731 mSurface = surface;
1732 }
1733 }
1734 }
1735 break;
1736 }
1737
1738 default:
1739 err = INVALID_OPERATION;
1740 break;
1741 }
1742
1743 PostReplyWithError(replyID, err);
1744 break;
1745 }
1746
1747 case kWhatCreateInputSurface:
1748 case kWhatSetInputSurface:
1749 {
1750 sp<AReplyToken> replyID;
1751 CHECK(msg->senderAwaitsResponse(&replyID));
1752
1753 // Must be configured, but can't have been started yet.
1754 if (mState != CONFIGURED) {
1755 PostReplyWithError(replyID, INVALID_OPERATION);
1756 break;
1757 }
1758
1759 mReplyID = replyID;
1760 if (msg->what() == kWhatCreateInputSurface) {
1761 mCodec->initiateCreateInputSurface();
1762 } else {
1763 sp<RefBase> obj;
1764 CHECK(msg->findObject("input-surface", &obj));
1765
1766 mCodec->initiateSetInputSurface(
1767 static_cast<PersistentSurface *>(obj.get()));
1768 }
1769 break;
1770 }
1771 case kWhatStart:
1772 {
1773 sp<AReplyToken> replyID;
1774 CHECK(msg->senderAwaitsResponse(&replyID));
1775
1776 if (mState == FLUSHED) {
1777 setState(STARTED);
1778 if (mHavePendingInputBuffers) {
1779 onInputBufferAvailable();
1780 mHavePendingInputBuffers = false;
1781 }
1782 mCodec->signalResume();
1783 PostReplyWithError(replyID, OK);
1784 break;
1785 } else if (mState != CONFIGURED) {
1786 PostReplyWithError(replyID, INVALID_OPERATION);
1787 break;
1788 }
1789
1790 mReplyID = replyID;
1791 setState(STARTING);
1792
1793 mCodec->initiateStart();
1794 break;
1795 }
1796
1797 case kWhatStop:
1798 case kWhatRelease:
1799 {
1800 State targetState =
1801 (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
1802
1803 sp<AReplyToken> replyID;
1804 CHECK(msg->senderAwaitsResponse(&replyID));
1805
1806 // already stopped/released
1807 if (mState == UNINITIALIZED && mReleasedByResourceManager) {
1808 sp<AMessage> response = new AMessage;
1809 response->setInt32("err", OK);
1810 response->postReply(replyID);
1811 break;
1812 }
1813
1814 int32_t reclaimed = 0;
1815 msg->findInt32("reclaimed", &reclaimed);
1816 if (reclaimed) {
1817 mReleasedByResourceManager = true;
1818
1819 int32_t force = 0;
1820 msg->findInt32("force", &force);
1821 if (!force && hasPendingBuffer()) {
1822 ALOGW("Can't reclaim codec right now due to pending buffers.");
1823
1824 // return WOULD_BLOCK to ask resource manager to retry later.
1825 sp<AMessage> response = new AMessage;
1826 response->setInt32("err", WOULD_BLOCK);
1827 response->postReply(replyID);
1828
1829 // notify the async client
1830 if (mFlags & kFlagIsAsync) {
1831 onError(DEAD_OBJECT, ACTION_CODE_FATAL);
1832 }
1833 break;
1834 }
1835 }
1836
1837 if (!((mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED) // See 1
1838 && mState != INITIALIZED
1839 && mState != CONFIGURED && !isExecuting()) {
1840 // 1) Permit release to shut down the component if allocated.
1841 //
1842 // 2) We may be in "UNINITIALIZED" state already and
1843 // also shutdown the encoder/decoder without the
1844 // client being aware of this if media server died while
1845 // we were being stopped. The client would assume that
1846 // after stop() returned, it would be safe to call release()
1847 // and it should be in this case, no harm to allow a release()
1848 // if we're already uninitialized.
1849 sp<AMessage> response = new AMessage;
1850 // TODO: we shouldn't throw an exception for stop/release. Change this to wait until
1851 // the previous stop/release completes and then reply with OK.
1852 status_t err = mState == targetState ? OK : INVALID_OPERATION;
1853 response->setInt32("err", err);
1854 if (err == OK && targetState == UNINITIALIZED) {
1855 mComponentName.clear();
1856 }
1857 response->postReply(replyID);
1858 break;
1859 }
1860
1861 if (mFlags & kFlagSawMediaServerDie) {
1862 // It's dead, Jim. Don't expect initiateShutdown to yield
1863 // any useful results now...
1864 setState(UNINITIALIZED);
1865 if (targetState == UNINITIALIZED) {
1866 mComponentName.clear();
1867 }
1868 (new AMessage)->postReply(replyID);
1869 break;
1870 }
1871
1872 mReplyID = replyID;
1873 setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
1874
1875 mCodec->initiateShutdown(
1876 msg->what() == kWhatStop /* keepComponentAllocated */);
1877
1878 returnBuffersToCodec();
1879
1880 if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1881 pushBlankBuffersToNativeWindow(mSurface.get());
1882 }
1883 break;
1884 }
1885
1886 case kWhatDequeueInputBuffer:
1887 {
1888 sp<AReplyToken> replyID;
1889 CHECK(msg->senderAwaitsResponse(&replyID));
1890
1891 if (mFlags & kFlagIsAsync) {
1892 ALOGE("dequeueOutputBuffer can't be used in async mode");
1893 PostReplyWithError(replyID, INVALID_OPERATION);
1894 break;
1895 }
1896
1897 if (mHaveInputSurface) {
1898 ALOGE("dequeueInputBuffer can't be used with input surface");
1899 PostReplyWithError(replyID, INVALID_OPERATION);
1900 break;
1901 }
1902
1903 if (handleDequeueInputBuffer(replyID, true /* new request */)) {
1904 break;
1905 }
1906
1907 int64_t timeoutUs;
1908 CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1909
1910 if (timeoutUs == 0ll) {
1911 PostReplyWithError(replyID, -EAGAIN);
1912 break;
1913 }
1914
1915 mFlags |= kFlagDequeueInputPending;
1916 mDequeueInputReplyID = replyID;
1917
1918 if (timeoutUs > 0ll) {
1919 sp<AMessage> timeoutMsg =
1920 new AMessage(kWhatDequeueInputTimedOut, this);
1921 timeoutMsg->setInt32(
1922 "generation", ++mDequeueInputTimeoutGeneration);
1923 timeoutMsg->post(timeoutUs);
1924 }
1925 break;
1926 }
1927
1928 case kWhatDequeueInputTimedOut:
1929 {
1930 int32_t generation;
1931 CHECK(msg->findInt32("generation", &generation));
1932
1933 if (generation != mDequeueInputTimeoutGeneration) {
1934 // Obsolete
1935 break;
1936 }
1937
1938 CHECK(mFlags & kFlagDequeueInputPending);
1939
1940 PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
1941
1942 mFlags &= ~kFlagDequeueInputPending;
1943 mDequeueInputReplyID = 0;
1944 break;
1945 }
1946
1947 case kWhatQueueInputBuffer:
1948 {
1949 sp<AReplyToken> replyID;
1950 CHECK(msg->senderAwaitsResponse(&replyID));
1951
1952 if (!isExecuting()) {
1953 PostReplyWithError(replyID, INVALID_OPERATION);
1954 break;
1955 } else if (mFlags & kFlagStickyError) {
1956 PostReplyWithError(replyID, getStickyError());
1957 break;
1958 }
1959
1960 status_t err = onQueueInputBuffer(msg);
1961
1962 PostReplyWithError(replyID, err);
1963 break;
1964 }
1965
1966 case kWhatDequeueOutputBuffer:
1967 {
1968 sp<AReplyToken> replyID;
1969 CHECK(msg->senderAwaitsResponse(&replyID));
1970
1971 if (mFlags & kFlagIsAsync) {
1972 ALOGE("dequeueOutputBuffer can't be used in async mode");
1973 PostReplyWithError(replyID, INVALID_OPERATION);
1974 break;
1975 }
1976
1977 if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
1978 break;
1979 }
1980
1981 int64_t timeoutUs;
1982 CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1983
1984 if (timeoutUs == 0ll) {
1985 PostReplyWithError(replyID, -EAGAIN);
1986 break;
1987 }
1988
1989 mFlags |= kFlagDequeueOutputPending;
1990 mDequeueOutputReplyID = replyID;
1991
1992 if (timeoutUs > 0ll) {
1993 sp<AMessage> timeoutMsg =
1994 new AMessage(kWhatDequeueOutputTimedOut, this);
1995 timeoutMsg->setInt32(
1996 "generation", ++mDequeueOutputTimeoutGeneration);
1997 timeoutMsg->post(timeoutUs);
1998 }
1999 break;
2000 }
2001
2002 case kWhatDequeueOutputTimedOut:
2003 {
2004 int32_t generation;
2005 CHECK(msg->findInt32("generation", &generation));
2006
2007 if (generation != mDequeueOutputTimeoutGeneration) {
2008 // Obsolete
2009 break;
2010 }
2011
2012 CHECK(mFlags & kFlagDequeueOutputPending);
2013
2014 PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
2015
2016 mFlags &= ~kFlagDequeueOutputPending;
2017 mDequeueOutputReplyID = 0;
2018 break;
2019 }
2020
2021 case kWhatReleaseOutputBuffer:
2022 {
2023 sp<AReplyToken> replyID;
2024 CHECK(msg->senderAwaitsResponse(&replyID));
2025
2026 if (!isExecuting()) {
2027 PostReplyWithError(replyID, INVALID_OPERATION);
2028 break;
2029 } else if (mFlags & kFlagStickyError) {
2030 PostReplyWithError(replyID, getStickyError());
2031 break;
2032 }
2033
2034 status_t err = onReleaseOutputBuffer(msg);
2035
2036 PostReplyWithError(replyID, err);
2037 break;
2038 }
2039
2040 case kWhatSignalEndOfInputStream:
2041 {
2042 sp<AReplyToken> replyID;
2043 CHECK(msg->senderAwaitsResponse(&replyID));
2044
2045 if (!isExecuting()) {
2046 PostReplyWithError(replyID, INVALID_OPERATION);
2047 break;
2048 } else if (mFlags & kFlagStickyError) {
2049 PostReplyWithError(replyID, getStickyError());
2050 break;
2051 }
2052
2053 mReplyID = replyID;
2054 mCodec->signalEndOfInputStream();
2055 break;
2056 }
2057
2058 case kWhatGetBuffers:
2059 {
2060 sp<AReplyToken> replyID;
2061 CHECK(msg->senderAwaitsResponse(&replyID));
2062 // Unfortunately widevine legacy source requires knowing all of the
2063 // codec input buffers, so we have to provide them even in async mode.
2064 int32_t widevine = 0;
2065 msg->findInt32("widevine", &widevine);
2066
2067 if (!isExecuting() || ((mFlags & kFlagIsAsync) && !widevine)) {
2068 PostReplyWithError(replyID, INVALID_OPERATION);
2069 break;
2070 } else if (mFlags & kFlagStickyError) {
2071 PostReplyWithError(replyID, getStickyError());
2072 break;
2073 }
2074
2075 int32_t portIndex;
2076 CHECK(msg->findInt32("portIndex", &portIndex));
2077
2078 Vector<sp<ABuffer> > *dstBuffers;
2079 CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
2080
2081 dstBuffers->clear();
2082 const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
2083
2084 for (size_t i = 0; i < srcBuffers.size(); ++i) {
2085 const BufferInfo &info = srcBuffers.itemAt(i);
2086
2087 dstBuffers->push_back(
2088 (portIndex == kPortIndexInput && mCrypto != NULL)
2089 ? info.mEncryptedData : info.mData);
2090 }
2091
2092 (new AMessage)->postReply(replyID);
2093 break;
2094 }
2095
2096 case kWhatFlush:
2097 {
2098 sp<AReplyToken> replyID;
2099 CHECK(msg->senderAwaitsResponse(&replyID));
2100
2101 if (!isExecuting()) {
2102 PostReplyWithError(replyID, INVALID_OPERATION);
2103 break;
2104 } else if (mFlags & kFlagStickyError) {
2105 PostReplyWithError(replyID, getStickyError());
2106 break;
2107 }
2108
2109 mReplyID = replyID;
2110 // TODO: skip flushing if already FLUSHED
2111 setState(FLUSHING);
2112
2113 mCodec->signalFlush();
2114 returnBuffersToCodec();
2115 break;
2116 }
2117
2118 case kWhatGetInputFormat:
2119 case kWhatGetOutputFormat:
2120 {
2121 sp<AMessage> format =
2122 (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
2123
2124 sp<AReplyToken> replyID;
2125 CHECK(msg->senderAwaitsResponse(&replyID));
2126
2127 if ((mState != CONFIGURED && mState != STARTING &&
2128 mState != STARTED && mState != FLUSHING &&
2129 mState != FLUSHED)
2130 || format == NULL) {
2131 PostReplyWithError(replyID, INVALID_OPERATION);
2132 break;
2133 } else if (mFlags & kFlagStickyError) {
2134 PostReplyWithError(replyID, getStickyError());
2135 break;
2136 }
2137
2138 sp<AMessage> response = new AMessage;
2139 response->setMessage("format", format);
2140 response->postReply(replyID);
2141 break;
2142 }
2143
2144 case kWhatRequestIDRFrame:
2145 {
2146 mCodec->signalRequestIDRFrame();
2147 break;
2148 }
2149
2150 case kWhatRequestActivityNotification:
2151 {
2152 CHECK(mActivityNotify == NULL);
2153 CHECK(msg->findMessage("notify", &mActivityNotify));
2154
2155 postActivityNotificationIfPossible();
2156 break;
2157 }
2158
2159 case kWhatGetName:
2160 {
2161 sp<AReplyToken> replyID;
2162 CHECK(msg->senderAwaitsResponse(&replyID));
2163
2164 if (mComponentName.empty()) {
2165 PostReplyWithError(replyID, INVALID_OPERATION);
2166 break;
2167 }
2168
2169 sp<AMessage> response = new AMessage;
2170 response->setString("name", mComponentName.c_str());
2171 response->postReply(replyID);
2172 break;
2173 }
2174
2175 case kWhatSetParameters:
2176 {
2177 sp<AReplyToken> replyID;
2178 CHECK(msg->senderAwaitsResponse(&replyID));
2179
2180 sp<AMessage> params;
2181 CHECK(msg->findMessage("params", ¶ms));
2182
2183 status_t err = onSetParameters(params);
2184
2185 PostReplyWithError(replyID, err);
2186 break;
2187 }
2188
2189 default:
2190 TRESPASS();
2191 }
2192 }
2193
extractCSD(const sp<AMessage> & format)2194 void MediaCodec::extractCSD(const sp<AMessage> &format) {
2195 mCSD.clear();
2196
2197 size_t i = 0;
2198 for (;;) {
2199 sp<ABuffer> csd;
2200 if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
2201 break;
2202 }
2203
2204 mCSD.push_back(csd);
2205 ++i;
2206 }
2207
2208 ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
2209 }
2210
queueCSDInputBuffer(size_t bufferIndex)2211 status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
2212 CHECK(!mCSD.empty());
2213
2214 const BufferInfo *info =
2215 &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
2216
2217 sp<ABuffer> csd = *mCSD.begin();
2218 mCSD.erase(mCSD.begin());
2219
2220 const sp<ABuffer> &codecInputData =
2221 (mCrypto != NULL) ? info->mEncryptedData : info->mData;
2222
2223 if (csd->size() > codecInputData->capacity()) {
2224 return -EINVAL;
2225 }
2226
2227 memcpy(codecInputData->data(), csd->data(), csd->size());
2228
2229 AString errorDetailMsg;
2230
2231 sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
2232 msg->setSize("index", bufferIndex);
2233 msg->setSize("offset", 0);
2234 msg->setSize("size", csd->size());
2235 msg->setInt64("timeUs", 0ll);
2236 msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
2237 msg->setPointer("errorDetailMsg", &errorDetailMsg);
2238
2239 return onQueueInputBuffer(msg);
2240 }
2241
setState(State newState)2242 void MediaCodec::setState(State newState) {
2243 if (newState == INITIALIZED || newState == UNINITIALIZED) {
2244 delete mSoftRenderer;
2245 mSoftRenderer = NULL;
2246
2247 mCrypto.clear();
2248 handleSetSurface(NULL);
2249
2250 mInputFormat.clear();
2251 mOutputFormat.clear();
2252 mFlags &= ~kFlagOutputFormatChanged;
2253 mFlags &= ~kFlagOutputBuffersChanged;
2254 mFlags &= ~kFlagStickyError;
2255 mFlags &= ~kFlagIsEncoder;
2256 mFlags &= ~kFlagGatherCodecSpecificData;
2257 mFlags &= ~kFlagIsAsync;
2258 mStickyError = OK;
2259
2260 mActivityNotify.clear();
2261 mCallback.clear();
2262 }
2263
2264 if (newState == UNINITIALIZED) {
2265 // return any straggling buffers, e.g. if we got here on an error
2266 returnBuffersToCodec();
2267
2268 // The component is gone, mediaserver's probably back up already
2269 // but should definitely be back up should we try to instantiate
2270 // another component.. and the cycle continues.
2271 mFlags &= ~kFlagSawMediaServerDie;
2272 }
2273
2274 mState = newState;
2275
2276 cancelPendingDequeueOperations();
2277
2278 updateBatteryStat();
2279 }
2280
returnBuffersToCodec()2281 void MediaCodec::returnBuffersToCodec() {
2282 returnBuffersToCodecOnPort(kPortIndexInput);
2283 returnBuffersToCodecOnPort(kPortIndexOutput);
2284 }
2285
returnBuffersToCodecOnPort(int32_t portIndex)2286 void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
2287 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2288 Mutex::Autolock al(mBufferLock);
2289
2290 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2291
2292 for (size_t i = 0; i < buffers->size(); ++i) {
2293 BufferInfo *info = &buffers->editItemAt(i);
2294
2295 if (info->mNotify != NULL) {
2296 sp<AMessage> msg = info->mNotify;
2297 info->mNotify = NULL;
2298 info->mOwnedByClient = false;
2299
2300 if (portIndex == kPortIndexInput) {
2301 /* no error, just returning buffers */
2302 msg->setInt32("err", OK);
2303 }
2304 msg->post();
2305 }
2306 }
2307
2308 mAvailPortBuffers[portIndex].clear();
2309 }
2310
updateBuffers(int32_t portIndex,const sp<AMessage> & msg)2311 size_t MediaCodec::updateBuffers(
2312 int32_t portIndex, const sp<AMessage> &msg) {
2313 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2314
2315 uint32_t bufferID;
2316 CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
2317
2318 Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2319
2320 for (size_t i = 0; i < buffers->size(); ++i) {
2321 BufferInfo *info = &buffers->editItemAt(i);
2322
2323 if (info->mBufferID == bufferID) {
2324 CHECK(info->mNotify == NULL);
2325 CHECK(msg->findMessage("reply", &info->mNotify));
2326
2327 info->mFormat =
2328 (portIndex == kPortIndexInput) ? mInputFormat : mOutputFormat;
2329 mAvailPortBuffers[portIndex].push_back(i);
2330
2331 return i;
2332 }
2333 }
2334
2335 TRESPASS();
2336
2337 return 0;
2338 }
2339
onQueueInputBuffer(const sp<AMessage> & msg)2340 status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
2341 size_t index;
2342 size_t offset;
2343 size_t size;
2344 int64_t timeUs;
2345 uint32_t flags;
2346 CHECK(msg->findSize("index", &index));
2347 CHECK(msg->findSize("offset", &offset));
2348 CHECK(msg->findInt64("timeUs", &timeUs));
2349 CHECK(msg->findInt32("flags", (int32_t *)&flags));
2350
2351 const CryptoPlugin::SubSample *subSamples;
2352 size_t numSubSamples;
2353 const uint8_t *key;
2354 const uint8_t *iv;
2355 CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
2356
2357 // We allow the simpler queueInputBuffer API to be used even in
2358 // secure mode, by fabricating a single unencrypted subSample.
2359 CryptoPlugin::SubSample ss;
2360
2361 if (msg->findSize("size", &size)) {
2362 if (mCrypto != NULL) {
2363 ss.mNumBytesOfClearData = size;
2364 ss.mNumBytesOfEncryptedData = 0;
2365
2366 subSamples = &ss;
2367 numSubSamples = 1;
2368 key = NULL;
2369 iv = NULL;
2370 }
2371 } else {
2372 if (mCrypto == NULL) {
2373 return -EINVAL;
2374 }
2375
2376 CHECK(msg->findPointer("subSamples", (void **)&subSamples));
2377 CHECK(msg->findSize("numSubSamples", &numSubSamples));
2378 CHECK(msg->findPointer("key", (void **)&key));
2379 CHECK(msg->findPointer("iv", (void **)&iv));
2380
2381 int32_t tmp;
2382 CHECK(msg->findInt32("mode", &tmp));
2383
2384 mode = (CryptoPlugin::Mode)tmp;
2385
2386 size = 0;
2387 for (size_t i = 0; i < numSubSamples; ++i) {
2388 size += subSamples[i].mNumBytesOfClearData;
2389 size += subSamples[i].mNumBytesOfEncryptedData;
2390 }
2391 }
2392
2393 if (index >= mPortBuffers[kPortIndexInput].size()) {
2394 return -ERANGE;
2395 }
2396
2397 BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
2398
2399 if (info->mNotify == NULL || !info->mOwnedByClient) {
2400 return -EACCES;
2401 }
2402
2403 if (offset + size > info->mData->capacity()) {
2404 return -EINVAL;
2405 }
2406
2407 sp<AMessage> reply = info->mNotify;
2408 info->mData->setRange(offset, size);
2409 info->mData->meta()->setInt64("timeUs", timeUs);
2410
2411 if (flags & BUFFER_FLAG_EOS) {
2412 info->mData->meta()->setInt32("eos", true);
2413 }
2414
2415 if (flags & BUFFER_FLAG_CODECCONFIG) {
2416 info->mData->meta()->setInt32("csd", true);
2417 }
2418
2419 if (mCrypto != NULL) {
2420 if (size > info->mEncryptedData->capacity()) {
2421 return -ERANGE;
2422 }
2423
2424 AString *errorDetailMsg;
2425 CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
2426
2427 ssize_t result = mCrypto->decrypt(
2428 (mFlags & kFlagIsSecure) != 0,
2429 key,
2430 iv,
2431 mode,
2432 info->mSharedEncryptedBuffer,
2433 offset,
2434 subSamples,
2435 numSubSamples,
2436 info->mData->base(),
2437 errorDetailMsg);
2438
2439 if (result < 0) {
2440 return result;
2441 }
2442
2443 info->mData->setRange(0, result);
2444 }
2445
2446 // synchronization boundary for getBufferAndFormat
2447 {
2448 Mutex::Autolock al(mBufferLock);
2449 info->mOwnedByClient = false;
2450 }
2451 reply->setBuffer("buffer", info->mData);
2452 reply->post();
2453
2454 info->mNotify = NULL;
2455
2456 return OK;
2457 }
2458
2459 //static
CreateFramesRenderedMessage(std::list<FrameRenderTracker::Info> done,sp<AMessage> & msg)2460 size_t MediaCodec::CreateFramesRenderedMessage(
2461 std::list<FrameRenderTracker::Info> done, sp<AMessage> &msg) {
2462 size_t index = 0;
2463
2464 for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
2465 it != done.cend(); ++it) {
2466 if (it->getRenderTimeNs() < 0) {
2467 continue; // dropped frame from tracking
2468 }
2469 msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
2470 msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
2471 ++index;
2472 }
2473 return index;
2474 }
2475
onReleaseOutputBuffer(const sp<AMessage> & msg)2476 status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
2477 size_t index;
2478 CHECK(msg->findSize("index", &index));
2479
2480 int32_t render;
2481 if (!msg->findInt32("render", &render)) {
2482 render = 0;
2483 }
2484
2485 if (!isExecuting()) {
2486 return -EINVAL;
2487 }
2488
2489 if (index >= mPortBuffers[kPortIndexOutput].size()) {
2490 return -ERANGE;
2491 }
2492
2493 BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
2494
2495 if (info->mNotify == NULL || !info->mOwnedByClient) {
2496 return -EACCES;
2497 }
2498
2499 // synchronization boundary for getBufferAndFormat
2500 {
2501 Mutex::Autolock al(mBufferLock);
2502 info->mOwnedByClient = false;
2503 }
2504
2505 if (render && info->mData != NULL && info->mData->size() != 0) {
2506 info->mNotify->setInt32("render", true);
2507
2508 int64_t mediaTimeUs = -1;
2509 info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
2510
2511 int64_t renderTimeNs = 0;
2512 if (!msg->findInt64("timestampNs", &renderTimeNs)) {
2513 // use media timestamp if client did not request a specific render timestamp
2514 ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
2515 renderTimeNs = mediaTimeUs * 1000;
2516 }
2517 info->mNotify->setInt64("timestampNs", renderTimeNs);
2518
2519 if (mSoftRenderer != NULL) {
2520 std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render(
2521 info->mData->data(), info->mData->size(),
2522 mediaTimeUs, renderTimeNs, NULL, info->mFormat);
2523
2524 // if we are running, notify rendered frames
2525 if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) {
2526 sp<AMessage> notify = mOnFrameRenderedNotification->dup();
2527 sp<AMessage> data = new AMessage;
2528 if (CreateFramesRenderedMessage(doneFrames, data)) {
2529 notify->setMessage("data", data);
2530 notify->post();
2531 }
2532 }
2533 }
2534 }
2535
2536 info->mNotify->post();
2537 info->mNotify = NULL;
2538
2539 return OK;
2540 }
2541
dequeuePortBuffer(int32_t portIndex)2542 ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
2543 CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2544
2545 List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
2546
2547 if (availBuffers->empty()) {
2548 return -EAGAIN;
2549 }
2550
2551 size_t index = *availBuffers->begin();
2552 availBuffers->erase(availBuffers->begin());
2553
2554 BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
2555 CHECK(!info->mOwnedByClient);
2556 {
2557 Mutex::Autolock al(mBufferLock);
2558 info->mOwnedByClient = true;
2559
2560 // set image-data
2561 if (info->mFormat != NULL) {
2562 sp<ABuffer> imageData;
2563 if (info->mFormat->findBuffer("image-data", &imageData)) {
2564 info->mData->meta()->setBuffer("image-data", imageData);
2565 }
2566 int32_t left, top, right, bottom;
2567 if (info->mFormat->findRect("crop", &left, &top, &right, &bottom)) {
2568 info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
2569 }
2570 }
2571 }
2572
2573 return index;
2574 }
2575
connectToSurface(const sp<Surface> & surface)2576 status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
2577 status_t err = OK;
2578 if (surface != NULL) {
2579 err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2580 if (err == BAD_VALUE) {
2581 ALOGI("native window already connected. Assuming no change of surface");
2582 return err;
2583 } else if (err == OK) {
2584 // Require a fresh set of buffers after each connect by using a unique generation
2585 // number. Rely on the fact that max supported process id by Linux is 2^22.
2586 // PID is never 0 so we don't have to worry that we use the default generation of 0.
2587 // TODO: come up with a unique scheme if other producers also set the generation number.
2588 static uint32_t mSurfaceGeneration = 0;
2589 uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
2590 surface->setGenerationNumber(generation);
2591 ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
2592
2593 // HACK: clear any free buffers. Remove when connect will automatically do this.
2594 // This is needed as the consumer may be holding onto stale frames that it can reattach
2595 // to this surface after disconnect/connect, and those free frames would inherit the new
2596 // generation number. Disconnecting after setting a unique generation prevents this.
2597 native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2598 err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2599 }
2600
2601 if (err != OK) {
2602 ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
2603 }
2604 }
2605 return err;
2606 }
2607
disconnectFromSurface()2608 status_t MediaCodec::disconnectFromSurface() {
2609 status_t err = OK;
2610 if (mSurface != NULL) {
2611 // Resetting generation is not technically needed, but there is no need to keep it either
2612 mSurface->setGenerationNumber(0);
2613 err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
2614 if (err != OK) {
2615 ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
2616 }
2617 // assume disconnected even on error
2618 mSurface.clear();
2619 }
2620 return err;
2621 }
2622
handleSetSurface(const sp<Surface> & surface)2623 status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
2624 status_t err = OK;
2625 if (mSurface != NULL) {
2626 (void)disconnectFromSurface();
2627 }
2628 if (surface != NULL) {
2629 err = connectToSurface(surface);
2630 if (err == OK) {
2631 mSurface = surface;
2632 }
2633 }
2634 return err;
2635 }
2636
onInputBufferAvailable()2637 void MediaCodec::onInputBufferAvailable() {
2638 int32_t index;
2639 while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
2640 sp<AMessage> msg = mCallback->dup();
2641 msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
2642 msg->setInt32("index", index);
2643 msg->post();
2644 }
2645 }
2646
onOutputBufferAvailable()2647 void MediaCodec::onOutputBufferAvailable() {
2648 int32_t index;
2649 while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
2650 const sp<ABuffer> &buffer =
2651 mPortBuffers[kPortIndexOutput].itemAt(index).mData;
2652 sp<AMessage> msg = mCallback->dup();
2653 msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
2654 msg->setInt32("index", index);
2655 msg->setSize("offset", buffer->offset());
2656 msg->setSize("size", buffer->size());
2657
2658 int64_t timeUs;
2659 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2660
2661 msg->setInt64("timeUs", timeUs);
2662
2663 int32_t omxFlags;
2664 CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
2665
2666 uint32_t flags = 0;
2667 if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
2668 flags |= BUFFER_FLAG_SYNCFRAME;
2669 }
2670 if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
2671 flags |= BUFFER_FLAG_CODECCONFIG;
2672 }
2673 if (omxFlags & OMX_BUFFERFLAG_EOS) {
2674 flags |= BUFFER_FLAG_EOS;
2675 }
2676
2677 msg->setInt32("flags", flags);
2678
2679 msg->post();
2680 }
2681 }
2682
onError(status_t err,int32_t actionCode,const char * detail)2683 void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
2684 if (mCallback != NULL) {
2685 sp<AMessage> msg = mCallback->dup();
2686 msg->setInt32("callbackID", CB_ERROR);
2687 msg->setInt32("err", err);
2688 msg->setInt32("actionCode", actionCode);
2689
2690 if (detail != NULL) {
2691 msg->setString("detail", detail);
2692 }
2693
2694 msg->post();
2695 }
2696 }
2697
onOutputFormatChanged()2698 void MediaCodec::onOutputFormatChanged() {
2699 if (mCallback != NULL) {
2700 sp<AMessage> msg = mCallback->dup();
2701 msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
2702 msg->setMessage("format", mOutputFormat);
2703 msg->post();
2704 }
2705 }
2706
2707
postActivityNotificationIfPossible()2708 void MediaCodec::postActivityNotificationIfPossible() {
2709 if (mActivityNotify == NULL) {
2710 return;
2711 }
2712
2713 bool isErrorOrOutputChanged =
2714 (mFlags & (kFlagStickyError
2715 | kFlagOutputBuffersChanged
2716 | kFlagOutputFormatChanged));
2717
2718 if (isErrorOrOutputChanged
2719 || !mAvailPortBuffers[kPortIndexInput].empty()
2720 || !mAvailPortBuffers[kPortIndexOutput].empty()) {
2721 mActivityNotify->setInt32("input-buffers",
2722 mAvailPortBuffers[kPortIndexInput].size());
2723
2724 if (isErrorOrOutputChanged) {
2725 // we want consumer to dequeue as many times as it can
2726 mActivityNotify->setInt32("output-buffers", INT32_MAX);
2727 } else {
2728 mActivityNotify->setInt32("output-buffers",
2729 mAvailPortBuffers[kPortIndexOutput].size());
2730 }
2731 mActivityNotify->post();
2732 mActivityNotify.clear();
2733 }
2734 }
2735
setParameters(const sp<AMessage> & params)2736 status_t MediaCodec::setParameters(const sp<AMessage> ¶ms) {
2737 sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
2738 msg->setMessage("params", params);
2739
2740 sp<AMessage> response;
2741 return PostAndAwaitResponse(msg, &response);
2742 }
2743
onSetParameters(const sp<AMessage> & params)2744 status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) {
2745 mCodec->signalSetParameters(params);
2746
2747 return OK;
2748 }
2749
amendOutputFormatWithCodecSpecificData(const sp<ABuffer> & buffer)2750 status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
2751 const sp<ABuffer> &buffer) {
2752 AString mime;
2753 CHECK(mOutputFormat->findString("mime", &mime));
2754
2755 if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
2756 // Codec specific data should be SPS and PPS in a single buffer,
2757 // each prefixed by a startcode (0x00 0x00 0x00 0x01).
2758 // We separate the two and put them into the output format
2759 // under the keys "csd-0" and "csd-1".
2760
2761 unsigned csdIndex = 0;
2762
2763 const uint8_t *data = buffer->data();
2764 size_t size = buffer->size();
2765
2766 const uint8_t *nalStart;
2767 size_t nalSize;
2768 while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
2769 sp<ABuffer> csd = new ABuffer(nalSize + 4);
2770 memcpy(csd->data(), "\x00\x00\x00\x01", 4);
2771 memcpy(csd->data() + 4, nalStart, nalSize);
2772
2773 mOutputFormat->setBuffer(
2774 AStringPrintf("csd-%u", csdIndex).c_str(), csd);
2775
2776 ++csdIndex;
2777 }
2778
2779 if (csdIndex != 2) {
2780 return ERROR_MALFORMED;
2781 }
2782 } else {
2783 // For everything else we just stash the codec specific data into
2784 // the output format as a single piece of csd under "csd-0".
2785 mOutputFormat->setBuffer("csd-0", buffer);
2786 }
2787
2788 return OK;
2789 }
2790
updateBatteryStat()2791 void MediaCodec::updateBatteryStat() {
2792 if (mState == CONFIGURED && !mBatteryStatNotified) {
2793 BatteryNotifier& notifier(BatteryNotifier::getInstance());
2794
2795 if (mIsVideo) {
2796 notifier.noteStartVideo();
2797 } else {
2798 notifier.noteStartAudio();
2799 }
2800
2801 mBatteryStatNotified = true;
2802 } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
2803 BatteryNotifier& notifier(BatteryNotifier::getInstance());
2804
2805 if (mIsVideo) {
2806 notifier.noteStopVideo();
2807 } else {
2808 notifier.noteStopAudio();
2809 }
2810
2811 mBatteryStatNotified = false;
2812 }
2813 }
2814
2815 } // namespace android
2816