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