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