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