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