MediaCodec.cpp revision ad60a0f6cd9012507f8086fe741236d12d280ef3
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
1343                    size_t totalSize = 0;
1344                    for (size_t i = 0; i < numBuffers; ++i) {
1345                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
1346                            totalSize += portDesc->bufferAt(i)->capacity();
1347                        }
1348                    }
1349
1350                    if (totalSize) {
1351                        mDealer = new MemoryDealer(totalSize, "MediaCodec");
1352                    }
1353
1354                    for (size_t i = 0; i < numBuffers; ++i) {
1355                        BufferInfo info;
1356                        info.mBufferID = portDesc->bufferIDAt(i);
1357                        info.mOwnedByClient = false;
1358                        sp<MediaCodecBuffer> buffer = portDesc->bufferAt(i);
1359                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
1360                            info.mSharedEncryptedBuffer = mDealer->allocate(buffer->capacity());
1361                            buffer = new SharedMemoryBuffer(
1362                                    mInputFormat, info.mSharedEncryptedBuffer);
1363                        }
1364                        buffers->push_back(info);
1365                        mPortBufferArrays[portIndex].push_back(buffer);
1366                    }
1367
1368                    if (portIndex == kPortIndexOutput) {
1369                        if (mState == STARTING) {
1370                            // We're always allocating output buffers after
1371                            // allocating input buffers, so this is a good
1372                            // indication that now all buffers are allocated.
1373                            if (mIsVideo) {
1374                                addResource(
1375                                        MediaResource::kGraphicMemory,
1376                                        MediaResource::kUnspecifiedSubType,
1377                                        getGraphicBufferSize());
1378                            }
1379                            setState(STARTED);
1380                            (new AMessage)->postReply(mReplyID);
1381                        } else {
1382                            mFlags |= kFlagOutputBuffersChanged;
1383                            postActivityNotificationIfPossible();
1384                        }
1385                    }
1386                    break;
1387                }
1388
1389                case CodecBase::kWhatOutputFramesRendered:
1390                {
1391                    // ignore these in all states except running, and check that we have a
1392                    // notification set
1393                    if (mState == STARTED && mOnFrameRenderedNotification != NULL) {
1394                        sp<AMessage> notify = mOnFrameRenderedNotification->dup();
1395                        notify->setMessage("data", msg);
1396                        notify->post();
1397                    }
1398                    break;
1399                }
1400
1401                case CodecBase::kWhatFillThisBuffer:
1402                {
1403                    /* size_t index = */updateBuffers(kPortIndexInput, msg);
1404
1405                    if (mState == FLUSHING
1406                            || mState == STOPPING
1407                            || mState == RELEASING) {
1408                        returnBuffersToCodecOnPort(kPortIndexInput);
1409                        break;
1410                    }
1411
1412                    // TODO: hold reference of buffer from downstream when
1413                    // mPortBuffers is removed.
1414
1415                    if (!mCSD.empty()) {
1416                        ssize_t index = dequeuePortBuffer(kPortIndexInput);
1417                        CHECK_GE(index, 0);
1418
1419                        // If codec specific data had been specified as
1420                        // part of the format in the call to configure and
1421                        // if there's more csd left, we submit it here
1422                        // clients only get access to input buffers once
1423                        // this data has been exhausted.
1424
1425                        status_t err = queueCSDInputBuffer(index);
1426
1427                        if (err != OK) {
1428                            ALOGE("queueCSDInputBuffer failed w/ error %d",
1429                                  err);
1430
1431                            setStickyError(err);
1432                            postActivityNotificationIfPossible();
1433
1434                            cancelPendingDequeueOperations();
1435                        }
1436                        break;
1437                    }
1438
1439                    if (mFlags & kFlagIsAsync) {
1440                        if (!mHaveInputSurface) {
1441                            if (mState == FLUSHED) {
1442                                mHavePendingInputBuffers = true;
1443                            } else {
1444                                onInputBufferAvailable();
1445                            }
1446                        }
1447                    } else if (mFlags & kFlagDequeueInputPending) {
1448                        CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
1449
1450                        ++mDequeueInputTimeoutGeneration;
1451                        mFlags &= ~kFlagDequeueInputPending;
1452                        mDequeueInputReplyID = 0;
1453                    } else {
1454                        postActivityNotificationIfPossible();
1455                    }
1456                    break;
1457                }
1458
1459                case CodecBase::kWhatDrainThisBuffer:
1460                {
1461                    /* size_t index = */updateBuffers(kPortIndexOutput, msg);
1462
1463                    if (mState == FLUSHING
1464                            || mState == STOPPING
1465                            || mState == RELEASING) {
1466                        returnBuffersToCodecOnPort(kPortIndexOutput);
1467                        break;
1468                    }
1469
1470                    sp<RefBase> obj;
1471                    CHECK(msg->findObject("buffer", &obj));
1472                    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
1473                    // TODO: hold buffer's reference when we remove mPortBuffers
1474
1475                    int32_t omxFlags;
1476                    CHECK(msg->findInt32("flags", &omxFlags));
1477
1478                    buffer->meta()->setInt32("omxFlags", omxFlags);
1479                    if (mOutputFormat != buffer->format()) {
1480                        mOutputFormat = buffer->format();
1481                        ALOGV("[%s] output format changed to: %s",
1482                                mComponentName.c_str(), mOutputFormat->debugString(4).c_str());
1483
1484                        if (mSoftRenderer == NULL &&
1485                                mSurface != NULL &&
1486                                (mFlags & kFlagUsesSoftwareRenderer)) {
1487                            AString mime;
1488                            CHECK(mOutputFormat->findString("mime", &mime));
1489
1490                            // TODO: propagate color aspects to software renderer to allow better
1491                            // color conversion to RGB. For now, just mark dataspace for YUV
1492                            // rendering.
1493                            int32_t dataSpace;
1494                            if (mOutputFormat->findInt32("android._dataspace", &dataSpace)) {
1495                                ALOGD("[%s] setting dataspace on output surface to #%x",
1496                                        mComponentName.c_str(), dataSpace);
1497                                int err = native_window_set_buffers_data_space(
1498                                        mSurface.get(), (android_dataspace)dataSpace);
1499                                ALOGW_IF(err != 0, "failed to set dataspace on surface (%d)", err);
1500                            }
1501
1502                            if (mime.startsWithIgnoreCase("video/")) {
1503                                mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees);
1504                            }
1505                        }
1506
1507                        if (mFlags & kFlagIsEncoder) {
1508                            // Before we announce the format change we should
1509                            // collect codec specific data and amend the output
1510                            // format as necessary.
1511                            if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1512                                status_t err =
1513                                    amendOutputFormatWithCodecSpecificData(buffer);
1514
1515                                if (err != OK) {
1516                                    ALOGE("Codec spit out malformed codec "
1517                                          "specific data!");
1518                                }
1519                            }
1520                        }
1521
1522                        if (mFlags & kFlagIsAsync) {
1523                            onOutputFormatChanged();
1524                        } else {
1525                            mFlags |= kFlagOutputFormatChanged;
1526                            postActivityNotificationIfPossible();
1527                        }
1528
1529                        // Notify mCrypto of video resolution changes
1530                        if (mCrypto != NULL) {
1531                            int32_t left, top, right, bottom, width, height;
1532                            if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
1533                                mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
1534                            } else if (mOutputFormat->findInt32("width", &width)
1535                                    && mOutputFormat->findInt32("height", &height)) {
1536                                mCrypto->notifyResolution(width, height);
1537                            }
1538                        }
1539                    }
1540
1541                    if (mFlags & kFlagIsAsync) {
1542                        onOutputBufferAvailable();
1543                    } else if (mFlags & kFlagDequeueOutputPending) {
1544                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
1545
1546                        ++mDequeueOutputTimeoutGeneration;
1547                        mFlags &= ~kFlagDequeueOutputPending;
1548                        mDequeueOutputReplyID = 0;
1549                    } else {
1550                        postActivityNotificationIfPossible();
1551                    }
1552
1553                    break;
1554                }
1555
1556                case CodecBase::kWhatEOS:
1557                {
1558                    // We already notify the client of this by using the
1559                    // corresponding flag in "onOutputBufferReady".
1560                    break;
1561                }
1562
1563                case CodecBase::kWhatShutdownCompleted:
1564                {
1565                    if (mState == UNINITIALIZED) {
1566                        // Ignore shutdown complete if we're already released.
1567                        break;
1568                    }
1569                    if (mState == STOPPING) {
1570                        setState(INITIALIZED);
1571                    } else {
1572                        CHECK_EQ(mState, RELEASING);
1573                        setState(UNINITIALIZED);
1574                        mComponentName.clear();
1575                    }
1576                    mFlags &= ~kFlagIsComponentAllocated;
1577
1578                    mResourceManagerService->removeResource(getId(mResourceManagerClient));
1579
1580                    (new AMessage)->postReply(mReplyID);
1581                    break;
1582                }
1583
1584                case CodecBase::kWhatFlushCompleted:
1585                {
1586                    if (mState != FLUSHING) {
1587                        ALOGW("received FlushCompleted message in state %d",
1588                                mState);
1589                        break;
1590                    }
1591
1592                    if (mFlags & kFlagIsAsync) {
1593                        setState(FLUSHED);
1594                    } else {
1595                        setState(STARTED);
1596                        mCodec->signalResume();
1597                    }
1598
1599                    (new AMessage)->postReply(mReplyID);
1600                    break;
1601                }
1602
1603                default:
1604                    TRESPASS();
1605            }
1606            break;
1607        }
1608
1609        case kWhatInit:
1610        {
1611            sp<AReplyToken> replyID;
1612            CHECK(msg->senderAwaitsResponse(&replyID));
1613
1614            if (mState != UNINITIALIZED) {
1615                PostReplyWithError(replyID, INVALID_OPERATION);
1616                break;
1617            }
1618
1619            mReplyID = replyID;
1620            setState(INITIALIZING);
1621
1622            AString name;
1623            CHECK(msg->findString("name", &name));
1624
1625            int32_t nameIsType;
1626            int32_t encoder = false;
1627            CHECK(msg->findInt32("nameIsType", &nameIsType));
1628            if (nameIsType) {
1629                CHECK(msg->findInt32("encoder", &encoder));
1630            }
1631
1632            sp<AMessage> format = new AMessage;
1633
1634            if (nameIsType) {
1635                format->setString("mime", name.c_str());
1636                format->setInt32("encoder", encoder);
1637            } else {
1638                format->setString("componentName", name.c_str());
1639            }
1640
1641            mCodec->initiateAllocateComponent(format);
1642            break;
1643        }
1644
1645        case kWhatSetNotification:
1646        {
1647            sp<AMessage> notify;
1648            if (msg->findMessage("on-frame-rendered", &notify)) {
1649                mOnFrameRenderedNotification = notify;
1650            }
1651            break;
1652        }
1653
1654        case kWhatSetCallback:
1655        {
1656            sp<AReplyToken> replyID;
1657            CHECK(msg->senderAwaitsResponse(&replyID));
1658
1659            if (mState == UNINITIALIZED
1660                    || mState == INITIALIZING
1661                    || isExecuting()) {
1662                // callback can't be set after codec is executing,
1663                // or before it's initialized (as the callback
1664                // will be cleared when it goes to INITIALIZED)
1665                PostReplyWithError(replyID, INVALID_OPERATION);
1666                break;
1667            }
1668
1669            sp<AMessage> callback;
1670            CHECK(msg->findMessage("callback", &callback));
1671
1672            mCallback = callback;
1673
1674            if (mCallback != NULL) {
1675                ALOGI("MediaCodec will operate in async mode");
1676                mFlags |= kFlagIsAsync;
1677            } else {
1678                mFlags &= ~kFlagIsAsync;
1679            }
1680
1681            sp<AMessage> response = new AMessage;
1682            response->postReply(replyID);
1683            break;
1684        }
1685
1686        case kWhatConfigure:
1687        {
1688            sp<AReplyToken> replyID;
1689            CHECK(msg->senderAwaitsResponse(&replyID));
1690
1691            if (mState != INITIALIZED) {
1692                PostReplyWithError(replyID, INVALID_OPERATION);
1693                break;
1694            }
1695
1696            sp<RefBase> obj;
1697            CHECK(msg->findObject("surface", &obj));
1698
1699            sp<AMessage> format;
1700            CHECK(msg->findMessage("format", &format));
1701
1702            int32_t push;
1703            if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) {
1704                mFlags |= kFlagPushBlankBuffersOnShutdown;
1705            }
1706
1707            if (obj != NULL) {
1708                format->setObject("native-window", obj);
1709                status_t err = handleSetSurface(static_cast<Surface *>(obj.get()));
1710                if (err != OK) {
1711                    PostReplyWithError(replyID, err);
1712                    break;
1713                }
1714            } else {
1715                handleSetSurface(NULL);
1716            }
1717
1718            mReplyID = replyID;
1719            setState(CONFIGURING);
1720
1721            void *crypto;
1722            if (!msg->findPointer("crypto", &crypto)) {
1723                crypto = NULL;
1724            }
1725
1726            mCrypto = static_cast<ICrypto *>(crypto);
1727
1728            uint32_t flags;
1729            CHECK(msg->findInt32("flags", (int32_t *)&flags));
1730
1731            if (flags & CONFIGURE_FLAG_ENCODE) {
1732                format->setInt32("encoder", true);
1733                mFlags |= kFlagIsEncoder;
1734            }
1735
1736            extractCSD(format);
1737
1738            mCodec->initiateConfigureComponent(format);
1739            break;
1740        }
1741
1742        case kWhatSetSurface:
1743        {
1744            sp<AReplyToken> replyID;
1745            CHECK(msg->senderAwaitsResponse(&replyID));
1746
1747            status_t err = OK;
1748            sp<Surface> surface;
1749
1750            switch (mState) {
1751                case CONFIGURED:
1752                case STARTED:
1753                case FLUSHED:
1754                {
1755                    sp<RefBase> obj;
1756                    (void)msg->findObject("surface", &obj);
1757                    sp<Surface> surface = static_cast<Surface *>(obj.get());
1758                    if (mSurface == NULL) {
1759                        // do not support setting surface if it was not set
1760                        err = INVALID_OPERATION;
1761                    } else if (obj == NULL) {
1762                        // do not support unsetting surface
1763                        err = BAD_VALUE;
1764                    } else {
1765                        err = connectToSurface(surface);
1766                        if (err == ALREADY_EXISTS) {
1767                            // reconnecting to same surface
1768                            err = OK;
1769                        } else {
1770                            if (err == OK) {
1771                                if (mFlags & kFlagUsesSoftwareRenderer) {
1772                                    if (mSoftRenderer != NULL
1773                                            && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1774                                        pushBlankBuffersToNativeWindow(mSurface.get());
1775                                    }
1776                                    mSoftRenderer = new SoftwareRenderer(surface);
1777                                    // TODO: check if this was successful
1778                                } else {
1779                                    err = mCodec->setSurface(surface);
1780                                }
1781                            }
1782                            if (err == OK) {
1783                                (void)disconnectFromSurface();
1784                                mSurface = surface;
1785                            }
1786                        }
1787                    }
1788                    break;
1789                }
1790
1791                default:
1792                    err = INVALID_OPERATION;
1793                    break;
1794            }
1795
1796            PostReplyWithError(replyID, err);
1797            break;
1798        }
1799
1800        case kWhatCreateInputSurface:
1801        case kWhatSetInputSurface:
1802        {
1803            sp<AReplyToken> replyID;
1804            CHECK(msg->senderAwaitsResponse(&replyID));
1805
1806            // Must be configured, but can't have been started yet.
1807            if (mState != CONFIGURED) {
1808                PostReplyWithError(replyID, INVALID_OPERATION);
1809                break;
1810            }
1811
1812            mReplyID = replyID;
1813            if (msg->what() == kWhatCreateInputSurface) {
1814                mCodec->initiateCreateInputSurface();
1815            } else {
1816                sp<RefBase> obj;
1817                CHECK(msg->findObject("input-surface", &obj));
1818
1819                mCodec->initiateSetInputSurface(
1820                        static_cast<PersistentSurface *>(obj.get()));
1821            }
1822            break;
1823        }
1824        case kWhatStart:
1825        {
1826            sp<AReplyToken> replyID;
1827            CHECK(msg->senderAwaitsResponse(&replyID));
1828
1829            if (mState == FLUSHED) {
1830                setState(STARTED);
1831                if (mHavePendingInputBuffers) {
1832                    onInputBufferAvailable();
1833                    mHavePendingInputBuffers = false;
1834                }
1835                mCodec->signalResume();
1836                PostReplyWithError(replyID, OK);
1837                break;
1838            } else if (mState != CONFIGURED) {
1839                PostReplyWithError(replyID, INVALID_OPERATION);
1840                break;
1841            }
1842
1843            mReplyID = replyID;
1844            setState(STARTING);
1845
1846            mCodec->initiateStart();
1847            break;
1848        }
1849
1850        case kWhatStop:
1851        case kWhatRelease:
1852        {
1853            State targetState =
1854                (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
1855
1856            sp<AReplyToken> replyID;
1857            CHECK(msg->senderAwaitsResponse(&replyID));
1858
1859            // already stopped/released
1860            if (mState == UNINITIALIZED && mReleasedByResourceManager) {
1861                sp<AMessage> response = new AMessage;
1862                response->setInt32("err", OK);
1863                response->postReply(replyID);
1864                break;
1865            }
1866
1867            int32_t reclaimed = 0;
1868            msg->findInt32("reclaimed", &reclaimed);
1869            if (reclaimed) {
1870                mReleasedByResourceManager = true;
1871
1872                int32_t force = 0;
1873                msg->findInt32("force", &force);
1874                if (!force && hasPendingBuffer()) {
1875                    ALOGW("Can't reclaim codec right now due to pending buffers.");
1876
1877                    // return WOULD_BLOCK to ask resource manager to retry later.
1878                    sp<AMessage> response = new AMessage;
1879                    response->setInt32("err", WOULD_BLOCK);
1880                    response->postReply(replyID);
1881
1882                    // notify the async client
1883                    if (mFlags & kFlagIsAsync) {
1884                        onError(DEAD_OBJECT, ACTION_CODE_FATAL);
1885                    }
1886                    break;
1887                }
1888            }
1889
1890            bool isReleasingAllocatedComponent =
1891                    (mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED;
1892            if (!isReleasingAllocatedComponent // See 1
1893                    && mState != INITIALIZED
1894                    && mState != CONFIGURED && !isExecuting()) {
1895                // 1) Permit release to shut down the component if allocated.
1896                //
1897                // 2) We may be in "UNINITIALIZED" state already and
1898                // also shutdown the encoder/decoder without the
1899                // client being aware of this if media server died while
1900                // we were being stopped. The client would assume that
1901                // after stop() returned, it would be safe to call release()
1902                // and it should be in this case, no harm to allow a release()
1903                // if we're already uninitialized.
1904                sp<AMessage> response = new AMessage;
1905                // TODO: we shouldn't throw an exception for stop/release. Change this to wait until
1906                // the previous stop/release completes and then reply with OK.
1907                status_t err = mState == targetState ? OK : INVALID_OPERATION;
1908                response->setInt32("err", err);
1909                if (err == OK && targetState == UNINITIALIZED) {
1910                    mComponentName.clear();
1911                }
1912                response->postReply(replyID);
1913                break;
1914            }
1915
1916            // If we're flushing, or we're stopping but received a release
1917            // request, post the reply for the pending call first, and consider
1918            // it done. The reply token will be replaced after this, and we'll
1919            // no longer be able to reply.
1920            if (mState == FLUSHING || mState == STOPPING) {
1921                (new AMessage)->postReply(mReplyID);
1922            }
1923
1924            if (mFlags & kFlagSawMediaServerDie) {
1925                // It's dead, Jim. Don't expect initiateShutdown to yield
1926                // any useful results now...
1927                setState(UNINITIALIZED);
1928                if (targetState == UNINITIALIZED) {
1929                    mComponentName.clear();
1930                }
1931                (new AMessage)->postReply(replyID);
1932                break;
1933            }
1934
1935            // If we already have an error, component may not be able to
1936            // complete the shutdown properly. If we're stopping, post the
1937            // reply now with an error to unblock the client, client can
1938            // release after the failure (instead of ANR).
1939            if (msg->what() == kWhatStop && (mFlags & kFlagStickyError)) {
1940                PostReplyWithError(replyID, getStickyError());
1941                break;
1942            }
1943
1944            mReplyID = replyID;
1945            setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
1946
1947            mCodec->initiateShutdown(
1948                    msg->what() == kWhatStop /* keepComponentAllocated */);
1949
1950            returnBuffersToCodec(reclaimed);
1951
1952            if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1953                pushBlankBuffersToNativeWindow(mSurface.get());
1954            }
1955
1956            break;
1957        }
1958
1959        case kWhatDequeueInputBuffer:
1960        {
1961            sp<AReplyToken> replyID;
1962            CHECK(msg->senderAwaitsResponse(&replyID));
1963
1964            if (mFlags & kFlagIsAsync) {
1965                ALOGE("dequeueOutputBuffer can't be used in async mode");
1966                PostReplyWithError(replyID, INVALID_OPERATION);
1967                break;
1968            }
1969
1970            if (mHaveInputSurface) {
1971                ALOGE("dequeueInputBuffer can't be used with input surface");
1972                PostReplyWithError(replyID, INVALID_OPERATION);
1973                break;
1974            }
1975
1976            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
1977                break;
1978            }
1979
1980            int64_t timeoutUs;
1981            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1982
1983            if (timeoutUs == 0ll) {
1984                PostReplyWithError(replyID, -EAGAIN);
1985                break;
1986            }
1987
1988            mFlags |= kFlagDequeueInputPending;
1989            mDequeueInputReplyID = replyID;
1990
1991            if (timeoutUs > 0ll) {
1992                sp<AMessage> timeoutMsg =
1993                    new AMessage(kWhatDequeueInputTimedOut, this);
1994                timeoutMsg->setInt32(
1995                        "generation", ++mDequeueInputTimeoutGeneration);
1996                timeoutMsg->post(timeoutUs);
1997            }
1998            break;
1999        }
2000
2001        case kWhatDequeueInputTimedOut:
2002        {
2003            int32_t generation;
2004            CHECK(msg->findInt32("generation", &generation));
2005
2006            if (generation != mDequeueInputTimeoutGeneration) {
2007                // Obsolete
2008                break;
2009            }
2010
2011            CHECK(mFlags & kFlagDequeueInputPending);
2012
2013            PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
2014
2015            mFlags &= ~kFlagDequeueInputPending;
2016            mDequeueInputReplyID = 0;
2017            break;
2018        }
2019
2020        case kWhatQueueInputBuffer:
2021        {
2022            sp<AReplyToken> replyID;
2023            CHECK(msg->senderAwaitsResponse(&replyID));
2024
2025            if (!isExecuting()) {
2026                PostReplyWithError(replyID, INVALID_OPERATION);
2027                break;
2028            } else if (mFlags & kFlagStickyError) {
2029                PostReplyWithError(replyID, getStickyError());
2030                break;
2031            }
2032
2033            status_t err = onQueueInputBuffer(msg);
2034
2035            PostReplyWithError(replyID, err);
2036            break;
2037        }
2038
2039        case kWhatDequeueOutputBuffer:
2040        {
2041            sp<AReplyToken> replyID;
2042            CHECK(msg->senderAwaitsResponse(&replyID));
2043
2044            if (mFlags & kFlagIsAsync) {
2045                ALOGE("dequeueOutputBuffer can't be used in async mode");
2046                PostReplyWithError(replyID, INVALID_OPERATION);
2047                break;
2048            }
2049
2050            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
2051                break;
2052            }
2053
2054            int64_t timeoutUs;
2055            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
2056
2057            if (timeoutUs == 0ll) {
2058                PostReplyWithError(replyID, -EAGAIN);
2059                break;
2060            }
2061
2062            mFlags |= kFlagDequeueOutputPending;
2063            mDequeueOutputReplyID = replyID;
2064
2065            if (timeoutUs > 0ll) {
2066                sp<AMessage> timeoutMsg =
2067                    new AMessage(kWhatDequeueOutputTimedOut, this);
2068                timeoutMsg->setInt32(
2069                        "generation", ++mDequeueOutputTimeoutGeneration);
2070                timeoutMsg->post(timeoutUs);
2071            }
2072            break;
2073        }
2074
2075        case kWhatDequeueOutputTimedOut:
2076        {
2077            int32_t generation;
2078            CHECK(msg->findInt32("generation", &generation));
2079
2080            if (generation != mDequeueOutputTimeoutGeneration) {
2081                // Obsolete
2082                break;
2083            }
2084
2085            CHECK(mFlags & kFlagDequeueOutputPending);
2086
2087            PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
2088
2089            mFlags &= ~kFlagDequeueOutputPending;
2090            mDequeueOutputReplyID = 0;
2091            break;
2092        }
2093
2094        case kWhatReleaseOutputBuffer:
2095        {
2096            sp<AReplyToken> replyID;
2097            CHECK(msg->senderAwaitsResponse(&replyID));
2098
2099            if (!isExecuting()) {
2100                PostReplyWithError(replyID, INVALID_OPERATION);
2101                break;
2102            } else if (mFlags & kFlagStickyError) {
2103                PostReplyWithError(replyID, getStickyError());
2104                break;
2105            }
2106
2107            status_t err = onReleaseOutputBuffer(msg);
2108
2109            PostReplyWithError(replyID, err);
2110            break;
2111        }
2112
2113        case kWhatSignalEndOfInputStream:
2114        {
2115            sp<AReplyToken> replyID;
2116            CHECK(msg->senderAwaitsResponse(&replyID));
2117
2118            if (!isExecuting() || !mHaveInputSurface) {
2119                PostReplyWithError(replyID, INVALID_OPERATION);
2120                break;
2121            } else if (mFlags & kFlagStickyError) {
2122                PostReplyWithError(replyID, getStickyError());
2123                break;
2124            }
2125
2126            mReplyID = replyID;
2127            mCodec->signalEndOfInputStream();
2128            break;
2129        }
2130
2131        case kWhatGetBuffers:
2132        {
2133            sp<AReplyToken> replyID;
2134            CHECK(msg->senderAwaitsResponse(&replyID));
2135            // Unfortunately widevine legacy source requires knowing all of the
2136            // codec input buffers, so we have to provide them even in async mode.
2137            int32_t widevine = 0;
2138            msg->findInt32("widevine", &widevine);
2139
2140            if (!isExecuting() || ((mFlags & kFlagIsAsync) && !widevine)) {
2141                PostReplyWithError(replyID, INVALID_OPERATION);
2142                break;
2143            } else if (mFlags & kFlagStickyError) {
2144                PostReplyWithError(replyID, getStickyError());
2145                break;
2146            }
2147
2148            int32_t portIndex;
2149            CHECK(msg->findInt32("portIndex", &portIndex));
2150
2151            Vector<sp<MediaCodecBuffer> > *dstBuffers;
2152            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
2153
2154            dstBuffers->clear();
2155            // If we're using input surface (either non-persistent created by
2156            // createInputSurface(), or persistent set by setInputSurface()),
2157            // give the client an empty input buffers array.
2158            if (portIndex != kPortIndexInput || !mHaveInputSurface) {
2159                const Vector<sp<MediaCodecBuffer>> &srcBuffers = mPortBufferArrays[portIndex];
2160
2161                for (size_t i = 0; i < srcBuffers.size(); ++i) {
2162                    dstBuffers->push_back(srcBuffers[i]);
2163                }
2164            }
2165
2166            (new AMessage)->postReply(replyID);
2167            break;
2168        }
2169
2170        case kWhatFlush:
2171        {
2172            sp<AReplyToken> replyID;
2173            CHECK(msg->senderAwaitsResponse(&replyID));
2174
2175            if (!isExecuting()) {
2176                PostReplyWithError(replyID, INVALID_OPERATION);
2177                break;
2178            } else if (mFlags & kFlagStickyError) {
2179                PostReplyWithError(replyID, getStickyError());
2180                break;
2181            }
2182
2183            mReplyID = replyID;
2184            // TODO: skip flushing if already FLUSHED
2185            setState(FLUSHING);
2186
2187            mCodec->signalFlush();
2188            returnBuffersToCodec();
2189            break;
2190        }
2191
2192        case kWhatGetInputFormat:
2193        case kWhatGetOutputFormat:
2194        {
2195            sp<AMessage> format =
2196                (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
2197
2198            sp<AReplyToken> replyID;
2199            CHECK(msg->senderAwaitsResponse(&replyID));
2200
2201            if ((mState != CONFIGURED && mState != STARTING &&
2202                 mState != STARTED && mState != FLUSHING &&
2203                 mState != FLUSHED)
2204                    || format == NULL) {
2205                PostReplyWithError(replyID, INVALID_OPERATION);
2206                break;
2207            } else if (mFlags & kFlagStickyError) {
2208                PostReplyWithError(replyID, getStickyError());
2209                break;
2210            }
2211
2212            sp<AMessage> response = new AMessage;
2213            response->setMessage("format", format);
2214            response->postReply(replyID);
2215            break;
2216        }
2217
2218        case kWhatRequestIDRFrame:
2219        {
2220            mCodec->signalRequestIDRFrame();
2221            break;
2222        }
2223
2224        case kWhatRequestActivityNotification:
2225        {
2226            CHECK(mActivityNotify == NULL);
2227            CHECK(msg->findMessage("notify", &mActivityNotify));
2228
2229            postActivityNotificationIfPossible();
2230            break;
2231        }
2232
2233        case kWhatGetName:
2234        {
2235            sp<AReplyToken> replyID;
2236            CHECK(msg->senderAwaitsResponse(&replyID));
2237
2238            if (mComponentName.empty()) {
2239                PostReplyWithError(replyID, INVALID_OPERATION);
2240                break;
2241            }
2242
2243            sp<AMessage> response = new AMessage;
2244            response->setString("name", mComponentName.c_str());
2245            response->postReply(replyID);
2246            break;
2247        }
2248
2249        case kWhatSetParameters:
2250        {
2251            sp<AReplyToken> replyID;
2252            CHECK(msg->senderAwaitsResponse(&replyID));
2253
2254            sp<AMessage> params;
2255            CHECK(msg->findMessage("params", &params));
2256
2257            status_t err = onSetParameters(params);
2258
2259            PostReplyWithError(replyID, err);
2260            break;
2261        }
2262
2263        default:
2264            TRESPASS();
2265    }
2266}
2267
2268void MediaCodec::extractCSD(const sp<AMessage> &format) {
2269    mCSD.clear();
2270
2271    size_t i = 0;
2272    for (;;) {
2273        sp<ABuffer> csd;
2274        if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
2275            break;
2276        }
2277        if (csd->size() == 0) {
2278            ALOGW("csd-%zu size is 0", i);
2279        }
2280
2281        mCSD.push_back(csd);
2282        ++i;
2283    }
2284
2285    ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
2286}
2287
2288status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
2289    CHECK(!mCSD.empty());
2290
2291    const BufferInfo *info =
2292        &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
2293
2294    sp<ABuffer> csd = *mCSD.begin();
2295    mCSD.erase(mCSD.begin());
2296
2297    const sp<MediaCodecBuffer> &codecInputData = info->mData;
2298
2299    if (csd->size() > codecInputData->capacity()) {
2300        return -EINVAL;
2301    }
2302
2303    memcpy(codecInputData->data(), csd->data(), csd->size());
2304
2305    AString errorDetailMsg;
2306
2307    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
2308    msg->setSize("index", bufferIndex);
2309    msg->setSize("offset", 0);
2310    msg->setSize("size", csd->size());
2311    msg->setInt64("timeUs", 0ll);
2312    msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
2313    msg->setPointer("errorDetailMsg", &errorDetailMsg);
2314
2315    return onQueueInputBuffer(msg);
2316}
2317
2318void MediaCodec::setState(State newState) {
2319    if (newState == INITIALIZED || newState == UNINITIALIZED) {
2320        delete mSoftRenderer;
2321        mSoftRenderer = NULL;
2322
2323        mCrypto.clear();
2324        handleSetSurface(NULL);
2325
2326        mInputFormat.clear();
2327        mOutputFormat.clear();
2328        mFlags &= ~kFlagOutputFormatChanged;
2329        mFlags &= ~kFlagOutputBuffersChanged;
2330        mFlags &= ~kFlagStickyError;
2331        mFlags &= ~kFlagIsEncoder;
2332        mFlags &= ~kFlagIsAsync;
2333        mStickyError = OK;
2334
2335        mActivityNotify.clear();
2336        mCallback.clear();
2337    }
2338
2339    if (newState == UNINITIALIZED) {
2340        // return any straggling buffers, e.g. if we got here on an error
2341        returnBuffersToCodec();
2342
2343        // The component is gone, mediaserver's probably back up already
2344        // but should definitely be back up should we try to instantiate
2345        // another component.. and the cycle continues.
2346        mFlags &= ~kFlagSawMediaServerDie;
2347    }
2348
2349    mState = newState;
2350
2351    cancelPendingDequeueOperations();
2352
2353    updateBatteryStat();
2354}
2355
2356void MediaCodec::returnBuffersToCodec(bool isReclaim) {
2357    returnBuffersToCodecOnPort(kPortIndexInput, isReclaim);
2358    returnBuffersToCodecOnPort(kPortIndexOutput, isReclaim);
2359}
2360
2361void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex, bool isReclaim) {
2362    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2363    Mutex::Autolock al(mBufferLock);
2364
2365    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2366
2367    for (size_t i = 0; i < buffers->size(); ++i) {
2368        BufferInfo *info = &buffers->editItemAt(i);
2369
2370        if (info->mNotify != NULL) {
2371            sp<AMessage> msg = info->mNotify;
2372            info->mNotify = NULL;
2373            msg->setObject("buffer", (portIndex == kPortIndexInput && mCrypto != NULL)
2374                    ? info->mSecureData : info->mData);
2375            if (isReclaim && info->mOwnedByClient) {
2376                ALOGD("port %d buffer %zu still owned by client when codec is reclaimed",
2377                        portIndex, i);
2378            } else {
2379                info->mOwnedByClient = false;
2380                info->mData.clear();
2381                info->mSecureData.clear();
2382            }
2383
2384            if (portIndex == kPortIndexInput) {
2385                /* no error, just returning buffers */
2386                msg->setInt32("err", OK);
2387            }
2388            msg->post();
2389        }
2390    }
2391
2392    mAvailPortBuffers[portIndex].clear();
2393}
2394
2395size_t MediaCodec::updateBuffers(
2396        int32_t portIndex, const sp<AMessage> &msg) {
2397    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2398
2399    uint32_t bufferID;
2400    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
2401    sp<RefBase> obj;
2402    CHECK(msg->findObject("buffer", &obj));
2403    sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
2404
2405    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2406
2407    for (size_t i = 0; i < buffers->size(); ++i) {
2408        BufferInfo *info = &buffers->editItemAt(i);
2409
2410        if (info->mBufferID == bufferID) {
2411            CHECK(info->mNotify == NULL);
2412            CHECK(msg->findMessage("reply", &info->mNotify));
2413
2414            if (portIndex == kPortIndexInput && mCrypto != NULL) {
2415                info->mSecureData = buffer;
2416                info->mData = mPortBufferArrays[portIndex][i];
2417            } else {
2418                info->mData = buffer;
2419            }
2420            mAvailPortBuffers[portIndex].push_back(i);
2421
2422            return i;
2423        }
2424    }
2425
2426    TRESPASS();
2427
2428    return 0;
2429}
2430
2431status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
2432    size_t index;
2433    size_t offset;
2434    size_t size;
2435    int64_t timeUs;
2436    uint32_t flags;
2437    CHECK(msg->findSize("index", &index));
2438    CHECK(msg->findSize("offset", &offset));
2439    CHECK(msg->findInt64("timeUs", &timeUs));
2440    CHECK(msg->findInt32("flags", (int32_t *)&flags));
2441
2442    const CryptoPlugin::SubSample *subSamples;
2443    size_t numSubSamples;
2444    const uint8_t *key;
2445    const uint8_t *iv;
2446    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
2447
2448    // We allow the simpler queueInputBuffer API to be used even in
2449    // secure mode, by fabricating a single unencrypted subSample.
2450    CryptoPlugin::SubSample ss;
2451    CryptoPlugin::Pattern pattern;
2452
2453    if (msg->findSize("size", &size)) {
2454        if (mCrypto != NULL) {
2455            ss.mNumBytesOfClearData = size;
2456            ss.mNumBytesOfEncryptedData = 0;
2457
2458            subSamples = &ss;
2459            numSubSamples = 1;
2460            key = NULL;
2461            iv = NULL;
2462            pattern.mEncryptBlocks = 0;
2463            pattern.mSkipBlocks = 0;
2464        }
2465    } else {
2466        if (mCrypto == NULL) {
2467            return -EINVAL;
2468        }
2469
2470        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
2471        CHECK(msg->findSize("numSubSamples", &numSubSamples));
2472        CHECK(msg->findPointer("key", (void **)&key));
2473        CHECK(msg->findPointer("iv", (void **)&iv));
2474        CHECK(msg->findInt32("encryptBlocks", (int32_t *)&pattern.mEncryptBlocks));
2475        CHECK(msg->findInt32("skipBlocks", (int32_t *)&pattern.mSkipBlocks));
2476
2477        int32_t tmp;
2478        CHECK(msg->findInt32("mode", &tmp));
2479
2480        mode = (CryptoPlugin::Mode)tmp;
2481
2482        size = 0;
2483        for (size_t i = 0; i < numSubSamples; ++i) {
2484            size += subSamples[i].mNumBytesOfClearData;
2485            size += subSamples[i].mNumBytesOfEncryptedData;
2486        }
2487    }
2488
2489    if (index >= mPortBuffers[kPortIndexInput].size()) {
2490        return -ERANGE;
2491    }
2492
2493    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
2494
2495    if (info->mNotify == NULL || !info->mOwnedByClient) {
2496        return -EACCES;
2497    }
2498
2499    if (offset + size > info->mData->capacity()) {
2500        return -EINVAL;
2501    }
2502
2503    sp<AMessage> reply = info->mNotify;
2504    info->mData->setRange(offset, size);
2505
2506    sp<MediaCodecBuffer> buffer = info->mData;
2507    if (mCrypto != NULL) {
2508        AString *errorDetailMsg;
2509        CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
2510
2511        void *dst_pointer = nullptr;
2512        ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
2513
2514        if ((mFlags & kFlagIsSecure) == 0) {
2515            dst_pointer = info->mSecureData->base();
2516            dst_type = ICrypto::kDestinationTypeVmPointer;
2517        } else {
2518            sp<SecureBuffer> secureData = static_cast<SecureBuffer *>(info->mSecureData.get());
2519            dst_pointer = secureData->getDestinationPointer();
2520            dst_type = secureData->getDestinationType();
2521        }
2522
2523        ssize_t result = mCrypto->decrypt(
2524                dst_type,
2525                key,
2526                iv,
2527                mode,
2528                pattern,
2529                info->mSharedEncryptedBuffer,
2530                offset,
2531                subSamples,
2532                numSubSamples,
2533                dst_pointer,
2534                errorDetailMsg);
2535
2536        if (result < 0) {
2537            return result;
2538        }
2539
2540        info->mSecureData->setRange(0, result);
2541        buffer = info->mSecureData;
2542    }
2543    buffer->meta()->setInt64("timeUs", timeUs);
2544
2545    if (flags & BUFFER_FLAG_EOS) {
2546        buffer->meta()->setInt32("eos", true);
2547    }
2548
2549    if (flags & BUFFER_FLAG_CODECCONFIG) {
2550        buffer->meta()->setInt32("csd", true);
2551    }
2552
2553    // synchronization boundary for getBufferAndFormat
2554    {
2555        Mutex::Autolock al(mBufferLock);
2556        info->mOwnedByClient = false;
2557    }
2558    info->mData.clear();
2559    info->mSecureData.clear();
2560    reply->setObject("buffer", buffer);
2561    reply->post();
2562
2563    info->mNotify = NULL;
2564
2565    return OK;
2566}
2567
2568//static
2569size_t MediaCodec::CreateFramesRenderedMessage(
2570        const std::list<FrameRenderTracker::Info> &done, sp<AMessage> &msg) {
2571    size_t index = 0;
2572
2573    for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
2574            it != done.cend(); ++it) {
2575        if (it->getRenderTimeNs() < 0) {
2576            continue; // dropped frame from tracking
2577        }
2578        msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
2579        msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
2580        ++index;
2581    }
2582    return index;
2583}
2584
2585status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
2586    size_t index;
2587    CHECK(msg->findSize("index", &index));
2588
2589    int32_t render;
2590    if (!msg->findInt32("render", &render)) {
2591        render = 0;
2592    }
2593
2594    if (!isExecuting()) {
2595        return -EINVAL;
2596    }
2597
2598    if (index >= mPortBuffers[kPortIndexOutput].size()) {
2599        return -ERANGE;
2600    }
2601
2602    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
2603
2604    if (info->mNotify == NULL || !info->mOwnedByClient) {
2605        return -EACCES;
2606    }
2607
2608    // synchronization boundary for getBufferAndFormat
2609    {
2610        Mutex::Autolock al(mBufferLock);
2611        info->mOwnedByClient = false;
2612    }
2613
2614    if (render && info->mData != NULL && info->mData->size() != 0) {
2615        info->mNotify->setInt32("render", true);
2616
2617        int64_t mediaTimeUs = -1;
2618        info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
2619
2620        int64_t renderTimeNs = 0;
2621        if (!msg->findInt64("timestampNs", &renderTimeNs)) {
2622            // use media timestamp if client did not request a specific render timestamp
2623            ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
2624            renderTimeNs = mediaTimeUs * 1000;
2625        }
2626        info->mNotify->setInt64("timestampNs", renderTimeNs);
2627
2628        if (mSoftRenderer != NULL) {
2629            std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render(
2630                    info->mData->data(), info->mData->size(),
2631                    mediaTimeUs, renderTimeNs, NULL, info->mData->format());
2632
2633            // if we are running, notify rendered frames
2634            if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) {
2635                sp<AMessage> notify = mOnFrameRenderedNotification->dup();
2636                sp<AMessage> data = new AMessage;
2637                if (CreateFramesRenderedMessage(doneFrames, data)) {
2638                    notify->setMessage("data", data);
2639                    notify->post();
2640                }
2641            }
2642        }
2643    }
2644
2645    info->mNotify->setObject("buffer", info->mData);
2646    info->mData.clear();
2647    info->mNotify->post();
2648    info->mNotify.clear();
2649
2650    return OK;
2651}
2652
2653ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
2654    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2655
2656    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
2657
2658    if (availBuffers->empty()) {
2659        return -EAGAIN;
2660    }
2661
2662    size_t index = *availBuffers->begin();
2663    availBuffers->erase(availBuffers->begin());
2664
2665    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
2666    CHECK(!info->mOwnedByClient);
2667    {
2668        Mutex::Autolock al(mBufferLock);
2669        info->mOwnedByClient = true;
2670
2671        // set image-data
2672        if (info->mData->format() != NULL) {
2673            sp<ABuffer> imageData;
2674            if (info->mData->format()->findBuffer("image-data", &imageData)) {
2675                info->mData->meta()->setBuffer("image-data", imageData);
2676            }
2677            int32_t left, top, right, bottom;
2678            if (info->mData->format()->findRect("crop", &left, &top, &right, &bottom)) {
2679                info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
2680            }
2681        }
2682    }
2683
2684    return index;
2685}
2686
2687status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
2688    status_t err = OK;
2689    if (surface != NULL) {
2690        uint64_t oldId, newId;
2691        if (mSurface != NULL
2692                && surface->getUniqueId(&newId) == NO_ERROR
2693                && mSurface->getUniqueId(&oldId) == NO_ERROR
2694                && newId == oldId) {
2695            ALOGI("[%s] connecting to the same surface. Nothing to do.", mComponentName.c_str());
2696            return ALREADY_EXISTS;
2697        }
2698
2699        err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2700        if (err == OK) {
2701            // Require a fresh set of buffers after each connect by using a unique generation
2702            // number. Rely on the fact that max supported process id by Linux is 2^22.
2703            // PID is never 0 so we don't have to worry that we use the default generation of 0.
2704            // TODO: come up with a unique scheme if other producers also set the generation number.
2705            static uint32_t mSurfaceGeneration = 0;
2706            uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
2707            surface->setGenerationNumber(generation);
2708            ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
2709
2710            // HACK: clear any free buffers. Remove when connect will automatically do this.
2711            // This is needed as the consumer may be holding onto stale frames that it can reattach
2712            // to this surface after disconnect/connect, and those free frames would inherit the new
2713            // generation number. Disconnecting after setting a unique generation prevents this.
2714            native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2715            err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2716        }
2717
2718        if (err != OK) {
2719            ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
2720        }
2721    }
2722    // do not return ALREADY_EXISTS unless surfaces are the same
2723    return err == ALREADY_EXISTS ? BAD_VALUE : err;
2724}
2725
2726status_t MediaCodec::disconnectFromSurface() {
2727    status_t err = OK;
2728    if (mSurface != NULL) {
2729        // Resetting generation is not technically needed, but there is no need to keep it either
2730        mSurface->setGenerationNumber(0);
2731        err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
2732        if (err != OK) {
2733            ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
2734        }
2735        // assume disconnected even on error
2736        mSurface.clear();
2737    }
2738    return err;
2739}
2740
2741status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
2742    status_t err = OK;
2743    if (mSurface != NULL) {
2744        (void)disconnectFromSurface();
2745    }
2746    if (surface != NULL) {
2747        err = connectToSurface(surface);
2748        if (err == OK) {
2749            mSurface = surface;
2750        }
2751    }
2752    return err;
2753}
2754
2755void MediaCodec::onInputBufferAvailable() {
2756    int32_t index;
2757    while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
2758        sp<AMessage> msg = mCallback->dup();
2759        msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
2760        msg->setInt32("index", index);
2761        msg->post();
2762    }
2763}
2764
2765void MediaCodec::onOutputBufferAvailable() {
2766    int32_t index;
2767    while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
2768        const sp<MediaCodecBuffer> &buffer =
2769            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
2770        sp<AMessage> msg = mCallback->dup();
2771        msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
2772        msg->setInt32("index", index);
2773        msg->setSize("offset", buffer->offset());
2774        msg->setSize("size", buffer->size());
2775
2776        int64_t timeUs;
2777        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2778
2779        msg->setInt64("timeUs", timeUs);
2780
2781        int32_t omxFlags;
2782        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
2783
2784        uint32_t flags = 0;
2785        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
2786            flags |= BUFFER_FLAG_SYNCFRAME;
2787        }
2788        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
2789            flags |= BUFFER_FLAG_CODECCONFIG;
2790        }
2791        if (omxFlags & OMX_BUFFERFLAG_EOS) {
2792            flags |= BUFFER_FLAG_EOS;
2793        }
2794
2795        msg->setInt32("flags", flags);
2796
2797        msg->post();
2798    }
2799}
2800
2801void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
2802    if (mCallback != NULL) {
2803        sp<AMessage> msg = mCallback->dup();
2804        msg->setInt32("callbackID", CB_ERROR);
2805        msg->setInt32("err", err);
2806        msg->setInt32("actionCode", actionCode);
2807
2808        if (detail != NULL) {
2809            msg->setString("detail", detail);
2810        }
2811
2812        msg->post();
2813    }
2814}
2815
2816void MediaCodec::onOutputFormatChanged() {
2817    if (mCallback != NULL) {
2818        sp<AMessage> msg = mCallback->dup();
2819        msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
2820        msg->setMessage("format", mOutputFormat);
2821        msg->post();
2822    }
2823}
2824
2825
2826void MediaCodec::postActivityNotificationIfPossible() {
2827    if (mActivityNotify == NULL) {
2828        return;
2829    }
2830
2831    bool isErrorOrOutputChanged =
2832            (mFlags & (kFlagStickyError
2833                    | kFlagOutputBuffersChanged
2834                    | kFlagOutputFormatChanged));
2835
2836    if (isErrorOrOutputChanged
2837            || !mAvailPortBuffers[kPortIndexInput].empty()
2838            || !mAvailPortBuffers[kPortIndexOutput].empty()) {
2839        mActivityNotify->setInt32("input-buffers",
2840                mAvailPortBuffers[kPortIndexInput].size());
2841
2842        if (isErrorOrOutputChanged) {
2843            // we want consumer to dequeue as many times as it can
2844            mActivityNotify->setInt32("output-buffers", INT32_MAX);
2845        } else {
2846            mActivityNotify->setInt32("output-buffers",
2847                    mAvailPortBuffers[kPortIndexOutput].size());
2848        }
2849        mActivityNotify->post();
2850        mActivityNotify.clear();
2851    }
2852}
2853
2854status_t MediaCodec::setParameters(const sp<AMessage> &params) {
2855    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
2856    msg->setMessage("params", params);
2857
2858    sp<AMessage> response;
2859    return PostAndAwaitResponse(msg, &response);
2860}
2861
2862status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
2863    mCodec->signalSetParameters(params);
2864
2865    return OK;
2866}
2867
2868status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
2869        const sp<MediaCodecBuffer> &buffer) {
2870    AString mime;
2871    CHECK(mOutputFormat->findString("mime", &mime));
2872
2873    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
2874        // Codec specific data should be SPS and PPS in a single buffer,
2875        // each prefixed by a startcode (0x00 0x00 0x00 0x01).
2876        // We separate the two and put them into the output format
2877        // under the keys "csd-0" and "csd-1".
2878
2879        unsigned csdIndex = 0;
2880
2881        const uint8_t *data = buffer->data();
2882        size_t size = buffer->size();
2883
2884        const uint8_t *nalStart;
2885        size_t nalSize;
2886        while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
2887            sp<ABuffer> csd = new ABuffer(nalSize + 4);
2888            memcpy(csd->data(), "\x00\x00\x00\x01", 4);
2889            memcpy(csd->data() + 4, nalStart, nalSize);
2890
2891            mOutputFormat->setBuffer(
2892                    AStringPrintf("csd-%u", csdIndex).c_str(), csd);
2893
2894            ++csdIndex;
2895        }
2896
2897        if (csdIndex != 2) {
2898            return ERROR_MALFORMED;
2899        }
2900    } else {
2901        // For everything else we just stash the codec specific data into
2902        // the output format as a single piece of csd under "csd-0".
2903        sp<ABuffer> csd = new ABuffer(buffer->size());
2904        memcpy(csd->data(), buffer->data(), buffer->size());
2905        csd->setRange(0, buffer->size());
2906        mOutputFormat->setBuffer("csd-0", csd);
2907    }
2908
2909    return OK;
2910}
2911
2912void MediaCodec::updateBatteryStat() {
2913    if (!mIsVideo) {
2914        return;
2915    }
2916
2917    if (mState == CONFIGURED && !mBatteryStatNotified) {
2918        BatteryNotifier::getInstance().noteStartVideo(mUid);
2919        mBatteryStatNotified = true;
2920    } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
2921        BatteryNotifier::getInstance().noteStopVideo(mUid);
2922        mBatteryStatNotified = false;
2923    }
2924}
2925
2926}  // namespace android
2927