MediaCodec.cpp revision 79054b1f53b448511f1edb6e0dcab1d7b6f39964
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::getWidevineLegacyBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
1050    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
1051    msg->setInt32("portIndex", kPortIndexInput);
1052    msg->setPointer("buffers", buffers);
1053    msg->setInt32("widevine", true);
1054
1055    sp<AMessage> response;
1056    return PostAndAwaitResponse(msg, &response);
1057}
1058
1059status_t MediaCodec::getInputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
1060    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
1061    msg->setInt32("portIndex", kPortIndexInput);
1062    msg->setPointer("buffers", buffers);
1063
1064    sp<AMessage> response;
1065    return PostAndAwaitResponse(msg, &response);
1066}
1067
1068status_t MediaCodec::getOutputBuffers(Vector<sp<MediaCodecBuffer> > *buffers) const {
1069    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
1070    msg->setInt32("portIndex", kPortIndexOutput);
1071    msg->setPointer("buffers", buffers);
1072
1073    sp<AMessage> response;
1074    return PostAndAwaitResponse(msg, &response);
1075}
1076
1077status_t MediaCodec::getOutputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
1078    sp<AMessage> format;
1079    return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
1080}
1081
1082status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
1083    sp<MediaCodecBuffer> buffer;
1084    return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
1085}
1086
1087status_t MediaCodec::getInputBuffer(size_t index, sp<MediaCodecBuffer> *buffer) {
1088    sp<AMessage> format;
1089    return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
1090}
1091
1092bool MediaCodec::isExecuting() const {
1093    return mState == STARTED || mState == FLUSHED;
1094}
1095
1096status_t MediaCodec::getBufferAndFormat(
1097        size_t portIndex, size_t index,
1098        sp<MediaCodecBuffer> *buffer, sp<AMessage> *format) {
1099    // use mutex instead of a context switch
1100    if (mReleasedByResourceManager) {
1101        ALOGE("getBufferAndFormat - resource already released");
1102        return DEAD_OBJECT;
1103    }
1104
1105    if (buffer == NULL) {
1106        ALOGE("getBufferAndFormat - null MediaCodecBuffer");
1107        return INVALID_OPERATION;
1108    }
1109
1110    if (format == NULL) {
1111        ALOGE("getBufferAndFormat - null AMessage");
1112        return INVALID_OPERATION;
1113    }
1114
1115    buffer->clear();
1116    format->clear();
1117
1118    if (!isExecuting()) {
1119        ALOGE("getBufferAndFormat - not executing");
1120        return INVALID_OPERATION;
1121    }
1122
1123    // we do not want mPortBuffers to change during this section
1124    // we also don't want mOwnedByClient to change during this
1125    Mutex::Autolock al(mBufferLock);
1126
1127    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1128    if (index >= buffers->size()) {
1129        ALOGE("getBufferAndFormat - trying to get buffer with "
1130              "bad index (index=%zu buffer_size=%zu)", index, buffers->size());
1131        return INVALID_OPERATION;
1132    }
1133
1134    const BufferInfo &info = buffers->itemAt(index);
1135    if (!info.mOwnedByClient) {
1136        ALOGE("getBufferAndFormat - invalid operation "
1137              "(the index %zu is not owned by client)", index);
1138        return INVALID_OPERATION;
1139    }
1140
1141    *buffer = info.mData;
1142    *format = info.mData->format();
1143
1144    return OK;
1145}
1146
1147status_t MediaCodec::flush() {
1148    sp<AMessage> msg = new AMessage(kWhatFlush, this);
1149
1150    sp<AMessage> response;
1151    return PostAndAwaitResponse(msg, &response);
1152}
1153
1154status_t MediaCodec::requestIDRFrame() {
1155    (new AMessage(kWhatRequestIDRFrame, this))->post();
1156
1157    return OK;
1158}
1159
1160void MediaCodec::requestActivityNotification(const sp<AMessage> &notify) {
1161    sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, this);
1162    msg->setMessage("notify", notify);
1163    msg->post();
1164}
1165
1166////////////////////////////////////////////////////////////////////////////////
1167
1168void MediaCodec::cancelPendingDequeueOperations() {
1169    if (mFlags & kFlagDequeueInputPending) {
1170        PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
1171
1172        ++mDequeueInputTimeoutGeneration;
1173        mDequeueInputReplyID = 0;
1174        mFlags &= ~kFlagDequeueInputPending;
1175    }
1176
1177    if (mFlags & kFlagDequeueOutputPending) {
1178        PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
1179
1180        ++mDequeueOutputTimeoutGeneration;
1181        mDequeueOutputReplyID = 0;
1182        mFlags &= ~kFlagDequeueOutputPending;
1183    }
1184}
1185
1186bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
1187    if (!isExecuting() || (mFlags & kFlagIsAsync)
1188            || (newRequest && (mFlags & kFlagDequeueInputPending))) {
1189        PostReplyWithError(replyID, INVALID_OPERATION);
1190        return true;
1191    } else if (mFlags & kFlagStickyError) {
1192        PostReplyWithError(replyID, getStickyError());
1193        return true;
1194    }
1195
1196    ssize_t index = dequeuePortBuffer(kPortIndexInput);
1197
1198    if (index < 0) {
1199        CHECK_EQ(index, -EAGAIN);
1200        return false;
1201    }
1202
1203    sp<AMessage> response = new AMessage;
1204    response->setSize("index", index);
1205    response->postReply(replyID);
1206
1207    return true;
1208}
1209
1210bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
1211    if (!isExecuting() || (mFlags & kFlagIsAsync)
1212            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
1213        PostReplyWithError(replyID, INVALID_OPERATION);
1214    } else if (mFlags & kFlagStickyError) {
1215        PostReplyWithError(replyID, getStickyError());
1216    } else if (mFlags & kFlagOutputBuffersChanged) {
1217        PostReplyWithError(replyID, INFO_OUTPUT_BUFFERS_CHANGED);
1218        mFlags &= ~kFlagOutputBuffersChanged;
1219    } else if (mFlags & kFlagOutputFormatChanged) {
1220        PostReplyWithError(replyID, INFO_FORMAT_CHANGED);
1221        mFlags &= ~kFlagOutputFormatChanged;
1222    } else {
1223        sp<AMessage> response = new AMessage;
1224        ssize_t index = dequeuePortBuffer(kPortIndexOutput);
1225
1226        if (index < 0) {
1227            CHECK_EQ(index, -EAGAIN);
1228            return false;
1229        }
1230
1231        const sp<MediaCodecBuffer> &buffer =
1232            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
1233
1234        response->setSize("index", index);
1235        response->setSize("offset", buffer->offset());
1236        response->setSize("size", buffer->size());
1237
1238        int64_t timeUs;
1239        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1240
1241        response->setInt64("timeUs", timeUs);
1242
1243        int32_t omxFlags;
1244        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
1245
1246        uint32_t flags = 0;
1247        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
1248            flags |= BUFFER_FLAG_SYNCFRAME;
1249        }
1250        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1251            flags |= BUFFER_FLAG_CODECCONFIG;
1252        }
1253        if (omxFlags & OMX_BUFFERFLAG_EOS) {
1254            flags |= BUFFER_FLAG_EOS;
1255        }
1256
1257        response->setInt32("flags", flags);
1258        response->postReply(replyID);
1259    }
1260
1261    return true;
1262}
1263
1264void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
1265    switch (msg->what()) {
1266        case kWhatCodecNotify:
1267        {
1268            int32_t what;
1269            CHECK(msg->findInt32("what", &what));
1270
1271            switch (what) {
1272                case kWhatError:
1273                {
1274                    int32_t err, actionCode;
1275                    CHECK(msg->findInt32("err", &err));
1276                    CHECK(msg->findInt32("actionCode", &actionCode));
1277
1278                    ALOGE("Codec reported err %#x, actionCode %d, while in state %d",
1279                            err, actionCode, mState);
1280                    if (err == DEAD_OBJECT) {
1281                        mFlags |= kFlagSawMediaServerDie;
1282                        mFlags &= ~kFlagIsComponentAllocated;
1283                    }
1284
1285                    bool sendErrorResponse = true;
1286
1287                    switch (mState) {
1288                        case INITIALIZING:
1289                        {
1290                            setState(UNINITIALIZED);
1291                            break;
1292                        }
1293
1294                        case CONFIGURING:
1295                        {
1296                            setState(actionCode == ACTION_CODE_FATAL ?
1297                                    UNINITIALIZED : INITIALIZED);
1298                            break;
1299                        }
1300
1301                        case STARTING:
1302                        {
1303                            setState(actionCode == ACTION_CODE_FATAL ?
1304                                    UNINITIALIZED : CONFIGURED);
1305                            break;
1306                        }
1307
1308                        case RELEASING:
1309                        {
1310                            // Ignore the error, assuming we'll still get
1311                            // the shutdown complete notification. If we
1312                            // don't, we'll timeout and force release.
1313                            sendErrorResponse = false;
1314                        }
1315                        // fall-thru
1316                        case STOPPING:
1317                        {
1318                            if (mFlags & kFlagSawMediaServerDie) {
1319                                // MediaServer died, there definitely won't
1320                                // be a shutdown complete notification after
1321                                // all.
1322
1323                                // note that we're directly going from
1324                                // STOPPING->UNINITIALIZED, instead of the
1325                                // usual STOPPING->INITIALIZED state.
1326                                setState(UNINITIALIZED);
1327                                if (mState == RELEASING) {
1328                                    mComponentName.clear();
1329                                }
1330                                (new AMessage)->postReply(mReplyID);
1331                                sendErrorResponse = false;
1332                            }
1333                            break;
1334                        }
1335
1336                        case FLUSHING:
1337                        {
1338                            if (actionCode == ACTION_CODE_FATAL) {
1339                                setState(UNINITIALIZED);
1340                            } else {
1341                                setState(
1342                                        (mFlags & kFlagIsAsync) ? FLUSHED : STARTED);
1343                            }
1344                            break;
1345                        }
1346
1347                        case FLUSHED:
1348                        case STARTED:
1349                        {
1350                            sendErrorResponse = false;
1351
1352                            setStickyError(err);
1353                            postActivityNotificationIfPossible();
1354
1355                            cancelPendingDequeueOperations();
1356
1357                            if (mFlags & kFlagIsAsync) {
1358                                onError(err, actionCode);
1359                            }
1360                            switch (actionCode) {
1361                            case ACTION_CODE_TRANSIENT:
1362                                break;
1363                            case ACTION_CODE_RECOVERABLE:
1364                                setState(INITIALIZED);
1365                                break;
1366                            default:
1367                                setState(UNINITIALIZED);
1368                                break;
1369                            }
1370                            break;
1371                        }
1372
1373                        default:
1374                        {
1375                            sendErrorResponse = false;
1376
1377                            setStickyError(err);
1378                            postActivityNotificationIfPossible();
1379
1380                            // actionCode in an uninitialized state is always fatal.
1381                            if (mState == UNINITIALIZED) {
1382                                actionCode = ACTION_CODE_FATAL;
1383                            }
1384                            if (mFlags & kFlagIsAsync) {
1385                                onError(err, actionCode);
1386                            }
1387                            switch (actionCode) {
1388                            case ACTION_CODE_TRANSIENT:
1389                                break;
1390                            case ACTION_CODE_RECOVERABLE:
1391                                setState(INITIALIZED);
1392                                break;
1393                            default:
1394                                setState(UNINITIALIZED);
1395                                break;
1396                            }
1397                            break;
1398                        }
1399                    }
1400
1401                    if (sendErrorResponse) {
1402                        PostReplyWithError(mReplyID, err);
1403                    }
1404                    break;
1405                }
1406
1407                case kWhatComponentAllocated:
1408                {
1409                    CHECK_EQ(mState, INITIALIZING);
1410                    setState(INITIALIZED);
1411                    mFlags |= kFlagIsComponentAllocated;
1412
1413                    CHECK(msg->findString("componentName", &mComponentName));
1414
1415                    if (mComponentName.startsWith("OMX.google.")) {
1416                        mFlags |= kFlagUsesSoftwareRenderer;
1417                    } else {
1418                        mFlags &= ~kFlagUsesSoftwareRenderer;
1419                    }
1420
1421                    MediaResource::Type resourceType;
1422                    if (mComponentName.endsWith(".secure")) {
1423                        mFlags |= kFlagIsSecure;
1424                        resourceType = MediaResource::kSecureCodec;
1425                    } else {
1426                        mFlags &= ~kFlagIsSecure;
1427                        resourceType = MediaResource::kNonSecureCodec;
1428                    }
1429
1430                    if (mIsVideo) {
1431                        // audio codec is currently ignored.
1432                        addResource(resourceType, MediaResource::kVideoCodec, 1);
1433                    }
1434
1435                    (new AMessage)->postReply(mReplyID);
1436                    break;
1437                }
1438
1439                case kWhatComponentConfigured:
1440                {
1441                    if (mState == UNINITIALIZED || mState == INITIALIZED) {
1442                        // In case a kWhatError message came in and replied with error,
1443                        // we log a warning and ignore.
1444                        ALOGW("configure interrupted by error, current state %d", mState);
1445                        break;
1446                    }
1447                    CHECK_EQ(mState, CONFIGURING);
1448
1449                    // reset input surface flag
1450                    mHaveInputSurface = false;
1451
1452                    CHECK(msg->findMessage("input-format", &mInputFormat));
1453                    CHECK(msg->findMessage("output-format", &mOutputFormat));
1454                    ALOGV("[%s] configured as input format: %s, output format: %s",
1455                            mComponentName.c_str(),
1456                            mInputFormat->debugString(4).c_str(),
1457                            mOutputFormat->debugString(4).c_str());
1458                    int32_t usingSwRenderer;
1459                    if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer)
1460                            && usingSwRenderer) {
1461                        mFlags |= kFlagUsesSoftwareRenderer;
1462                    }
1463                    setState(CONFIGURED);
1464                    (new AMessage)->postReply(mReplyID);
1465                    break;
1466                }
1467
1468                case kWhatInputSurfaceCreated:
1469                {
1470                    // response to initiateCreateInputSurface()
1471                    status_t err = NO_ERROR;
1472                    sp<AMessage> response = new AMessage;
1473                    if (!msg->findInt32("err", &err)) {
1474                        sp<RefBase> obj;
1475                        msg->findObject("input-surface", &obj);
1476                        CHECK(msg->findMessage("input-format", &mInputFormat));
1477                        CHECK(msg->findMessage("output-format", &mOutputFormat));
1478                        ALOGV("[%s] input surface created as input format: %s, output format: %s",
1479                                mComponentName.c_str(),
1480                                mInputFormat->debugString(4).c_str(),
1481                                mOutputFormat->debugString(4).c_str());
1482                        CHECK(obj != NULL);
1483                        response->setObject("input-surface", obj);
1484                        mHaveInputSurface = true;
1485                    } else {
1486                        response->setInt32("err", err);
1487                    }
1488                    response->postReply(mReplyID);
1489                    break;
1490                }
1491
1492                case kWhatInputSurfaceAccepted:
1493                {
1494                    // response to initiateSetInputSurface()
1495                    status_t err = NO_ERROR;
1496                    sp<AMessage> response = new AMessage();
1497                    if (!msg->findInt32("err", &err)) {
1498                        CHECK(msg->findMessage("input-format", &mInputFormat));
1499                        CHECK(msg->findMessage("output-format", &mOutputFormat));
1500                        mHaveInputSurface = true;
1501                    } else {
1502                        response->setInt32("err", err);
1503                    }
1504                    response->postReply(mReplyID);
1505                    break;
1506                }
1507
1508                case kWhatSignaledInputEOS:
1509                {
1510                    // response to signalEndOfInputStream()
1511                    sp<AMessage> response = new AMessage;
1512                    status_t err;
1513                    if (msg->findInt32("err", &err)) {
1514                        response->setInt32("err", err);
1515                    }
1516                    response->postReply(mReplyID);
1517                    break;
1518                }
1519
1520
1521                case kWhatBuffersAllocated:
1522                {
1523                    Mutex::Autolock al(mBufferLock);
1524                    int32_t portIndex;
1525                    CHECK(msg->findInt32("portIndex", &portIndex));
1526
1527                    ALOGV("%s buffers allocated",
1528                          portIndex == kPortIndexInput ? "input" : "output");
1529
1530                    CHECK(portIndex == kPortIndexInput
1531                            || portIndex == kPortIndexOutput);
1532
1533                    mPortBuffers[portIndex].clear();
1534                    mPortBufferArrays[portIndex].clear();
1535
1536                    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1537
1538                    sp<RefBase> obj;
1539                    CHECK(msg->findObject("portDesc", &obj));
1540
1541                    sp<CodecBase::PortDescription> portDesc =
1542                        static_cast<CodecBase::PortDescription *>(obj.get());
1543
1544                    size_t numBuffers = portDesc->countBuffers();
1545
1546                    size_t totalSize = 0;
1547                    for (size_t i = 0; i < numBuffers; ++i) {
1548                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
1549                            totalSize += portDesc->bufferAt(i)->capacity();
1550                        }
1551                    }
1552
1553                    if (totalSize) {
1554                        mDealer = new MemoryDealer(totalSize, "MediaCodec");
1555                    }
1556
1557                    for (size_t i = 0; i < numBuffers; ++i) {
1558                        BufferInfo info;
1559                        info.mBufferID = portDesc->bufferIDAt(i);
1560                        info.mOwnedByClient = false;
1561                        sp<MediaCodecBuffer> buffer = portDesc->bufferAt(i);
1562                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
1563                            info.mSharedEncryptedBuffer = mDealer->allocate(buffer->capacity());
1564                            buffer = new SharedMemoryBuffer(
1565                                    mInputFormat, info.mSharedEncryptedBuffer);
1566                        }
1567                        buffers->push_back(info);
1568                        mPortBufferArrays[portIndex].push_back(buffer);
1569                    }
1570
1571                    if (portIndex == kPortIndexOutput) {
1572                        if (mState == STARTING) {
1573                            // We're always allocating output buffers after
1574                            // allocating input buffers, so this is a good
1575                            // indication that now all buffers are allocated.
1576                            if (mIsVideo) {
1577                                addResource(
1578                                        MediaResource::kGraphicMemory,
1579                                        MediaResource::kUnspecifiedSubType,
1580                                        getGraphicBufferSize());
1581                            }
1582                            setState(STARTED);
1583                            (new AMessage)->postReply(mReplyID);
1584                        } else {
1585                            mFlags |= kFlagOutputBuffersChanged;
1586                            postActivityNotificationIfPossible();
1587                        }
1588                    }
1589                    break;
1590                }
1591
1592                case kWhatOutputFramesRendered:
1593                {
1594                    // ignore these in all states except running, and check that we have a
1595                    // notification set
1596                    if (mState == STARTED && mOnFrameRenderedNotification != NULL) {
1597                        sp<AMessage> notify = mOnFrameRenderedNotification->dup();
1598                        notify->setMessage("data", msg);
1599                        notify->post();
1600                    }
1601                    break;
1602                }
1603
1604                case kWhatFillThisBuffer:
1605                {
1606                    /* size_t index = */updateBuffers(kPortIndexInput, msg);
1607
1608                    if (mState == FLUSHING
1609                            || mState == STOPPING
1610                            || mState == RELEASING) {
1611                        returnBuffersToCodecOnPort(kPortIndexInput);
1612                        break;
1613                    }
1614
1615                    // TODO: hold reference of buffer from downstream when
1616                    // mPortBuffers is removed.
1617
1618                    if (!mCSD.empty()) {
1619                        ssize_t index = dequeuePortBuffer(kPortIndexInput);
1620                        CHECK_GE(index, 0);
1621
1622                        // If codec specific data had been specified as
1623                        // part of the format in the call to configure and
1624                        // if there's more csd left, we submit it here
1625                        // clients only get access to input buffers once
1626                        // this data has been exhausted.
1627
1628                        status_t err = queueCSDInputBuffer(index);
1629
1630                        if (err != OK) {
1631                            ALOGE("queueCSDInputBuffer failed w/ error %d",
1632                                  err);
1633
1634                            setStickyError(err);
1635                            postActivityNotificationIfPossible();
1636
1637                            cancelPendingDequeueOperations();
1638                        }
1639                        break;
1640                    }
1641
1642                    if (mFlags & kFlagIsAsync) {
1643                        if (!mHaveInputSurface) {
1644                            if (mState == FLUSHED) {
1645                                mHavePendingInputBuffers = true;
1646                            } else {
1647                                onInputBufferAvailable();
1648                            }
1649                        }
1650                    } else if (mFlags & kFlagDequeueInputPending) {
1651                        CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
1652
1653                        ++mDequeueInputTimeoutGeneration;
1654                        mFlags &= ~kFlagDequeueInputPending;
1655                        mDequeueInputReplyID = 0;
1656                    } else {
1657                        postActivityNotificationIfPossible();
1658                    }
1659                    break;
1660                }
1661
1662                case kWhatDrainThisBuffer:
1663                {
1664                    /* size_t index = */updateBuffers(kPortIndexOutput, msg);
1665
1666                    if (mState == FLUSHING
1667                            || mState == STOPPING
1668                            || mState == RELEASING) {
1669                        returnBuffersToCodecOnPort(kPortIndexOutput);
1670                        break;
1671                    }
1672
1673                    sp<RefBase> obj;
1674                    CHECK(msg->findObject("buffer", &obj));
1675                    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
1676                    // TODO: hold buffer's reference when we remove mPortBuffers
1677
1678                    int32_t omxFlags;
1679                    CHECK(msg->findInt32("flags", &omxFlags));
1680
1681                    buffer->meta()->setInt32("omxFlags", omxFlags);
1682                    if (mOutputFormat != buffer->format()) {
1683                        mOutputFormat = buffer->format();
1684                        ALOGV("[%s] output format changed to: %s",
1685                                mComponentName.c_str(), mOutputFormat->debugString(4).c_str());
1686
1687                        if (mSoftRenderer == NULL &&
1688                                mSurface != NULL &&
1689                                (mFlags & kFlagUsesSoftwareRenderer)) {
1690                            AString mime;
1691                            CHECK(mOutputFormat->findString("mime", &mime));
1692
1693                            // TODO: propagate color aspects to software renderer to allow better
1694                            // color conversion to RGB. For now, just mark dataspace for YUV
1695                            // rendering.
1696                            int32_t dataSpace;
1697                            if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
1698                                ALOGD("[%s] setting dataspace on output surface to #%x",
1699                                        mComponentName.c_str(), dataSpace);
1700                                int err = native_window_set_buffers_data_space(
1701                                        mSurface.get(), (android_dataspace)dataSpace);
1702                                ALOGW_IF(err != 0, "failed to set dataspace on surface (%d)", err);
1703                            }
1704
1705                            if (mime.startsWithIgnoreCase("video/")) {
1706                                mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees);
1707                            }
1708                        }
1709
1710                        if (mFlags & kFlagIsEncoder) {
1711                            // Before we announce the format change we should
1712                            // collect codec specific data and amend the output
1713                            // format as necessary.
1714                            if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1715                                status_t err =
1716                                    amendOutputFormatWithCodecSpecificData(buffer);
1717
1718                                if (err != OK) {
1719                                    ALOGE("Codec spit out malformed codec "
1720                                          "specific data!");
1721                                }
1722                            }
1723                        }
1724
1725                        if (mFlags & kFlagIsAsync) {
1726                            onOutputFormatChanged();
1727                        } else {
1728                            mFlags |= kFlagOutputFormatChanged;
1729                            postActivityNotificationIfPossible();
1730                        }
1731
1732                        // Notify mCrypto of video resolution changes
1733                        if (mCrypto != NULL) {
1734                            int32_t left, top, right, bottom, width, height;
1735                            if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
1736                                mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
1737                            } else if (mOutputFormat->findInt32("width", &width)
1738                                    && mOutputFormat->findInt32("height", &height)) {
1739                                mCrypto->notifyResolution(width, height);
1740                            }
1741                        }
1742                    }
1743
1744                    if (mFlags & kFlagIsAsync) {
1745                        onOutputBufferAvailable();
1746                    } else if (mFlags & kFlagDequeueOutputPending) {
1747                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
1748
1749                        ++mDequeueOutputTimeoutGeneration;
1750                        mFlags &= ~kFlagDequeueOutputPending;
1751                        mDequeueOutputReplyID = 0;
1752                    } else {
1753                        postActivityNotificationIfPossible();
1754                    }
1755
1756                    break;
1757                }
1758
1759                case kWhatEOS:
1760                {
1761                    // We already notify the client of this by using the
1762                    // corresponding flag in "onOutputBufferReady".
1763                    break;
1764                }
1765
1766                case kWhatStopCompleted:
1767                {
1768                    if (mState != STOPPING) {
1769                        ALOGW("Received kWhatStopCompleted in state %d", mState);
1770                        break;
1771                    }
1772                    setState(INITIALIZED);
1773                    (new AMessage)->postReply(mReplyID);
1774                    break;
1775                }
1776
1777                case kWhatReleaseCompleted:
1778                {
1779                    if (mState != RELEASING) {
1780                        ALOGW("Received kWhatReleaseCompleted in state %d", mState);
1781                        break;
1782                    }
1783                    setState(UNINITIALIZED);
1784                    mComponentName.clear();
1785
1786                    mFlags &= ~kFlagIsComponentAllocated;
1787
1788                    mResourceManagerService->removeResource(getId(mResourceManagerClient));
1789
1790                    (new AMessage)->postReply(mReplyID);
1791                    break;
1792                }
1793
1794                case kWhatFlushCompleted:
1795                {
1796                    if (mState != FLUSHING) {
1797                        ALOGW("received FlushCompleted message in state %d",
1798                                mState);
1799                        break;
1800                    }
1801
1802                    if (mFlags & kFlagIsAsync) {
1803                        setState(FLUSHED);
1804                    } else {
1805                        setState(STARTED);
1806                        mCodec->signalResume();
1807                    }
1808
1809                    (new AMessage)->postReply(mReplyID);
1810                    break;
1811                }
1812
1813                default:
1814                    TRESPASS();
1815            }
1816            break;
1817        }
1818
1819        case kWhatInit:
1820        {
1821            sp<AReplyToken> replyID;
1822            CHECK(msg->senderAwaitsResponse(&replyID));
1823
1824            if (mState != UNINITIALIZED) {
1825                PostReplyWithError(replyID, INVALID_OPERATION);
1826                break;
1827            }
1828
1829            mReplyID = replyID;
1830            setState(INITIALIZING);
1831
1832            AString name;
1833            CHECK(msg->findString("name", &name));
1834
1835            int32_t nameIsType;
1836            int32_t encoder = false;
1837            CHECK(msg->findInt32("nameIsType", &nameIsType));
1838            if (nameIsType) {
1839                CHECK(msg->findInt32("encoder", &encoder));
1840            }
1841
1842            sp<AMessage> format = new AMessage;
1843
1844            if (nameIsType) {
1845                format->setString("mime", name.c_str());
1846                format->setInt32("encoder", encoder);
1847            } else {
1848                format->setString("componentName", name.c_str());
1849            }
1850
1851            mCodec->initiateAllocateComponent(format);
1852            break;
1853        }
1854
1855        case kWhatSetNotification:
1856        {
1857            sp<AMessage> notify;
1858            if (msg->findMessage("on-frame-rendered", &notify)) {
1859                mOnFrameRenderedNotification = notify;
1860            }
1861            break;
1862        }
1863
1864        case kWhatSetCallback:
1865        {
1866            sp<AReplyToken> replyID;
1867            CHECK(msg->senderAwaitsResponse(&replyID));
1868
1869            if (mState == UNINITIALIZED
1870                    || mState == INITIALIZING
1871                    || isExecuting()) {
1872                // callback can't be set after codec is executing,
1873                // or before it's initialized (as the callback
1874                // will be cleared when it goes to INITIALIZED)
1875                PostReplyWithError(replyID, INVALID_OPERATION);
1876                break;
1877            }
1878
1879            sp<AMessage> callback;
1880            CHECK(msg->findMessage("callback", &callback));
1881
1882            mCallback = callback;
1883
1884            if (mCallback != NULL) {
1885                ALOGI("MediaCodec will operate in async mode");
1886                mFlags |= kFlagIsAsync;
1887            } else {
1888                mFlags &= ~kFlagIsAsync;
1889            }
1890
1891            sp<AMessage> response = new AMessage;
1892            response->postReply(replyID);
1893            break;
1894        }
1895
1896        case kWhatConfigure:
1897        {
1898            sp<AReplyToken> replyID;
1899            CHECK(msg->senderAwaitsResponse(&replyID));
1900
1901            if (mState != INITIALIZED) {
1902                PostReplyWithError(replyID, INVALID_OPERATION);
1903                break;
1904            }
1905
1906            sp<RefBase> obj;
1907            CHECK(msg->findObject("surface", &obj));
1908
1909            sp<AMessage> format;
1910            CHECK(msg->findMessage("format", &format));
1911
1912            int32_t push;
1913            if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) {
1914                mFlags |= kFlagPushBlankBuffersOnShutdown;
1915            }
1916
1917            if (obj != NULL) {
1918                format->setObject("native-window", obj);
1919                status_t err = handleSetSurface(static_cast<Surface *>(obj.get()));
1920                if (err != OK) {
1921                    PostReplyWithError(replyID, err);
1922                    break;
1923                }
1924            } else {
1925                handleSetSurface(NULL);
1926            }
1927
1928            mReplyID = replyID;
1929            setState(CONFIGURING);
1930
1931            void *crypto;
1932            if (!msg->findPointer("crypto", &crypto)) {
1933                crypto = NULL;
1934            }
1935
1936            mCrypto = static_cast<ICrypto *>(crypto);
1937
1938            uint32_t flags;
1939            CHECK(msg->findInt32("flags", (int32_t *)&flags));
1940
1941            if (flags & CONFIGURE_FLAG_ENCODE) {
1942                format->setInt32("encoder", true);
1943                mFlags |= kFlagIsEncoder;
1944            }
1945
1946            extractCSD(format);
1947
1948            mCodec->initiateConfigureComponent(format);
1949            break;
1950        }
1951
1952        case kWhatSetSurface:
1953        {
1954            sp<AReplyToken> replyID;
1955            CHECK(msg->senderAwaitsResponse(&replyID));
1956
1957            status_t err = OK;
1958            sp<Surface> surface;
1959
1960            switch (mState) {
1961                case CONFIGURED:
1962                case STARTED:
1963                case FLUSHED:
1964                {
1965                    sp<RefBase> obj;
1966                    (void)msg->findObject("surface", &obj);
1967                    sp<Surface> surface = static_cast<Surface *>(obj.get());
1968                    if (mSurface == NULL) {
1969                        // do not support setting surface if it was not set
1970                        err = INVALID_OPERATION;
1971                    } else if (obj == NULL) {
1972                        // do not support unsetting surface
1973                        err = BAD_VALUE;
1974                    } else {
1975                        err = connectToSurface(surface);
1976                        if (err == ALREADY_EXISTS) {
1977                            // reconnecting to same surface
1978                            err = OK;
1979                        } else {
1980                            if (err == OK) {
1981                                if (mFlags & kFlagUsesSoftwareRenderer) {
1982                                    if (mSoftRenderer != NULL
1983                                            && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1984                                        pushBlankBuffersToNativeWindow(mSurface.get());
1985                                    }
1986                                    mSoftRenderer = new SoftwareRenderer(surface);
1987                                    // TODO: check if this was successful
1988                                } else {
1989                                    err = mCodec->setSurface(surface);
1990                                }
1991                            }
1992                            if (err == OK) {
1993                                (void)disconnectFromSurface();
1994                                mSurface = surface;
1995                            }
1996                        }
1997                    }
1998                    break;
1999                }
2000
2001                default:
2002                    err = INVALID_OPERATION;
2003                    break;
2004            }
2005
2006            PostReplyWithError(replyID, err);
2007            break;
2008        }
2009
2010        case kWhatCreateInputSurface:
2011        case kWhatSetInputSurface:
2012        {
2013            sp<AReplyToken> replyID;
2014            CHECK(msg->senderAwaitsResponse(&replyID));
2015
2016            // Must be configured, but can't have been started yet.
2017            if (mState != CONFIGURED) {
2018                PostReplyWithError(replyID, INVALID_OPERATION);
2019                break;
2020            }
2021
2022            mReplyID = replyID;
2023            if (msg->what() == kWhatCreateInputSurface) {
2024                mCodec->initiateCreateInputSurface();
2025            } else {
2026                sp<RefBase> obj;
2027                CHECK(msg->findObject("input-surface", &obj));
2028
2029                mCodec->initiateSetInputSurface(
2030                        static_cast<PersistentSurface *>(obj.get()));
2031            }
2032            break;
2033        }
2034        case kWhatStart:
2035        {
2036            sp<AReplyToken> replyID;
2037            CHECK(msg->senderAwaitsResponse(&replyID));
2038
2039            if (mState == FLUSHED) {
2040                setState(STARTED);
2041                if (mHavePendingInputBuffers) {
2042                    onInputBufferAvailable();
2043                    mHavePendingInputBuffers = false;
2044                }
2045                mCodec->signalResume();
2046                PostReplyWithError(replyID, OK);
2047                break;
2048            } else if (mState != CONFIGURED) {
2049                PostReplyWithError(replyID, INVALID_OPERATION);
2050                break;
2051            }
2052
2053            mReplyID = replyID;
2054            setState(STARTING);
2055
2056            mCodec->initiateStart();
2057            break;
2058        }
2059
2060        case kWhatStop:
2061        case kWhatRelease:
2062        {
2063            State targetState =
2064                (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
2065
2066            sp<AReplyToken> replyID;
2067            CHECK(msg->senderAwaitsResponse(&replyID));
2068
2069            // already stopped/released
2070            if (mState == UNINITIALIZED && mReleasedByResourceManager) {
2071                sp<AMessage> response = new AMessage;
2072                response->setInt32("err", OK);
2073                response->postReply(replyID);
2074                break;
2075            }
2076
2077            int32_t reclaimed = 0;
2078            msg->findInt32("reclaimed", &reclaimed);
2079            if (reclaimed) {
2080                mReleasedByResourceManager = true;
2081
2082                int32_t force = 0;
2083                msg->findInt32("force", &force);
2084                if (!force && hasPendingBuffer()) {
2085                    ALOGW("Can't reclaim codec right now due to pending buffers.");
2086
2087                    // return WOULD_BLOCK to ask resource manager to retry later.
2088                    sp<AMessage> response = new AMessage;
2089                    response->setInt32("err", WOULD_BLOCK);
2090                    response->postReply(replyID);
2091
2092                    // notify the async client
2093                    if (mFlags & kFlagIsAsync) {
2094                        onError(DEAD_OBJECT, ACTION_CODE_FATAL);
2095                    }
2096                    break;
2097                }
2098            }
2099
2100            bool isReleasingAllocatedComponent =
2101                    (mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED;
2102            if (!isReleasingAllocatedComponent // See 1
2103                    && mState != INITIALIZED
2104                    && mState != CONFIGURED && !isExecuting()) {
2105                // 1) Permit release to shut down the component if allocated.
2106                //
2107                // 2) We may be in "UNINITIALIZED" state already and
2108                // also shutdown the encoder/decoder without the
2109                // client being aware of this if media server died while
2110                // we were being stopped. The client would assume that
2111                // after stop() returned, it would be safe to call release()
2112                // and it should be in this case, no harm to allow a release()
2113                // if we're already uninitialized.
2114                sp<AMessage> response = new AMessage;
2115                // TODO: we shouldn't throw an exception for stop/release. Change this to wait until
2116                // the previous stop/release completes and then reply with OK.
2117                status_t err = mState == targetState ? OK : INVALID_OPERATION;
2118                response->setInt32("err", err);
2119                if (err == OK && targetState == UNINITIALIZED) {
2120                    mComponentName.clear();
2121                }
2122                response->postReply(replyID);
2123                break;
2124            }
2125
2126            // If we're flushing, or we're stopping but received a release
2127            // request, post the reply for the pending call first, and consider
2128            // it done. The reply token will be replaced after this, and we'll
2129            // no longer be able to reply.
2130            if (mState == FLUSHING || mState == STOPPING) {
2131                (new AMessage)->postReply(mReplyID);
2132            }
2133
2134            if (mFlags & kFlagSawMediaServerDie) {
2135                // It's dead, Jim. Don't expect initiateShutdown to yield
2136                // any useful results now...
2137                setState(UNINITIALIZED);
2138                if (targetState == UNINITIALIZED) {
2139                    mComponentName.clear();
2140                }
2141                (new AMessage)->postReply(replyID);
2142                break;
2143            }
2144
2145            // If we already have an error, component may not be able to
2146            // complete the shutdown properly. If we're stopping, post the
2147            // reply now with an error to unblock the client, client can
2148            // release after the failure (instead of ANR).
2149            if (msg->what() == kWhatStop && (mFlags & kFlagStickyError)) {
2150                PostReplyWithError(replyID, getStickyError());
2151                break;
2152            }
2153
2154            mReplyID = replyID;
2155            setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
2156
2157            mCodec->initiateShutdown(
2158                    msg->what() == kWhatStop /* keepComponentAllocated */);
2159
2160            returnBuffersToCodec(reclaimed);
2161
2162            if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
2163                pushBlankBuffersToNativeWindow(mSurface.get());
2164            }
2165
2166            break;
2167        }
2168
2169        case kWhatDequeueInputBuffer:
2170        {
2171            sp<AReplyToken> replyID;
2172            CHECK(msg->senderAwaitsResponse(&replyID));
2173
2174            if (mFlags & kFlagIsAsync) {
2175                ALOGE("dequeueOutputBuffer can't be used in async mode");
2176                PostReplyWithError(replyID, INVALID_OPERATION);
2177                break;
2178            }
2179
2180            if (mHaveInputSurface) {
2181                ALOGE("dequeueInputBuffer can't be used with input surface");
2182                PostReplyWithError(replyID, INVALID_OPERATION);
2183                break;
2184            }
2185
2186            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
2187                break;
2188            }
2189
2190            int64_t timeoutUs;
2191            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
2192
2193            if (timeoutUs == 0ll) {
2194                PostReplyWithError(replyID, -EAGAIN);
2195                break;
2196            }
2197
2198            mFlags |= kFlagDequeueInputPending;
2199            mDequeueInputReplyID = replyID;
2200
2201            if (timeoutUs > 0ll) {
2202                sp<AMessage> timeoutMsg =
2203                    new AMessage(kWhatDequeueInputTimedOut, this);
2204                timeoutMsg->setInt32(
2205                        "generation", ++mDequeueInputTimeoutGeneration);
2206                timeoutMsg->post(timeoutUs);
2207            }
2208            break;
2209        }
2210
2211        case kWhatDequeueInputTimedOut:
2212        {
2213            int32_t generation;
2214            CHECK(msg->findInt32("generation", &generation));
2215
2216            if (generation != mDequeueInputTimeoutGeneration) {
2217                // Obsolete
2218                break;
2219            }
2220
2221            CHECK(mFlags & kFlagDequeueInputPending);
2222
2223            PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
2224
2225            mFlags &= ~kFlagDequeueInputPending;
2226            mDequeueInputReplyID = 0;
2227            break;
2228        }
2229
2230        case kWhatQueueInputBuffer:
2231        {
2232            sp<AReplyToken> replyID;
2233            CHECK(msg->senderAwaitsResponse(&replyID));
2234
2235            if (!isExecuting()) {
2236                PostReplyWithError(replyID, INVALID_OPERATION);
2237                break;
2238            } else if (mFlags & kFlagStickyError) {
2239                PostReplyWithError(replyID, getStickyError());
2240                break;
2241            }
2242
2243            status_t err = onQueueInputBuffer(msg);
2244
2245            PostReplyWithError(replyID, err);
2246            break;
2247        }
2248
2249        case kWhatDequeueOutputBuffer:
2250        {
2251            sp<AReplyToken> replyID;
2252            CHECK(msg->senderAwaitsResponse(&replyID));
2253
2254            if (mFlags & kFlagIsAsync) {
2255                ALOGE("dequeueOutputBuffer can't be used in async mode");
2256                PostReplyWithError(replyID, INVALID_OPERATION);
2257                break;
2258            }
2259
2260            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
2261                break;
2262            }
2263
2264            int64_t timeoutUs;
2265            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
2266
2267            if (timeoutUs == 0ll) {
2268                PostReplyWithError(replyID, -EAGAIN);
2269                break;
2270            }
2271
2272            mFlags |= kFlagDequeueOutputPending;
2273            mDequeueOutputReplyID = replyID;
2274
2275            if (timeoutUs > 0ll) {
2276                sp<AMessage> timeoutMsg =
2277                    new AMessage(kWhatDequeueOutputTimedOut, this);
2278                timeoutMsg->setInt32(
2279                        "generation", ++mDequeueOutputTimeoutGeneration);
2280                timeoutMsg->post(timeoutUs);
2281            }
2282            break;
2283        }
2284
2285        case kWhatDequeueOutputTimedOut:
2286        {
2287            int32_t generation;
2288            CHECK(msg->findInt32("generation", &generation));
2289
2290            if (generation != mDequeueOutputTimeoutGeneration) {
2291                // Obsolete
2292                break;
2293            }
2294
2295            CHECK(mFlags & kFlagDequeueOutputPending);
2296
2297            PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
2298
2299            mFlags &= ~kFlagDequeueOutputPending;
2300            mDequeueOutputReplyID = 0;
2301            break;
2302        }
2303
2304        case kWhatReleaseOutputBuffer:
2305        {
2306            sp<AReplyToken> replyID;
2307            CHECK(msg->senderAwaitsResponse(&replyID));
2308
2309            if (!isExecuting()) {
2310                PostReplyWithError(replyID, INVALID_OPERATION);
2311                break;
2312            } else if (mFlags & kFlagStickyError) {
2313                PostReplyWithError(replyID, getStickyError());
2314                break;
2315            }
2316
2317            status_t err = onReleaseOutputBuffer(msg);
2318
2319            PostReplyWithError(replyID, err);
2320            break;
2321        }
2322
2323        case kWhatSignalEndOfInputStream:
2324        {
2325            sp<AReplyToken> replyID;
2326            CHECK(msg->senderAwaitsResponse(&replyID));
2327
2328            if (!isExecuting() || !mHaveInputSurface) {
2329                PostReplyWithError(replyID, INVALID_OPERATION);
2330                break;
2331            } else if (mFlags & kFlagStickyError) {
2332                PostReplyWithError(replyID, getStickyError());
2333                break;
2334            }
2335
2336            mReplyID = replyID;
2337            mCodec->signalEndOfInputStream();
2338            break;
2339        }
2340
2341        case kWhatGetBuffers:
2342        {
2343            sp<AReplyToken> replyID;
2344            CHECK(msg->senderAwaitsResponse(&replyID));
2345            // Unfortunately widevine legacy source requires knowing all of the
2346            // codec input buffers, so we have to provide them even in async mode.
2347            int32_t widevine = 0;
2348            msg->findInt32("widevine", &widevine);
2349
2350            if (!isExecuting() || ((mFlags & kFlagIsAsync) && !widevine)) {
2351                PostReplyWithError(replyID, INVALID_OPERATION);
2352                break;
2353            } else if (mFlags & kFlagStickyError) {
2354                PostReplyWithError(replyID, getStickyError());
2355                break;
2356            }
2357
2358            int32_t portIndex;
2359            CHECK(msg->findInt32("portIndex", &portIndex));
2360
2361            Vector<sp<MediaCodecBuffer> > *dstBuffers;
2362            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
2363
2364            dstBuffers->clear();
2365            // If we're using input surface (either non-persistent created by
2366            // createInputSurface(), or persistent set by setInputSurface()),
2367            // give the client an empty input buffers array.
2368            if (portIndex != kPortIndexInput || !mHaveInputSurface) {
2369                const Vector<sp<MediaCodecBuffer>> &srcBuffers = mPortBufferArrays[portIndex];
2370
2371                for (size_t i = 0; i < srcBuffers.size(); ++i) {
2372                    dstBuffers->push_back(srcBuffers[i]);
2373                }
2374            }
2375
2376            (new AMessage)->postReply(replyID);
2377            break;
2378        }
2379
2380        case kWhatFlush:
2381        {
2382            sp<AReplyToken> replyID;
2383            CHECK(msg->senderAwaitsResponse(&replyID));
2384
2385            if (!isExecuting()) {
2386                PostReplyWithError(replyID, INVALID_OPERATION);
2387                break;
2388            } else if (mFlags & kFlagStickyError) {
2389                PostReplyWithError(replyID, getStickyError());
2390                break;
2391            }
2392
2393            mReplyID = replyID;
2394            // TODO: skip flushing if already FLUSHED
2395            setState(FLUSHING);
2396
2397            mCodec->signalFlush();
2398            returnBuffersToCodec();
2399            break;
2400        }
2401
2402        case kWhatGetInputFormat:
2403        case kWhatGetOutputFormat:
2404        {
2405            sp<AMessage> format =
2406                (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
2407
2408            sp<AReplyToken> replyID;
2409            CHECK(msg->senderAwaitsResponse(&replyID));
2410
2411            if ((mState != CONFIGURED && mState != STARTING &&
2412                 mState != STARTED && mState != FLUSHING &&
2413                 mState != FLUSHED)
2414                    || format == NULL) {
2415                PostReplyWithError(replyID, INVALID_OPERATION);
2416                break;
2417            } else if (mFlags & kFlagStickyError) {
2418                PostReplyWithError(replyID, getStickyError());
2419                break;
2420            }
2421
2422            sp<AMessage> response = new AMessage;
2423            response->setMessage("format", format);
2424            response->postReply(replyID);
2425            break;
2426        }
2427
2428        case kWhatRequestIDRFrame:
2429        {
2430            mCodec->signalRequestIDRFrame();
2431            break;
2432        }
2433
2434        case kWhatRequestActivityNotification:
2435        {
2436            CHECK(mActivityNotify == NULL);
2437            CHECK(msg->findMessage("notify", &mActivityNotify));
2438
2439            postActivityNotificationIfPossible();
2440            break;
2441        }
2442
2443        case kWhatGetName:
2444        {
2445            sp<AReplyToken> replyID;
2446            CHECK(msg->senderAwaitsResponse(&replyID));
2447
2448            if (mComponentName.empty()) {
2449                PostReplyWithError(replyID, INVALID_OPERATION);
2450                break;
2451            }
2452
2453            sp<AMessage> response = new AMessage;
2454            response->setString("name", mComponentName.c_str());
2455            response->postReply(replyID);
2456            break;
2457        }
2458
2459        case kWhatSetParameters:
2460        {
2461            sp<AReplyToken> replyID;
2462            CHECK(msg->senderAwaitsResponse(&replyID));
2463
2464            sp<AMessage> params;
2465            CHECK(msg->findMessage("params", &params));
2466
2467            status_t err = onSetParameters(params);
2468
2469            PostReplyWithError(replyID, err);
2470            break;
2471        }
2472
2473        default:
2474            TRESPASS();
2475    }
2476}
2477
2478void MediaCodec::extractCSD(const sp<AMessage> &format) {
2479    mCSD.clear();
2480
2481    size_t i = 0;
2482    for (;;) {
2483        sp<ABuffer> csd;
2484        if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
2485            break;
2486        }
2487        if (csd->size() == 0) {
2488            ALOGW("csd-%zu size is 0", i);
2489        }
2490
2491        mCSD.push_back(csd);
2492        ++i;
2493    }
2494
2495    ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
2496}
2497
2498status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
2499    CHECK(!mCSD.empty());
2500
2501    const BufferInfo *info =
2502        &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
2503
2504    sp<ABuffer> csd = *mCSD.begin();
2505    mCSD.erase(mCSD.begin());
2506
2507    const sp<MediaCodecBuffer> &codecInputData = info->mData;
2508
2509    if (csd->size() > codecInputData->capacity()) {
2510        return -EINVAL;
2511    }
2512
2513    memcpy(codecInputData->data(), csd->data(), csd->size());
2514
2515    AString errorDetailMsg;
2516
2517    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
2518    msg->setSize("index", bufferIndex);
2519    msg->setSize("offset", 0);
2520    msg->setSize("size", csd->size());
2521    msg->setInt64("timeUs", 0ll);
2522    msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
2523    msg->setPointer("errorDetailMsg", &errorDetailMsg);
2524
2525    return onQueueInputBuffer(msg);
2526}
2527
2528void MediaCodec::setState(State newState) {
2529    if (newState == INITIALIZED || newState == UNINITIALIZED) {
2530        delete mSoftRenderer;
2531        mSoftRenderer = NULL;
2532
2533        mCrypto.clear();
2534        handleSetSurface(NULL);
2535
2536        mInputFormat.clear();
2537        mOutputFormat.clear();
2538        mFlags &= ~kFlagOutputFormatChanged;
2539        mFlags &= ~kFlagOutputBuffersChanged;
2540        mFlags &= ~kFlagStickyError;
2541        mFlags &= ~kFlagIsEncoder;
2542        mFlags &= ~kFlagIsAsync;
2543        mStickyError = OK;
2544
2545        mActivityNotify.clear();
2546        mCallback.clear();
2547    }
2548
2549    if (newState == UNINITIALIZED) {
2550        // return any straggling buffers, e.g. if we got here on an error
2551        returnBuffersToCodec();
2552
2553        // The component is gone, mediaserver's probably back up already
2554        // but should definitely be back up should we try to instantiate
2555        // another component.. and the cycle continues.
2556        mFlags &= ~kFlagSawMediaServerDie;
2557    }
2558
2559    mState = newState;
2560
2561    cancelPendingDequeueOperations();
2562
2563    updateBatteryStat();
2564}
2565
2566void MediaCodec::returnBuffersToCodec(bool isReclaim) {
2567    returnBuffersToCodecOnPort(kPortIndexInput, isReclaim);
2568    returnBuffersToCodecOnPort(kPortIndexOutput, isReclaim);
2569}
2570
2571void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) {
2572    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2573    Mutex::Autolock al(mBufferLock);
2574
2575    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2576
2577    for (size_t i = 0; i < buffers->size(); ++i) {
2578        BufferInfo *info = &buffers->editItemAt(i);
2579
2580        if (info->mNotify != NULL) {
2581            sp<AMessage> msg = info->mNotify;
2582            info->mNotify = NULL;
2583            msg->setObject("buffer", (portIndex == kPortIndexInput && mCrypto != NULL)
2584                    ? info->mSecureData : info->mData);
2585            if (isReclaim && info->mOwnedByClient) {
2586                ALOGD("port %d buffer %zu still owned by client when codec is reclaimed",
2587                        portIndex, i);
2588            } else {
2589                info->mOwnedByClient = false;
2590                info->mData.clear();
2591                info->mSecureData.clear();
2592            }
2593
2594            if (portIndex == kPortIndexInput) {
2595                /* no error, just returning buffers */
2596                msg->setInt32("err", OK);
2597            }
2598            msg->post();
2599        }
2600    }
2601
2602    mAvailPortBuffers[portIndex].clear();
2603}
2604
2605size_t MediaCodec::updateBuffers(
2606        int32_t portIndex, const sp<AMessage> &msg) {
2607    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2608
2609    uint32_t bufferID;
2610    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
2611    sp<RefBase> obj;
2612    CHECK(msg->findObject("buffer", &obj));
2613    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
2614
2615    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2616
2617    for (size_t i = 0; i < buffers->size(); ++i) {
2618        BufferInfo *info = &buffers->editItemAt(i);
2619
2620        if (info->mBufferID == bufferID) {
2621            CHECK(info->mNotify == NULL);
2622            CHECK(msg->findMessage("reply", &info->mNotify));
2623
2624            if (portIndex == kPortIndexInput && mCrypto != NULL) {
2625                info->mSecureData = buffer;
2626                info->mData = mPortBufferArrays[portIndex][i];
2627            } else {
2628                info->mData = buffer;
2629            }
2630            mAvailPortBuffers[portIndex].push_back(i);
2631
2632            return i;
2633        }
2634    }
2635
2636    TRESPASS();
2637
2638    return 0;
2639}
2640
2641status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
2642    size_t index;
2643    size_t offset;
2644    size_t size;
2645    int64_t timeUs;
2646    uint32_t flags;
2647    CHECK(msg->findSize("index", &index));
2648    CHECK(msg->findSize("offset", &offset));
2649    CHECK(msg->findInt64("timeUs", &timeUs));
2650    CHECK(msg->findInt32("flags", (int32_t *)&flags));
2651
2652    const CryptoPlugin::SubSample *subSamples;
2653    size_t numSubSamples;
2654    const uint8_t *key;
2655    const uint8_t *iv;
2656    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
2657
2658    // We allow the simpler queueInputBuffer API to be used even in
2659    // secure mode, by fabricating a single unencrypted subSample.
2660    CryptoPlugin::SubSample ss;
2661    CryptoPlugin::Pattern pattern;
2662
2663    if (msg->findSize("size", &size)) {
2664        if (mCrypto != NULL) {
2665            ss.mNumBytesOfClearData = size;
2666            ss.mNumBytesOfEncryptedData = 0;
2667
2668            subSamples = &ss;
2669            numSubSamples = 1;
2670            key = NULL;
2671            iv = NULL;
2672            pattern.mEncryptBlocks = 0;
2673            pattern.mSkipBlocks = 0;
2674        }
2675    } else {
2676        if (mCrypto == NULL) {
2677            return -EINVAL;
2678        }
2679
2680        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
2681        CHECK(msg->findSize("numSubSamples", &numSubSamples));
2682        CHECK(msg->findPointer("key", (void **)&key));
2683        CHECK(msg->findPointer("iv", (void **)&iv));
2684        CHECK(msg->findInt32("encryptBlocks", (int32_t *)&pattern.mEncryptBlocks));
2685        CHECK(msg->findInt32("skipBlocks", (int32_t *)&pattern.mSkipBlocks));
2686
2687        int32_t tmp;
2688        CHECK(msg->findInt32("mode", &tmp));
2689
2690        mode = (CryptoPlugin::Mode)tmp;
2691
2692        size = 0;
2693        for (size_t i = 0; i < numSubSamples; ++i) {
2694            size += subSamples[i].mNumBytesOfClearData;
2695            size += subSamples[i].mNumBytesOfEncryptedData;
2696        }
2697    }
2698
2699    if (index >= mPortBuffers[kPortIndexInput].size()) {
2700        return -ERANGE;
2701    }
2702
2703    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
2704
2705    if (info->mNotify == NULL || !info->mOwnedByClient) {
2706        return -EACCES;
2707    }
2708
2709    if (offset + size > info->mData->capacity()) {
2710        return -EINVAL;
2711    }
2712
2713    sp<AMessage> reply = info->mNotify;
2714    info->mData->setRange(offset, size);
2715
2716    sp<MediaCodecBuffer> buffer = info->mData;
2717    if (mCrypto != NULL) {
2718        AString *errorDetailMsg;
2719        CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
2720
2721        void *dst_pointer = nullptr;
2722        ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
2723
2724        if ((mFlags & kFlagIsSecure) == 0) {
2725            dst_pointer = info->mSecureData->base();
2726            dst_type = ICrypto::kDestinationTypeVmPointer;
2727        } else {
2728            sp<SecureBuffer> secureData = static_cast<SecureBuffer *>(info->mSecureData.get());
2729            dst_pointer = secureData->getDestinationPointer();
2730            dst_type = secureData->getDestinationType();
2731        }
2732
2733        ssize_t result = mCrypto->decrypt(
2734                dst_type,
2735                key,
2736                iv,
2737                mode,
2738                pattern,
2739                info->mSharedEncryptedBuffer,
2740                offset,
2741                subSamples,
2742                numSubSamples,
2743                dst_pointer,
2744                errorDetailMsg);
2745
2746        if (result < 0) {
2747            return result;
2748        }
2749
2750        info->mSecureData->setRange(0, result);
2751        buffer = info->mSecureData;
2752    }
2753    buffer->meta()->setInt64("timeUs", timeUs);
2754
2755    if (flags & BUFFER_FLAG_EOS) {
2756        buffer->meta()->setInt32("eos", true);
2757    }
2758
2759    if (flags & BUFFER_FLAG_CODECCONFIG) {
2760        buffer->meta()->setInt32("csd", true);
2761    }
2762
2763    // synchronization boundary for getBufferAndFormat
2764    {
2765        Mutex::Autolock al(mBufferLock);
2766        info->mOwnedByClient = false;
2767    }
2768    info->mData.clear();
2769    info->mSecureData.clear();
2770    reply->setObject("buffer", buffer);
2771    reply->post();
2772
2773    info->mNotify = NULL;
2774
2775    return OK;
2776}
2777
2778//static
2779size_t MediaCodec::CreateFramesRenderedMessage(
2780        const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
2781    size_t index = 0;
2782
2783    for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
2784            it != done.cend(); ++it) {
2785        if (it->getRenderTimeNs() < 0) {
2786            continue; // dropped frame from tracking
2787        }
2788        msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
2789        msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
2790        ++index;
2791    }
2792    return index;
2793}
2794
2795status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
2796    size_t index;
2797    CHECK(msg->findSize("index", &index));
2798
2799    int32_t render;
2800    if (!msg->findInt32("render", &render)) {
2801        render = 0;
2802    }
2803
2804    if (!isExecuting()) {
2805        return -EINVAL;
2806    }
2807
2808    if (index >= mPortBuffers[kPortIndexOutput].size()) {
2809        return -ERANGE;
2810    }
2811
2812    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
2813
2814    if (info->mNotify == NULL || !info->mOwnedByClient) {
2815        return -EACCES;
2816    }
2817
2818    // synchronization boundary for getBufferAndFormat
2819    {
2820        Mutex::Autolock al(mBufferLock);
2821        info->mOwnedByClient = false;
2822    }
2823
2824    if (render && info->mData != NULL && info->mData->size() != 0) {
2825        info->mNotify->setInt32("render", true);
2826
2827        int64_t mediaTimeUs = -1;
2828        info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
2829
2830        int64_t renderTimeNs = 0;
2831        if (!msg->findInt64("timestampNs", &renderTimeNs)) {
2832            // use media timestamp if client did not request a specific render timestamp
2833            ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
2834            renderTimeNs = mediaTimeUs * 1000;
2835        }
2836        info->mNotify->setInt64("timestampNs", renderTimeNs);
2837
2838        if (mSoftRenderer != NULL) {
2839            std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render(
2840                    info->mData->data(), info->mData->size(),
2841                    mediaTimeUs, renderTimeNs, NULL, info->mData->format());
2842
2843            // if we are running, notify rendered frames
2844            if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) {
2845                sp<AMessage> notify = mOnFrameRenderedNotification->dup();
2846                sp<AMessage> data = new AMessage;
2847                if (CreateFramesRenderedMessage(doneFrames, data)) {
2848                    notify->setMessage("data", data);
2849                    notify->post();
2850                }
2851            }
2852        }
2853    }
2854
2855    info->mNotify->setObject("buffer", info->mData);
2856    info->mData.clear();
2857    info->mNotify->post();
2858    info->mNotify.clear();
2859
2860    return OK;
2861}
2862
2863ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
2864    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2865
2866    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
2867
2868    if (availBuffers->empty()) {
2869        return -EAGAIN;
2870    }
2871
2872    size_t index = *availBuffers->begin();
2873    availBuffers->erase(availBuffers->begin());
2874
2875    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
2876    CHECK(!info->mOwnedByClient);
2877    {
2878        Mutex::Autolock al(mBufferLock);
2879        info->mOwnedByClient = true;
2880
2881        // set image-data
2882        if (info->mData->format() != NULL) {
2883            sp<ABuffer> imageData;
2884            if (info->mData->format()->findBuffer("image-data", &imageData)) {
2885                info->mData->meta()->setBuffer("image-data", imageData);
2886            }
2887            int32_t left, top, right, bottom;
2888            if (info->mData->format()->findRect("crop", &left, &top, &right, &bottom)) {
2889                info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
2890            }
2891        }
2892    }
2893
2894    return index;
2895}
2896
2897status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
2898    status_t err = OK;
2899    if (surface != NULL) {
2900        uint64_t oldId, newId;
2901        if (mSurface != NULL
2902                && surface->getUniqueId(&newId) == NO_ERROR
2903                && mSurface->getUniqueId(&oldId) == NO_ERROR
2904                && newId == oldId) {
2905            ALOGI("[%s] connecting to the same surface. Nothing to do.", mComponentName.c_str());
2906            return ALREADY_EXISTS;
2907        }
2908
2909        err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2910        if (err == OK) {
2911            // Require a fresh set of buffers after each connect by using a unique generation
2912            // number. Rely on the fact that max supported process id by Linux is 2^22.
2913            // PID is never 0 so we don't have to worry that we use the default generation of 0.
2914            // TODO: come up with a unique scheme if other producers also set the generation number.
2915            static uint32_t mSurfaceGeneration = 0;
2916            uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
2917            surface->setGenerationNumber(generation);
2918            ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
2919
2920            // HACK: clear any free buffers. Remove when connect will automatically do this.
2921            // This is needed as the consumer may be holding onto stale frames that it can reattach
2922            // to this surface after disconnect/connect, and those free frames would inherit the new
2923            // generation number. Disconnecting after setting a unique generation prevents this.
2924            native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2925            err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2926        }
2927
2928        if (err != OK) {
2929            ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
2930        }
2931    }
2932    // do not return ALREADY_EXISTS unless surfaces are the same
2933    return err == ALREADY_EXISTS ? BAD_VALUE : err;
2934}
2935
2936status_t MediaCodec::disconnectFromSurface() {
2937    status_t err = OK;
2938    if (mSurface != NULL) {
2939        // Resetting generation is not technically needed, but there is no need to keep it either
2940        mSurface->setGenerationNumber(0);
2941        err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
2942        if (err != OK) {
2943            ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
2944        }
2945        // assume disconnected even on error
2946        mSurface.clear();
2947    }
2948    return err;
2949}
2950
2951status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
2952    status_t err = OK;
2953    if (mSurface != NULL) {
2954        (void)disconnectFromSurface();
2955    }
2956    if (surface != NULL) {
2957        err = connectToSurface(surface);
2958        if (err == OK) {
2959            mSurface = surface;
2960        }
2961    }
2962    return err;
2963}
2964
2965void MediaCodec::onInputBufferAvailable() {
2966    int32_t index;
2967    while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
2968        sp<AMessage> msg = mCallback->dup();
2969        msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
2970        msg->setInt32("index", index);
2971        msg->post();
2972    }
2973}
2974
2975void MediaCodec::onOutputBufferAvailable() {
2976    int32_t index;
2977    while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
2978        const sp<MediaCodecBuffer> &buffer =
2979            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
2980        sp<AMessage> msg = mCallback->dup();
2981        msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
2982        msg->setInt32("index", index);
2983        msg->setSize("offset", buffer->offset());
2984        msg->setSize("size", buffer->size());
2985
2986        int64_t timeUs;
2987        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2988
2989        msg->setInt64("timeUs", timeUs);
2990
2991        int32_t omxFlags;
2992        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
2993
2994        uint32_t flags = 0;
2995        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
2996            flags |= BUFFER_FLAG_SYNCFRAME;
2997        }
2998        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
2999            flags |= BUFFER_FLAG_CODECCONFIG;
3000        }
3001        if (omxFlags & OMX_BUFFERFLAG_EOS) {
3002            flags |= BUFFER_FLAG_EOS;
3003        }
3004
3005        msg->setInt32("flags", flags);
3006
3007        msg->post();
3008    }
3009}
3010
3011void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
3012    if (mCallback != NULL) {
3013        sp<AMessage> msg = mCallback->dup();
3014        msg->setInt32("callbackID", CB_ERROR);
3015        msg->setInt32("err", err);
3016        msg->setInt32("actionCode", actionCode);
3017
3018        if (detail != NULL) {
3019            msg->setString("detail", detail);
3020        }
3021
3022        msg->post();
3023    }
3024}
3025
3026void MediaCodec::onOutputFormatChanged() {
3027    if (mCallback != NULL) {
3028        sp<AMessage> msg = mCallback->dup();
3029        msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
3030        msg->setMessage("format", mOutputFormat);
3031        msg->post();
3032    }
3033}
3034
3035
3036void MediaCodec::postActivityNotificationIfPossible() {
3037    if (mActivityNotify == NULL) {
3038        return;
3039    }
3040
3041    bool isErrorOrOutputChanged =
3042            (mFlags & (kFlagStickyError
3043                    | kFlagOutputBuffersChanged
3044                    | kFlagOutputFormatChanged));
3045
3046    if (isErrorOrOutputChanged
3047            || !mAvailPortBuffers[kPortIndexInput].empty()
3048            || !mAvailPortBuffers[kPortIndexOutput].empty()) {
3049        mActivityNotify->setInt32("input-buffers",
3050                mAvailPortBuffers[kPortIndexInput].size());
3051
3052        if (isErrorOrOutputChanged) {
3053            // we want consumer to dequeue as many times as it can
3054            mActivityNotify->setInt32("output-buffers", INT32_MAX);
3055        } else {
3056            mActivityNotify->setInt32("output-buffers",
3057                    mAvailPortBuffers[kPortIndexOutput].size());
3058        }
3059        mActivityNotify->post();
3060        mActivityNotify.clear();
3061    }
3062}
3063
3064status_t MediaCodec::setParameters(const sp<AMessage> &params) {
3065    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
3066    msg->setMessage("params", params);
3067
3068    sp<AMessage> response;
3069    return PostAndAwaitResponse(msg, &response);
3070}
3071
3072status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
3073    mCodec->signalSetParameters(params);
3074
3075    return OK;
3076}
3077
3078status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
3079        const sp<MediaCodecBuffer> &buffer) {
3080    AString mime;
3081    CHECK(mOutputFormat->findString("mime", &mime));
3082
3083    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
3084        // Codec specific data should be SPS and PPS in a single buffer,
3085        // each prefixed by a startcode (0x00 0x00 0x00 0x01).
3086        // We separate the two and put them into the output format
3087        // under the keys "csd-0" and "csd-1".
3088
3089        unsigned csdIndex = 0;
3090
3091        const uint8_t *data = buffer->data();
3092        size_t size = buffer->size();
3093
3094        const uint8_t *nalStart;
3095        size_t nalSize;
3096        while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
3097            sp<ABuffer> csd = new ABuffer(nalSize + 4);
3098            memcpy(csd->data(), "\x00\x00\x00\x01", 4);
3099            memcpy(csd->data() + 4, nalStart, nalSize);
3100
3101            mOutputFormat->setBuffer(
3102                    AStringPrintf("csd-%u", csdIndex).c_str(), csd);
3103
3104            ++csdIndex;
3105        }
3106
3107        if (csdIndex != 2) {
3108            return ERROR_MALFORMED;
3109        }
3110    } else {
3111        // For everything else we just stash the codec specific data into
3112        // the output format as a single piece of csd under "csd-0".
3113        sp<ABuffer> csd = new ABuffer(buffer->size());
3114        memcpy(csd->data(), buffer->data(), buffer->size());
3115        csd->setRange(0, buffer->size());
3116        mOutputFormat->setBuffer("csd-0", csd);
3117    }
3118
3119    return OK;
3120}
3121
3122void MediaCodec::updateBatteryStat() {
3123    if (!mIsVideo) {
3124        return;
3125    }
3126
3127    if (mState == CONFIGURED && !mBatteryStatNotified) {
3128        BatteryNotifier::getInstance().noteStartVideo(mUid);
3129        mBatteryStatNotified = true;
3130    } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
3131        BatteryNotifier::getInstance().noteStopVideo(mUid);
3132        mBatteryStatNotified = false;
3133    }
3134}
3135
3136}  // namespace android
3137