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