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