MediaCodec.cpp revision 671160ffe81592efa376dc1ff0fc3f4ddcdebc35
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright 2012, The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//#define LOG_NDEBUG 0
18c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#define LOG_TAG "MediaCodec"
1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h>
2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <inttypes.h>
2189e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
22c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/MediaCodec.h>
2389e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber
2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include "include/SoftwareRenderer.h"
2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <gui/Surface.h>
270c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber#include <media/ICrypto.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/foundation/ADebug.h>
3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/foundation/AMessage.h>
3120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/foundation/AString.h>
32c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/foundation/hexdump.h>
33c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/ACodec.h>
34c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/BufferProducerWrapper.h>
35c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/MediaCodecList.h>
36c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/MediaDefs.h>
37c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/MediaErrors.h>
38c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/MetaData.h>
39c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include <media/stagefright/NativeWindowWrapper.h>
40c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
41c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber#include "include/avc_utils.h"
4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
43693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubernamespace android {
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MediaCodec> MediaCodec::CreateByType(
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<ALooper> &looper, const char *mime, bool encoder) {
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MediaCodec> codec = new MediaCodec(looper);
4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (codec->init(mime, true /* nameIsType */, encoder) != OK) {
5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return codec;
5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
564678a6dc5f09008481524949a9667af5a6190374Andreas Huber// static
574931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Hubersp<MediaCodec> MediaCodec::CreateByComponentName(
584931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        const sp<ALooper> &looper, const char *name) {
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MediaCodec> codec = new MediaCodec(looper);
60c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    if (codec->init(name, false /* nameIsType */, false /* encoder */) != OK) {
618bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        return NULL;
628bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    }
63c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
64c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    return codec;
6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
6620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMediaCodec::MediaCodec(const sp<ALooper> &looper)
68c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    : mState(UNINITIALIZED),
69c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber      mLooper(looper),
70c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber      mCodec(NULL),
718bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber      mReplyID(0),
728bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber      mFlags(0),
738bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber      mSoftRenderer(NULL),
744931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber      mDequeueInputTimeoutGeneration(0),
754931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber      mDequeueInputReplyID(0),
764931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber      mDequeueOutputTimeoutGeneration(0),
774678a6dc5f09008481524949a9667af5a6190374Andreas Huber      mDequeueOutputReplyID(0),
784678a6dc5f09008481524949a9667af5a6190374Andreas Huber      mHaveInputSurface(false) {
794678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMediaCodec::~MediaCodec() {
82c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    CHECK_EQ(mState, UNINITIALIZED);
83c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber}
84c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::PostAndAwaitResponse(
8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<AMessage> &msg, sp<AMessage> *response) {
88c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t err = msg->postAndAwaitResponse(response);
8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (err != OK) {
9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return err;
9220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
930c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber
9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!(*response)->findInt32("err", &err)) {
9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        err = OK;
9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return err;
9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber// static
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MediaCodec::PostReplyWithError(int32_t replyID, int32_t err) {
10334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    sp<AMessage> response = new AMessage;
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    response->setInt32("err", err);
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    response->postReply(replyID);
10620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::init(const char *name, bool nameIsType, bool encoder) {
10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // save init parameters for reset
11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mInitName = name;
11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mInitNameIsType = nameIsType;
11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mInitIsEncoder = encoder;
11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Current video decoders do not return from OMX_FillThisBuffer
11520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // quickly, violating the OpenMAX specs, until that is remedied
11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // we need to invest in an extra looper to free the main event
11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // queue.
11820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCodec = new ACodec;
11920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool needDedicatedLooper = false;
12020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (nameIsType && !strncasecmp(name, "video/", 6)) {
12120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        needDedicatedLooper = true;
12220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
12320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        AString tmp = name;
12420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (tmp.endsWith(".secure")) {
12520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            tmp.erase(tmp.size() - 7, 7);
12620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
12720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const MediaCodecList *mcl = MediaCodecList::getInstance();
12820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
129c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        if (codecIdx >= 0) {
13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            Vector<AString> types;
13120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (mcl->getSupportedTypes(codecIdx, &types) == OK) {
13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                for (size_t i = 0; i < types.size(); i++) {
13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    if (types[i].startsWith("video/")) {
13420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        needDedicatedLooper = true;
13520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        break;
13620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    }
13720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
13820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
13920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
14020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
14134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber
14220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (needDedicatedLooper) {
14320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mCodecLooper == NULL) {
14420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecLooper = new ALooper;
14520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecLooper->setName("CodecLooper");
14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodecLooper->registerHandler(mCodec);
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mLooper->registerHandler(mCodec);
15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
15320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mLooper->registerHandler(this);
15520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, id()));
157c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
158c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    sp<AMessage> msg = new AMessage(kWhatInit, id());
159c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    msg->setString("name", name);
160c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    msg->setInt32("nameIsType", nameIsType);
161c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
162c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    if (nameIsType) {
163c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        msg->setInt32("encoder", encoder);
164c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    }
165c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
166c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    sp<AMessage> response;
167c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    return PostAndAwaitResponse(msg, &response);
168c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber}
169c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
170c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huberstatus_t MediaCodec::setCallback(const sp<AMessage> &callback) {
171c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    sp<AMessage> msg = new AMessage(kWhatSetCallback, id());
172c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    msg->setMessage("callback", callback);
173c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
174c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    sp<AMessage> response;
175c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    return PostAndAwaitResponse(msg, &response);
17620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
17720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
17820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::configure(
17920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<AMessage> &format,
180c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        const sp<Surface> &nativeWindow,
18120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<ICrypto> &crypto,
18220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t flags) {
18320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> msg = new AMessage(kWhatConfigure, id());
18420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1850c89199745bc1bf05b997fc7c342017807676b6fAndreas Huber    msg->setMessage("format", format);
18620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setInt32("flags", flags);
18720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
18820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (nativeWindow != NULL) {
18920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        msg->setObject(
19020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                "native-window",
19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                new NativeWindowWrapper(nativeWindow));
19220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
19320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (crypto != NULL) {
19520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        msg->setPointer("crypto", crypto.get());
19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> response;
19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return PostAndAwaitResponse(msg, &response);
20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::createInputSurface(
20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        sp<IGraphicBufferProducer>* bufferProducer) {
20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, id());
20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> response;
20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err = PostAndAwaitResponse(msg, &response);
20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (err == NO_ERROR) {
20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // unwrap the sp<IGraphicBufferProducer>
21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        sp<RefBase> obj;
21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        bool found = response->findObject("input-surface", &obj);
21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        CHECK(found);
21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        sp<BufferProducerWrapper> wrapper(
21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                static_cast<BufferProducerWrapper*>(obj.get()));
21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *bufferProducer = wrapper->getBufferProducer();
21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ALOGW("createInputSurface failed, err=%d", err);
21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return err;
22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::start() {
2239f753df58a70f20db220af31cb202bbd21b30f36Andreas Huber    sp<AMessage> msg = new AMessage(kWhatStart, id());
22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> response;
22620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return PostAndAwaitResponse(msg, &response);
22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::stop() {
23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> msg = new AMessage(kWhatStop, id());
23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> response;
23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return PostAndAwaitResponse(msg, &response);
23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
23520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::release() {
23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> msg = new AMessage(kWhatRelease, id());
23820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> response;
240c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    return PostAndAwaitResponse(msg, &response);
24120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::reset() {
24420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    /* When external-facing MediaCodec object is created,
24520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber       it is already initialized.  Thus, reset is essentially
24634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber       release() followed by init(), plus clearing the state */
24720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err = release();
24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
25020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // unregister handlers
25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mCodec != NULL) {
25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mCodecLooper != NULL) {
25320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mCodecLooper->unregisterHandler(mCodec->id());
25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        } else {
25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLooper->unregisterHandler(mCodec->id());
25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mCodec = NULL;
25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mLooper->unregisterHandler(id());
26034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFlags = 0;    // clear all flags
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // reset state not reset by setState(UNINITIALIZED)
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mReplyID = 0;
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDequeueInputReplyID = 0;
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDequeueOutputReplyID = 0;
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDequeueInputTimeoutGeneration = 0;
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mDequeueOutputTimeoutGeneration = 0;
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mHaveInputSurface = false;
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (err == OK) {
2724931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        err = init(mInitName.c_str(), mInitNameIsType, mInitIsEncoder);
2734931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
2744931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    return err;
2754931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber}
2764931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
2774931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huberstatus_t MediaCodec::queueInputBuffer(
2784931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        size_t index,
2794931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        size_t offset,
2804931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        size_t size,
2814931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        int64_t presentationTimeUs,
2824931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        uint32_t flags,
2834931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        AString *errorDetailMsg) {
2844931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    if (errorDetailMsg != NULL) {
2854931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        errorDetailMsg->clear();
2864931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
2874931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
2884931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
2894931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    msg->setSize("index", index);
2904931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    msg->setSize("offset", offset);
2914931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    msg->setSize("size", size);
2924931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    msg->setInt64("timeUs", presentationTimeUs);
2934931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    msg->setInt32("flags", flags);
2944931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    msg->setPointer("errorDetailMsg", errorDetailMsg);
2954931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
2964931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    sp<AMessage> response;
2974931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    return PostAndAwaitResponse(msg, &response);
2984931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber}
2994931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
3004931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huberstatus_t MediaCodec::queueSecureInputBuffer(
3014931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        size_t index,
3024931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        size_t offset,
3034931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        const CryptoPlugin::SubSample *subSamples,
3044931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        size_t numSubSamples,
3054931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        const uint8_t key[16],
3064931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        const uint8_t iv[16],
3074931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        CryptoPlugin::Mode mode,
3084931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        int64_t presentationTimeUs,
3094931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        uint32_t flags,
3104931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        AString *errorDetailMsg) {
3114931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    if (errorDetailMsg != NULL) {
3124931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        errorDetailMsg->clear();
3134931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    }
3144931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
3154931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
3164931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber    msg->setSize("index", index);
317c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    msg->setSize("offset", offset);
31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setPointer("subSamples", (void *)subSamples);
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setSize("numSubSamples", numSubSamples);
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setPointer("key", (void *)key);
32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setPointer("iv", (void *)iv);
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setInt32("mode", mode);
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setInt64("timeUs", presentationTimeUs);
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setInt32("flags", flags);
32534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    msg->setPointer("errorDetailMsg", errorDetailMsg);
32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> response;
32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err = PostAndAwaitResponse(msg, &response);
32920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return err;
33120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, id());
33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setInt64("timeoutUs", timeoutUs);
33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> response;
33875fc7654280ac2a72fa8124b88e616219a3e61e2Andreas Huber    status_t err;
33920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
3408bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        return err;
3418bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    }
3428bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3438bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    CHECK(response->findSize("index", index));
3448bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3458bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    return OK;
3468bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber}
3478bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3488bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huberstatus_t MediaCodec::dequeueOutputBuffer(
3498bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        size_t *index,
3508bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        size_t *offset,
3518bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        size_t *size,
35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        int64_t *presentationTimeUs,
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t *flags,
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        int64_t timeoutUs) {
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, id());
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setInt64("timeoutUs", timeoutUs);
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> response;
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return err;
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    CHECK(response->findSize("index", index));
36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    CHECK(response->findSize("offset", offset));
36620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    CHECK(response->findSize("size", size));
36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    CHECK(response->findInt64("timeUs", presentationTimeUs));
36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    CHECK(response->findInt32("flags", (int32_t *)flags));
36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
370c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber    return OK;
371da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber}
37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setSize("index", index);
37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setInt32("render", true);
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> response;
37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return PostAndAwaitResponse(msg, &response);
38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
38120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
38220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) {
38320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
384da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber    msg->setSize("index", index);
385da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber    msg->setInt32("render", true);
386da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber    msg->setInt64("timestampNs", timestampNs);
387da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber
3884678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> response;
3894678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return PostAndAwaitResponse(msg, &response);
3904678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
3914678a6dc5f09008481524949a9667af5a6190374Andreas Huber
3924931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huberstatus_t MediaCodec::releaseOutputBuffer(size_t index) {
3934678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, id());
3944678a6dc5f09008481524949a9667af5a6190374Andreas Huber    msg->setSize("index", index);
3954678a6dc5f09008481524949a9667af5a6190374Andreas Huber
3964678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> response;
3974678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return PostAndAwaitResponse(msg, &response);
398abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber}
3994678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4004678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::signalEndOfInputStream() {
4014678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, id());
4024678a6dc5f09008481524949a9667af5a6190374Andreas Huber
40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> response;
40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return PostAndAwaitResponse(msg, &response);
4054678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
4064678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4074678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
4084678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, id());
4094678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4104678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> response;
4114678a6dc5f09008481524949a9667af5a6190374Andreas Huber    status_t err;
4124678a6dc5f09008481524949a9667af5a6190374Andreas Huber    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
4134678a6dc5f09008481524949a9667af5a6190374Andreas Huber        return err;
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    CHECK(response->findMessage("format", format));
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4184678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return OK;
4194678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4214678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getInputFormat(sp<AMessage> *format) const {
422abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    sp<AMessage> msg = new AMessage(kWhatGetInputFormat, id());
4234678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4244678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> response;
4254678a6dc5f09008481524949a9667af5a6190374Andreas Huber    status_t err;
4264678a6dc5f09008481524949a9667af5a6190374Andreas Huber    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
4274678a6dc5f09008481524949a9667af5a6190374Andreas Huber        return err;
4284678a6dc5f09008481524949a9667af5a6190374Andreas Huber    }
4294678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4304678a6dc5f09008481524949a9667af5a6190374Andreas Huber    CHECK(response->findMessage("format", format));
4314678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4324678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return OK;
4334678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
4344678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4354678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getName(AString *name) const {
4364678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> msg = new AMessage(kWhatGetName, id());
4374678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4384678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> response;
4394678a6dc5f09008481524949a9667af5a6190374Andreas Huber    status_t err;
4404678a6dc5f09008481524949a9667af5a6190374Andreas Huber    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
4414678a6dc5f09008481524949a9667af5a6190374Andreas Huber        return err;
4424678a6dc5f09008481524949a9667af5a6190374Andreas Huber    }
4434678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4444678a6dc5f09008481524949a9667af5a6190374Andreas Huber    CHECK(response->findString("name", name));
4454678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4464678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return OK;
4474678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
4484678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4494678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
4504678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
4514678a6dc5f09008481524949a9667af5a6190374Andreas Huber    msg->setInt32("portIndex", kPortIndexInput);
4524678a6dc5f09008481524949a9667af5a6190374Andreas Huber    msg->setPointer("buffers", buffers);
4534678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4544678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> response;
4554678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return PostAndAwaitResponse(msg, &response);
456a488c7daf91357611fcdbff7a32e5a73ec630070Andreas Huber}
457a488c7daf91357611fcdbff7a32e5a73ec630070Andreas Huber
458a488c7daf91357611fcdbff7a32e5a73ec630070Andreas Huberstatus_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
459a488c7daf91357611fcdbff7a32e5a73ec630070Andreas Huber    sp<AMessage> msg = new AMessage(kWhatGetBuffers, id());
4604678a6dc5f09008481524949a9667af5a6190374Andreas Huber    msg->setInt32("portIndex", kPortIndexOutput);
4614678a6dc5f09008481524949a9667af5a6190374Andreas Huber    msg->setPointer("buffers", buffers);
4624678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4634678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> response;
464abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    return PostAndAwaitResponse(msg, &response);
4654678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
4664678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4674678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getOutputBuffer(size_t index, sp<ABuffer> *buffer) {
4684678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> format;
4694678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
4704678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
4714678a6dc5f09008481524949a9667af5a6190374Andreas Huber
47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
4734678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<ABuffer> buffer;
4744678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
4764678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4774678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getInputBuffer(size_t index, sp<ABuffer> *buffer) {
4784678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> format;
4794678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
4804678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
4814678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4824678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::getBufferAndFormat(
4834678a6dc5f09008481524949a9667af5a6190374Andreas Huber        size_t portIndex, size_t index,
48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        sp<ABuffer> *buffer, sp<AMessage> *format) {
48520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // use mutex instead of a context switch
4864678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4874678a6dc5f09008481524949a9667af5a6190374Andreas Huber    buffer->clear();
4884678a6dc5f09008481524949a9667af5a6190374Andreas Huber    format->clear();
4894678a6dc5f09008481524949a9667af5a6190374Andreas Huber    if (mState != STARTED) {
4904678a6dc5f09008481524949a9667af5a6190374Andreas Huber        return INVALID_OPERATION;
4914678a6dc5f09008481524949a9667af5a6190374Andreas Huber    }
4924678a6dc5f09008481524949a9667af5a6190374Andreas Huber
4934678a6dc5f09008481524949a9667af5a6190374Andreas Huber    // we do not want mPortBuffers to change during this section
4944678a6dc5f09008481524949a9667af5a6190374Andreas Huber    // we also don't want mOwnedByClient to change during this
4954678a6dc5f09008481524949a9667af5a6190374Andreas Huber    Mutex::Autolock al(mBufferLock);
4964678a6dc5f09008481524949a9667af5a6190374Andreas Huber    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
4974678a6dc5f09008481524949a9667af5a6190374Andreas Huber    if (index < buffers->size()) {
4984678a6dc5f09008481524949a9667af5a6190374Andreas Huber        const BufferInfo &info = buffers->itemAt(index);
4994678a6dc5f09008481524949a9667af5a6190374Andreas Huber        if (info.mOwnedByClient) {
5004678a6dc5f09008481524949a9667af5a6190374Andreas Huber            *buffer = info.mData;
5014678a6dc5f09008481524949a9667af5a6190374Andreas Huber            *format = info.mFormat;
5024678a6dc5f09008481524949a9667af5a6190374Andreas Huber        }
5034678a6dc5f09008481524949a9667af5a6190374Andreas Huber    }
5044678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return OK;
5054678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
5064678a6dc5f09008481524949a9667af5a6190374Andreas Huber
5074678a6dc5f09008481524949a9667af5a6190374Andreas Huberstatus_t MediaCodec::flush() {
5084678a6dc5f09008481524949a9667af5a6190374Andreas Huber    sp<AMessage> msg = new AMessage(kWhatFlush, id());
50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> response;
5114678a6dc5f09008481524949a9667af5a6190374Andreas Huber    return PostAndAwaitResponse(msg, &response);
5124678a6dc5f09008481524949a9667af5a6190374Andreas Huber}
5134678a6dc5f09008481524949a9667af5a6190374Andreas Huber
51420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MediaCodec::requestIDRFrame() {
51520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    (new AMessage(kWhatRequestIDRFrame, id()))->post();
516abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
517abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    return OK;
518abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber}
519abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubervoid MediaCodec::requestActivityNotification(const sp<AMessage> &notify) {
52120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, id());
52220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->setMessage("notify", notify);
52320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    msg->post();
52420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
52520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
528abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Hubervoid MediaCodec::cancelPendingDequeueOperations() {
529abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (mFlags & kFlagDequeueInputPending) {
530abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
531abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
532da76c64dee7d95c967e2841302300cfb081e67b2Andreas Huber        ++mDequeueInputTimeoutGeneration;
533abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mDequeueInputReplyID = 0;
534abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mFlags &= ~kFlagDequeueInputPending;
5358bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    }
53620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
537abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (mFlags & kFlagDequeueOutputPending) {
53820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
53920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
540abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        ++mDequeueOutputTimeoutGeneration;
541abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mDequeueOutputReplyID = 0;
542abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mFlags &= ~kFlagDequeueOutputPending;
543f53263a7d580fb550dbc6c8d4f104119beb82ad7James Dong    }
544f53263a7d580fb550dbc6c8d4f104119beb82ad7James Dong}
545f53263a7d580fb550dbc6c8d4f104119beb82ad7James Dong
546abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huberbool MediaCodec::handleDequeueInputBuffer(uint32_t replyID, bool newRequest) {
547abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (mState != STARTED
548abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            || (mFlags & kFlagStickyError)
549abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            || (newRequest && (mFlags & kFlagDequeueInputPending))) {
550abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        PostReplyWithError(replyID, INVALID_OPERATION);
551abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        return true;
552abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    }
553abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
554abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ssize_t index = dequeuePortBuffer(kPortIndexInput);
555abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
556abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (index < 0) {
5578bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        CHECK_EQ(index, -EAGAIN);
558abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        return false;
559abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    }
560abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
561abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    sp<AMessage> response = new AMessage;
562abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    response->setSize("index", index);
563abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    response->postReply(replyID);
564abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
565abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    return true;
566abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber}
567abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
568abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huberbool MediaCodec::handleDequeueOutputBuffer(uint32_t replyID, bool newRequest) {
569abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    sp<AMessage> response = new AMessage;
570abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
571abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (mState != STARTED
572abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            || (mFlags & kFlagStickyError)
573abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
574abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        response->setInt32("err", INVALID_OPERATION);
575abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    } else if (mFlags & kFlagOutputBuffersChanged) {
576abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        response->setInt32("err", INFO_OUTPUT_BUFFERS_CHANGED);
577abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mFlags &= ~kFlagOutputBuffersChanged;
578abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    } else if (mFlags & kFlagOutputFormatChanged) {
579abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        response->setInt32("err", INFO_FORMAT_CHANGED);
580abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mFlags &= ~kFlagOutputFormatChanged;
581abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    } else {
582abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        ssize_t index = dequeuePortBuffer(kPortIndexOutput);
583abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
584abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (index < 0) {
585abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            CHECK_EQ(index, -EAGAIN);
586abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            return false;
587abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
588abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
589abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        const sp<ABuffer> &buffer =
590abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
591abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
592abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        response->setSize("index", index);
593abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        response->setSize("offset", buffer->offset());
594abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        response->setSize("size", buffer->size());
595abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
596abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        int64_t timeUs;
597abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
598abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
599abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        response->setInt64("timeUs", timeUs);
600abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
601abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        int32_t omxFlags;
602abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
603abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
604abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t flags = 0;
605abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
606abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            flags |= BUFFER_FLAG_SYNCFRAME;
607abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
608abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
609abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            flags |= BUFFER_FLAG_CODECCONFIG;
610abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
611abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (omxFlags & OMX_BUFFERFLAG_EOS) {
612abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            flags |= BUFFER_FLAG_EOS;
613abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
614abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
6158bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        response->setInt32("flags", flags);
616abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    }
617abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
618abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    response->postReply(replyID);
619abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
620abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    return true;
621abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber}
622abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
623abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Hubervoid MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
624abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    switch (msg->what()) {
62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case kWhatCodecNotify:
62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
627abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            int32_t what;
62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            CHECK(msg->findInt32("what", &what));
62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            switch (what) {
63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                case CodecBase::kWhatError:
6327e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                {
633c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                    int32_t omxError, internalError;
634c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                    CHECK(msg->findInt32("omx-error", &omxError));
6357e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                    CHECK(msg->findInt32("err", &internalError));
6367e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
6377e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                    ALOGE("Codec reported an error. "
6387e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                          "(omx error 0x%08x, internalError %d)",
6397e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                          omxError, internalError);
6407e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
6417e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                    if (omxError == OMX_ErrorResourcesLost
6427e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                            && internalError == DEAD_OBJECT) {
6437e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        mFlags |= kFlagSawMediaServerDie;
6447e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                    }
6457e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
6467e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                    bool sendErrorReponse = true;
6477e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
6487e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                    switch (mState) {
6497e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        case INITIALIZING:
6507e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        {
6517e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                            setState(UNINITIALIZED);
6527e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                            break;
6537e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        }
6547e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
6558bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                        case CONFIGURING:
6567e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        {
6577e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                            setState(INITIALIZED);
6587e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                            break;
659c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                        }
6607e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
6617e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        case STARTING:
6627e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        {
6637e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                            setState(CONFIGURED);
6647e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                            break;
6657e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        }
6667e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
6677e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        case STOPPING:
6687e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        case RELEASING:
6697e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                        {
6707e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                            // Ignore the error, assuming we'll still get
6717e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                            // the shutdown complete notification.
6727e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
6737e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber                            sendErrorReponse = false;
6747e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
675c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                            if (mFlags & kFlagSawMediaServerDie) {
676c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                                // MediaServer died, there definitely won't
677c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                                // be a shutdown complete notification after
678c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                                // all.
679c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
680c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                                // note that we're directly going from
681c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                                // STOPPING->UNINITIALIZED, instead of the
682c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                                // usual STOPPING->INITIALIZED state.
683c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong                                setState(UNINITIALIZED);
684c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
6854678a6dc5f09008481524949a9667af5a6190374Andreas Huber                                (new AMessage)->postReply(mReplyID);
6868bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                            }
687c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                            break;
688c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                        }
689c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
690c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                        case FLUSHING:
691c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                        {
692c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                            setState(STARTED);
693c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                            break;
694c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                        }
695c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
696c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                        case STARTED:
697c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                        {
698c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                            sendErrorReponse = false;
699c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
700c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                            mFlags |= kFlagStickyError;
701c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                            postActivityNotificationIfPossible();
7024678a6dc5f09008481524949a9667af5a6190374Andreas Huber
7034678a6dc5f09008481524949a9667af5a6190374Andreas Huber                            cancelPendingDequeueOperations();
704c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
705c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                            if (mFlags & kFlagIsAsync) {
7068bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                                onError(omxError, 0);
7078bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                            }
7088bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                            setState(UNINITIALIZED);
7098bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                            break;
7108bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                        }
7118bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
7128bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                        default:
7138bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                        {
7148bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                            sendErrorReponse = false;
7158bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
7168bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                            mFlags |= kFlagStickyError;
7178bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                            postActivityNotificationIfPossible();
7188bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
7198bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                            if (mFlags & kFlagIsAsync) {
7208bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                                onError(omxError, 0);
7218bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                            }
7228bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                            setState(UNINITIALIZED);
7238bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                            break;
7248bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                        }
7258bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                    }
7268bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
7278bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                    if (sendErrorReponse) {
728c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                        PostReplyWithError(mReplyID, UNKNOWN_ERROR);
729c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                    }
730c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber                    break;
7314931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                }
7324931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
7334931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                case CodecBase::kWhatComponentAllocated:
7344931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                {
7354931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                    CHECK_EQ(mState, INITIALIZING);
7364931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                    setState(INITIALIZED);
7374931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
7384931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                    CHECK(msg->findString("componentName", &mComponentName));
7394931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
7404931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                    if (mComponentName.startsWith("OMX.google.")) {
7414931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        mFlags |= kFlagIsSoftwareCodec;
7424931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                    } else {
7434931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        mFlags &= ~kFlagIsSoftwareCodec;
7444931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                    }
7454931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
7464931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                    if (mComponentName.endsWith(".secure")) {
7474931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        mFlags |= kFlagIsSecure;
7484931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                    } else {
7494931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        mFlags &= ~kFlagIsSecure;
7504931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                    }
7514931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    (new AMessage)->postReply(mReplyID);
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    break;
754                }
755
756                case CodecBase::kWhatComponentConfigured:
757                {
758                    CHECK_EQ(mState, CONFIGURING);
759                    setState(CONFIGURED);
760
761                    // reset input surface flag
762                    mHaveInputSurface = false;
763
764                    CHECK(msg->findMessage("input-format", &mInputFormat));
765                    CHECK(msg->findMessage("output-format", &mOutputFormat));
766
767                    (new AMessage)->postReply(mReplyID);
768                    break;
769                }
770
771                case CodecBase::kWhatInputSurfaceCreated:
772                {
773                    // response to initiateCreateInputSurface()
774                    status_t err = NO_ERROR;
775                    sp<AMessage> response = new AMessage();
776                    if (!msg->findInt32("err", &err)) {
777                        sp<RefBase> obj;
778                        msg->findObject("input-surface", &obj);
779                        CHECK(obj != NULL);
780                        response->setObject("input-surface", obj);
781                        mHaveInputSurface = true;
782                    } else {
783                        response->setInt32("err", err);
784                    }
785                    response->postReply(mReplyID);
786                    break;
787                }
788
789                case CodecBase::kWhatSignaledInputEOS:
790                {
791                    // response to signalEndOfInputStream()
792                    sp<AMessage> response = new AMessage();
793                    status_t err;
794                    if (msg->findInt32("err", &err)) {
795                        response->setInt32("err", err);
796                    }
797                    response->postReply(mReplyID);
798                    break;
799                }
800
801
802                case CodecBase::kWhatBuffersAllocated:
803                {
804                    Mutex::Autolock al(mBufferLock);
805                    int32_t portIndex;
806                    CHECK(msg->findInt32("portIndex", &portIndex));
807
808                    ALOGV("%s buffers allocated",
809                          portIndex == kPortIndexInput ? "input" : "output");
810
811                    CHECK(portIndex == kPortIndexInput
812                            || portIndex == kPortIndexOutput);
813
814                    mPortBuffers[portIndex].clear();
815
816                    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
817
818                    sp<RefBase> obj;
819                    CHECK(msg->findObject("portDesc", &obj));
820
821                    sp<CodecBase::PortDescription> portDesc =
822                        static_cast<CodecBase::PortDescription *>(obj.get());
823
824                    size_t numBuffers = portDesc->countBuffers();
825
826                    for (size_t i = 0; i < numBuffers; ++i) {
827                        BufferInfo info;
828                        info.mBufferID = portDesc->bufferIDAt(i);
829                        info.mOwnedByClient = false;
830                        info.mData = portDesc->bufferAt(i);
831
832                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
833                            info.mEncryptedData =
834                                new ABuffer(info.mData->capacity());
835                        }
836
837                        buffers->push_back(info);
838                    }
839
840                    if (portIndex == kPortIndexOutput) {
841                        if (mState == STARTING) {
842                            // We're always allocating output buffers after
843                            // allocating input buffers, so this is a good
844                            // indication that now all buffers are allocated.
845                            setState(STARTED);
846                            (new AMessage)->postReply(mReplyID);
847                        } else {
848                            mFlags |= kFlagOutputBuffersChanged;
849                            postActivityNotificationIfPossible();
850                        }
851                    }
852                    break;
853                }
854
855                case CodecBase::kWhatOutputFormatChanged:
856                {
857                    ALOGV("codec output format changed");
858
859                    if ((mFlags & kFlagIsSoftwareCodec)
860                            && mNativeWindow != NULL) {
861                        AString mime;
862                        CHECK(msg->findString("mime", &mime));
863
864                        if (!strncasecmp("video/", mime.c_str(), 6)) {
865                            delete mSoftRenderer;
866                            mSoftRenderer = NULL;
867
868                            int32_t width, height;
869                            CHECK(msg->findInt32("width", &width));
870                            CHECK(msg->findInt32("height", &height));
871
872                            int32_t cropLeft, cropTop, cropRight, cropBottom;
873                            CHECK(msg->findRect("crop",
874                                &cropLeft, &cropTop, &cropRight, &cropBottom));
875
876                            int32_t colorFormat;
877                            CHECK(msg->findInt32(
878                                        "color-format", &colorFormat));
879
880                            sp<MetaData> meta = new MetaData;
881                            meta->setInt32(kKeyWidth, width);
882                            meta->setInt32(kKeyHeight, height);
883                            meta->setRect(kKeyCropRect,
884                                cropLeft, cropTop, cropRight, cropBottom);
885                            meta->setInt32(kKeyColorFormat, colorFormat);
886
887                            mSoftRenderer =
888                                new SoftwareRenderer(mNativeWindow, meta);
889                        }
890                    }
891
892                    mOutputFormat = msg;
893
894                    if (mFlags & kFlagIsEncoder) {
895                        // Before we announce the format change we should
896                        // collect codec specific data and amend the output
897                        // format as necessary.
898                        mFlags |= kFlagGatherCodecSpecificData;
899                    } else if (mFlags & kFlagIsAsync) {
900                        onOutputFormatChanged();
901                    } else {
902                        mFlags |= kFlagOutputFormatChanged;
903                        postActivityNotificationIfPossible();
904                    }
905                    break;
906                }
907
908                case CodecBase::kWhatFillThisBuffer:
909                {
910                    /* size_t index = */updateBuffers(kPortIndexInput, msg);
911
912                    if (mState == FLUSHING
913                            || mState == STOPPING
914                            || mState == RELEASING) {
915                        returnBuffersToCodecOnPort(kPortIndexInput);
916                        break;
917                    }
918
919                    if (!mCSD.empty()) {
920                        ssize_t index = dequeuePortBuffer(kPortIndexInput);
921                        CHECK_GE(index, 0);
922
923                        // If codec specific data had been specified as
924                        // part of the format in the call to configure and
925                        // if there's more csd left, we submit it here
926                        // clients only get access to input buffers once
927                        // this data has been exhausted.
928
929                        status_t err = queueCSDInputBuffer(index);
930
931                        if (err != OK) {
932                            ALOGE("queueCSDInputBuffer failed w/ error %d",
933                                  err);
934
935                            mFlags |= kFlagStickyError;
936                            postActivityNotificationIfPossible();
937
938                            cancelPendingDequeueOperations();
939                        }
940                        break;
941                    }
942
943                    if (mFlags & kFlagIsAsync) {
944                        onInputBufferAvailable();
945                    } else if (mFlags & kFlagDequeueInputPending) {
946                        CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
947
948                        ++mDequeueInputTimeoutGeneration;
949                        mFlags &= ~kFlagDequeueInputPending;
950                        mDequeueInputReplyID = 0;
951                    } else {
952                        postActivityNotificationIfPossible();
953                    }
954                    break;
955                }
956
957                case CodecBase::kWhatDrainThisBuffer:
958                {
959                    /* size_t index = */updateBuffers(kPortIndexOutput, msg);
960
961                    if (mState == FLUSHING
962                            || mState == STOPPING
963                            || mState == RELEASING) {
964                        returnBuffersToCodecOnPort(kPortIndexOutput);
965                        break;
966                    }
967
968                    sp<ABuffer> buffer;
969                    CHECK(msg->findBuffer("buffer", &buffer));
970
971                    int32_t omxFlags;
972                    CHECK(msg->findInt32("flags", &omxFlags));
973
974                    buffer->meta()->setInt32("omxFlags", omxFlags);
975
976                    if (mFlags & kFlagGatherCodecSpecificData) {
977                        // This is the very first output buffer after a
978                        // format change was signalled, it'll either contain
979                        // the one piece of codec specific data we can expect
980                        // or there won't be codec specific data.
981                        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
982                            status_t err =
983                                amendOutputFormatWithCodecSpecificData(buffer);
984
985                            if (err != OK) {
986                                ALOGE("Codec spit out malformed codec "
987                                      "specific data!");
988                            }
989                        }
990
991                        mFlags &= ~kFlagGatherCodecSpecificData;
992                        if (mFlags & kFlagIsAsync) {
993                            onOutputFormatChanged();
994                        } else {
995                            mFlags |= kFlagOutputFormatChanged;
996                        }
997                    }
998
999                    if (mFlags & kFlagIsAsync) {
1000                        onOutputBufferAvailable();
1001                    } else if (mFlags & kFlagDequeueOutputPending) {
1002                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
1003
1004                        ++mDequeueOutputTimeoutGeneration;
1005                        mFlags &= ~kFlagDequeueOutputPending;
1006                        mDequeueOutputReplyID = 0;
1007                    } else {
1008                        postActivityNotificationIfPossible();
1009                    }
1010
1011                    break;
1012                }
1013
1014                case CodecBase::kWhatEOS:
1015                {
1016                    // We already notify the client of this by using the
1017                    // corresponding flag in "onOutputBufferReady".
1018                    break;
1019                }
1020
1021                case CodecBase::kWhatShutdownCompleted:
1022                {
1023                    if (mState == STOPPING) {
1024                        setState(INITIALIZED);
1025                    } else {
1026                        CHECK_EQ(mState, RELEASING);
1027                        setState(UNINITIALIZED);
1028                    }
1029
1030                    (new AMessage)->postReply(mReplyID);
1031                    break;
1032                }
1033
1034                case CodecBase::kWhatFlushCompleted:
1035                {
1036                    CHECK_EQ(mState, FLUSHING);
1037                    setState(STARTED);
1038
1039                    mCodec->signalResume();
1040
1041                    (new AMessage)->postReply(mReplyID);
1042                    break;
1043                }
1044
1045                default:
1046                    TRESPASS();
1047            }
1048            break;
1049        }
1050
1051        case kWhatInit:
1052        {
1053            uint32_t replyID;
1054            CHECK(msg->senderAwaitsResponse(&replyID));
1055
1056            if (mState != UNINITIALIZED) {
1057                PostReplyWithError(replyID, INVALID_OPERATION);
1058                break;
1059            }
1060
1061            mReplyID = replyID;
1062            setState(INITIALIZING);
1063
1064            AString name;
1065            CHECK(msg->findString("name", &name));
1066
1067            int32_t nameIsType;
1068            int32_t encoder = false;
1069            CHECK(msg->findInt32("nameIsType", &nameIsType));
1070            if (nameIsType) {
1071                CHECK(msg->findInt32("encoder", &encoder));
1072            }
1073
1074            sp<AMessage> format = new AMessage;
1075
1076            if (nameIsType) {
1077                format->setString("mime", name.c_str());
1078                format->setInt32("encoder", encoder);
1079            } else {
1080                format->setString("componentName", name.c_str());
1081            }
1082
1083            mCodec->initiateAllocateComponent(format);
1084            break;
1085        }
1086
1087        case kWhatSetCallback:
1088        {
1089            uint32_t replyID;
1090            CHECK(msg->senderAwaitsResponse(&replyID));
1091
1092            if (mState == UNINITIALIZED
1093                    || mState == INITIALIZING
1094                    || mState == STARTED) {
1095                // callback can't be set after codec is started,
1096                // or before it's initialized (as the callback
1097                // will be cleared when it goes to INITIALIZED)
1098                PostReplyWithError(replyID, INVALID_OPERATION);
1099                break;
1100            }
1101
1102            sp<AMessage> callback;
1103            CHECK(msg->findMessage("callback", &callback));
1104
1105            mCallback = callback;
1106
1107            if (mCallback != NULL) {
1108                ALOGI("MediaCodec will operate in async mode");
1109                mFlags |= kFlagIsAsync;
1110            } else {
1111                mFlags &= ~kFlagIsAsync;
1112            }
1113
1114            sp<AMessage> response = new AMessage;
1115            response->postReply(replyID);
1116            break;
1117        }
1118
1119        case kWhatConfigure:
1120        {
1121            uint32_t replyID;
1122            CHECK(msg->senderAwaitsResponse(&replyID));
1123
1124            if (mState != INITIALIZED) {
1125                PostReplyWithError(replyID, INVALID_OPERATION);
1126                break;
1127            }
1128
1129            sp<RefBase> obj;
1130            if (!msg->findObject("native-window", &obj)) {
1131                obj.clear();
1132            }
1133
1134            sp<AMessage> format;
1135            CHECK(msg->findMessage("format", &format));
1136
1137            if (obj != NULL) {
1138                format->setObject("native-window", obj);
1139
1140                status_t err = setNativeWindow(
1141                    static_cast<NativeWindowWrapper *>(obj.get())
1142                        ->getSurfaceTextureClient());
1143
1144                if (err != OK) {
1145                    PostReplyWithError(replyID, err);
1146                    break;
1147                }
1148            } else {
1149                setNativeWindow(NULL);
1150            }
1151
1152            mReplyID = replyID;
1153            setState(CONFIGURING);
1154
1155            void *crypto;
1156            if (!msg->findPointer("crypto", &crypto)) {
1157                crypto = NULL;
1158            }
1159
1160            mCrypto = static_cast<ICrypto *>(crypto);
1161
1162            uint32_t flags;
1163            CHECK(msg->findInt32("flags", (int32_t *)&flags));
1164
1165            if (flags & CONFIGURE_FLAG_ENCODE) {
1166                format->setInt32("encoder", true);
1167                mFlags |= kFlagIsEncoder;
1168            }
1169
1170            extractCSD(format);
1171
1172            mCodec->initiateConfigureComponent(format);
1173            break;
1174        }
1175
1176        case kWhatCreateInputSurface:
1177        {
1178            uint32_t replyID;
1179            CHECK(msg->senderAwaitsResponse(&replyID));
1180
1181            // Must be configured, but can't have been started yet.
1182            if (mState != CONFIGURED) {
1183                PostReplyWithError(replyID, INVALID_OPERATION);
1184                break;
1185            }
1186
1187            mReplyID = replyID;
1188            mCodec->initiateCreateInputSurface();
1189            break;
1190        }
1191
1192        case kWhatStart:
1193        {
1194            uint32_t replyID;
1195            CHECK(msg->senderAwaitsResponse(&replyID));
1196
1197            if (mState != CONFIGURED) {
1198                PostReplyWithError(replyID, INVALID_OPERATION);
1199                break;
1200            }
1201
1202            mReplyID = replyID;
1203            setState(STARTING);
1204
1205            mCodec->initiateStart();
1206            break;
1207        }
1208
1209        case kWhatStop:
1210        case kWhatRelease:
1211        {
1212            State targetState =
1213                (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
1214
1215            uint32_t replyID;
1216            CHECK(msg->senderAwaitsResponse(&replyID));
1217
1218            if (mState != INITIALIZED
1219                    && mState != CONFIGURED && mState != STARTED) {
1220                // We may be in "UNINITIALIZED" state already without the
1221                // client being aware of this if media server died while
1222                // we were being stopped. The client would assume that
1223                // after stop() returned, it would be safe to call release()
1224                // and it should be in this case, no harm to allow a release()
1225                // if we're already uninitialized.
1226                // Similarly stopping a stopped MediaCodec should be benign.
1227                sp<AMessage> response = new AMessage;
1228                response->setInt32(
1229                        "err",
1230                        mState == targetState ? OK : INVALID_OPERATION);
1231
1232                response->postReply(replyID);
1233                break;
1234            }
1235
1236            if (mFlags & kFlagSawMediaServerDie) {
1237                // It's dead, Jim. Don't expect initiateShutdown to yield
1238                // any useful results now...
1239                setState(UNINITIALIZED);
1240                (new AMessage)->postReply(replyID);
1241                break;
1242            }
1243
1244            mReplyID = replyID;
1245            setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
1246
1247            mCodec->initiateShutdown(
1248                    msg->what() == kWhatStop /* keepComponentAllocated */);
1249
1250            returnBuffersToCodec();
1251            break;
1252        }
1253
1254        case kWhatDequeueInputBuffer:
1255        {
1256            uint32_t replyID;
1257            CHECK(msg->senderAwaitsResponse(&replyID));
1258
1259            if (mFlags & kFlagIsAsync) {
1260                ALOGE("dequeueOutputBuffer can't be used in async mode");
1261                PostReplyWithError(replyID, INVALID_OPERATION);
1262                break;
1263            }
1264
1265            if (mHaveInputSurface) {
1266                ALOGE("dequeueInputBuffer can't be used with input surface");
1267                PostReplyWithError(replyID, INVALID_OPERATION);
1268                break;
1269            }
1270
1271            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
1272                break;
1273            }
1274
1275            int64_t timeoutUs;
1276            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1277
1278            if (timeoutUs == 0ll) {
1279                PostReplyWithError(replyID, -EAGAIN);
1280                break;
1281            }
1282
1283            mFlags |= kFlagDequeueInputPending;
1284            mDequeueInputReplyID = replyID;
1285
1286            if (timeoutUs > 0ll) {
1287                sp<AMessage> timeoutMsg =
1288                    new AMessage(kWhatDequeueInputTimedOut, id());
1289                timeoutMsg->setInt32(
1290                        "generation", ++mDequeueInputTimeoutGeneration);
1291                timeoutMsg->post(timeoutUs);
1292            }
1293            break;
1294        }
1295
1296        case kWhatDequeueInputTimedOut:
1297        {
1298            int32_t generation;
1299            CHECK(msg->findInt32("generation", &generation));
1300
1301            if (generation != mDequeueInputTimeoutGeneration) {
1302                // Obsolete
1303                break;
1304            }
1305
1306            CHECK(mFlags & kFlagDequeueInputPending);
1307
1308            PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
1309
1310            mFlags &= ~kFlagDequeueInputPending;
1311            mDequeueInputReplyID = 0;
1312            break;
1313        }
1314
1315        case kWhatQueueInputBuffer:
1316        {
1317            uint32_t replyID;
1318            CHECK(msg->senderAwaitsResponse(&replyID));
1319
1320            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1321                PostReplyWithError(replyID, INVALID_OPERATION);
1322                break;
1323            }
1324
1325            status_t err = onQueueInputBuffer(msg);
1326
1327            PostReplyWithError(replyID, err);
1328            break;
1329        }
1330
1331        case kWhatDequeueOutputBuffer:
1332        {
1333            uint32_t replyID;
1334            CHECK(msg->senderAwaitsResponse(&replyID));
1335
1336            if (mFlags & kFlagIsAsync) {
1337                ALOGE("dequeueOutputBuffer can't be used in async mode");
1338                PostReplyWithError(replyID, INVALID_OPERATION);
1339                break;
1340            }
1341
1342            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
1343                break;
1344            }
1345
1346            int64_t timeoutUs;
1347            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1348
1349            if (timeoutUs == 0ll) {
1350                PostReplyWithError(replyID, -EAGAIN);
1351                break;
1352            }
1353
1354            mFlags |= kFlagDequeueOutputPending;
1355            mDequeueOutputReplyID = replyID;
1356
1357            if (timeoutUs > 0ll) {
1358                sp<AMessage> timeoutMsg =
1359                    new AMessage(kWhatDequeueOutputTimedOut, id());
1360                timeoutMsg->setInt32(
1361                        "generation", ++mDequeueOutputTimeoutGeneration);
1362                timeoutMsg->post(timeoutUs);
1363            }
1364            break;
1365        }
1366
1367        case kWhatDequeueOutputTimedOut:
1368        {
1369            int32_t generation;
1370            CHECK(msg->findInt32("generation", &generation));
1371
1372            if (generation != mDequeueOutputTimeoutGeneration) {
1373                // Obsolete
1374                break;
1375            }
1376
1377            CHECK(mFlags & kFlagDequeueOutputPending);
1378
1379            PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
1380
1381            mFlags &= ~kFlagDequeueOutputPending;
1382            mDequeueOutputReplyID = 0;
1383            break;
1384        }
1385
1386        case kWhatReleaseOutputBuffer:
1387        {
1388            uint32_t replyID;
1389            CHECK(msg->senderAwaitsResponse(&replyID));
1390
1391            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1392                PostReplyWithError(replyID, INVALID_OPERATION);
1393                break;
1394            }
1395
1396            status_t err = onReleaseOutputBuffer(msg);
1397
1398            PostReplyWithError(replyID, err);
1399            break;
1400        }
1401
1402        case kWhatSignalEndOfInputStream:
1403        {
1404            uint32_t replyID;
1405            CHECK(msg->senderAwaitsResponse(&replyID));
1406
1407            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1408                PostReplyWithError(replyID, INVALID_OPERATION);
1409                break;
1410            }
1411
1412            mReplyID = replyID;
1413            mCodec->signalEndOfInputStream();
1414            break;
1415        }
1416
1417        case kWhatGetBuffers:
1418        {
1419            uint32_t replyID;
1420            CHECK(msg->senderAwaitsResponse(&replyID));
1421
1422            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1423                PostReplyWithError(replyID, INVALID_OPERATION);
1424                break;
1425            }
1426
1427            int32_t portIndex;
1428            CHECK(msg->findInt32("portIndex", &portIndex));
1429
1430            Vector<sp<ABuffer> > *dstBuffers;
1431            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
1432
1433            dstBuffers->clear();
1434            const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
1435
1436            for (size_t i = 0; i < srcBuffers.size(); ++i) {
1437                const BufferInfo &info = srcBuffers.itemAt(i);
1438
1439                dstBuffers->push_back(
1440                        (portIndex == kPortIndexInput && mCrypto != NULL)
1441                                ? info.mEncryptedData : info.mData);
1442            }
1443
1444            (new AMessage)->postReply(replyID);
1445            break;
1446        }
1447
1448        case kWhatFlush:
1449        {
1450            uint32_t replyID;
1451            CHECK(msg->senderAwaitsResponse(&replyID));
1452
1453            if (mState != STARTED || (mFlags & kFlagStickyError)) {
1454                PostReplyWithError(replyID, INVALID_OPERATION);
1455                break;
1456            }
1457
1458            mReplyID = replyID;
1459            setState(FLUSHING);
1460
1461            mCodec->signalFlush();
1462            returnBuffersToCodec();
1463            break;
1464        }
1465
1466        case kWhatGetInputFormat:
1467        case kWhatGetOutputFormat:
1468        {
1469            sp<AMessage> format =
1470                (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
1471
1472            uint32_t replyID;
1473            CHECK(msg->senderAwaitsResponse(&replyID));
1474
1475            if ((mState != CONFIGURED && mState != STARTING &&
1476                 mState != STARTED && mState != FLUSHING)
1477                    || (mFlags & kFlagStickyError)
1478                    || format == NULL) {
1479                PostReplyWithError(replyID, INVALID_OPERATION);
1480                break;
1481            }
1482
1483            sp<AMessage> response = new AMessage;
1484            response->setMessage("format", format);
1485            response->postReply(replyID);
1486            break;
1487        }
1488
1489        case kWhatRequestIDRFrame:
1490        {
1491            mCodec->signalRequestIDRFrame();
1492            break;
1493        }
1494
1495        case kWhatRequestActivityNotification:
1496        {
1497            CHECK(mActivityNotify == NULL);
1498            CHECK(msg->findMessage("notify", &mActivityNotify));
1499
1500            postActivityNotificationIfPossible();
1501            break;
1502        }
1503
1504        case kWhatGetName:
1505        {
1506            uint32_t replyID;
1507            CHECK(msg->senderAwaitsResponse(&replyID));
1508
1509            if (mComponentName.empty()) {
1510                PostReplyWithError(replyID, INVALID_OPERATION);
1511                break;
1512            }
1513
1514            sp<AMessage> response = new AMessage;
1515            response->setString("name", mComponentName.c_str());
1516            response->postReply(replyID);
1517            break;
1518        }
1519
1520        case kWhatSetParameters:
1521        {
1522            uint32_t replyID;
1523            CHECK(msg->senderAwaitsResponse(&replyID));
1524
1525            sp<AMessage> params;
1526            CHECK(msg->findMessage("params", &params));
1527
1528            status_t err = onSetParameters(params);
1529
1530            PostReplyWithError(replyID, err);
1531            break;
1532        }
1533
1534        default:
1535            TRESPASS();
1536    }
1537}
1538
1539void MediaCodec::extractCSD(const sp<AMessage> &format) {
1540    mCSD.clear();
1541
1542    size_t i = 0;
1543    for (;;) {
1544        sp<ABuffer> csd;
1545        if (!format->findBuffer(StringPrintf("csd-%u", i).c_str(), &csd)) {
1546            break;
1547        }
1548
1549        mCSD.push_back(csd);
1550        ++i;
1551    }
1552
1553    ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
1554}
1555
1556status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
1557    CHECK(!mCSD.empty());
1558
1559    const BufferInfo *info =
1560        &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
1561
1562    sp<ABuffer> csd = *mCSD.begin();
1563    mCSD.erase(mCSD.begin());
1564
1565    const sp<ABuffer> &codecInputData =
1566        (mCrypto != NULL) ? info->mEncryptedData : info->mData;
1567
1568    if (csd->size() > codecInputData->capacity()) {
1569        return -EINVAL;
1570    }
1571
1572    memcpy(codecInputData->data(), csd->data(), csd->size());
1573
1574    AString errorDetailMsg;
1575
1576    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, id());
1577    msg->setSize("index", bufferIndex);
1578    msg->setSize("offset", 0);
1579    msg->setSize("size", csd->size());
1580    msg->setInt64("timeUs", 0ll);
1581    msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
1582    msg->setPointer("errorDetailMsg", &errorDetailMsg);
1583
1584    return onQueueInputBuffer(msg);
1585}
1586
1587void MediaCodec::setState(State newState) {
1588    if (newState == INITIALIZED || newState == UNINITIALIZED) {
1589        delete mSoftRenderer;
1590        mSoftRenderer = NULL;
1591
1592        mCrypto.clear();
1593        setNativeWindow(NULL);
1594
1595        mInputFormat.clear();
1596        mOutputFormat.clear();
1597        mFlags &= ~kFlagOutputFormatChanged;
1598        mFlags &= ~kFlagOutputBuffersChanged;
1599        mFlags &= ~kFlagStickyError;
1600        mFlags &= ~kFlagIsEncoder;
1601        mFlags &= ~kFlagGatherCodecSpecificData;
1602        mFlags &= ~kFlagIsAsync;
1603
1604        mActivityNotify.clear();
1605        mCallback.clear();
1606    }
1607
1608    if (newState == UNINITIALIZED) {
1609        // return any straggling buffers, e.g. if we got here on an error
1610        returnBuffersToCodec();
1611
1612        mComponentName.clear();
1613
1614        // The component is gone, mediaserver's probably back up already
1615        // but should definitely be back up should we try to instantiate
1616        // another component.. and the cycle continues.
1617        mFlags &= ~kFlagSawMediaServerDie;
1618    }
1619
1620    mState = newState;
1621
1622    cancelPendingDequeueOperations();
1623}
1624
1625void MediaCodec::returnBuffersToCodec() {
1626    returnBuffersToCodecOnPort(kPortIndexInput);
1627    returnBuffersToCodecOnPort(kPortIndexOutput);
1628}
1629
1630void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
1631    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1632    Mutex::Autolock al(mBufferLock);
1633
1634    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1635
1636    for (size_t i = 0; i < buffers->size(); ++i) {
1637        BufferInfo *info = &buffers->editItemAt(i);
1638
1639        if (info->mNotify != NULL) {
1640            sp<AMessage> msg = info->mNotify;
1641            info->mNotify = NULL;
1642            info->mOwnedByClient = false;
1643
1644            if (portIndex == kPortIndexInput) {
1645                /* no error, just returning buffers */
1646                msg->setInt32("err", OK);
1647            }
1648            msg->post();
1649        }
1650    }
1651
1652    mAvailPortBuffers[portIndex].clear();
1653}
1654
1655size_t MediaCodec::updateBuffers(
1656        int32_t portIndex, const sp<AMessage> &msg) {
1657    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1658
1659    uint32_t bufferID;
1660    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
1661
1662    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1663
1664    for (size_t i = 0; i < buffers->size(); ++i) {
1665        BufferInfo *info = &buffers->editItemAt(i);
1666
1667        if (info->mBufferID == bufferID) {
1668            CHECK(info->mNotify == NULL);
1669            CHECK(msg->findMessage("reply", &info->mNotify));
1670
1671            mAvailPortBuffers[portIndex].push_back(i);
1672
1673            return i;
1674        }
1675    }
1676
1677    TRESPASS();
1678
1679    return 0;
1680}
1681
1682status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
1683    size_t index;
1684    size_t offset;
1685    size_t size;
1686    int64_t timeUs;
1687    uint32_t flags;
1688    CHECK(msg->findSize("index", &index));
1689    CHECK(msg->findSize("offset", &offset));
1690    CHECK(msg->findInt64("timeUs", &timeUs));
1691    CHECK(msg->findInt32("flags", (int32_t *)&flags));
1692
1693    const CryptoPlugin::SubSample *subSamples;
1694    size_t numSubSamples;
1695    const uint8_t *key;
1696    const uint8_t *iv;
1697    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
1698
1699    // We allow the simpler queueInputBuffer API to be used even in
1700    // secure mode, by fabricating a single unencrypted subSample.
1701    CryptoPlugin::SubSample ss;
1702
1703    if (msg->findSize("size", &size)) {
1704        if (mCrypto != NULL) {
1705            ss.mNumBytesOfClearData = size;
1706            ss.mNumBytesOfEncryptedData = 0;
1707
1708            subSamples = &ss;
1709            numSubSamples = 1;
1710            key = NULL;
1711            iv = NULL;
1712        }
1713    } else {
1714        if (mCrypto == NULL) {
1715            return -EINVAL;
1716        }
1717
1718        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
1719        CHECK(msg->findSize("numSubSamples", &numSubSamples));
1720        CHECK(msg->findPointer("key", (void **)&key));
1721        CHECK(msg->findPointer("iv", (void **)&iv));
1722
1723        int32_t tmp;
1724        CHECK(msg->findInt32("mode", &tmp));
1725
1726        mode = (CryptoPlugin::Mode)tmp;
1727
1728        size = 0;
1729        for (size_t i = 0; i < numSubSamples; ++i) {
1730            size += subSamples[i].mNumBytesOfClearData;
1731            size += subSamples[i].mNumBytesOfEncryptedData;
1732        }
1733    }
1734
1735    if (index >= mPortBuffers[kPortIndexInput].size()) {
1736        return -ERANGE;
1737    }
1738
1739    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
1740
1741    if (info->mNotify == NULL || !info->mOwnedByClient) {
1742        return -EACCES;
1743    }
1744
1745    if (offset + size > info->mData->capacity()) {
1746        return -EINVAL;
1747    }
1748
1749    sp<AMessage> reply = info->mNotify;
1750    info->mData->setRange(offset, size);
1751    info->mData->meta()->setInt64("timeUs", timeUs);
1752
1753    if (flags & BUFFER_FLAG_EOS) {
1754        info->mData->meta()->setInt32("eos", true);
1755    }
1756
1757    if (flags & BUFFER_FLAG_CODECCONFIG) {
1758        info->mData->meta()->setInt32("csd", true);
1759    }
1760
1761    if (mCrypto != NULL) {
1762        if (size > info->mEncryptedData->capacity()) {
1763            return -ERANGE;
1764        }
1765
1766        AString *errorDetailMsg;
1767        CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
1768
1769        ssize_t result = mCrypto->decrypt(
1770                (mFlags & kFlagIsSecure) != 0,
1771                key,
1772                iv,
1773                mode,
1774                info->mEncryptedData->base() + offset,
1775                subSamples,
1776                numSubSamples,
1777                info->mData->base(),
1778                errorDetailMsg);
1779
1780        if (result < 0) {
1781            return result;
1782        }
1783
1784        info->mData->setRange(0, result);
1785    }
1786
1787    // synchronization boundary for getBufferAndFormat
1788    {
1789        Mutex::Autolock al(mBufferLock);
1790        info->mOwnedByClient = false;
1791    }
1792    reply->setBuffer("buffer", info->mData);
1793    reply->post();
1794
1795    info->mNotify = NULL;
1796
1797    return OK;
1798}
1799
1800status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
1801    size_t index;
1802    CHECK(msg->findSize("index", &index));
1803
1804    int32_t render;
1805    if (!msg->findInt32("render", &render)) {
1806        render = 0;
1807    }
1808
1809    if (mState != STARTED) {
1810        return -EINVAL;
1811    }
1812
1813    if (index >= mPortBuffers[kPortIndexOutput].size()) {
1814        return -ERANGE;
1815    }
1816
1817    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
1818
1819    if (info->mNotify == NULL || !info->mOwnedByClient) {
1820        return -EACCES;
1821    }
1822
1823    // synchronization boundary for getBufferAndFormat
1824    {
1825        Mutex::Autolock al(mBufferLock);
1826        info->mOwnedByClient = false;
1827    }
1828
1829    if (render && info->mData != NULL && info->mData->size() != 0) {
1830        info->mNotify->setInt32("render", true);
1831
1832        int64_t timestampNs = 0;
1833        if (msg->findInt64("timestampNs", &timestampNs)) {
1834            info->mNotify->setInt64("timestampNs", timestampNs);
1835        } else {
1836            // TODO: it seems like we should use the timestamp
1837            // in the (media)buffer as it potentially came from
1838            // an input surface, but we did not propagate it prior to
1839            // API 20.  Perhaps check for target SDK version.
1840#if 0
1841            if (info->mData->meta()->findInt64("timeUs", &timestampNs)) {
1842                ALOGV("using buffer PTS of %" PRId64, timestampNs);
1843                timestampNs *= 1000;
1844            }
1845#endif
1846        }
1847
1848        if (mSoftRenderer != NULL) {
1849            mSoftRenderer->render(
1850                    info->mData->data(), info->mData->size(), timestampNs, NULL);
1851        }
1852    }
1853
1854    info->mNotify->post();
1855    info->mNotify = NULL;
1856
1857    return OK;
1858}
1859
1860ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
1861    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
1862
1863    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
1864
1865    if (availBuffers->empty()) {
1866        return -EAGAIN;
1867    }
1868
1869    size_t index = *availBuffers->begin();
1870    availBuffers->erase(availBuffers->begin());
1871
1872    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
1873    CHECK(!info->mOwnedByClient);
1874    {
1875        Mutex::Autolock al(mBufferLock);
1876        info->mFormat = portIndex == kPortIndexInput ? mInputFormat : mOutputFormat;
1877        info->mOwnedByClient = true;
1878    }
1879
1880    return index;
1881}
1882
1883status_t MediaCodec::setNativeWindow(
1884        const sp<Surface> &surfaceTextureClient) {
1885    status_t err;
1886
1887    if (mNativeWindow != NULL) {
1888        err = native_window_api_disconnect(
1889                mNativeWindow.get(), NATIVE_WINDOW_API_MEDIA);
1890
1891        if (err != OK) {
1892            ALOGW("native_window_api_disconnect returned an error: %s (%d)",
1893                    strerror(-err), err);
1894        }
1895
1896        mNativeWindow.clear();
1897    }
1898
1899    if (surfaceTextureClient != NULL) {
1900        err = native_window_api_connect(
1901                surfaceTextureClient.get(), NATIVE_WINDOW_API_MEDIA);
1902
1903        if (err != OK) {
1904            ALOGE("native_window_api_connect returned an error: %s (%d)",
1905                    strerror(-err), err);
1906
1907            return err;
1908        }
1909
1910        mNativeWindow = surfaceTextureClient;
1911    }
1912
1913    return OK;
1914}
1915
1916void MediaCodec::onInputBufferAvailable() {
1917    int32_t index;
1918    while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
1919        sp<AMessage> msg = mCallback->dup();
1920        msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
1921        msg->setInt32("index", index);
1922        msg->post();
1923    }
1924}
1925
1926void MediaCodec::onOutputBufferAvailable() {
1927    int32_t index;
1928    while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
1929        const sp<ABuffer> &buffer =
1930            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
1931        sp<AMessage> msg = mCallback->dup();
1932        msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
1933        msg->setInt32("index", index);
1934        msg->setSize("offset", buffer->offset());
1935        msg->setSize("size", buffer->size());
1936
1937        int64_t timeUs;
1938        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
1939
1940        msg->setInt64("timeUs", timeUs);
1941
1942        int32_t omxFlags;
1943        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
1944
1945        uint32_t flags = 0;
1946        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
1947            flags |= BUFFER_FLAG_SYNCFRAME;
1948        }
1949        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1950            flags |= BUFFER_FLAG_CODECCONFIG;
1951        }
1952        if (omxFlags & OMX_BUFFERFLAG_EOS) {
1953            flags |= BUFFER_FLAG_EOS;
1954        }
1955
1956        msg->setInt32("flags", flags);
1957
1958        msg->post();
1959    }
1960}
1961
1962void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
1963    if (mCallback != NULL) {
1964        sp<AMessage> msg = mCallback->dup();
1965        msg->setInt32("callbackID", CB_ERROR);
1966        msg->setInt32("err", err);
1967        msg->setInt32("actionCode", actionCode);
1968
1969        if (detail != NULL) {
1970            msg->setString("detail", detail);
1971        }
1972
1973        msg->post();
1974    }
1975}
1976
1977void MediaCodec::onOutputFormatChanged() {
1978    if (mCallback != NULL) {
1979        sp<AMessage> msg = mCallback->dup();
1980        msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
1981        msg->setMessage("format", mOutputFormat);
1982        msg->post();
1983    }
1984}
1985
1986
1987void MediaCodec::postActivityNotificationIfPossible() {
1988    if (mActivityNotify == NULL) {
1989        return;
1990    }
1991
1992    if ((mFlags & (kFlagStickyError
1993                    | kFlagOutputBuffersChanged
1994                    | kFlagOutputFormatChanged))
1995            || !mAvailPortBuffers[kPortIndexInput].empty()
1996            || !mAvailPortBuffers[kPortIndexOutput].empty()) {
1997        mActivityNotify->post();
1998        mActivityNotify.clear();
1999    }
2000}
2001
2002status_t MediaCodec::setParameters(const sp<AMessage> &params) {
2003    sp<AMessage> msg = new AMessage(kWhatSetParameters, id());
2004    msg->setMessage("params", params);
2005
2006    sp<AMessage> response;
2007    return PostAndAwaitResponse(msg, &response);
2008}
2009
2010status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
2011    mCodec->signalSetParameters(params);
2012
2013    return OK;
2014}
2015
2016status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
2017        const sp<ABuffer> &buffer) {
2018    AString mime;
2019    CHECK(mOutputFormat->findString("mime", &mime));
2020
2021    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
2022        // Codec specific data should be SPS and PPS in a single buffer,
2023        // each prefixed by a startcode (0x00 0x00 0x00 0x01).
2024        // We separate the two and put them into the output format
2025        // under the keys "csd-0" and "csd-1".
2026
2027        unsigned csdIndex = 0;
2028
2029        const uint8_t *data = buffer->data();
2030        size_t size = buffer->size();
2031
2032        const uint8_t *nalStart;
2033        size_t nalSize;
2034        while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
2035            sp<ABuffer> csd = new ABuffer(nalSize + 4);
2036            memcpy(csd->data(), "\x00\x00\x00\x01", 4);
2037            memcpy(csd->data() + 4, nalStart, nalSize);
2038
2039            mOutputFormat->setBuffer(
2040                    StringPrintf("csd-%u", csdIndex).c_str(), csd);
2041
2042            ++csdIndex;
2043        }
2044
2045        if (csdIndex != 2) {
2046            return ERROR_MALFORMED;
2047        }
2048    } else {
2049        // For everything else we just stash the codec specific data into
2050        // the output format as a single piece of csd under "csd-0".
2051        mOutputFormat->setBuffer("csd-0", buffer);
2052    }
2053
2054    return OK;
2055}
2056
2057}  // namespace android
2058