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