• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &notify) {
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> &notify) {
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", &notify)) {
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", &params));
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> &params) {
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> &params) {
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