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