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