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