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