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