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