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