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