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