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
20a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
21a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
22a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
2372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/IGraphicBufferProducer.h>
2472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/Surface.h>
2572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/ICrypto.h>
2672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ABuffer.h>
2772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ADebug.h>
2872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ALooper.h>
2972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/AMessage.h>
3072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaBuffer.h>
3172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodec.h>
3272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MetaData.h>
3372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaErrors.h>
3472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaSource.h>
3572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodecSource.h>
3672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/Utils.h>
3772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangnamespace android {
3972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstruct MediaCodecSource::Puller : public AHandler {
4172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    Puller(const sp<MediaSource> &source);
4272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t start(const sp<MetaData> &meta, const sp<AMessage> &notify);
4416e79115e497386eaf010af388627f94314a55a3Chong Zhang    void stop();
4572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void pause();
4772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void resume();
4872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprotected:
5072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual void onMessageReceived(const sp<AMessage> &msg);
5172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual ~Puller();
5272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprivate:
5472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    enum {
5572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStart = 'msta',
5672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStop,
5772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatPull,
5872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatPause,
5972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatResume,
6072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    };
6172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaSource> mSource;
6372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> mNotify;
6472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<ALooper> mLooper;
6572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    int32_t mPullGeneration;
6672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mIsAudio;
6772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mPaused;
6872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mReachedEOS;
6972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
7172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void schedulePull();
7272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void handleEOS();
7372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    DISALLOW_EVIL_CONSTRUCTORS(Puller);
7572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang};
7672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7772cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::Puller(const sp<MediaSource> &source)
7872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mSource(source),
7972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mLooper(new ALooper()),
8072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mPullGeneration(0),
8172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mIsAudio(false),
8272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mPaused(false),
8372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mReachedEOS(false) {
8472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MetaData> meta = source->getFormat();
8572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    const char *mime;
8672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(meta->findCString(kKeyMIMEType, &mime));
8772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mIsAudio = !strncasecmp(mime, "audio/", 6);
8972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->setName("pull_looper");
9172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
9272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9372cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::~Puller() {
9472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(id());
9572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->stop();
9672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
9772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::postSynchronouslyAndReturnError(
9972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
10072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
10172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
10272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
10472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
10572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
10672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
10872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
10972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
11072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
11272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
11372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::start(const sp<MetaData> &meta,
11572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &notify) {
11672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("puller (%s) start", mIsAudio ? "audio" : "video");
11772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->start(
11872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* runOnCallingThread */,
11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* canCallJava */,
12072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            PRIORITY_AUDIO);
12172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(this);
12272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mNotify = notify;
12372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
12472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> msg = new AMessage(kWhatStart, id());
12572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", meta);
12672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
12772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
12872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
12916e79115e497386eaf010af388627f94314a55a3Chong Zhangvoid MediaCodecSource::Puller::stop() {
13016e79115e497386eaf010af388627f94314a55a3Chong Zhang    // Stop source from caller's thread instead of puller's looper.
13116e79115e497386eaf010af388627f94314a55a3Chong Zhang    // mSource->stop() is thread-safe, doing it outside the puller's
13216e79115e497386eaf010af388627f94314a55a3Chong Zhang    // looper allows us to at least stop if source gets stuck.
13316e79115e497386eaf010af388627f94314a55a3Chong Zhang    // If source gets stuck in read(), the looper would never
13416e79115e497386eaf010af388627f94314a55a3Chong Zhang    // be able to process the stop(), which could lead to ANR.
13516e79115e497386eaf010af388627f94314a55a3Chong Zhang
13616e79115e497386eaf010af388627f94314a55a3Chong Zhang    ALOGV("source (%s) stopping", mIsAudio ? "audio" : "video");
13716e79115e497386eaf010af388627f94314a55a3Chong Zhang    mSource->stop();
13816e79115e497386eaf010af388627f94314a55a3Chong Zhang    ALOGV("source (%s) stopped", mIsAudio ? "audio" : "video");
13916e79115e497386eaf010af388627f94314a55a3Chong Zhang
14072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    (new AMessage(kWhatStop, id()))->post();
14172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
14272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
14372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::pause() {
14472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    (new AMessage(kWhatPause, id()))->post();
14572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
14672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
14772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::resume() {
14872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    (new AMessage(kWhatResume, id()))->post();
14972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
15072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::schedulePull() {
15272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> msg = new AMessage(kWhatPull, id());
15372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setInt32("generation", mPullGeneration);
15472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->post();
15572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
15672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::handleEOS() {
15872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!mReachedEOS) {
15972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video");
16072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mReachedEOS = true;
16172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> notify = mNotify->dup();
16272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        notify->setPointer("accessUnit", NULL);
16372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        notify->post();
16472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
16572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
16672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
16772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) {
16872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
16972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStart:
17072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
17172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<RefBase> obj;
17272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->findObject("meta", &obj));
17372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
17472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mReachedEOS = false;
17572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
17672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->start(static_cast<MetaData *>(obj.get()));
17772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
17872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err == OK) {
17972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                schedulePull();
18072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
18172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
18272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<AMessage> response = new AMessage;
18372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->setInt32("err", err);
18472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
18572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            uint32_t replyID;
18672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
18772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->postReply(replyID);
18872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
18972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
19072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
19172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStop:
19272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
19372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ++mPullGeneration;
19472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
19572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            handleEOS();
19672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
19772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
19872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
19972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatPull:
20072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
20172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            int32_t generation;
20272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->findInt32("generation", &generation));
20372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (generation != mPullGeneration) {
20572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
20672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
20772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            MediaBuffer *mbuf;
20972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->read(&mbuf);
21072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mPaused) {
21272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (err == OK) {
21372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf->release();
21472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf = NULL;
21572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
21672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                msg->post();
21872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
21972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
22072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err != OK) {
22272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (err == ERROR_END_OF_STREAM) {
22372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGV("stream ended, mbuf %p", mbuf);
22472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                } else {
22572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGE("error %d reading stream.", err);
22672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
22772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                handleEOS();
22872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
22972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                sp<AMessage> notify = mNotify->dup();
23072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                notify->setPointer("accessUnit", mbuf);
23272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                notify->post();
23372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                msg->post();
23572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
23672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
23772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
23872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatPause:
24072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
24172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPaused = true;
24272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
24372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
24472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatResume:
24672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
24772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPaused = false;
24872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
24972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
25072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
25172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        default:
25272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            TRESPASS();
25372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
25472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
25572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
25672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang// static
25772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<MediaCodecSource> MediaCodecSource::Create(
25872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
25972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &format,
26072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
26172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags) {
26272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaCodecSource> mediaSource =
26372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            new MediaCodecSource(looper, format, source, flags);
26472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
26572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mediaSource->init() == OK) {
26672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return mediaSource;
26772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
26872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return NULL;
26972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
27072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
27172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::start(MetaData* params) {
27272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> msg = new AMessage(kWhatStart, mReflector->id());
27372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", params);
27472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
27572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
27672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
27772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::stop() {
27872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> msg = new AMessage(kWhatStop, mReflector->id());
27916e79115e497386eaf010af388627f94314a55a3Chong Zhang    status_t err = postSynchronouslyAndReturnError(msg);
28016e79115e497386eaf010af388627f94314a55a3Chong Zhang
28116e79115e497386eaf010af388627f94314a55a3Chong Zhang    // mPuller->stop() needs to be done outside MediaCodecSource's looper,
28216e79115e497386eaf010af388627f94314a55a3Chong Zhang    // as it contains a synchronous call to stop the underlying MediaSource,
28316e79115e497386eaf010af388627f94314a55a3Chong Zhang    // which often waits for all outstanding MediaBuffers to return, but
28416e79115e497386eaf010af388627f94314a55a3Chong Zhang    // MediaBuffers are only returned when MediaCodecSource looper gets
28516e79115e497386eaf010af388627f94314a55a3Chong Zhang    // to process them.
28616e79115e497386eaf010af388627f94314a55a3Chong Zhang
28716e79115e497386eaf010af388627f94314a55a3Chong Zhang    if (mPuller != NULL) {
28816e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("puller (%s) stopping", mIsVideo ? "video" : "audio");
28916e79115e497386eaf010af388627f94314a55a3Chong Zhang        mPuller->stop();
29016e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("puller (%s) stopped", mIsVideo ? "video" : "audio");
29116e79115e497386eaf010af388627f94314a55a3Chong Zhang    }
29216e79115e497386eaf010af388627f94314a55a3Chong Zhang
29316e79115e497386eaf010af388627f94314a55a3Chong Zhang    return err;
29472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
29572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
29672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::pause() {
29772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    (new AMessage(kWhatPause, mReflector->id()))->post();
29872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
29972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
30072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
30172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() {
30272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
30372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mGraphicBufferProducer;
30472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
30572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
30684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MediaCodecSource::read(
30784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        MediaBuffer** buffer, const ReadOptions* /* options */) {
30872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    Mutex::Autolock autolock(mOutputBufferLock);
30972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
31072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    *buffer = NULL;
31116e79115e497386eaf010af388627f94314a55a3Chong Zhang    while (mOutputBufferQueue.size() == 0 && !mEncoderReachedEOS) {
31272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputBufferCond.wait(mOutputBufferLock);
31372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
31416e79115e497386eaf010af388627f94314a55a3Chong Zhang    if (!mEncoderReachedEOS) {
31572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        *buffer = *mOutputBufferQueue.begin();
31672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputBufferQueue.erase(mOutputBufferQueue.begin());
31772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
31872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
31972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mErrorCode;
32072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
32172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
32272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) {
32372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->setObserver(0);
32472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->release();
32572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
32672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
32772cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::MediaCodecSource(
32872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
32972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &outputFormat,
33072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
33172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags)
33272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mLooper(looper),
33372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mOutputFormat(outputFormat),
33472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mMeta(new MetaData),
33572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFlags(flags),
33672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mIsVideo(false),
33772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStarted(false),
33872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStopping(false),
33972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mDoMoreWorkPending(false),
34072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFirstSampleTimeUs(-1ll),
34116e79115e497386eaf010af388627f94314a55a3Chong Zhang      mEncoderReachedEOS(false),
34272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mErrorCode(OK) {
34372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mLooper != NULL);
34472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
34572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString mime;
34672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &mime));
34772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
34872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!strncasecmp("video/", mime.c_str(), 6)) {
34972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mIsVideo = true;
35072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
35172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
35372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mPuller = new Puller(source);
35472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
35572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
35672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35772cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::~MediaCodecSource() {
35872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    releaseEncoder();
35972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->stop();
36172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(mReflector->id());
36272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
36372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::init() {
36572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = initEncoder();
36672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
36872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        releaseEncoder();
36972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
37072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
37272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
37372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::initEncoder() {
37572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mReflector = new AHandlerReflector<MediaCodecSource>(this);
37672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(mReflector);
37772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper = new ALooper;
37972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->setName("codec_looper");
38072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->start();
38172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_METADATA_INPUT) {
38372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("store-metadata-in-buffers", 1);
38472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
38572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
38772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("create-input-buffers-suspended", 1);
38872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
38972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString outputMIME;
39172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &outputMIME));
39272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder = MediaCodec::CreateByType(
39472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mCodecLooper, outputMIME.c_str(), true /* encoder */);
39572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder == NULL) {
39772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return NO_INIT;
39872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
39972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
40172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = mEncoder->configure(
40372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mOutputFormat,
40472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                NULL /* nativeWindow */,
40572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                NULL /* crypto */,
40672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                MediaCodec::CONFIGURE_FLAG_ENCODE);
40772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
40972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
41072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
41172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->getOutputFormat(&mOutputFormat);
41372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    convertMessageToMetaData(mOutputFormat, mMeta);
41472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
41672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mIsVideo);
41772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = mEncoder->createInputSurface(&mGraphicBufferProducer);
41972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
42172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
42272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
42372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
42472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4251099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan    mEncoderActivityNotify = new AMessage(
4261099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            kWhatEncoderActivity, mReflector->id());
4271099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan    mEncoder->setCallback(mEncoderActivityNotify);
42872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4291099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan    err = mEncoder->start();
43072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
43272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
43372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
43472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43516e79115e497386eaf010af388627f94314a55a3Chong Zhang    mEncoderReachedEOS = false;
43672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mErrorCode = OK;
43772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
43972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
44072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::releaseEncoder() {
44272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder == NULL) {
44372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return;
44472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
44572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->release();
44772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder.clear();
44872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    while (!mInputBufferQueue.empty()) {
45072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MediaBuffer *mbuf = *mInputBufferQueue.begin();
45172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mInputBufferQueue.erase(mInputBufferQueue.begin());
45272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf != NULL) {
45372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mbuf->release();
45472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
45572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
45672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
45772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
45872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::postSynchronouslyAndReturnError(
45972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
46072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
46172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
46272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
46472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
46572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
46672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
46872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
46972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
47072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
47272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
47372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalEOS(status_t err) {
47516e79115e497386eaf010af388627f94314a55a3Chong Zhang    if (!mEncoderReachedEOS) {
47616e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio");
47772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
47872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            Mutex::Autolock autoLock(mOutputBufferLock);
47972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // release all unread media buffers
48072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            for (List<MediaBuffer*>::iterator it = mOutputBufferQueue.begin();
48172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    it != mOutputBufferQueue.end(); it++) {
48272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                (*it)->release();
48372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
48472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mOutputBufferQueue.clear();
48516e79115e497386eaf010af388627f94314a55a3Chong Zhang            mEncoderReachedEOS = true;
48672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mErrorCode = err;
48772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mOutputBufferCond.signal();
48872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
48972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
49072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        releaseEncoder();
49172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
49216e79115e497386eaf010af388627f94314a55a3Chong Zhang    if (mStopping && mEncoderReachedEOS) {
49316e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio");
49472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // posting reply to everyone that's waiting
49572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        List<uint32_t>::iterator it;
49672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        for (it = mStopReplyIDQueue.begin();
49772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                it != mStopReplyIDQueue.end(); it++) {
49872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(*it);
49972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
50072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.clear();
50172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = false;
50272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
50372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
50472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
50572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::suspend() {
50672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
50772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
50872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
50972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", true);
51072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
51172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
51272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
51372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
51472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::resume(int64_t skipFramesBeforeUs) {
51572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
51672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
51772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
51872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", false);
51972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (skipFramesBeforeUs > 0) {
52072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            params->setInt64("skip-frames-before", skipFramesBeforeUs);
52172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
52272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
52372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
52472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
52572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
52672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::feedEncoderInputBuffers() {
52772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    while (!mInputBufferQueue.empty()
52872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            && !mAvailEncoderInputIndices.empty()) {
52972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MediaBuffer* mbuf = *mInputBufferQueue.begin();
53072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mInputBufferQueue.erase(mInputBufferQueue.begin());
53172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
53272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t bufferIndex = *mAvailEncoderInputIndices.begin();
53372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
53472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
53572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t timeUs = 0ll;
53672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags = 0;
53772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t size = 0;
53872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
53972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf != NULL) {
54072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
54172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
54272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // push decoding time for video, or drift time for audio
54372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
54472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDecodingTimeQueue.push_back(timeUs);
54572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
54672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME
54772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mFirstSampleTimeUs < 0ll) {
54872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mFirstSampleTimeUs = timeUs;
54972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
55072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
55172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                int64_t driftTimeUs = 0;
55272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs)
55372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        && driftTimeUs) {
55472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs;
55572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
55672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDriftTimeQueue.push_back(driftTimeUs);
55772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME
55872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
55972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5601099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            sp<ABuffer> inbuf;
5611099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
5621099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (err != OK || inbuf == NULL) {
5631099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->release();
5641099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
5651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
5661099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
5671099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
56872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            size = mbuf->size();
56972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5701099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            memcpy(inbuf->data(), mbuf->data(), size);
57172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
57272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
57372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // video encoder will release MediaBuffer when done
57472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // with underlying data.
5751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                inbuf->setMediaBufferBase(mbuf);
57672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
57772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->release();
57872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
57972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
58072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            flags = MediaCodec::BUFFER_FLAG_EOS;
58172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
58272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
58372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        status_t err = mEncoder->queueInputBuffer(
58472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                bufferIndex, 0, size, timeUs, flags);
58572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
58672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
58772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
58872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
58972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
59072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
59172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
59272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
59372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
59472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::onStart(MetaData *params) {
59572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStopping) {
59672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("Failed to start while we're stopping");
59772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return INVALID_OPERATION;
59872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
59972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
60072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStarted) {
60172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
60272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
60372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            resume();
60472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
60572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
60672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->resume();
60772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
60872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
60972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
61072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio");
61272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = OK;
61472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
61672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t startTimeUs;
61772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
61872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            startTimeUs = -1ll;
61972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
62072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        resume(startTimeUs);
62172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else {
62272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mPuller != NULL);
62372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> notify = new AMessage(
62472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                kWhatPullerNotify, mReflector->id());
62572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = mPuller->start(params, notify);
62672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
62772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
62872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
62972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
63072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
63172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio");
63272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
63372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mStarted = true;
63472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
63572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
63672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
63772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
63872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
63972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPullerNotify:
64072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
64172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MediaBuffer *mbuf;
64272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->findPointer("accessUnit", (void**)&mbuf));
64372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
64472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf == NULL) {
64516e79115e497386eaf010af388627f94314a55a3Chong Zhang            ALOGV("puller (%s) reached EOS",
64672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mIsVideo ? "video" : "audio");
64716e79115e497386eaf010af388627f94314a55a3Chong Zhang            signalEOS();
64872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
64972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
65072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
65172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ALOGV("got msg '%s' after encoder shutdown.",
65272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                  msg->debugString().c_str());
65372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
65472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mbuf != NULL) {
65572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->release();
65672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
65716e79115e497386eaf010af388627f94314a55a3Chong Zhang
65872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
65972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
66072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
66172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mInputBufferQueue.push_back(mbuf);
66272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
66372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        feedEncoderInputBuffers();
66472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
66572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
66672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
66772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatEncoderActivity:
66872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
66972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
67072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
67172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
67272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6731099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        int32_t cbID;
6741099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        CHECK(msg->findInt32("callbackID", &cbID));
6751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        if (cbID == MediaCodec::CB_INPUT_AVAILABLE) {
6761099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
6771099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
6781099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
6791099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mAvailEncoderInputIndices.push_back(index);
6801099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            feedEncoderInputBuffers();
6811099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) {
6821099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
6831099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t offset;
6841099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t size;
6851099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int64_t timeUs;
6861099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t flags;
6871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            native_handle_t* handle = NULL;
6881099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
6891099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
6901099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("offset", &offset));
6911099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("size", &size));
6921099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt64("timeUs", &timeUs));
6931099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("flags", &flags));
6941099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
6951099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_EOS) {
6961099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mEncoder->releaseOutputBuffer(index);
6971099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
6981099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
6991099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
700f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
7011099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            sp<ABuffer> outbuf;
7021099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getOutputBuffer(index, &outbuf);
7031099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (err != OK || outbuf == NULL) {
7041099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
7051099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
7061099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
707f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
7081099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            MediaBuffer *mbuf = new MediaBuffer(outbuf->size());
7091099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            memcpy(mbuf->data(), outbuf->data(), outbuf->size());
71072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7111099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) {
7121099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                if (mIsVideo) {
7131099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t decodingTimeUs;
7141099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    if (mFlags & FLAG_USE_SURFACE_INPUT) {
7151099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // GraphicBufferSource is supposed to discard samples
7161099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // queued before start, and offset timeUs by start time
7171099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        CHECK_GE(timeUs, 0ll);
7181099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // TODO:
7191099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // Decoding time for surface source is unavailable,
7201099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // use presentation time for now. May need to move
7211099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // this logic into MediaCodec.
7221099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = timeUs;
7231099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    } else {
7241099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        CHECK(!mDecodingTimeQueue.empty());
7251099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = *(mDecodingTimeQueue.begin());
7261099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        mDecodingTimeQueue.erase(mDecodingTimeQueue.begin());
7271099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    }
7281099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
72972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7301099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64,
7311099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, decodingTimeUs - timeUs);
7321099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                } else {
7331099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t driftTimeUs = 0;
7341099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#if DEBUG_DRIFT_TIME
7351099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    CHECK(!mDriftTimeQueue.empty());
7361099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    driftTimeUs = *(mDriftTimeQueue.begin());
7371099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mDriftTimeQueue.erase(mDriftTimeQueue.begin());
7381099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs);
7391099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#endif // DEBUG_DRIFT_TIME
7401099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64,
7411099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, driftTimeUs);
7421099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                }
7431099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt64(kKeyTime, timeUs);
7441099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            } else {
7451099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true);
7461099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
7471099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
7481099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true);
7491099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
7501099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mbuf->setObserver(this);
7511099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mbuf->add_ref();
7521099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7531099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            {
7541099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                Mutex::Autolock autoLock(mOutputBufferLock);
7551099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mOutputBufferQueue.push_back(mbuf);
7561099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mOutputBufferCond.signal();
7571099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
7581099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7591099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mEncoder->releaseOutputBuffer(index);
7601099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       } else if (cbID == MediaCodec::CB_ERROR) {
7611099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err;
7621099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("err", &err));
7631099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            ALOGE("Encoder (%s) reported error : 0x%x",
7641099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mIsVideo ? "video" : "audio", err);
7651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            signalEOS();
7661099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       }
7671099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       break;
76872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
76972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStart:
77072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
77172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t replyID;
77272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
77372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
77472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<RefBase> obj;
77572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->findObject("meta", &obj));
77672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MetaData *params = static_cast<MetaData *>(obj.get());
77772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
77872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> response = new AMessage;
77972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->setInt32("err", onStart(params));
78072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->postReply(replyID);
78172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
78272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
78372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStop:
78472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
78516e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio");
78672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
78772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t replyID;
78872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
78972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
79016e79115e497386eaf010af388627f94314a55a3Chong Zhang        if (mEncoderReachedEOS) {
79172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // if we already reached EOS, reply and return now
79216e79115e497386eaf010af388627f94314a55a3Chong Zhang            ALOGI("encoder (%s) already stopped",
79372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mIsVideo ? "video" : "audio");
79472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(replyID);
79572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
79672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
79772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
79872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.push_back(replyID);
79972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mStopping) {
80072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // nothing to do if we're already stopping, reply will be posted
80172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // to all when we're stopped.
80272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
80372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
80472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
80572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = true;
80672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
80772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // if using surface, signal source EOS and wait for EOS to come back.
80872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // otherwise, release encoder and post EOS if haven't done already
80972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
81072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mEncoder->signalEndOfInputStream();
81172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
81272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            signalEOS();
81372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
81472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
81572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
81672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPause:
81772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
81872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags && FLAG_USE_SURFACE_INPUT) {
81972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            suspend();
82072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
82172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
82272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->pause();
82372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
82472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
82572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
82672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    default:
82772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        TRESPASS();
82872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
82972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
83072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
83172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} // namespace android
832