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