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