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