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             const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
2164 
2165             for (size_t i = 0; i < srcBuffers.size(); ++i) {
2166                 const BufferInfo &info = srcBuffers.itemAt(i);
2167 
2168                 dstBuffers->push_back(
2169                         (portIndex == kPortIndexInput && mCrypto != NULL)
2170                                 ? info.mEncryptedData : info.mData);
2171             }
2172 
2173             (new AMessage)->postReply(replyID);
2174             break;
2175         }
2176 
2177         case kWhatFlush:
2178         {
2179             sp<AReplyToken> replyID;
2180             CHECK(msg->senderAwaitsResponse(&replyID));
2181 
2182             if (!isExecuting()) {
2183                 PostReplyWithError(replyID, INVALID_OPERATION);
2184                 break;
2185             } else if (mFlags & kFlagStickyError) {
2186                 PostReplyWithError(replyID, getStickyError());
2187                 break;
2188             }
2189 
2190             mReplyID = replyID;
2191             // TODO: skip flushing if already FLUSHED
2192             setState(FLUSHING);
2193 
2194             mCodec->signalFlush();
2195             returnBuffersToCodec();
2196             break;
2197         }
2198 
2199         case kWhatGetInputFormat:
2200         case kWhatGetOutputFormat:
2201         {
2202             sp<AMessage> format =
2203                 (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
2204 
2205             sp<AReplyToken> replyID;
2206             CHECK(msg->senderAwaitsResponse(&replyID));
2207 
2208             if ((mState != CONFIGURED && mState != STARTING &&
2209                  mState != STARTED && mState != FLUSHING &&
2210                  mState != FLUSHED)
2211                     || format == NULL) {
2212                 PostReplyWithError(replyID, INVALID_OPERATION);
2213                 break;
2214             } else if (mFlags & kFlagStickyError) {
2215                 PostReplyWithError(replyID, getStickyError());
2216                 break;
2217             }
2218 
2219             sp<AMessage> response = new AMessage;
2220             response->setMessage("format", format);
2221             response->postReply(replyID);
2222             break;
2223         }
2224 
2225         case kWhatRequestIDRFrame:
2226         {
2227             mCodec->signalRequestIDRFrame();
2228             break;
2229         }
2230 
2231         case kWhatRequestActivityNotification:
2232         {
2233             CHECK(mActivityNotify == NULL);
2234             CHECK(msg->findMessage("notify", &mActivityNotify));
2235 
2236             postActivityNotificationIfPossible();
2237             break;
2238         }
2239 
2240         case kWhatGetName:
2241         {
2242             sp<AReplyToken> replyID;
2243             CHECK(msg->senderAwaitsResponse(&replyID));
2244 
2245             if (mComponentName.empty()) {
2246                 PostReplyWithError(replyID, INVALID_OPERATION);
2247                 break;
2248             }
2249 
2250             sp<AMessage> response = new AMessage;
2251             response->setString("name", mComponentName.c_str());
2252             response->postReply(replyID);
2253             break;
2254         }
2255 
2256         case kWhatSetParameters:
2257         {
2258             sp<AReplyToken> replyID;
2259             CHECK(msg->senderAwaitsResponse(&replyID));
2260 
2261             sp<AMessage> params;
2262             CHECK(msg->findMessage("params", &params));
2263 
2264             status_t err = onSetParameters(params);
2265 
2266             PostReplyWithError(replyID, err);
2267             break;
2268         }
2269 
2270         default:
2271             TRESPASS();
2272     }
2273 }
2274 
extractCSD(const sp<AMessage> & format)2275 void MediaCodec::extractCSD(const sp<AMessage> &format) {
2276     mCSD.clear();
2277 
2278     size_t i = 0;
2279     for (;;) {
2280         sp<ABuffer> csd;
2281         if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
2282             break;
2283         }
2284         if (csd->size() == 0) {
2285             ALOGW("csd-%zu size is 0", i);
2286         }
2287 
2288         mCSD.push_back(csd);
2289         ++i;
2290     }
2291 
2292     ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
2293 }
2294 
queueCSDInputBuffer(size_t bufferIndex)2295 status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
2296     CHECK(!mCSD.empty());
2297 
2298     const BufferInfo *info =
2299         &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
2300 
2301     sp<ABuffer> csd = *mCSD.begin();
2302     mCSD.erase(mCSD.begin());
2303 
2304     const sp<ABuffer> &codecInputData =
2305         (mCrypto != NULL) ? info->mEncryptedData : info->mData;
2306 
2307     if (csd->size() > codecInputData->capacity()) {
2308         return -EINVAL;
2309     }
2310 
2311     memcpy(codecInputData->data(), csd->data(), csd->size());
2312 
2313     AString errorDetailMsg;
2314 
2315     sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
2316     msg->setSize("index", bufferIndex);
2317     msg->setSize("offset", 0);
2318     msg->setSize("size", csd->size());
2319     msg->setInt64("timeUs", 0ll);
2320     msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
2321     msg->setPointer("errorDetailMsg", &errorDetailMsg);
2322 
2323     return onQueueInputBuffer(msg);
2324 }
2325 
setState(State newState)2326 void MediaCodec::setState(State newState) {
2327     if (newState == INITIALIZED || newState == UNINITIALIZED) {
2328         delete mSoftRenderer;
2329         mSoftRenderer = NULL;
2330 
2331         mCrypto.clear();
2332         handleSetSurface(NULL);
2333 
2334         mInputFormat.clear();
2335         mOutputFormat.clear();
2336         mFlags &= ~kFlagOutputFormatChanged;
2337         mFlags &= ~kFlagOutputBuffersChanged;
2338         mFlags &= ~kFlagStickyError;
2339         mFlags &= ~kFlagIsEncoder;
2340         mFlags &= ~kFlagGatherCodecSpecificData;
2341         mFlags &= ~kFlagIsAsync;
2342         mStickyError = OK;
2343 
2344         mActivityNotify.clear();
2345         mCallback.clear();
2346     }
2347 
2348     if (newState == UNINITIALIZED) {
2349         // return any straggling buffers, e.g. if we got here on an error
2350         returnBuffersToCodec();
2351 
2352         // The component is gone, mediaserver's probably back up already
2353         // but should definitely be back up should we try to instantiate
2354         // another component.. and the cycle continues.
2355         mFlags &= ~kFlagSawMediaServerDie;
2356     }
2357 
2358     mState = newState;
2359 
2360     cancelPendingDequeueOperations();
2361 
2362     updateBatteryStat();
2363 }
2364 
returnBuffersToCodec(bool isReclaim)2365 void MediaCodec::returnBuffersToCodec(bool isReclaim) {
2366     returnBuffersToCodecOnPort(kPortIndexInput, isReclaim);
2367     returnBuffersToCodecOnPort(kPortIndexOutput, isReclaim);
2368 }
2369 
returnBuffersToCodecOnPort(int32_t portIndex,bool isReclaim)2370 void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) {
2371     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2372     Mutex::Autolock al(mBufferLock);
2373 
2374     Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2375 
2376     for (size_t i = 0; i < buffers->size(); ++i) {
2377         BufferInfo *info = &buffers->editItemAt(i);
2378 
2379         if (info->mNotify != NULL) {
2380             sp<AMessage> msg = info->mNotify;
2381             info->mNotify = NULL;
2382             if (isReclaim && info->mOwnedByClient) {
2383                 ALOGD("port %d buffer %zu still owned by client when codec is reclaimed",
2384                         portIndex, i);
2385             } else {
2386                 info->mMemRef = NULL;
2387                 info->mOwnedByClient = false;
2388             }
2389 
2390             if (portIndex == kPortIndexInput) {
2391                 /* no error, just returning buffers */
2392                 msg->setInt32("err", OK);
2393             }
2394             msg->post();
2395         }
2396     }
2397 
2398     mAvailPortBuffers[portIndex].clear();
2399 }
2400 
updateBuffers(int32_t portIndex,const sp<AMessage> & msg)2401 size_t MediaCodec::updateBuffers(
2402         int32_t portIndex, const sp<AMessage> &msg) {
2403     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2404 
2405     uint32_t bufferID;
2406     CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
2407 
2408     Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2409 
2410     for (size_t i = 0; i < buffers->size(); ++i) {
2411         BufferInfo *info = &buffers->editItemAt(i);
2412 
2413         if (info->mBufferID == bufferID) {
2414             CHECK(info->mNotify == NULL);
2415             CHECK(msg->findMessage("reply", &info->mNotify));
2416 
2417             info->mFormat =
2418                 (portIndex == kPortIndexInput) ? mInputFormat : mOutputFormat;
2419             mAvailPortBuffers[portIndex].push_back(i);
2420 
2421             return i;
2422         }
2423     }
2424 
2425     TRESPASS();
2426 
2427     return 0;
2428 }
2429 
onQueueInputBuffer(const sp<AMessage> & msg)2430 status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
2431     size_t index;
2432     size_t offset;
2433     size_t size;
2434     int64_t timeUs;
2435     uint32_t flags;
2436     CHECK(msg->findSize("index", &index));
2437     CHECK(msg->findSize("offset", &offset));
2438     CHECK(msg->findInt64("timeUs", &timeUs));
2439     CHECK(msg->findInt32("flags", (int32_t *)&flags));
2440 
2441     const CryptoPlugin::SubSample *subSamples;
2442     size_t numSubSamples;
2443     const uint8_t *key;
2444     const uint8_t *iv;
2445     CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
2446 
2447     // We allow the simpler queueInputBuffer API to be used even in
2448     // secure mode, by fabricating a single unencrypted subSample.
2449     CryptoPlugin::SubSample ss;
2450     CryptoPlugin::Pattern pattern;
2451 
2452     if (msg->findSize("size", &size)) {
2453         if (mCrypto != NULL) {
2454             ss.mNumBytesOfClearData = size;
2455             ss.mNumBytesOfEncryptedData = 0;
2456 
2457             subSamples = &ss;
2458             numSubSamples = 1;
2459             key = NULL;
2460             iv = NULL;
2461             pattern.mEncryptBlocks = 0;
2462             pattern.mSkipBlocks = 0;
2463         }
2464     } else {
2465         if (mCrypto == NULL) {
2466             return -EINVAL;
2467         }
2468 
2469         CHECK(msg->findPointer("subSamples", (void **)&subSamples));
2470         CHECK(msg->findSize("numSubSamples", &numSubSamples));
2471         CHECK(msg->findPointer("key", (void **)&key));
2472         CHECK(msg->findPointer("iv", (void **)&iv));
2473         CHECK(msg->findInt32("encryptBlocks", (int32_t *)&pattern.mEncryptBlocks));
2474         CHECK(msg->findInt32("skipBlocks", (int32_t *)&pattern.mSkipBlocks));
2475 
2476         int32_t tmp;
2477         CHECK(msg->findInt32("mode", &tmp));
2478 
2479         mode = (CryptoPlugin::Mode)tmp;
2480 
2481         size = 0;
2482         for (size_t i = 0; i < numSubSamples; ++i) {
2483             size += subSamples[i].mNumBytesOfClearData;
2484             size += subSamples[i].mNumBytesOfEncryptedData;
2485         }
2486     }
2487 
2488     if (index >= mPortBuffers[kPortIndexInput].size()) {
2489         return -ERANGE;
2490     }
2491 
2492     BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
2493 
2494     if (info->mNotify == NULL || !info->mOwnedByClient) {
2495         return -EACCES;
2496     }
2497 
2498     if (offset + size > info->mData->capacity()) {
2499         return -EINVAL;
2500     }
2501 
2502     sp<AMessage> reply = info->mNotify;
2503     info->mData->setRange(offset, size);
2504     info->mData->meta()->setInt64("timeUs", timeUs);
2505 
2506     if (flags & BUFFER_FLAG_EOS) {
2507         info->mData->meta()->setInt32("eos", true);
2508     }
2509 
2510     if (flags & BUFFER_FLAG_CODECCONFIG) {
2511         info->mData->meta()->setInt32("csd", true);
2512     }
2513 
2514     if (mCrypto != NULL) {
2515         if (size > info->mEncryptedData->capacity()) {
2516             return -ERANGE;
2517         }
2518 
2519         AString *errorDetailMsg;
2520         CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
2521 
2522         void *dst_pointer = info->mData->base();
2523         ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
2524 
2525         if (info->mNativeHandle != NULL) {
2526             dst_pointer = (void *)info->mNativeHandle->handle();
2527             dst_type = ICrypto::kDestinationTypeNativeHandle;
2528         } else if ((mFlags & kFlagIsSecure) == 0) {
2529             dst_type = ICrypto::kDestinationTypeVmPointer;
2530         }
2531 
2532         ssize_t result = mCrypto->decrypt(
2533                 dst_type,
2534                 key,
2535                 iv,
2536                 mode,
2537                 pattern,
2538                 info->mSharedEncryptedBuffer,
2539                 offset,
2540                 subSamples,
2541                 numSubSamples,
2542                 dst_pointer,
2543                 errorDetailMsg);
2544 
2545         if (result < 0) {
2546             return result;
2547         }
2548 
2549         info->mData->setRange(0, result);
2550     }
2551 
2552     // synchronization boundary for getBufferAndFormat
2553     {
2554         Mutex::Autolock al(mBufferLock);
2555         info->mOwnedByClient = false;
2556     }
2557     reply->setBuffer("buffer", info->mData);
2558     reply->post();
2559 
2560     info->mNotify = NULL;
2561 
2562     return OK;
2563 }
2564 
2565 //static
CreateFramesRenderedMessage(std::list<FrameRenderTracker::Info> done,sp<AMessage> & msg)2566 size_t MediaCodec::CreateFramesRenderedMessage(
2567         std::list<FrameRenderTracker::Info> done, sp<AMessage> &msg) {
2568     size_t index = 0;
2569 
2570     for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
2571             it != done.cend(); ++it) {
2572         if (it->getRenderTimeNs() < 0) {
2573             continue; // dropped frame from tracking
2574         }
2575         msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
2576         msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
2577         ++index;
2578     }
2579     return index;
2580 }
2581 
onReleaseOutputBuffer(const sp<AMessage> & msg)2582 status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
2583     size_t index;
2584     CHECK(msg->findSize("index", &index));
2585 
2586     int32_t render;
2587     if (!msg->findInt32("render", &render)) {
2588         render = 0;
2589     }
2590 
2591     if (!isExecuting()) {
2592         return -EINVAL;
2593     }
2594 
2595     if (index >= mPortBuffers[kPortIndexOutput].size()) {
2596         return -ERANGE;
2597     }
2598 
2599     BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
2600 
2601     if (info->mNotify == NULL || !info->mOwnedByClient) {
2602         return -EACCES;
2603     }
2604 
2605     // synchronization boundary for getBufferAndFormat
2606     {
2607         Mutex::Autolock al(mBufferLock);
2608         info->mOwnedByClient = false;
2609     }
2610 
2611     if (render && info->mData != NULL && info->mData->size() != 0) {
2612         info->mNotify->setInt32("render", true);
2613 
2614         int64_t mediaTimeUs = -1;
2615         info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
2616 
2617         int64_t renderTimeNs = 0;
2618         if (!msg->findInt64("timestampNs", &renderTimeNs)) {
2619             // use media timestamp if client did not request a specific render timestamp
2620             ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
2621             renderTimeNs = mediaTimeUs * 1000;
2622         }
2623         info->mNotify->setInt64("timestampNs", renderTimeNs);
2624 
2625         if (mSoftRenderer != NULL) {
2626             std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render(
2627                     info->mData->data(), info->mData->size(),
2628                     mediaTimeUs, renderTimeNs, NULL, info->mFormat);
2629 
2630             // if we are running, notify rendered frames
2631             if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) {
2632                 sp<AMessage> notify = mOnFrameRenderedNotification->dup();
2633                 sp<AMessage> data = new AMessage;
2634                 if (CreateFramesRenderedMessage(doneFrames, data)) {
2635                     notify->setMessage("data", data);
2636                     notify->post();
2637                 }
2638             }
2639         }
2640     }
2641 
2642     info->mNotify->post();
2643     info->mNotify = NULL;
2644 
2645     return OK;
2646 }
2647 
dequeuePortBuffer(int32_t portIndex)2648 ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
2649     CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2650 
2651     List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
2652 
2653     if (availBuffers->empty()) {
2654         return -EAGAIN;
2655     }
2656 
2657     size_t index = *availBuffers->begin();
2658     availBuffers->erase(availBuffers->begin());
2659 
2660     BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
2661     CHECK(!info->mOwnedByClient);
2662     {
2663         Mutex::Autolock al(mBufferLock);
2664         info->mOwnedByClient = true;
2665 
2666         // set image-data
2667         if (info->mFormat != NULL) {
2668             sp<ABuffer> imageData;
2669             if (info->mFormat->findBuffer("image-data", &imageData)) {
2670                 info->mData->meta()->setBuffer("image-data", imageData);
2671             }
2672             int32_t left, top, right, bottom;
2673             if (info->mFormat->findRect("crop", &left, &top, &right, &bottom)) {
2674                 info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
2675             }
2676         }
2677     }
2678 
2679     return index;
2680 }
2681 
connectToSurface(const sp<Surface> & surface)2682 status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
2683     status_t err = OK;
2684     if (surface != NULL) {
2685         uint64_t oldId, newId;
2686         if (mSurface != NULL
2687                 && surface->getUniqueId(&newId) == NO_ERROR
2688                 && mSurface->getUniqueId(&oldId) == NO_ERROR
2689                 && newId == oldId) {
2690             ALOGI("[%s] connecting to the same surface. Nothing to do.", mComponentName.c_str());
2691             return ALREADY_EXISTS;
2692         }
2693 
2694         err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2695         if (err == OK) {
2696             // Require a fresh set of buffers after each connect by using a unique generation
2697             // number. Rely on the fact that max supported process id by Linux is 2^22.
2698             // PID is never 0 so we don't have to worry that we use the default generation of 0.
2699             // TODO: come up with a unique scheme if other producers also set the generation number.
2700             static uint32_t mSurfaceGeneration = 0;
2701             uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
2702             surface->setGenerationNumber(generation);
2703             ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
2704 
2705             // HACK: clear any free buffers. Remove when connect will automatically do this.
2706             // This is needed as the consumer may be holding onto stale frames that it can reattach
2707             // to this surface after disconnect/connect, and those free frames would inherit the new
2708             // generation number. Disconnecting after setting a unique generation prevents this.
2709             native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2710             err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2711         }
2712 
2713         if (err != OK) {
2714             ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
2715         }
2716     }
2717     // do not return ALREADY_EXISTS unless surfaces are the same
2718     return err == ALREADY_EXISTS ? BAD_VALUE : err;
2719 }
2720 
disconnectFromSurface()2721 status_t MediaCodec::disconnectFromSurface() {
2722     status_t err = OK;
2723     if (mSurface != NULL) {
2724         // Resetting generation is not technically needed, but there is no need to keep it either
2725         mSurface->setGenerationNumber(0);
2726         err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
2727         if (err != OK) {
2728             ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
2729         }
2730         // assume disconnected even on error
2731         mSurface.clear();
2732     }
2733     return err;
2734 }
2735 
handleSetSurface(const sp<Surface> & surface)2736 status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
2737     status_t err = OK;
2738     if (mSurface != NULL) {
2739         (void)disconnectFromSurface();
2740     }
2741     if (surface != NULL) {
2742         err = connectToSurface(surface);
2743         if (err == OK) {
2744             mSurface = surface;
2745         }
2746     }
2747     return err;
2748 }
2749 
onInputBufferAvailable()2750 void MediaCodec::onInputBufferAvailable() {
2751     int32_t index;
2752     while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
2753         sp<AMessage> msg = mCallback->dup();
2754         msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
2755         msg->setInt32("index", index);
2756         msg->post();
2757     }
2758 }
2759 
onOutputBufferAvailable()2760 void MediaCodec::onOutputBufferAvailable() {
2761     int32_t index;
2762     while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
2763         const sp<ABuffer> &buffer =
2764             mPortBuffers[kPortIndexOutput].itemAt(index).mData;
2765         sp<AMessage> msg = mCallback->dup();
2766         msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
2767         msg->setInt32("index", index);
2768         msg->setSize("offset", buffer->offset());
2769         msg->setSize("size", buffer->size());
2770 
2771         int64_t timeUs;
2772         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2773 
2774         msg->setInt64("timeUs", timeUs);
2775 
2776         int32_t omxFlags;
2777         CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
2778 
2779         uint32_t flags = 0;
2780         if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
2781             flags |= BUFFER_FLAG_SYNCFRAME;
2782         }
2783         if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
2784             flags |= BUFFER_FLAG_CODECCONFIG;
2785         }
2786         if (omxFlags & OMX_BUFFERFLAG_EOS) {
2787             flags |= BUFFER_FLAG_EOS;
2788         }
2789 
2790         msg->setInt32("flags", flags);
2791 
2792         msg->post();
2793     }
2794 }
2795 
onError(status_t err,int32_t actionCode,const char * detail)2796 void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
2797     if (mCallback != NULL) {
2798         sp<AMessage> msg = mCallback->dup();
2799         msg->setInt32("callbackID", CB_ERROR);
2800         msg->setInt32("err", err);
2801         msg->setInt32("actionCode", actionCode);
2802 
2803         if (detail != NULL) {
2804             msg->setString("detail", detail);
2805         }
2806 
2807         msg->post();
2808     }
2809 }
2810 
onOutputFormatChanged()2811 void MediaCodec::onOutputFormatChanged() {
2812     if (mCallback != NULL) {
2813         sp<AMessage> msg = mCallback->dup();
2814         msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
2815         msg->setMessage("format", mOutputFormat);
2816         msg->post();
2817     }
2818 }
2819 
2820 
postActivityNotificationIfPossible()2821 void MediaCodec::postActivityNotificationIfPossible() {
2822     if (mActivityNotify == NULL) {
2823         return;
2824     }
2825 
2826     bool isErrorOrOutputChanged =
2827             (mFlags & (kFlagStickyError
2828                     | kFlagOutputBuffersChanged
2829                     | kFlagOutputFormatChanged));
2830 
2831     if (isErrorOrOutputChanged
2832             || !mAvailPortBuffers[kPortIndexInput].empty()
2833             || !mAvailPortBuffers[kPortIndexOutput].empty()) {
2834         mActivityNotify->setInt32("input-buffers",
2835                 mAvailPortBuffers[kPortIndexInput].size());
2836 
2837         if (isErrorOrOutputChanged) {
2838             // we want consumer to dequeue as many times as it can
2839             mActivityNotify->setInt32("output-buffers", INT32_MAX);
2840         } else {
2841             mActivityNotify->setInt32("output-buffers",
2842                     mAvailPortBuffers[kPortIndexOutput].size());
2843         }
2844         mActivityNotify->post();
2845         mActivityNotify.clear();
2846     }
2847 }
2848 
setParameters(const sp<AMessage> & params)2849 status_t MediaCodec::setParameters(const sp<AMessage> &params) {
2850     sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
2851     msg->setMessage("params", params);
2852 
2853     sp<AMessage> response;
2854     return PostAndAwaitResponse(msg, &response);
2855 }
2856 
onSetParameters(const sp<AMessage> & params)2857 status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
2858     mCodec->signalSetParameters(params);
2859 
2860     return OK;
2861 }
2862 
amendOutputFormatWithCodecSpecificData(const sp<ABuffer> & buffer)2863 status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
2864         const sp<ABuffer> &buffer) {
2865     AString mime;
2866     CHECK(mOutputFormat->findString("mime", &mime));
2867 
2868     if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
2869         // Codec specific data should be SPS and PPS in a single buffer,
2870         // each prefixed by a startcode (0x00 0x00 0x00 0x01).
2871         // We separate the two and put them into the output format
2872         // under the keys "csd-0" and "csd-1".
2873 
2874         unsigned csdIndex = 0;
2875 
2876         const uint8_t *data = buffer->data();
2877         size_t size = buffer->size();
2878 
2879         const uint8_t *nalStart;
2880         size_t nalSize;
2881         while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
2882             sp<ABuffer> csd = new ABuffer(nalSize + 4);
2883             memcpy(csd->data(), "\x00\x00\x00\x01", 4);
2884             memcpy(csd->data() + 4, nalStart, nalSize);
2885 
2886             mOutputFormat->setBuffer(
2887                     AStringPrintf("csd-%u", csdIndex).c_str(), csd);
2888 
2889             ++csdIndex;
2890         }
2891 
2892         if (csdIndex != 2) {
2893             return ERROR_MALFORMED;
2894         }
2895     } else {
2896         // For everything else we just stash the codec specific data into
2897         // the output format as a single piece of csd under "csd-0".
2898         mOutputFormat->setBuffer("csd-0", buffer);
2899     }
2900 
2901     return OK;
2902 }
2903 
updateBatteryStat()2904 void MediaCodec::updateBatteryStat() {
2905     if (!mIsVideo) {
2906         return;
2907     }
2908 
2909     if (mState == CONFIGURED && !mBatteryStatNotified) {
2910         BatteryNotifier::getInstance().noteStartVideo();
2911         mBatteryStatNotified = true;
2912     } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
2913         BatteryNotifier::getInstance().noteStopVideo();
2914         mBatteryStatNotified = false;
2915     }
2916 }
2917 
2918 }  // namespace android
2919