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