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