MediaCodecSource.cpp revision e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049
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
23e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <gui/IGraphicBufferConsumer.h>
2472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/IGraphicBufferProducer.h>
2572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/Surface.h>
2672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/ICrypto.h>
2772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ABuffer.h>
2872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ADebug.h>
2972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ALooper.h>
3072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/AMessage.h>
3172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaBuffer.h>
3272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodec.h>
33e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MediaCodecSource.h>
3472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaErrors.h>
3572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaSource.h>
36e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MetaData.h>
37e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/PersistentSurface.h>
3872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/Utils.h>
3972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangnamespace android {
4172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstruct MediaCodecSource::Puller : public AHandler {
4372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    Puller(const sp<MediaSource> &source);
4472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t start(const sp<MetaData> &meta, const sp<AMessage> &notify);
4616e79115e497386eaf010af388627f94314a55a3Chong Zhang    void stop();
4772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void pause();
4972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void resume();
5072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprotected:
5272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual void onMessageReceived(const sp<AMessage> &msg);
5372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual ~Puller();
5472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprivate:
5672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    enum {
5772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStart = 'msta',
5872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStop,
5972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatPull,
6072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatPause,
6172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatResume,
6272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    };
6372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaSource> mSource;
6572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> mNotify;
6672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<ALooper> mLooper;
6772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    int32_t mPullGeneration;
6872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mIsAudio;
6972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mPaused;
7072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mReachedEOS;
7172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
7372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void schedulePull();
7472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void handleEOS();
7572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    DISALLOW_EVIL_CONSTRUCTORS(Puller);
7772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang};
7872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7972cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::Puller(const sp<MediaSource> &source)
8072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mSource(source),
8172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mLooper(new ALooper()),
8272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mPullGeneration(0),
8372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mIsAudio(false),
8472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mPaused(false),
8572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mReachedEOS(false) {
8672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MetaData> meta = source->getFormat();
8772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    const char *mime;
8872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(meta->findCString(kKeyMIMEType, &mime));
8972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mIsAudio = !strncasecmp(mime, "audio/", 6);
9172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->setName("pull_looper");
9372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
9472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9572cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::~Puller() {
9672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(id());
9772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->stop();
9872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
9972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::postSynchronouslyAndReturnError(
10172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
10272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
10372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
10472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
10672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
10772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
10872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
11072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
11172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
11272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
11472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
11572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::start(const sp<MetaData> &meta,
11772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &notify) {
11872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("puller (%s) start", mIsAudio ? "audio" : "video");
11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->start(
12072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* runOnCallingThread */,
12172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* canCallJava */,
12272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            PRIORITY_AUDIO);
12372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(this);
12472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mNotify = notify;
12572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1261d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStart, this);
12772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", meta);
12872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
12972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
13072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
13116e79115e497386eaf010af388627f94314a55a3Chong Zhangvoid MediaCodecSource::Puller::stop() {
13216e79115e497386eaf010af388627f94314a55a3Chong Zhang    // Stop source from caller's thread instead of puller's looper.
13316e79115e497386eaf010af388627f94314a55a3Chong Zhang    // mSource->stop() is thread-safe, doing it outside the puller's
13416e79115e497386eaf010af388627f94314a55a3Chong Zhang    // looper allows us to at least stop if source gets stuck.
13516e79115e497386eaf010af388627f94314a55a3Chong Zhang    // If source gets stuck in read(), the looper would never
13616e79115e497386eaf010af388627f94314a55a3Chong Zhang    // be able to process the stop(), which could lead to ANR.
13716e79115e497386eaf010af388627f94314a55a3Chong Zhang
13816e79115e497386eaf010af388627f94314a55a3Chong Zhang    ALOGV("source (%s) stopping", mIsAudio ? "audio" : "video");
13916e79115e497386eaf010af388627f94314a55a3Chong Zhang    mSource->stop();
14016e79115e497386eaf010af388627f94314a55a3Chong Zhang    ALOGV("source (%s) stopped", mIsAudio ? "audio" : "video");
14116e79115e497386eaf010af388627f94314a55a3Chong Zhang
1421d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatStop, this))->post();
14372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
14472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
14572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::pause() {
1461d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPause, this))->post();
14772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
14872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
14972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::resume() {
1501d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatResume, this))->post();
15172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
15272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::schedulePull() {
1541d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatPull, this);
15572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setInt32("generation", mPullGeneration);
15672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->post();
15772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
15872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::handleEOS() {
16072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!mReachedEOS) {
16172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video");
16272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mReachedEOS = true;
16372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> notify = mNotify->dup();
16472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        notify->setPointer("accessUnit", NULL);
16572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        notify->post();
16672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
16772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
16872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
16972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) {
17072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
17172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStart:
17272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
17372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<RefBase> obj;
17472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->findObject("meta", &obj));
17572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
17672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mReachedEOS = false;
17772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
17872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->start(static_cast<MetaData *>(obj.get()));
17972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
18072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err == OK) {
18172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                schedulePull();
18272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
18372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
18472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<AMessage> response = new AMessage;
18572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->setInt32("err", err);
18672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1873f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
18872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
18972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->postReply(replyID);
19072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
19172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
19272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
19372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStop:
19472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
19572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ++mPullGeneration;
19672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
19772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            handleEOS();
19872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
19972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
20072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatPull:
20272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
20372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            int32_t generation;
20472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->findInt32("generation", &generation));
20572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (generation != mPullGeneration) {
20772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
20872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
20972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            MediaBuffer *mbuf;
21172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->read(&mbuf);
21272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mPaused) {
21472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (err == OK) {
21572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf->release();
21672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf = NULL;
21772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
21872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                msg->post();
22072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
22172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
22272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err != OK) {
22472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (err == ERROR_END_OF_STREAM) {
22572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGV("stream ended, mbuf %p", mbuf);
22672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                } else {
22772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGE("error %d reading stream.", err);
22872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
22972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                handleEOS();
23072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
23172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                sp<AMessage> notify = mNotify->dup();
23272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                notify->setPointer("accessUnit", mbuf);
23472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                notify->post();
23572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                msg->post();
23772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
23872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
23972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
24072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatPause:
24272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
24372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPaused = true;
24472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
24572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
24672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatResume:
24872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
24972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPaused = false;
25072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
25172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
25272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
25372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        default:
25472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            TRESPASS();
25572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
25672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
25772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
25872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang// static
25972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<MediaCodecSource> MediaCodecSource::Create(
26072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
26172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &format,
26272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
263e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        const sp<IGraphicBufferConsumer> &consumer,
26472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags) {
26572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaCodecSource> mediaSource =
266e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            new MediaCodecSource(looper, format, source, consumer, flags);
26772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
26872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mediaSource->init() == OK) {
26972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return mediaSource;
27072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
27172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return NULL;
27272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
27372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
27472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::start(MetaData* params) {
2751d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStart, mReflector);
27672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", params);
27772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
27872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
27972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
28072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::stop() {
2811d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStop, mReflector);
28216e79115e497386eaf010af388627f94314a55a3Chong Zhang    status_t err = postSynchronouslyAndReturnError(msg);
28316e79115e497386eaf010af388627f94314a55a3Chong Zhang
28416e79115e497386eaf010af388627f94314a55a3Chong Zhang    // mPuller->stop() needs to be done outside MediaCodecSource's looper,
28516e79115e497386eaf010af388627f94314a55a3Chong Zhang    // as it contains a synchronous call to stop the underlying MediaSource,
28616e79115e497386eaf010af388627f94314a55a3Chong Zhang    // which often waits for all outstanding MediaBuffers to return, but
28716e79115e497386eaf010af388627f94314a55a3Chong Zhang    // MediaBuffers are only returned when MediaCodecSource looper gets
28816e79115e497386eaf010af388627f94314a55a3Chong Zhang    // to process them.
28916e79115e497386eaf010af388627f94314a55a3Chong Zhang
29016e79115e497386eaf010af388627f94314a55a3Chong Zhang    if (mPuller != NULL) {
29116e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("puller (%s) stopping", mIsVideo ? "video" : "audio");
29216e79115e497386eaf010af388627f94314a55a3Chong Zhang        mPuller->stop();
29316e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("puller (%s) stopped", mIsVideo ? "video" : "audio");
29416e79115e497386eaf010af388627f94314a55a3Chong Zhang    }
29516e79115e497386eaf010af388627f94314a55a3Chong Zhang
29616e79115e497386eaf010af388627f94314a55a3Chong Zhang    return err;
29772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
29872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
29972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::pause() {
3001d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPause, mReflector))->post();
30172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
30272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
30372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
30472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() {
30572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
30672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mGraphicBufferProducer;
30772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
30872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
30984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MediaCodecSource::read(
31084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        MediaBuffer** buffer, const ReadOptions* /* options */) {
31172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    Mutex::Autolock autolock(mOutputBufferLock);
31272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
31372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    *buffer = NULL;
31416e79115e497386eaf010af388627f94314a55a3Chong Zhang    while (mOutputBufferQueue.size() == 0 && !mEncoderReachedEOS) {
31572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputBufferCond.wait(mOutputBufferLock);
31672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
31716e79115e497386eaf010af388627f94314a55a3Chong Zhang    if (!mEncoderReachedEOS) {
31872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        *buffer = *mOutputBufferQueue.begin();
31972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputBufferQueue.erase(mOutputBufferQueue.begin());
32072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
32172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
32272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mErrorCode;
32372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
32472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
32572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) {
32672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->setObserver(0);
32772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->release();
32872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
32972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
33072cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::MediaCodecSource(
33172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
33272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &outputFormat,
33372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
334e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        const sp<IGraphicBufferConsumer> &consumer,
33572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags)
33672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mLooper(looper),
33772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mOutputFormat(outputFormat),
33872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mMeta(new MetaData),
33972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFlags(flags),
34072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mIsVideo(false),
34172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStarted(false),
34272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStopping(false),
34372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mDoMoreWorkPending(false),
344e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang      mGraphicBufferConsumer(consumer),
34572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFirstSampleTimeUs(-1ll),
34616e79115e497386eaf010af388627f94314a55a3Chong Zhang      mEncoderReachedEOS(false),
34772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mErrorCode(OK) {
34872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mLooper != NULL);
34972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString mime;
35172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &mime));
35272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!strncasecmp("video/", mime.c_str(), 6)) {
35472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mIsVideo = true;
35572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
35672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
35872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mPuller = new Puller(source);
35972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
36072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
36172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36272cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::~MediaCodecSource() {
36372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    releaseEncoder();
36472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->stop();
36672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(mReflector->id());
36772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
36872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::init() {
37072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = initEncoder();
37172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
37372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        releaseEncoder();
37472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
37572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
37772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
37872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::initEncoder() {
38072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mReflector = new AHandlerReflector<MediaCodecSource>(this);
38172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(mReflector);
38272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper = new ALooper;
38472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->setName("codec_looper");
38572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->start();
38672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_METADATA_INPUT) {
38872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("store-metadata-in-buffers", 1);
38972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
39072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
39272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("create-input-buffers-suspended", 1);
39372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
39472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString outputMIME;
39672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &outputMIME));
39772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder = MediaCodec::CreateByType(
39972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mCodecLooper, outputMIME.c_str(), true /* encoder */);
40072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder == NULL) {
40272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return NO_INIT;
40372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
40472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
40672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
407421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen    mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector);
408421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen    mEncoder->setCallback(mEncoderActivityNotify);
409421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen
41072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = mEncoder->configure(
41172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mOutputFormat,
41272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                NULL /* nativeWindow */,
41372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                NULL /* crypto */,
41472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                MediaCodec::CONFIGURE_FLAG_ENCODE);
41572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
41772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
41872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
41972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->getOutputFormat(&mOutputFormat);
42172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    convertMessageToMetaData(mOutputFormat, mMeta);
42272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
42472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mIsVideo);
42572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
426e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        if (mGraphicBufferConsumer != NULL) {
427e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // When using persistent surface, we are only interested in the
428e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // consumer, but have to use PersistentSurface as a wrapper to
429e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // pass consumer over messages (similar to BufferProducerWrapper)
430e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            err = mEncoder->usePersistentInputSurface(
431e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang                    new PersistentSurface(NULL, mGraphicBufferConsumer));
432e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        } else {
433e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            err = mEncoder->createInputSurface(&mGraphicBufferProducer);
434e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        }
43572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
43772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
43872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
43972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
44072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4411099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan    err = mEncoder->start();
44272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
44472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
44572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
44672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44716e79115e497386eaf010af388627f94314a55a3Chong Zhang    mEncoderReachedEOS = false;
44872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mErrorCode = OK;
44972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
45072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
45172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
45272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
45372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::releaseEncoder() {
45472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder == NULL) {
45572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return;
45672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
45772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
45872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->release();
45972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder.clear();
46072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    while (!mInputBufferQueue.empty()) {
46272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MediaBuffer *mbuf = *mInputBufferQueue.begin();
46372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mInputBufferQueue.erase(mInputBufferQueue.begin());
46472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf != NULL) {
46572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mbuf->release();
46672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
46772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
46872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
46972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::postSynchronouslyAndReturnError(
47172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
47272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
47372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
47472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
47672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
47772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
47872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
48072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
48172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
48272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
48372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
48472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
48572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
48672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalEOS(status_t err) {
48716e79115e497386eaf010af388627f94314a55a3Chong Zhang    if (!mEncoderReachedEOS) {
48816e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio");
48972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
49072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            Mutex::Autolock autoLock(mOutputBufferLock);
49172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // release all unread media buffers
49272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            for (List<MediaBuffer*>::iterator it = mOutputBufferQueue.begin();
49372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    it != mOutputBufferQueue.end(); it++) {
49472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                (*it)->release();
49572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
49672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mOutputBufferQueue.clear();
49716e79115e497386eaf010af388627f94314a55a3Chong Zhang            mEncoderReachedEOS = true;
49872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mErrorCode = err;
49972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mOutputBufferCond.signal();
50072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
50172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
50272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        releaseEncoder();
50372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
50416e79115e497386eaf010af388627f94314a55a3Chong Zhang    if (mStopping && mEncoderReachedEOS) {
50516e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio");
50672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // posting reply to everyone that's waiting
5073f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        List<sp<AReplyToken>>::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 Zhangstatus_t MediaCodecSource::feedEncoderInputBuffers() {
53972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    while (!mInputBufferQueue.empty()
54072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            && !mAvailEncoderInputIndices.empty()) {
54172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MediaBuffer* mbuf = *mInputBufferQueue.begin();
54272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mInputBufferQueue.erase(mInputBufferQueue.begin());
54372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
54472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t bufferIndex = *mAvailEncoderInputIndices.begin();
54572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
54672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
54772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t timeUs = 0ll;
54872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags = 0;
54972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t size = 0;
55072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
55172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf != NULL) {
55272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
55372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
55472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // push decoding time for video, or drift time for audio
55572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
55672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDecodingTimeQueue.push_back(timeUs);
55772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
55872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME
55972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mFirstSampleTimeUs < 0ll) {
56072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mFirstSampleTimeUs = timeUs;
56172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
56272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
56372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                int64_t driftTimeUs = 0;
56472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs)
56572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        && driftTimeUs) {
56672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs;
56772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
56872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDriftTimeQueue.push_back(driftTimeUs);
56972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME
57072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
57172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5721099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            sp<ABuffer> inbuf;
5731099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
5741099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (err != OK || inbuf == NULL) {
5751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->release();
5761099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
5771099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
5781099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
5791099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
58072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            size = mbuf->size();
58172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5821099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            memcpy(inbuf->data(), mbuf->data(), size);
58372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
58472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
58572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // video encoder will release MediaBuffer when done
58672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // with underlying data.
5871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                inbuf->setMediaBufferBase(mbuf);
58872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
58972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->release();
59072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
59172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
59272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            flags = MediaCodec::BUFFER_FLAG_EOS;
59372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
59472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
59572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        status_t err = mEncoder->queueInputBuffer(
59672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                bufferIndex, 0, size, timeUs, flags);
59772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
59872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
59972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
60072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
60172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
60272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
60372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
60472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
60572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
60672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::onStart(MetaData *params) {
60772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStopping) {
60872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("Failed to start while we're stopping");
60972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return INVALID_OPERATION;
61072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
61172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStarted) {
61372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
61472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
61572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            resume();
61672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
61772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
61872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->resume();
61972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
62072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
62172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
62272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio");
62472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = OK;
62672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
62872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t startTimeUs;
62972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
63072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            startTimeUs = -1ll;
63172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
63272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        resume(startTimeUs);
63372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else {
63472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mPuller != NULL);
6351d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> notify = new AMessage(kWhatPullerNotify, mReflector);
63672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = mPuller->start(params, notify);
63772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
63872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
63972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
64072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
64172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
64272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio");
64372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
64472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mStarted = true;
64572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
64672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
64772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
64872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
64972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
65072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPullerNotify:
65172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
65272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MediaBuffer *mbuf;
65372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->findPointer("accessUnit", (void**)&mbuf));
65472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
65572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf == NULL) {
65616e79115e497386eaf010af388627f94314a55a3Chong Zhang            ALOGV("puller (%s) reached EOS",
65772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mIsVideo ? "video" : "audio");
65816e79115e497386eaf010af388627f94314a55a3Chong Zhang            signalEOS();
65972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
66072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
66172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
66272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ALOGV("got msg '%s' after encoder shutdown.",
66372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                  msg->debugString().c_str());
66472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
66572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mbuf != NULL) {
66672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->release();
66772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
66816e79115e497386eaf010af388627f94314a55a3Chong Zhang
66972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
67072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
67172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
67272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mInputBufferQueue.push_back(mbuf);
67372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
67472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        feedEncoderInputBuffers();
67572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
67672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
67772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
67872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatEncoderActivity:
67972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
68072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
68172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
68272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
68372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6841099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        int32_t cbID;
6851099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        CHECK(msg->findInt32("callbackID", &cbID));
6861099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        if (cbID == MediaCodec::CB_INPUT_AVAILABLE) {
6871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
6881099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
6891099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
6901099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mAvailEncoderInputIndices.push_back(index);
6911099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            feedEncoderInputBuffers();
6921099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) {
6931099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
6941099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t offset;
6951099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t size;
6961099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int64_t timeUs;
6971099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t flags;
6981099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
6991099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
7001099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("offset", &offset));
7011099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("size", &size));
7021099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt64("timeUs", &timeUs));
7031099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("flags", &flags));
7041099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7051099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_EOS) {
7061099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mEncoder->releaseOutputBuffer(index);
7071099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
7081099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
7091099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
710f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
7111099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            sp<ABuffer> outbuf;
7121099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getOutputBuffer(index, &outbuf);
7131099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (err != OK || outbuf == NULL) {
7141099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
7151099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
7161099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
717f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
7181099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            MediaBuffer *mbuf = new MediaBuffer(outbuf->size());
7191099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            memcpy(mbuf->data(), outbuf->data(), outbuf->size());
72072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7211099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) {
7221099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                if (mIsVideo) {
7231099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t decodingTimeUs;
7241099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    if (mFlags & FLAG_USE_SURFACE_INPUT) {
7251099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // GraphicBufferSource is supposed to discard samples
7261099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // queued before start, and offset timeUs by start time
7271099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        CHECK_GE(timeUs, 0ll);
7281099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // TODO:
7291099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // Decoding time for surface source is unavailable,
7301099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // use presentation time for now. May need to move
7311099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // this logic into MediaCodec.
7321099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = timeUs;
7331099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    } else {
7341099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        CHECK(!mDecodingTimeQueue.empty());
7351099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = *(mDecodingTimeQueue.begin());
7361099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        mDecodingTimeQueue.erase(mDecodingTimeQueue.begin());
7371099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    }
7381099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
73972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7401099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64,
7411099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, decodingTimeUs - timeUs);
7421099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                } else {
7431099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t driftTimeUs = 0;
7441099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#if DEBUG_DRIFT_TIME
7451099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    CHECK(!mDriftTimeQueue.empty());
7461099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    driftTimeUs = *(mDriftTimeQueue.begin());
7471099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mDriftTimeQueue.erase(mDriftTimeQueue.begin());
7481099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs);
7491099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#endif // DEBUG_DRIFT_TIME
7501099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64,
7511099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, driftTimeUs);
7521099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                }
7531099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt64(kKeyTime, timeUs);
7541099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            } else {
7551099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true);
7561099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
7571099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
7581099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true);
7591099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
7601099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mbuf->setObserver(this);
7611099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mbuf->add_ref();
7621099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7631099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            {
7641099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                Mutex::Autolock autoLock(mOutputBufferLock);
7651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mOutputBufferQueue.push_back(mbuf);
7661099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mOutputBufferCond.signal();
7671099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
7681099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7691099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mEncoder->releaseOutputBuffer(index);
7701099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       } else if (cbID == MediaCodec::CB_ERROR) {
7711099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err;
7721099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("err", &err));
7731099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            ALOGE("Encoder (%s) reported error : 0x%x",
7741099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mIsVideo ? "video" : "audio", err);
7751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            signalEOS();
7761099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       }
7771099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       break;
77872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
77972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStart:
78072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
7813f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
78272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
78372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
78472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<RefBase> obj;
78572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->findObject("meta", &obj));
78672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MetaData *params = static_cast<MetaData *>(obj.get());
78772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
78872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> response = new AMessage;
78972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->setInt32("err", onStart(params));
79072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->postReply(replyID);
79172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
79272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
79372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStop:
79472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
79516e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio");
79672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7973f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
79872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
79972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
80016e79115e497386eaf010af388627f94314a55a3Chong Zhang        if (mEncoderReachedEOS) {
80172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // if we already reached EOS, reply and return now
80216e79115e497386eaf010af388627f94314a55a3Chong Zhang            ALOGI("encoder (%s) already stopped",
80372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mIsVideo ? "video" : "audio");
80472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(replyID);
80572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
80672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
80772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
80872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.push_back(replyID);
80972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mStopping) {
81072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // nothing to do if we're already stopping, reply will be posted
81172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // to all when we're stopped.
81272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
81372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
81472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
81572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = true;
81672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
81772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // if using surface, signal source EOS and wait for EOS to come back.
81872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // otherwise, release encoder and post EOS if haven't done already
81972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
82072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mEncoder->signalEndOfInputStream();
82172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
82272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            signalEOS();
82372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
82472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
82572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
82672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPause:
82772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
82872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags && FLAG_USE_SURFACE_INPUT) {
82972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            suspend();
83072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
83172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
83272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->pause();
83372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
83472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
83572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
83672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    default:
83772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        TRESPASS();
83872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
83972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
84072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
84172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} // namespace android
842