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