MediaCodecSource.cpp revision 72cecca17d735db6532c45f0a7e10c47ee6f065a
172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang/*
272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Copyright 2014, The Android Open Source Project
372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *
472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Licensed under the Apache License, Version 2.0 (the "License");
572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * you may not use this file except in compliance with the License.
672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * You may obtain a copy of the License at
772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *
872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *     http://www.apache.org/licenses/LICENSE-2.0
972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *
1072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Unless required by applicable law or agreed to in writing, software
1172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * distributed under the License is distributed on an "AS IS" BASIS,
1272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * See the License for the specific language governing permissions and
1472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * limitations under the License.
1572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang */
1672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang//#define LOG_NDEBUG 0
1872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#define LOG_TAG "MediaCodecSource"
1972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#define DEBUG_DRIFT_TIME 0
2072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/IGraphicBufferProducer.h>
2172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/Surface.h>
2272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/ICrypto.h>
2372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ABuffer.h>
2472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ADebug.h>
2572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ALooper.h>
2672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/AMessage.h>
2772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaBuffer.h>
2872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodec.h>
2972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MetaData.h>
3072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaErrors.h>
3172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaSource.h>
3272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodecSource.h>
3372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/Utils.h>
3472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangnamespace android {
3672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatic void ReleaseMediaBufferReference(const sp<ABuffer> &accessUnit) {
3872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void *mbuf;
3972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (accessUnit->meta()->findPointer("mediaBuffer", &mbuf)
4072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            && mbuf != NULL) {
4172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGV("releasing mbuf %p", mbuf);
4272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        accessUnit->meta()->setPointer("mediaBuffer", NULL);
4472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        static_cast<MediaBuffer *>(mbuf)->release();
4672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mbuf = NULL;
4772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
4872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
4972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstruct MediaCodecSource::Puller : public AHandler {
5172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    Puller(const sp<MediaSource> &source);
5272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t start(const sp<MetaData> &meta, const sp<AMessage> &notify);
5472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void stopAsync();
5572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void pause();
5772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void resume();
5872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprotected:
6072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual void onMessageReceived(const sp<AMessage> &msg);
6172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual ~Puller();
6272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprivate:
6472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    enum {
6572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStart = 'msta',
6672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStop,
6772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatPull,
6872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatPause,
6972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatResume,
7072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    };
7172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaSource> mSource;
7372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> mNotify;
7472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<ALooper> mLooper;
7572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    int32_t mPullGeneration;
7672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mIsAudio;
7772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mPaused;
7872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mReachedEOS;
7972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
8172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void schedulePull();
8272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void handleEOS();
8372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    DISALLOW_EVIL_CONSTRUCTORS(Puller);
8572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang};
8672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8772cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::Puller(const sp<MediaSource> &source)
8872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mSource(source),
8972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mLooper(new ALooper()),
9072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mPullGeneration(0),
9172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mIsAudio(false),
9272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mPaused(false),
9372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mReachedEOS(false) {
9472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MetaData> meta = source->getFormat();
9572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    const char *mime;
9672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(meta->findCString(kKeyMIMEType, &mime));
9772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mIsAudio = !strncasecmp(mime, "audio/", 6);
9972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->setName("pull_looper");
10172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
10272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10372cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::~Puller() {
10472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(id());
10572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->stop();
10672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
10772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::postSynchronouslyAndReturnError(
10972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
11072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
11172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
11272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
11472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
11572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
11672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
11872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
12072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
12172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
12272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
12372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
12472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::start(const sp<MetaData> &meta,
12572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &notify) {
12672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("puller (%s) start", mIsAudio ? "audio" : "video");
12772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->start(
12872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* runOnCallingThread */,
12972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* canCallJava */,
13072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            PRIORITY_AUDIO);
13172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(this);
13272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mNotify = notify;
13372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
13472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> msg = new AMessage(kWhatStart, id());
13572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", meta);
13672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
13772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
13872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
13972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::stopAsync() {
14072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("puller (%s) stopAsync", mIsAudio ? "audio" : "video");
14172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    (new AMessage(kWhatStop, id()))->post();
14272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
14372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
14472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::pause() {
14572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    (new AMessage(kWhatPause, id()))->post();
14672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
14772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
14872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::resume() {
14972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    (new AMessage(kWhatResume, id()))->post();
15072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
15172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::schedulePull() {
15372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> msg = new AMessage(kWhatPull, id());
15472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setInt32("generation", mPullGeneration);
15572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->post();
15672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
15772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::handleEOS() {
15972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!mReachedEOS) {
16072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video");
16172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mReachedEOS = true;
16272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> notify = mNotify->dup();
16372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        notify->setPointer("accessUnit", NULL);
16472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        notify->post();
16572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
16672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
16772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
16872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) {
16972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
17072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStart:
17172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
17272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<RefBase> obj;
17372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->findObject("meta", &obj));
17472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
17572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mReachedEOS = false;
17672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
17772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->start(static_cast<MetaData *>(obj.get()));
17872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
17972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err == OK) {
18072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                schedulePull();
18172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
18272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
18372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<AMessage> response = new AMessage;
18472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->setInt32("err", err);
18572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
18672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            uint32_t replyID;
18772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
18872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->postReply(replyID);
18972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
19072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
19172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
19272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStop:
19372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
19472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ALOGV("source (%s) stopping", mIsAudio ? "audio" : "video");
19572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mSource->stop();
19672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ALOGV("source (%s) stopped", mIsAudio ? "audio" : "video");
19772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ++mPullGeneration;
19872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
19972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            handleEOS();
20072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
20172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
20272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatPull:
20472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
20572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            int32_t generation;
20672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->findInt32("generation", &generation));
20772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (generation != mPullGeneration) {
20972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
21072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
21172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            MediaBuffer *mbuf;
21372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->read(&mbuf);
21472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mPaused) {
21672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (err == OK) {
21772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf->release();
21872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf = NULL;
21972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
22072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                msg->post();
22272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
22372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
22472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err != OK) {
22672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (err == ERROR_END_OF_STREAM) {
22772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGV("stream ended, mbuf %p", mbuf);
22872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                } else {
22972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGE("error %d reading stream.", err);
23072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
23172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                handleEOS();
23272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
23372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                sp<AMessage> notify = mNotify->dup();
23472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                notify->setPointer("accessUnit", mbuf);
23672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                notify->post();
23772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                msg->post();
23972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
24072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
24172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
24272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatPause:
24472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
24572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPaused = true;
24672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
24772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
24872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatResume:
25072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
25172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPaused = false;
25272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
25372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
25472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
25572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        default:
25672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            TRESPASS();
25772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
25872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
25972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
26072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang// static
26172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<MediaCodecSource> MediaCodecSource::Create(
26272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
26372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &format,
26472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
26572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags) {
26672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaCodecSource> mediaSource =
26772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            new MediaCodecSource(looper, format, source, flags);
26872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
26972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mediaSource->init() == OK) {
27072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return mediaSource;
27172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
27272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return NULL;
27372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
27472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
27572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::start(MetaData* params) {
27672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> msg = new AMessage(kWhatStart, mReflector->id());
27772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", params);
27872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
27972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
28072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
28172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::stop() {
28272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> msg = new AMessage(kWhatStop, mReflector->id());
28372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
28472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
28572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
28672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::pause() {
28772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    (new AMessage(kWhatPause, mReflector->id()))->post();
28872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
28972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
29072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
29172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() {
29272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
29372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mGraphicBufferProducer;
29472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
29572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
29672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::read(MediaBuffer** buffer,
29772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const ReadOptions* options) {
29872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    Mutex::Autolock autolock(mOutputBufferLock);
29972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
30072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    *buffer = NULL;
30172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    while (mOutputBufferQueue.size() == 0 && !mEncodedReachedEOS) {
30272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputBufferCond.wait(mOutputBufferLock);
30372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
30472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!mEncodedReachedEOS) {
30572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        *buffer = *mOutputBufferQueue.begin();
30672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputBufferQueue.erase(mOutputBufferQueue.begin());
30772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
30872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
30972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mErrorCode;
31072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
31172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
31272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) {
31372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->setObserver(0);
31472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->release();
31572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
31672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
31772cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::MediaCodecSource(
31872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
31972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &outputFormat,
32072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
32172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags)
32272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mLooper(looper),
32372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mOutputFormat(outputFormat),
32472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mMeta(new MetaData),
32572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFlags(flags),
32672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mIsVideo(false),
32772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStarted(false),
32872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStopping(false),
32972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mDoMoreWorkPending(false),
33072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mPullerReachedEOS(false),
33172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFirstSampleTimeUs(-1ll),
33272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mEncodedReachedEOS(false),
33372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mErrorCode(OK) {
33472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mLooper != NULL);
33572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
33672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString mime;
33772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &mime));
33872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
33972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!strncasecmp("video/", mime.c_str(), 6)) {
34072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mIsVideo = true;
34172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
34272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
34372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
34472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mPuller = new Puller(source);
34572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
34672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
34772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
34872cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::~MediaCodecSource() {
34972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    releaseEncoder();
35072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->stop();
35272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(mReflector->id());
35372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
35472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::init() {
35672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = initEncoder();
35772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
35972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        releaseEncoder();
36072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
36172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
36372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
36472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::initEncoder() {
36672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mReflector = new AHandlerReflector<MediaCodecSource>(this);
36772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(mReflector);
36872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper = new ALooper;
37072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->setName("codec_looper");
37172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->start();
37272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_METADATA_INPUT) {
37472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("store-metadata-in-buffers", 1);
37572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
37672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
37872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("create-input-buffers-suspended", 1);
37972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
38072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString outputMIME;
38272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &outputMIME));
38372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder = MediaCodec::CreateByType(
38572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mCodecLooper, outputMIME.c_str(), true /* encoder */);
38672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder == NULL) {
38872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return NO_INIT;
38972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
39072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
39272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = mEncoder->configure(
39472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mOutputFormat,
39572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                NULL /* nativeWindow */,
39672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                NULL /* crypto */,
39772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                MediaCodec::CONFIGURE_FLAG_ENCODE);
39872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
40072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
40172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
40272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->getOutputFormat(&mOutputFormat);
40472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    convertMessageToMetaData(mOutputFormat, mMeta);
40572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
40772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mIsVideo);
40872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = mEncoder->createInputSurface(&mGraphicBufferProducer);
41072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
41272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
41372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
41472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
41572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    err = mEncoder->start();
41772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
41972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
42072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
42172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    err = mEncoder->getInputBuffers(&mEncoderInputBuffers);
42372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
42572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
42672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
42772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    err = mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
42972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
43172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
43272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
43372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncodedReachedEOS = false;
43572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mErrorCode = OK;
43672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
43872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
43972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::releaseEncoder() {
44172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder == NULL) {
44272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return;
44372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
44472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->release();
44672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder.clear();
44772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    while (!mInputBufferQueue.empty()) {
44972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MediaBuffer *mbuf = *mInputBufferQueue.begin();
45072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mInputBufferQueue.erase(mInputBufferQueue.begin());
45172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf != NULL) {
45272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mbuf->release();
45372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
45472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
45572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
45672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    for (size_t i = 0; i < mEncoderInputBuffers.size(); ++i) {
45772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<ABuffer> accessUnit = mEncoderInputBuffers.itemAt(i);
45872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ReleaseMediaBufferReference(accessUnit);
45972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
46072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoderInputBuffers.clear();
46272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoderOutputBuffers.clear();
46372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
46472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangbool MediaCodecSource::reachedEOS() {
46672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mEncodedReachedEOS && ((mPuller == NULL) || mPullerReachedEOS);
46772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
46872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::postSynchronouslyAndReturnError(
47072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
47172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
47272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
47372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
47572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
47672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
47772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
47972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
48072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
48172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
48272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
48372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
48472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
48572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalEOS(status_t err) {
48672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!mEncodedReachedEOS) {
48772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGI("encoder (%s) reached EOS", mIsVideo ? "video" : "audio");
48872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
48972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            Mutex::Autolock autoLock(mOutputBufferLock);
49072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // release all unread media buffers
49172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            for (List<MediaBuffer*>::iterator it = mOutputBufferQueue.begin();
49272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    it != mOutputBufferQueue.end(); it++) {
49372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                (*it)->release();
49472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
49572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mOutputBufferQueue.clear();
49672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mEncodedReachedEOS = true;
49772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mErrorCode = err;
49872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mOutputBufferCond.signal();
49972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
50072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
50172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        releaseEncoder();
50272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
50372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStopping && reachedEOS()) {
50472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGI("MediaCodecSource (%s) fully stopped",
50572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mIsVideo ? "video" : "audio");
50672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // posting reply to everyone that's waiting
50772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        List<uint32_t>::iterator it;
50872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        for (it = mStopReplyIDQueue.begin();
50972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                it != mStopReplyIDQueue.end(); it++) {
51072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(*it);
51172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
51272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.clear();
51372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = false;
51472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
51572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
51672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
51772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::suspend() {
51872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
51972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
52072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
52172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", true);
52272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
52372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
52472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
52572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
52672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::resume(int64_t skipFramesBeforeUs) {
52772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
52872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
52972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
53072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", false);
53172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (skipFramesBeforeUs > 0) {
53272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            params->setInt64("skip-frames-before", skipFramesBeforeUs);
53372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
53472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
53572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
53672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
53772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
53872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::scheduleDoMoreWork() {
53972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mDoMoreWorkPending) {
54072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return;
54172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
54272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
54372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mDoMoreWorkPending = true;
54472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
54572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoderActivityNotify == NULL) {
54672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoderActivityNotify = new AMessage(
54772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                kWhatEncoderActivity, mReflector->id());
54872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
54972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->requestActivityNotification(mEncoderActivityNotify);
55072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
55172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
55272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::feedEncoderInputBuffers() {
55372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    while (!mInputBufferQueue.empty()
55472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            && !mAvailEncoderInputIndices.empty()) {
55572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MediaBuffer* mbuf = *mInputBufferQueue.begin();
55672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mInputBufferQueue.erase(mInputBufferQueue.begin());
55772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
55872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t bufferIndex = *mAvailEncoderInputIndices.begin();
55972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
56072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
56172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t timeUs = 0ll;
56272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags = 0;
56372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t size = 0;
56472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
56572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf != NULL) {
56672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
56772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
56872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // push decoding time for video, or drift time for audio
56972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
57072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDecodingTimeQueue.push_back(timeUs);
57172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
57272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME
57372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mFirstSampleTimeUs < 0ll) {
57472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mFirstSampleTimeUs = timeUs;
57572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
57672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
57772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                int64_t driftTimeUs = 0;
57872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs)
57972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        && driftTimeUs) {
58072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs;
58172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
58272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDriftTimeQueue.push_back(driftTimeUs);
58372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME
58472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
58572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
58672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            size = mbuf->size();
58772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
58872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            memcpy(mEncoderInputBuffers.itemAt(bufferIndex)->data(),
58972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                   mbuf->data(), size);
59072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
59172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
59272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // video encoder will release MediaBuffer when done
59372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // with underlying data.
59472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mEncoderInputBuffers.itemAt(bufferIndex)->meta()
59572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        ->setPointer("mediaBuffer", mbuf);
59672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
59772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->release();
59872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
59972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
60072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            flags = MediaCodec::BUFFER_FLAG_EOS;
60172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
60272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
60372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        status_t err = mEncoder->queueInputBuffer(
60472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                bufferIndex, 0, size, timeUs, flags);
60572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
60672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
60772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
60872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
60972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
61072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
61272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
61372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::doMoreWork() {
61572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err;
61672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
61872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        for (;;) {
61972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            size_t bufferIndex;
62072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            err = mEncoder->dequeueInputBuffer(&bufferIndex);
62172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err != OK) {
62372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
62472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
62572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mAvailEncoderInputIndices.push_back(bufferIndex);
62772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
62872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        feedEncoderInputBuffers();
63072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
63172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
63272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    for (;;) {
63372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t bufferIndex;
63472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t offset;
63572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t size;
63672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t timeUs;
63772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags;
63872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        native_handle_t* handle = NULL;
63972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = mEncoder->dequeueOutputBuffer(
64072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                &bufferIndex, &offset, &size, &timeUs, &flags);
64172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
64272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
64372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err == INFO_FORMAT_CHANGED) {
64472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                continue;
64572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
64672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
64772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                continue;
64872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
64972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
65072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err == -EAGAIN) {
65172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                err = OK;
65272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
65372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
65472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
65572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (!(flags & MediaCodec::BUFFER_FLAG_EOS)) {
65672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<ABuffer> outbuf = mEncoderOutputBuffers.itemAt(bufferIndex);
65772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
65872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            MediaBuffer *mbuf = new MediaBuffer(outbuf->size());
65972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            memcpy(mbuf->data(), outbuf->data(), outbuf->size());
66072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
66172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) {
66272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mIsVideo) {
66372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    int64_t decodingTimeUs;
66472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    if (mFlags & FLAG_USE_SURFACE_INPUT) {
66572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        // GraphicBufferSource is supposed to discard samples
66672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        // queued before start, and offset timeUs by start time
66772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        CHECK_GE(timeUs, 0ll);
66872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        // TODO:
66972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        // Decoding time for surface source is unavailable,
67072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        // use presentation time for now. May need to move
67172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        // this logic into MediaCodec.
67272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        decodingTimeUs = timeUs;
67372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    } else {
67472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        CHECK(!mDecodingTimeQueue.empty());
67572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        decodingTimeUs = *(mDecodingTimeQueue.begin());
67672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        mDecodingTimeQueue.erase(mDecodingTimeQueue.begin());
67772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    }
67872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
67972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
68072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGV("[video] time %lld us (%.2f secs), dts/pts diff %lld",
68172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                            timeUs, timeUs / 1E6, decodingTimeUs - timeUs);
68272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                } else {
68372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    int64_t driftTimeUs = 0;
68472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME
68572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    CHECK(!mDriftTimeQueue.empty());
68672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    driftTimeUs = *(mDriftTimeQueue.begin());
68772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mDriftTimeQueue.erase(mDriftTimeQueue.begin());
68872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs);
68972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME
69072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGV("[audio] time %lld us (%.2f secs), drift %lld",
69172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                            timeUs, timeUs / 1E6, driftTimeUs);
69272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
69372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->meta_data()->setInt64(kKeyTime, timeUs);
69472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
69572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true);
69672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
69772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
69872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true);
69972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
70072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mbuf->setObserver(this);
70172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mbuf->add_ref();
70272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
70372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            {
70472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                Mutex::Autolock autoLock(mOutputBufferLock);
70572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mOutputBufferQueue.push_back(mbuf);
70672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mOutputBufferCond.signal();
70772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
70872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
70972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
71072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->releaseOutputBuffer(bufferIndex);
71172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
71272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (flags & MediaCodec::BUFFER_FLAG_EOS) {
71372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            err = ERROR_END_OF_STREAM;
71472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
71572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
71672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
71772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
71872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
71972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
72072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
72172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::onStart(MetaData *params) {
72272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStopping) {
72372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("Failed to start while we're stopping");
72472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return INVALID_OPERATION;
72572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
72672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
72772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStarted) {
72872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
72972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
73072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            resume();
73172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
73272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
73372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->resume();
73472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
73572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
73672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
73772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
73872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio");
73972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
74072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = OK;
74172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
74272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
74372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t startTimeUs;
74472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
74572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            startTimeUs = -1ll;
74672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
74772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        resume(startTimeUs);
74872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        scheduleDoMoreWork();
74972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else {
75072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mPuller != NULL);
75172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> notify = new AMessage(
75272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                kWhatPullerNotify, mReflector->id());
75372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = mPuller->start(params, notify);
75472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
75572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPullerReachedEOS = true;
75672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
75772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
75872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
75972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
76072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio");
76172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
76272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mStarted = true;
76372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
76472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
76572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
76672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
76772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
76872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPullerNotify:
76972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
77072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MediaBuffer *mbuf;
77172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->findPointer("accessUnit", (void**)&mbuf));
77272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
77372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf == NULL) {
77472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ALOGI("puller (%s) reached EOS",
77572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mIsVideo ? "video" : "audio");
77672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPullerReachedEOS = true;
77772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
77872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
77972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
78072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ALOGV("got msg '%s' after encoder shutdown.",
78172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                  msg->debugString().c_str());
78272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
78372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mbuf != NULL) {
78472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->release();
78572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
78672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                signalEOS();
78772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
78872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
78972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
79072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
79172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mInputBufferQueue.push_back(mbuf);
79272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
79372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        feedEncoderInputBuffers();
79472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        scheduleDoMoreWork();
79572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
79672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
79772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
79872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatEncoderActivity:
79972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
80072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mDoMoreWorkPending = false;
80172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
80272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
80372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
80472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
80572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
80672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        status_t err = doMoreWork();
80772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
80872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err == OK) {
80972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            scheduleDoMoreWork();
81072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
81172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // reached EOS, or error
81272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            signalEOS(err);
81372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
81472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
81572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
81672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
81772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStart:
81872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
81972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t replyID;
82072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
82172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
82272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<RefBase> obj;
82372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->findObject("meta", &obj));
82472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MetaData *params = static_cast<MetaData *>(obj.get());
82572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
82672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> response = new AMessage;
82772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->setInt32("err", onStart(params));
82872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->postReply(replyID);
82972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
83072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
83172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStop:
83272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
83372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGI("MediaCodecSource (%s) stopping", mIsVideo ? "video" : "audio");
83472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
83572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t replyID;
83672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
83772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
83872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (reachedEOS()) {
83972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // if we already reached EOS, reply and return now
84072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ALOGI("MediaCodecSource (%s) already stopped",
84172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mIsVideo ? "video" : "audio");
84272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(replyID);
84372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
84472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
84572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
84672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.push_back(replyID);
84772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mStopping) {
84872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // nothing to do if we're already stopping, reply will be posted
84972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // to all when we're stopped.
85072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
85172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
85272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
85372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = true;
85472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
85572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // if using surface, signal source EOS and wait for EOS to come back.
85672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // otherwise, release encoder and post EOS if haven't done already
85772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
85872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mEncoder->signalEndOfInputStream();
85972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
86072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
86172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->stopAsync();
86272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            signalEOS();
86372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
86472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
86572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
86672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPause:
86772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
86872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags && FLAG_USE_SURFACE_INPUT) {
86972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            suspend();
87072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
87172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
87272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->pause();
87372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
87472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
87572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
87672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    default:
87772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        TRESPASS();
87872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
87972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
88072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
88172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} // namespace android
882