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