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