MediaCodec.cpp revision 47734c9509ecb472c2844cae46e2d916b9358321
1/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "MediaCodec"
19#include <inttypes.h>
20
21#include "include/avc_utils.h"
22#include "include/SoftwareRenderer.h"
23
24#include <binder/IMemory.h>
25#include <binder/IPCThreadState.h>
26#include <binder/IServiceManager.h>
27#include <binder/MemoryDealer.h>
28#include <gui/BufferQueue.h>
29#include <gui/Surface.h>
30#include <media/ICrypto.h>
31#include <media/IOMX.h>
32#include <media/IResourceManagerService.h>
33#include <media/stagefright/foundation/ABuffer.h>
34#include <media/stagefright/foundation/ADebug.h>
35#include <media/stagefright/foundation/AMessage.h>
36#include <media/stagefright/foundation/AString.h>
37#include <media/stagefright/foundation/hexdump.h>
38#include <media/stagefright/ACodec.h>
39#include <media/stagefright/BufferProducerWrapper.h>
40#include <media/stagefright/MediaCodec.h>
41#include <media/stagefright/MediaCodecList.h>
42#include <media/stagefright/MediaDefs.h>
43#include <media/stagefright/MediaErrors.h>
44#include <media/stagefright/MediaFilter.h>
45#include <media/stagefright/MetaData.h>
46#include <media/stagefright/OMXClient.h>
47#include <media/stagefright/PersistentSurface.h>
48#include <media/stagefright/SurfaceUtils.h>
49#include <mediautils/BatteryNotifier.h>
50#include <private/android_filesystem_config.h>
51#include <utils/Log.h>
52#include <utils/Singleton.h>
53
54namespace android {
55
56static int64_t getId(sp<IResourceManagerClient> client) {
57    return (int64_t) client.get();
58}
59
60static bool isResourceError(status_t err) {
61    return (err == NO_MEMORY);
62}
63
64static const int kMaxRetry = 2;
65static const int kMaxReclaimWaitTimeInUs = 500000;  // 0.5s
66
67struct ResourceManagerClient : public BnResourceManagerClient {
68    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 == BAD_VALUE) {
1795                            // assuming reconnecting to same surface
1796                            // TODO: check if it is the same surface
1797                            err = OK;
1798                        } else {
1799                            if (err == OK) {
1800                                if (mFlags & kFlagUsesSoftwareRenderer) {
1801                                    if (mSoftRenderer != NULL
1802                                            && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1803                                        pushBlankBuffersToNativeWindow(mSurface.get());
1804                                    }
1805                                    mSoftRenderer = new SoftwareRenderer(surface);
1806                                    // TODO: check if this was successful
1807                                } else {
1808                                    err = mCodec->setSurface(surface);
1809                                }
1810                            }
1811                            if (err == OK) {
1812                                (void)disconnectFromSurface();
1813                                mSurface = surface;
1814                            }
1815                        }
1816                    }
1817                    break;
1818                }
1819
1820                default:
1821                    err = INVALID_OPERATION;
1822                    break;
1823            }
1824
1825            PostReplyWithError(replyID, err);
1826            break;
1827        }
1828
1829        case kWhatCreateInputSurface:
1830        case kWhatSetInputSurface:
1831        {
1832            sp<AReplyToken> replyID;
1833            CHECK(msg->senderAwaitsResponse(&replyID));
1834
1835            // Must be configured, but can't have been started yet.
1836            if (mState != CONFIGURED) {
1837                PostReplyWithError(replyID, INVALID_OPERATION);
1838                break;
1839            }
1840
1841            mReplyID = replyID;
1842            if (msg->what() == kWhatCreateInputSurface) {
1843                mCodec->initiateCreateInputSurface();
1844            } else {
1845                sp<RefBase> obj;
1846                CHECK(msg->findObject("input-surface", &obj));
1847
1848                mCodec->initiateSetInputSurface(
1849                        static_cast<PersistentSurface *>(obj.get()));
1850            }
1851            break;
1852        }
1853        case kWhatStart:
1854        {
1855            sp<AReplyToken> replyID;
1856            CHECK(msg->senderAwaitsResponse(&replyID));
1857
1858            if (mState == FLUSHED) {
1859                setState(STARTED);
1860                if (mHavePendingInputBuffers) {
1861                    onInputBufferAvailable();
1862                    mHavePendingInputBuffers = false;
1863                }
1864                mCodec->signalResume();
1865                PostReplyWithError(replyID, OK);
1866                break;
1867            } else if (mState != CONFIGURED) {
1868                PostReplyWithError(replyID, INVALID_OPERATION);
1869                break;
1870            }
1871
1872            mReplyID = replyID;
1873            setState(STARTING);
1874
1875            mCodec->initiateStart();
1876            break;
1877        }
1878
1879        case kWhatStop:
1880        case kWhatRelease:
1881        {
1882            State targetState =
1883                (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
1884
1885            sp<AReplyToken> replyID;
1886            CHECK(msg->senderAwaitsResponse(&replyID));
1887
1888            // already stopped/released
1889            if (mState == UNINITIALIZED && mReleasedByResourceManager) {
1890                sp<AMessage> response = new AMessage;
1891                response->setInt32("err", OK);
1892                response->postReply(replyID);
1893                break;
1894            }
1895
1896            int32_t reclaimed = 0;
1897            msg->findInt32("reclaimed", &reclaimed);
1898            if (reclaimed) {
1899                mReleasedByResourceManager = true;
1900
1901                int32_t force = 0;
1902                msg->findInt32("force", &force);
1903                if (!force && hasPendingBuffer()) {
1904                    ALOGW("Can't reclaim codec right now due to pending buffers.");
1905
1906                    // return WOULD_BLOCK to ask resource manager to retry later.
1907                    sp<AMessage> response = new AMessage;
1908                    response->setInt32("err", WOULD_BLOCK);
1909                    response->postReply(replyID);
1910
1911                    // notify the async client
1912                    if (mFlags & kFlagIsAsync) {
1913                        onError(DEAD_OBJECT, ACTION_CODE_FATAL);
1914                    }
1915                    break;
1916                }
1917            }
1918
1919            if (!((mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED) // See 1
1920                    && mState != INITIALIZED
1921                    && mState != CONFIGURED && !isExecuting()) {
1922                // 1) Permit release to shut down the component if allocated.
1923                //
1924                // 2) We may be in "UNINITIALIZED" state already and
1925                // also shutdown the encoder/decoder without the
1926                // client being aware of this if media server died while
1927                // we were being stopped. The client would assume that
1928                // after stop() returned, it would be safe to call release()
1929                // and it should be in this case, no harm to allow a release()
1930                // if we're already uninitialized.
1931                sp<AMessage> response = new AMessage;
1932                // TODO: we shouldn't throw an exception for stop/release. Change this to wait until
1933                // the previous stop/release completes and then reply with OK.
1934                status_t err = mState == targetState ? OK : INVALID_OPERATION;
1935                response->setInt32("err", err);
1936                if (err == OK && targetState == UNINITIALIZED) {
1937                    mComponentName.clear();
1938                }
1939                response->postReply(replyID);
1940                break;
1941            }
1942
1943            if (mFlags & kFlagSawMediaServerDie) {
1944                // It's dead, Jim. Don't expect initiateShutdown to yield
1945                // any useful results now...
1946                setState(UNINITIALIZED);
1947                if (targetState == UNINITIALIZED) {
1948                    mComponentName.clear();
1949                }
1950                (new AMessage)->postReply(replyID);
1951                break;
1952            }
1953
1954            mReplyID = replyID;
1955            setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
1956
1957            mCodec->initiateShutdown(
1958                    msg->what() == kWhatStop /* keepComponentAllocated */);
1959
1960            returnBuffersToCodec(reclaimed);
1961
1962            if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1963                pushBlankBuffersToNativeWindow(mSurface.get());
1964            }
1965            break;
1966        }
1967
1968        case kWhatDequeueInputBuffer:
1969        {
1970            sp<AReplyToken> replyID;
1971            CHECK(msg->senderAwaitsResponse(&replyID));
1972
1973            if (mFlags & kFlagIsAsync) {
1974                ALOGE("dequeueOutputBuffer can't be used in async mode");
1975                PostReplyWithError(replyID, INVALID_OPERATION);
1976                break;
1977            }
1978
1979            if (mHaveInputSurface) {
1980                ALOGE("dequeueInputBuffer can't be used with input surface");
1981                PostReplyWithError(replyID, INVALID_OPERATION);
1982                break;
1983            }
1984
1985            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
1986                break;
1987            }
1988
1989            int64_t timeoutUs;
1990            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1991
1992            if (timeoutUs == 0ll) {
1993                PostReplyWithError(replyID, -EAGAIN);
1994                break;
1995            }
1996
1997            mFlags |= kFlagDequeueInputPending;
1998            mDequeueInputReplyID = replyID;
1999
2000            if (timeoutUs > 0ll) {
2001                sp<AMessage> timeoutMsg =
2002                    new AMessage(kWhatDequeueInputTimedOut, this);
2003                timeoutMsg->setInt32(
2004                        "generation", ++mDequeueInputTimeoutGeneration);
2005                timeoutMsg->post(timeoutUs);
2006            }
2007            break;
2008        }
2009
2010        case kWhatDequeueInputTimedOut:
2011        {
2012            int32_t generation;
2013            CHECK(msg->findInt32("generation", &generation));
2014
2015            if (generation != mDequeueInputTimeoutGeneration) {
2016                // Obsolete
2017                break;
2018            }
2019
2020            CHECK(mFlags & kFlagDequeueInputPending);
2021
2022            PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
2023
2024            mFlags &= ~kFlagDequeueInputPending;
2025            mDequeueInputReplyID = 0;
2026            break;
2027        }
2028
2029        case kWhatQueueInputBuffer:
2030        {
2031            sp<AReplyToken> replyID;
2032            CHECK(msg->senderAwaitsResponse(&replyID));
2033
2034            if (!isExecuting()) {
2035                PostReplyWithError(replyID, INVALID_OPERATION);
2036                break;
2037            } else if (mFlags & kFlagStickyError) {
2038                PostReplyWithError(replyID, getStickyError());
2039                break;
2040            }
2041
2042            status_t err = onQueueInputBuffer(msg);
2043
2044            PostReplyWithError(replyID, err);
2045            break;
2046        }
2047
2048        case kWhatDequeueOutputBuffer:
2049        {
2050            sp<AReplyToken> replyID;
2051            CHECK(msg->senderAwaitsResponse(&replyID));
2052
2053            if (mFlags & kFlagIsAsync) {
2054                ALOGE("dequeueOutputBuffer can't be used in async mode");
2055                PostReplyWithError(replyID, INVALID_OPERATION);
2056                break;
2057            }
2058
2059            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
2060                break;
2061            }
2062
2063            int64_t timeoutUs;
2064            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
2065
2066            if (timeoutUs == 0ll) {
2067                PostReplyWithError(replyID, -EAGAIN);
2068                break;
2069            }
2070
2071            mFlags |= kFlagDequeueOutputPending;
2072            mDequeueOutputReplyID = replyID;
2073
2074            if (timeoutUs > 0ll) {
2075                sp<AMessage> timeoutMsg =
2076                    new AMessage(kWhatDequeueOutputTimedOut, this);
2077                timeoutMsg->setInt32(
2078                        "generation", ++mDequeueOutputTimeoutGeneration);
2079                timeoutMsg->post(timeoutUs);
2080            }
2081            break;
2082        }
2083
2084        case kWhatDequeueOutputTimedOut:
2085        {
2086            int32_t generation;
2087            CHECK(msg->findInt32("generation", &generation));
2088
2089            if (generation != mDequeueOutputTimeoutGeneration) {
2090                // Obsolete
2091                break;
2092            }
2093
2094            CHECK(mFlags & kFlagDequeueOutputPending);
2095
2096            PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
2097
2098            mFlags &= ~kFlagDequeueOutputPending;
2099            mDequeueOutputReplyID = 0;
2100            break;
2101        }
2102
2103        case kWhatReleaseOutputBuffer:
2104        {
2105            sp<AReplyToken> replyID;
2106            CHECK(msg->senderAwaitsResponse(&replyID));
2107
2108            if (!isExecuting()) {
2109                PostReplyWithError(replyID, INVALID_OPERATION);
2110                break;
2111            } else if (mFlags & kFlagStickyError) {
2112                PostReplyWithError(replyID, getStickyError());
2113                break;
2114            }
2115
2116            status_t err = onReleaseOutputBuffer(msg);
2117
2118            PostReplyWithError(replyID, err);
2119            break;
2120        }
2121
2122        case kWhatSignalEndOfInputStream:
2123        {
2124            sp<AReplyToken> replyID;
2125            CHECK(msg->senderAwaitsResponse(&replyID));
2126
2127            if (!isExecuting()) {
2128                PostReplyWithError(replyID, INVALID_OPERATION);
2129                break;
2130            } else if (mFlags & kFlagStickyError) {
2131                PostReplyWithError(replyID, getStickyError());
2132                break;
2133            }
2134
2135            mReplyID = replyID;
2136            mCodec->signalEndOfInputStream();
2137            break;
2138        }
2139
2140        case kWhatGetBuffers:
2141        {
2142            sp<AReplyToken> replyID;
2143            CHECK(msg->senderAwaitsResponse(&replyID));
2144            // Unfortunately widevine legacy source requires knowing all of the
2145            // codec input buffers, so we have to provide them even in async mode.
2146            int32_t widevine = 0;
2147            msg->findInt32("widevine", &widevine);
2148
2149            if (!isExecuting() || ((mFlags & kFlagIsAsync) && !widevine)) {
2150                PostReplyWithError(replyID, INVALID_OPERATION);
2151                break;
2152            } else if (mFlags & kFlagStickyError) {
2153                PostReplyWithError(replyID, getStickyError());
2154                break;
2155            }
2156
2157            int32_t portIndex;
2158            CHECK(msg->findInt32("portIndex", &portIndex));
2159
2160            Vector<sp<ABuffer> > *dstBuffers;
2161            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
2162
2163            dstBuffers->clear();
2164            const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
2165
2166            for (size_t i = 0; i < srcBuffers.size(); ++i) {
2167                const BufferInfo &info = srcBuffers.itemAt(i);
2168
2169                dstBuffers->push_back(
2170                        (portIndex == kPortIndexInput && mCrypto != NULL)
2171                                ? info.mEncryptedData : info.mData);
2172            }
2173
2174            (new AMessage)->postReply(replyID);
2175            break;
2176        }
2177
2178        case kWhatFlush:
2179        {
2180            sp<AReplyToken> replyID;
2181            CHECK(msg->senderAwaitsResponse(&replyID));
2182
2183            if (!isExecuting()) {
2184                PostReplyWithError(replyID, INVALID_OPERATION);
2185                break;
2186            } else if (mFlags & kFlagStickyError) {
2187                PostReplyWithError(replyID, getStickyError());
2188                break;
2189            }
2190
2191            mReplyID = replyID;
2192            // TODO: skip flushing if already FLUSHED
2193            setState(FLUSHING);
2194
2195            mCodec->signalFlush();
2196            returnBuffersToCodec();
2197            break;
2198        }
2199
2200        case kWhatGetInputFormat:
2201        case kWhatGetOutputFormat:
2202        {
2203            sp<AMessage> format =
2204                (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
2205
2206            sp<AReplyToken> replyID;
2207            CHECK(msg->senderAwaitsResponse(&replyID));
2208
2209            if ((mState != CONFIGURED && mState != STARTING &&
2210                 mState != STARTED && mState != FLUSHING &&
2211                 mState != FLUSHED)
2212                    || format == NULL) {
2213                PostReplyWithError(replyID, INVALID_OPERATION);
2214                break;
2215            } else if (mFlags & kFlagStickyError) {
2216                PostReplyWithError(replyID, getStickyError());
2217                break;
2218            }
2219
2220            sp<AMessage> response = new AMessage;
2221            response->setMessage("format", format);
2222            response->postReply(replyID);
2223            break;
2224        }
2225
2226        case kWhatRequestIDRFrame:
2227        {
2228            mCodec->signalRequestIDRFrame();
2229            break;
2230        }
2231
2232        case kWhatRequestActivityNotification:
2233        {
2234            CHECK(mActivityNotify == NULL);
2235            CHECK(msg->findMessage("notify", &mActivityNotify));
2236
2237            postActivityNotificationIfPossible();
2238            break;
2239        }
2240
2241        case kWhatGetName:
2242        {
2243            sp<AReplyToken> replyID;
2244            CHECK(msg->senderAwaitsResponse(&replyID));
2245
2246            if (mComponentName.empty()) {
2247                PostReplyWithError(replyID, INVALID_OPERATION);
2248                break;
2249            }
2250
2251            sp<AMessage> response = new AMessage;
2252            response->setString("name", mComponentName.c_str());
2253            response->postReply(replyID);
2254            break;
2255        }
2256
2257        case kWhatSetParameters:
2258        {
2259            sp<AReplyToken> replyID;
2260            CHECK(msg->senderAwaitsResponse(&replyID));
2261
2262            sp<AMessage> params;
2263            CHECK(msg->findMessage("params", &params));
2264
2265            status_t err = onSetParameters(params);
2266
2267            PostReplyWithError(replyID, err);
2268            break;
2269        }
2270
2271        default:
2272            TRESPASS();
2273    }
2274}
2275
2276void MediaCodec::extractCSD(const sp<AMessage> &format) {
2277    mCSD.clear();
2278
2279    size_t i = 0;
2280    for (;;) {
2281        sp<ABuffer> csd;
2282        if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
2283            break;
2284        }
2285        if (csd->size() == 0) {
2286            ALOGW("csd-%zu size is 0", i);
2287        }
2288
2289        mCSD.push_back(csd);
2290        ++i;
2291    }
2292
2293    ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
2294}
2295
2296status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
2297    CHECK(!mCSD.empty());
2298
2299    const BufferInfo *info =
2300        &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
2301
2302    sp<ABuffer> csd = *mCSD.begin();
2303    mCSD.erase(mCSD.begin());
2304
2305    const sp<ABuffer> &codecInputData =
2306        (mCrypto != NULL) ? info->mEncryptedData : info->mData;
2307
2308    if (csd->size() > codecInputData->capacity()) {
2309        return -EINVAL;
2310    }
2311
2312    memcpy(codecInputData->data(), csd->data(), csd->size());
2313
2314    AString errorDetailMsg;
2315
2316    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
2317    msg->setSize("index", bufferIndex);
2318    msg->setSize("offset", 0);
2319    msg->setSize("size", csd->size());
2320    msg->setInt64("timeUs", 0ll);
2321    msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
2322    msg->setPointer("errorDetailMsg", &errorDetailMsg);
2323
2324    return onQueueInputBuffer(msg);
2325}
2326
2327void MediaCodec::setState(State newState) {
2328    if (newState == INITIALIZED || newState == UNINITIALIZED) {
2329        delete mSoftRenderer;
2330        mSoftRenderer = NULL;
2331
2332        mCrypto.clear();
2333        handleSetSurface(NULL);
2334
2335        mInputFormat.clear();
2336        mOutputFormat.clear();
2337        mFlags &= ~kFlagOutputFormatChanged;
2338        mFlags &= ~kFlagOutputBuffersChanged;
2339        mFlags &= ~kFlagStickyError;
2340        mFlags &= ~kFlagIsEncoder;
2341        mFlags &= ~kFlagGatherCodecSpecificData;
2342        mFlags &= ~kFlagIsAsync;
2343        mStickyError = OK;
2344
2345        mActivityNotify.clear();
2346        mCallback.clear();
2347    }
2348
2349    if (newState == UNINITIALIZED) {
2350        // return any straggling buffers, e.g. if we got here on an error
2351        returnBuffersToCodec();
2352
2353        // The component is gone, mediaserver's probably back up already
2354        // but should definitely be back up should we try to instantiate
2355        // another component.. and the cycle continues.
2356        mFlags &= ~kFlagSawMediaServerDie;
2357    }
2358
2359    mState = newState;
2360
2361    cancelPendingDequeueOperations();
2362
2363    updateBatteryStat();
2364}
2365
2366void MediaCodec::returnBuffersToCodec(bool isReclaim) {
2367    returnBuffersToCodecOnPort(kPortIndexInput, isReclaim);
2368    returnBuffersToCodecOnPort(kPortIndexOutput, isReclaim);
2369}
2370
2371void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) {
2372    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2373    Mutex::Autolock al(mBufferLock);
2374
2375    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2376
2377    for (size_t i = 0; i < buffers->size(); ++i) {
2378        BufferInfo *info = &buffers->editItemAt(i);
2379
2380        if (info->mNotify != NULL) {
2381            sp<AMessage> msg = info->mNotify;
2382            info->mNotify = NULL;
2383            if (isReclaim && info->mOwnedByClient) {
2384                ALOGD("port %d buffer %zu still owned by client when codec is reclaimed",
2385                        portIndex, i);
2386            } else {
2387                info->mMemRef = NULL;
2388                info->mOwnedByClient = false;
2389            }
2390
2391            if (portIndex == kPortIndexInput) {
2392                /* no error, just returning buffers */
2393                msg->setInt32("err", OK);
2394            }
2395            msg->post();
2396        }
2397    }
2398
2399    mAvailPortBuffers[portIndex].clear();
2400}
2401
2402size_t MediaCodec::updateBuffers(
2403        int32_t portIndex, const sp<AMessage> &msg) {
2404    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2405
2406    uint32_t bufferID;
2407    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
2408
2409    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2410
2411    for (size_t i = 0; i < buffers->size(); ++i) {
2412        BufferInfo *info = &buffers->editItemAt(i);
2413
2414        if (info->mBufferID == bufferID) {
2415            CHECK(info->mNotify == NULL);
2416            CHECK(msg->findMessage("reply", &info->mNotify));
2417
2418            info->mFormat =
2419                (portIndex == kPortIndexInput) ? mInputFormat : mOutputFormat;
2420            mAvailPortBuffers[portIndex].push_back(i);
2421
2422            return i;
2423        }
2424    }
2425
2426    TRESPASS();
2427
2428    return 0;
2429}
2430
2431status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
2432    size_t index;
2433    size_t offset;
2434    size_t size;
2435    int64_t timeUs;
2436    uint32_t flags;
2437    CHECK(msg->findSize("index", &index));
2438    CHECK(msg->findSize("offset", &offset));
2439    CHECK(msg->findInt64("timeUs", &timeUs));
2440    CHECK(msg->findInt32("flags", (int32_t *)&flags));
2441
2442    const CryptoPlugin::SubSample *subSamples;
2443    size_t numSubSamples;
2444    const uint8_t *key;
2445    const uint8_t *iv;
2446    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
2447
2448    // We allow the simpler queueInputBuffer API to be used even in
2449    // secure mode, by fabricating a single unencrypted subSample.
2450    CryptoPlugin::SubSample ss;
2451    CryptoPlugin::Pattern pattern;
2452
2453    if (msg->findSize("size", &size)) {
2454        if (mCrypto != NULL) {
2455            ss.mNumBytesOfClearData = size;
2456            ss.mNumBytesOfEncryptedData = 0;
2457
2458            subSamples = &ss;
2459            numSubSamples = 1;
2460            key = NULL;
2461            iv = NULL;
2462            pattern.mEncryptBlocks = 0;
2463            pattern.mSkipBlocks = 0;
2464        }
2465    } else {
2466        if (mCrypto == NULL) {
2467            return -EINVAL;
2468        }
2469
2470        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
2471        CHECK(msg->findSize("numSubSamples", &numSubSamples));
2472        CHECK(msg->findPointer("key", (void **)&key));
2473        CHECK(msg->findPointer("iv", (void **)&iv));
2474        CHECK(msg->findInt32("encryptBlocks", (int32_t *)&pattern.mEncryptBlocks));
2475        CHECK(msg->findInt32("skipBlocks", (int32_t *)&pattern.mSkipBlocks));
2476
2477        int32_t tmp;
2478        CHECK(msg->findInt32("mode", &tmp));
2479
2480        mode = (CryptoPlugin::Mode)tmp;
2481
2482        size = 0;
2483        for (size_t i = 0; i < numSubSamples; ++i) {
2484            size += subSamples[i].mNumBytesOfClearData;
2485            size += subSamples[i].mNumBytesOfEncryptedData;
2486        }
2487    }
2488
2489    if (index >= mPortBuffers[kPortIndexInput].size()) {
2490        return -ERANGE;
2491    }
2492
2493    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
2494
2495    if (info->mNotify == NULL || !info->mOwnedByClient) {
2496        return -EACCES;
2497    }
2498
2499    if (offset + size > info->mData->capacity()) {
2500        return -EINVAL;
2501    }
2502
2503    sp<AMessage> reply = info->mNotify;
2504    info->mData->setRange(offset, size);
2505    info->mData->meta()->setInt64("timeUs", timeUs);
2506
2507    if (flags & BUFFER_FLAG_EOS) {
2508        info->mData->meta()->setInt32("eos", true);
2509    }
2510
2511    if (flags & BUFFER_FLAG_CODECCONFIG) {
2512        info->mData->meta()->setInt32("csd", true);
2513    }
2514
2515    if (mCrypto != NULL) {
2516        if (size > info->mEncryptedData->capacity()) {
2517            return -ERANGE;
2518        }
2519
2520        AString *errorDetailMsg;
2521        CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
2522
2523        void *dst_pointer = info->mData->base();
2524        ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
2525
2526        if (info->mNativeHandle != NULL) {
2527            dst_pointer = (void *)info->mNativeHandle->handle();
2528            dst_type = ICrypto::kDestinationTypeNativeHandle;
2529        } else if ((mFlags & kFlagIsSecure) == 0) {
2530            dst_type = ICrypto::kDestinationTypeVmPointer;
2531        }
2532
2533        ssize_t result = mCrypto->decrypt(
2534                dst_type,
2535                key,
2536                iv,
2537                mode,
2538                pattern,
2539                info->mSharedEncryptedBuffer,
2540                offset,
2541                subSamples,
2542                numSubSamples,
2543                dst_pointer,
2544                errorDetailMsg);
2545
2546        if (result < 0) {
2547            return result;
2548        }
2549
2550        info->mData->setRange(0, result);
2551    }
2552
2553    // synchronization boundary for getBufferAndFormat
2554    {
2555        Mutex::Autolock al(mBufferLock);
2556        info->mOwnedByClient = false;
2557    }
2558    reply->setBuffer("buffer", info->mData);
2559    reply->post();
2560
2561    info->mNotify = NULL;
2562
2563    return OK;
2564}
2565
2566//static
2567size_t MediaCodec::CreateFramesRenderedMessage(
2568        std::list<FrameRenderTracker::Info> done, sp<AMessage> &msg) {
2569    size_t index = 0;
2570
2571    for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
2572            it != done.cend(); ++it) {
2573        if (it->getRenderTimeNs() < 0) {
2574            continue; // dropped frame from tracking
2575        }
2576        msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
2577        msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
2578        ++index;
2579    }
2580    return index;
2581}
2582
2583status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
2584    size_t index;
2585    CHECK(msg->findSize("index", &index));
2586
2587    int32_t render;
2588    if (!msg->findInt32("render", &render)) {
2589        render = 0;
2590    }
2591
2592    if (!isExecuting()) {
2593        return -EINVAL;
2594    }
2595
2596    if (index >= mPortBuffers[kPortIndexOutput].size()) {
2597        return -ERANGE;
2598    }
2599
2600    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
2601
2602    if (info->mNotify == NULL || !info->mOwnedByClient) {
2603        return -EACCES;
2604    }
2605
2606    // synchronization boundary for getBufferAndFormat
2607    {
2608        Mutex::Autolock al(mBufferLock);
2609        info->mOwnedByClient = false;
2610    }
2611
2612    if (render && info->mData != NULL && info->mData->size() != 0) {
2613        info->mNotify->setInt32("render", true);
2614
2615        int64_t mediaTimeUs = -1;
2616        info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
2617
2618        int64_t renderTimeNs = 0;
2619        if (!msg->findInt64("timestampNs", &renderTimeNs)) {
2620            // use media timestamp if client did not request a specific render timestamp
2621            ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
2622            renderTimeNs = mediaTimeUs * 1000;
2623        }
2624        info->mNotify->setInt64("timestampNs", renderTimeNs);
2625
2626        if (mSoftRenderer != NULL) {
2627            std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render(
2628                    info->mData->data(), info->mData->size(),
2629                    mediaTimeUs, renderTimeNs, NULL, info->mFormat);
2630
2631            // if we are running, notify rendered frames
2632            if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) {
2633                sp<AMessage> notify = mOnFrameRenderedNotification->dup();
2634                sp<AMessage> data = new AMessage;
2635                if (CreateFramesRenderedMessage(doneFrames, data)) {
2636                    notify->setMessage("data", data);
2637                    notify->post();
2638                }
2639            }
2640        }
2641    }
2642
2643    info->mNotify->post();
2644    info->mNotify = NULL;
2645
2646    return OK;
2647}
2648
2649ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
2650    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2651
2652    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
2653
2654    if (availBuffers->empty()) {
2655        return -EAGAIN;
2656    }
2657
2658    size_t index = *availBuffers->begin();
2659    availBuffers->erase(availBuffers->begin());
2660
2661    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
2662    CHECK(!info->mOwnedByClient);
2663    {
2664        Mutex::Autolock al(mBufferLock);
2665        info->mOwnedByClient = true;
2666
2667        // set image-data
2668        if (info->mFormat != NULL) {
2669            sp<ABuffer> imageData;
2670            if (info->mFormat->findBuffer("image-data", &imageData)) {
2671                info->mData->meta()->setBuffer("image-data", imageData);
2672            }
2673            int32_t left, top, right, bottom;
2674            if (info->mFormat->findRect("crop", &left, &top, &right, &bottom)) {
2675                info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
2676            }
2677        }
2678    }
2679
2680    return index;
2681}
2682
2683status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
2684    status_t err = OK;
2685    if (surface != NULL) {
2686        err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2687        if (err == BAD_VALUE) {
2688            ALOGI("native window already connected. Assuming no change of surface");
2689            return err;
2690        } else if (err == OK) {
2691            // Require a fresh set of buffers after each connect by using a unique generation
2692            // number. Rely on the fact that max supported process id by Linux is 2^22.
2693            // PID is never 0 so we don't have to worry that we use the default generation of 0.
2694            // TODO: come up with a unique scheme if other producers also set the generation number.
2695            static uint32_t mSurfaceGeneration = 0;
2696            uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
2697            surface->setGenerationNumber(generation);
2698            ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
2699
2700            // HACK: clear any free buffers. Remove when connect will automatically do this.
2701            // This is needed as the consumer may be holding onto stale frames that it can reattach
2702            // to this surface after disconnect/connect, and those free frames would inherit the new
2703            // generation number. Disconnecting after setting a unique generation prevents this.
2704            native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2705            err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2706        }
2707
2708        if (err != OK) {
2709            ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
2710        }
2711    }
2712    return err;
2713}
2714
2715status_t MediaCodec::disconnectFromSurface() {
2716    status_t err = OK;
2717    if (mSurface != NULL) {
2718        // Resetting generation is not technically needed, but there is no need to keep it either
2719        mSurface->setGenerationNumber(0);
2720        err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
2721        if (err != OK) {
2722            ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
2723        }
2724        // assume disconnected even on error
2725        mSurface.clear();
2726    }
2727    return err;
2728}
2729
2730status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
2731    status_t err = OK;
2732    if (mSurface != NULL) {
2733        (void)disconnectFromSurface();
2734    }
2735    if (surface != NULL) {
2736        err = connectToSurface(surface);
2737        if (err == OK) {
2738            mSurface = surface;
2739        }
2740    }
2741    return err;
2742}
2743
2744void MediaCodec::onInputBufferAvailable() {
2745    int32_t index;
2746    while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
2747        sp<AMessage> msg = mCallback->dup();
2748        msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
2749        msg->setInt32("index", index);
2750        msg->post();
2751    }
2752}
2753
2754void MediaCodec::onOutputBufferAvailable() {
2755    int32_t index;
2756    while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
2757        const sp<ABuffer> &buffer =
2758            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
2759        sp<AMessage> msg = mCallback->dup();
2760        msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
2761        msg->setInt32("index", index);
2762        msg->setSize("offset", buffer->offset());
2763        msg->setSize("size", buffer->size());
2764
2765        int64_t timeUs;
2766        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2767
2768        msg->setInt64("timeUs", timeUs);
2769
2770        int32_t omxFlags;
2771        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
2772
2773        uint32_t flags = 0;
2774        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
2775            flags |= BUFFER_FLAG_SYNCFRAME;
2776        }
2777        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
2778            flags |= BUFFER_FLAG_CODECCONFIG;
2779        }
2780        if (omxFlags & OMX_BUFFERFLAG_EOS) {
2781            flags |= BUFFER_FLAG_EOS;
2782        }
2783
2784        msg->setInt32("flags", flags);
2785
2786        msg->post();
2787    }
2788}
2789
2790void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
2791    if (mCallback != NULL) {
2792        sp<AMessage> msg = mCallback->dup();
2793        msg->setInt32("callbackID", CB_ERROR);
2794        msg->setInt32("err", err);
2795        msg->setInt32("actionCode", actionCode);
2796
2797        if (detail != NULL) {
2798            msg->setString("detail", detail);
2799        }
2800
2801        msg->post();
2802    }
2803}
2804
2805void MediaCodec::onOutputFormatChanged() {
2806    if (mCallback != NULL) {
2807        sp<AMessage> msg = mCallback->dup();
2808        msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
2809        msg->setMessage("format", mOutputFormat);
2810        msg->post();
2811    }
2812}
2813
2814
2815void MediaCodec::postActivityNotificationIfPossible() {
2816    if (mActivityNotify == NULL) {
2817        return;
2818    }
2819
2820    bool isErrorOrOutputChanged =
2821            (mFlags & (kFlagStickyError
2822                    | kFlagOutputBuffersChanged
2823                    | kFlagOutputFormatChanged));
2824
2825    if (isErrorOrOutputChanged
2826            || !mAvailPortBuffers[kPortIndexInput].empty()
2827            || !mAvailPortBuffers[kPortIndexOutput].empty()) {
2828        mActivityNotify->setInt32("input-buffers",
2829                mAvailPortBuffers[kPortIndexInput].size());
2830
2831        if (isErrorOrOutputChanged) {
2832            // we want consumer to dequeue as many times as it can
2833            mActivityNotify->setInt32("output-buffers", INT32_MAX);
2834        } else {
2835            mActivityNotify->setInt32("output-buffers",
2836                    mAvailPortBuffers[kPortIndexOutput].size());
2837        }
2838        mActivityNotify->post();
2839        mActivityNotify.clear();
2840    }
2841}
2842
2843status_t MediaCodec::setParameters(const sp<AMessage> &params) {
2844    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
2845    msg->setMessage("params", params);
2846
2847    sp<AMessage> response;
2848    return PostAndAwaitResponse(msg, &response);
2849}
2850
2851status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
2852    mCodec->signalSetParameters(params);
2853
2854    return OK;
2855}
2856
2857status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
2858        const sp<ABuffer> &buffer) {
2859    AString mime;
2860    CHECK(mOutputFormat->findString("mime", &mime));
2861
2862    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
2863        // Codec specific data should be SPS and PPS in a single buffer,
2864        // each prefixed by a startcode (0x00 0x00 0x00 0x01).
2865        // We separate the two and put them into the output format
2866        // under the keys "csd-0" and "csd-1".
2867
2868        unsigned csdIndex = 0;
2869
2870        const uint8_t *data = buffer->data();
2871        size_t size = buffer->size();
2872
2873        const uint8_t *nalStart;
2874        size_t nalSize;
2875        while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
2876            sp<ABuffer> csd = new ABuffer(nalSize + 4);
2877            memcpy(csd->data(), "\x00\x00\x00\x01", 4);
2878            memcpy(csd->data() + 4, nalStart, nalSize);
2879
2880            mOutputFormat->setBuffer(
2881                    AStringPrintf("csd-%u", csdIndex).c_str(), csd);
2882
2883            ++csdIndex;
2884        }
2885
2886        if (csdIndex != 2) {
2887            return ERROR_MALFORMED;
2888        }
2889    } else {
2890        // For everything else we just stash the codec specific data into
2891        // the output format as a single piece of csd under "csd-0".
2892        mOutputFormat->setBuffer("csd-0", buffer);
2893    }
2894
2895    return OK;
2896}
2897
2898void MediaCodec::updateBatteryStat() {
2899    if (!mIsVideo) {
2900        return;
2901    }
2902
2903    if (mState == CONFIGURED && !mBatteryStatNotified) {
2904        BatteryNotifier::getInstance().noteStartVideo();
2905        mBatteryStatNotified = true;
2906    } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
2907        BatteryNotifier::getInstance().noteStopVideo();
2908        mBatteryStatNotified = false;
2909    }
2910}
2911
2912}  // namespace android
2913