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