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