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