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