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