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