MediaCodecSource.cpp revision c93a13669ce1b5a9e6527b4c86c9d8f5e92be828
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
42c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnarconst int kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
43c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnarconst int kDefaultSwVideoEncoderDataSpace = HAL_DATASPACE_BT709;
44c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
4572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstruct MediaCodecSource::Puller : public AHandler {
4672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    Puller(const sp<MediaSource> &source);
4772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t start(const sp<MetaData> &meta, const sp<AMessage> &notify);
4916e79115e497386eaf010af388627f94314a55a3Chong Zhang    void stop();
5072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void pause();
5272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void resume();
5372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprotected:
5572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual void onMessageReceived(const sp<AMessage> &msg);
5672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual ~Puller();
5772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprivate:
5972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    enum {
6072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStart = 'msta',
6172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStop,
6272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatPull,
6372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatPause,
6472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatResume,
6572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    };
6672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaSource> mSource;
6872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> mNotify;
6972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<ALooper> mLooper;
7072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    int32_t mPullGeneration;
7172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mIsAudio;
7272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mPaused;
7372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mReachedEOS;
7472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
7672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void schedulePull();
7772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void handleEOS();
7872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    DISALLOW_EVIL_CONSTRUCTORS(Puller);
8072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang};
8172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8272cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::Puller(const sp<MediaSource> &source)
8372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mSource(source),
8472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mLooper(new ALooper()),
8572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mPullGeneration(0),
8672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mIsAudio(false),
8772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mPaused(false),
8872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mReachedEOS(false) {
8972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MetaData> meta = source->getFormat();
9072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    const char *mime;
9172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(meta->findCString(kKeyMIMEType, &mime));
9272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mIsAudio = !strncasecmp(mime, "audio/", 6);
9472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->setName("pull_looper");
9672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
9772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9872cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::~Puller() {
9972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(id());
10072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->stop();
10172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
10272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::postSynchronouslyAndReturnError(
10472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
10572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
10672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
10772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
10972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
11072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
11172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
11372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
11472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
11572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
11772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
11872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::start(const sp<MetaData> &meta,
12072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &notify) {
12172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("puller (%s) start", mIsAudio ? "audio" : "video");
12272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->start(
12372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* runOnCallingThread */,
12472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* canCallJava */,
12572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            PRIORITY_AUDIO);
12672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(this);
12772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mNotify = notify;
12872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1291d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStart, this);
13072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", meta);
13172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
13272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
13372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
13416e79115e497386eaf010af388627f94314a55a3Chong Zhangvoid MediaCodecSource::Puller::stop() {
13516e79115e497386eaf010af388627f94314a55a3Chong Zhang    // Stop source from caller's thread instead of puller's looper.
13616e79115e497386eaf010af388627f94314a55a3Chong Zhang    // mSource->stop() is thread-safe, doing it outside the puller's
13716e79115e497386eaf010af388627f94314a55a3Chong Zhang    // looper allows us to at least stop if source gets stuck.
13816e79115e497386eaf010af388627f94314a55a3Chong Zhang    // If source gets stuck in read(), the looper would never
13916e79115e497386eaf010af388627f94314a55a3Chong Zhang    // be able to process the stop(), which could lead to ANR.
14016e79115e497386eaf010af388627f94314a55a3Chong Zhang
14116e79115e497386eaf010af388627f94314a55a3Chong Zhang    ALOGV("source (%s) stopping", mIsAudio ? "audio" : "video");
14216e79115e497386eaf010af388627f94314a55a3Chong Zhang    mSource->stop();
14316e79115e497386eaf010af388627f94314a55a3Chong Zhang    ALOGV("source (%s) stopped", mIsAudio ? "audio" : "video");
14416e79115e497386eaf010af388627f94314a55a3Chong Zhang
1451d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatStop, this))->post();
14672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
14772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
14872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::pause() {
1491d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPause, this))->post();
15072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
15172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::resume() {
1531d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatResume, this))->post();
15472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
15572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::schedulePull() {
1571d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatPull, this);
15872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setInt32("generation", mPullGeneration);
15972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->post();
16072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
16172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
16272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::handleEOS() {
16372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!mReachedEOS) {
16472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video");
16572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mReachedEOS = true;
16672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> notify = mNotify->dup();
16772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        notify->setPointer("accessUnit", NULL);
16872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        notify->post();
16972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
17072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
17172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
17272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) {
17372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
17472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStart:
17572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
17672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<RefBase> obj;
17772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->findObject("meta", &obj));
17872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
17972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mReachedEOS = false;
18072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
18172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->start(static_cast<MetaData *>(obj.get()));
18272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
18372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err == OK) {
18472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                schedulePull();
18572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
18672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
18772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<AMessage> response = new AMessage;
18872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->setInt32("err", err);
18972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1903f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
19172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
19272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->postReply(replyID);
19372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
19472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
19572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
19672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStop:
19772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
19872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ++mPullGeneration;
19972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            handleEOS();
20172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
20272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
20372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatPull:
20572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
20672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            int32_t generation;
20772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->findInt32("generation", &generation));
20872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (generation != mPullGeneration) {
21072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
21172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
21272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            MediaBuffer *mbuf;
21472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->read(&mbuf);
21572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mPaused) {
21772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (err == OK) {
21872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf->release();
21972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf = NULL;
22072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
22172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                msg->post();
22372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
22472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
22572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err != OK) {
22772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (err == ERROR_END_OF_STREAM) {
22872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGV("stream ended, mbuf %p", mbuf);
22972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                } else {
23072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGE("error %d reading stream.", err);
23172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
23272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                handleEOS();
23372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
23472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                sp<AMessage> notify = mNotify->dup();
23572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                notify->setPointer("accessUnit", mbuf);
23772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                notify->post();
23872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                msg->post();
24072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
24172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
24272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
24372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatPause:
24572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
24672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPaused = true;
24772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
24872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
24972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
25072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatResume:
25172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
25272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPaused = false;
25372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
25472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
25572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
25672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        default:
25772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            TRESPASS();
25872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
25972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
26072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
26172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang// static
26272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<MediaCodecSource> MediaCodecSource::Create(
26372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
26472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &format,
26572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
266e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        const sp<IGraphicBufferConsumer> &consumer,
26772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags) {
26872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaCodecSource> mediaSource =
269e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            new MediaCodecSource(looper, format, source, consumer, flags);
27072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
27172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mediaSource->init() == OK) {
27272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return mediaSource;
27372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
27472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return NULL;
27572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
27672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
27772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::start(MetaData* params) {
2781d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStart, mReflector);
27972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", params);
28072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
28172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
28272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
28372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::stop() {
2841d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStop, mReflector);
28516e79115e497386eaf010af388627f94314a55a3Chong Zhang    status_t err = postSynchronouslyAndReturnError(msg);
28616e79115e497386eaf010af388627f94314a55a3Chong Zhang
28716e79115e497386eaf010af388627f94314a55a3Chong Zhang    // mPuller->stop() needs to be done outside MediaCodecSource's looper,
28816e79115e497386eaf010af388627f94314a55a3Chong Zhang    // as it contains a synchronous call to stop the underlying MediaSource,
28916e79115e497386eaf010af388627f94314a55a3Chong Zhang    // which often waits for all outstanding MediaBuffers to return, but
29016e79115e497386eaf010af388627f94314a55a3Chong Zhang    // MediaBuffers are only returned when MediaCodecSource looper gets
29116e79115e497386eaf010af388627f94314a55a3Chong Zhang    // to process them.
29216e79115e497386eaf010af388627f94314a55a3Chong Zhang
29316e79115e497386eaf010af388627f94314a55a3Chong Zhang    if (mPuller != NULL) {
29416e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("puller (%s) stopping", mIsVideo ? "video" : "audio");
29516e79115e497386eaf010af388627f94314a55a3Chong Zhang        mPuller->stop();
29616e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("puller (%s) stopped", mIsVideo ? "video" : "audio");
29716e79115e497386eaf010af388627f94314a55a3Chong Zhang    }
29816e79115e497386eaf010af388627f94314a55a3Chong Zhang
29916e79115e497386eaf010af388627f94314a55a3Chong Zhang    return err;
30072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
30172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
30272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::pause() {
3031d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPause, mReflector))->post();
30472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
30572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
30672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
30772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() {
30872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
30972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mGraphicBufferProducer;
31072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
31172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
31284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MediaCodecSource::read(
31384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        MediaBuffer** buffer, const ReadOptions* /* options */) {
31472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    Mutex::Autolock autolock(mOutputBufferLock);
31572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
31672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    *buffer = NULL;
31716e79115e497386eaf010af388627f94314a55a3Chong Zhang    while (mOutputBufferQueue.size() == 0 && !mEncoderReachedEOS) {
31872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputBufferCond.wait(mOutputBufferLock);
31972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
32016e79115e497386eaf010af388627f94314a55a3Chong Zhang    if (!mEncoderReachedEOS) {
32172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        *buffer = *mOutputBufferQueue.begin();
32272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputBufferQueue.erase(mOutputBufferQueue.begin());
32372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
32472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
32572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mErrorCode;
32672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
32772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
32872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) {
32972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->setObserver(0);
33072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->release();
33172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
33272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
33372cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::MediaCodecSource(
33472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
33572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &outputFormat,
33672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
337e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        const sp<IGraphicBufferConsumer> &consumer,
33872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags)
33972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mLooper(looper),
34072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mOutputFormat(outputFormat),
34172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mMeta(new MetaData),
34272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFlags(flags),
34372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mIsVideo(false),
34472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStarted(false),
34572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStopping(false),
34672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mDoMoreWorkPending(false),
347c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mSetEncoderFormat(false),
348c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mEncoderFormat(0),
349c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mEncoderDataSpace(0),
350e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang      mGraphicBufferConsumer(consumer),
35172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFirstSampleTimeUs(-1ll),
35216e79115e497386eaf010af388627f94314a55a3Chong Zhang      mEncoderReachedEOS(false),
35372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mErrorCode(OK) {
35472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mLooper != NULL);
35572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString mime;
35772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &mime));
35872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!strncasecmp("video/", mime.c_str(), 6)) {
36072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mIsVideo = true;
36172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
36272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
36472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mPuller = new Puller(source);
36572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
36672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
36772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36872cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::~MediaCodecSource() {
36972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    releaseEncoder();
37072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->stop();
37272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(mReflector->id());
37372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
37472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::init() {
37672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = initEncoder();
37772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
37972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        releaseEncoder();
38072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
38172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
38372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
38472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::initEncoder() {
38672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mReflector = new AHandlerReflector<MediaCodecSource>(this);
38772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(mReflector);
38872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper = new ALooper;
39072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->setName("codec_looper");
39172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->start();
39272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_METADATA_INPUT) {
39472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("store-metadata-in-buffers", 1);
39572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
39672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
39872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("create-input-buffers-suspended", 1);
39972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
40072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString outputMIME;
40272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &outputMIME));
40372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder = MediaCodec::CreateByType(
40572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mCodecLooper, outputMIME.c_str(), true /* encoder */);
40672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder == NULL) {
40872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return NO_INIT;
40972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
41072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
41272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
413421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen    mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector);
414421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen    mEncoder->setCallback(mEncoderActivityNotify);
415421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen
41672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = mEncoder->configure(
41772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mOutputFormat,
41872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                NULL /* nativeWindow */,
41972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                NULL /* crypto */,
42072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                MediaCodec::CONFIGURE_FLAG_ENCODE);
42172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
42372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
42472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
42572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->getOutputFormat(&mOutputFormat);
42772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    convertMessageToMetaData(mOutputFormat, mMeta);
42872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
43072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mIsVideo);
43172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
432e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        if (mGraphicBufferConsumer != NULL) {
433e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // When using persistent surface, we are only interested in the
434e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // consumer, but have to use PersistentSurface as a wrapper to
435e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // pass consumer over messages (similar to BufferProducerWrapper)
4368f469e18c307cb9dc0d16ed9225972aa8be4516fChong Zhang            err = mEncoder->setInputSurface(
437e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang                    new PersistentSurface(NULL, mGraphicBufferConsumer));
438e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        } else {
439e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            err = mEncoder->createInputSurface(&mGraphicBufferProducer);
440e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        }
44172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
44372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
44472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
44572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
44672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
447c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    sp<AMessage> inputFormat;
448c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    int32_t usingSwReadOften;
449c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    mSetEncoderFormat = false;
450c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    if (mEncoder->getInputFormat(&inputFormat) == OK
451c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            && inputFormat->findInt32("using-sw-read-often", &usingSwReadOften)
452c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            && usingSwReadOften) {
453c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        // this is a SW encoder; signal source to allocate SW readable buffers
454c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        mSetEncoderFormat = true;
455c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        mEncoderFormat = kDefaultSwVideoEncoderFormat;
456c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        mEncoderDataSpace = kDefaultSwVideoEncoderDataSpace;
457c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    }
458c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
4591099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan    err = mEncoder->start();
46072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
46272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
46372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
46472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46516e79115e497386eaf010af388627f94314a55a3Chong Zhang    mEncoderReachedEOS = false;
46672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mErrorCode = OK;
46772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
46972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
47072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::releaseEncoder() {
47272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder == NULL) {
47372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return;
47472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
47572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->release();
47772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder.clear();
47872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    while (!mInputBufferQueue.empty()) {
48072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MediaBuffer *mbuf = *mInputBufferQueue.begin();
48172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mInputBufferQueue.erase(mInputBufferQueue.begin());
48272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf != NULL) {
48372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mbuf->release();
48472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
48572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
48672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
48772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
48872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::postSynchronouslyAndReturnError(
48972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
49072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
49172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
49272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
49372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
49472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
49572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
49672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
49772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
49872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
49972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
50072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
50172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
50272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
50372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
50472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalEOS(status_t err) {
50516e79115e497386eaf010af388627f94314a55a3Chong Zhang    if (!mEncoderReachedEOS) {
50616e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio");
50772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
50872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            Mutex::Autolock autoLock(mOutputBufferLock);
50972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // release all unread media buffers
51072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            for (List<MediaBuffer*>::iterator it = mOutputBufferQueue.begin();
51172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    it != mOutputBufferQueue.end(); it++) {
51272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                (*it)->release();
51372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
51472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mOutputBufferQueue.clear();
51516e79115e497386eaf010af388627f94314a55a3Chong Zhang            mEncoderReachedEOS = true;
51672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mErrorCode = err;
51772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mOutputBufferCond.signal();
51872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
51972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
52072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        releaseEncoder();
52172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
52216e79115e497386eaf010af388627f94314a55a3Chong Zhang    if (mStopping && mEncoderReachedEOS) {
52316e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio");
52472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // posting reply to everyone that's waiting
5253f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        List<sp<AReplyToken>>::iterator it;
52672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        for (it = mStopReplyIDQueue.begin();
52772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                it != mStopReplyIDQueue.end(); it++) {
52872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(*it);
52972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
53072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.clear();
53172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = false;
53272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
53372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
53472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
53572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::suspend() {
53672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
53772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
53872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
53972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", true);
54072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
54172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
54272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
54372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
54472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::resume(int64_t skipFramesBeforeUs) {
54572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
54672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
54772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
54872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", false);
54972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (skipFramesBeforeUs > 0) {
55072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            params->setInt64("skip-frames-before", skipFramesBeforeUs);
55172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
55272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
55372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
55472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
55572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
55672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::feedEncoderInputBuffers() {
55772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    while (!mInputBufferQueue.empty()
55872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            && !mAvailEncoderInputIndices.empty()) {
55972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MediaBuffer* mbuf = *mInputBufferQueue.begin();
56072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mInputBufferQueue.erase(mInputBufferQueue.begin());
56172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
56272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t bufferIndex = *mAvailEncoderInputIndices.begin();
56372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
56472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
56572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t timeUs = 0ll;
56672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags = 0;
56772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t size = 0;
56872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
56972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf != NULL) {
57072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
57172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
57272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // push decoding time for video, or drift time for audio
57372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
57472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDecodingTimeQueue.push_back(timeUs);
57572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
57672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME
57772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mFirstSampleTimeUs < 0ll) {
57872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mFirstSampleTimeUs = timeUs;
57972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
58072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
58172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                int64_t driftTimeUs = 0;
58272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs)
58372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        && driftTimeUs) {
58472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs;
58572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
58672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDriftTimeQueue.push_back(driftTimeUs);
58772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME
58872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
58972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5901099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            sp<ABuffer> inbuf;
5911099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
5921099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (err != OK || inbuf == NULL) {
5931099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->release();
5941099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
5951099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
5961099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
5971099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
59872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            size = mbuf->size();
59972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6001099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            memcpy(inbuf->data(), mbuf->data(), size);
60172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
60272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
60372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // video encoder will release MediaBuffer when done
60472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // with underlying data.
6051099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                inbuf->setMediaBufferBase(mbuf);
60672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
60772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->release();
60872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
60972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
61072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            flags = MediaCodec::BUFFER_FLAG_EOS;
61172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
61272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        status_t err = mEncoder->queueInputBuffer(
61472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                bufferIndex, 0, size, timeUs, flags);
61572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
61772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
61872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
61972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
62072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
62272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
62372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::onStart(MetaData *params) {
62572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStopping) {
62672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("Failed to start while we're stopping");
62772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return INVALID_OPERATION;
62872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
62972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
63072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStarted) {
63172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
63272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
63372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            resume();
63472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
63572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
63672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->resume();
63772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
63872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
63972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
64072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
64172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio");
64272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
64372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = OK;
64472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
64572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
64672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t startTimeUs;
64772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
64872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            startTimeUs = -1ll;
64972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
65072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        resume(startTimeUs);
65172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else {
65272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mPuller != NULL);
653c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        sp<MetaData> meta = params;
654c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        if (mSetEncoderFormat) {
655c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            if (meta == NULL) {
656c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar                meta = new MetaData;
657c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            }
658c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            meta->setInt32(kKeyPixelFormat, mEncoderFormat);
659c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            meta->setInt32(kKeyColorSpace, mEncoderDataSpace);
660c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        }
661c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
6621d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> notify = new AMessage(kWhatPullerNotify, mReflector);
663c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        err = mPuller->start(meta.get(), notify);
66472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
66572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
66672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
66772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
66872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
66972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio");
67072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
67172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mStarted = true;
67272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
67372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
67472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
67572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
67672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
67772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPullerNotify:
67872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
67972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MediaBuffer *mbuf;
68072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->findPointer("accessUnit", (void**)&mbuf));
68172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
68272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf == NULL) {
68316e79115e497386eaf010af388627f94314a55a3Chong Zhang            ALOGV("puller (%s) reached EOS",
68472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mIsVideo ? "video" : "audio");
68516e79115e497386eaf010af388627f94314a55a3Chong Zhang            signalEOS();
68672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
68772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
68872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
68972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            ALOGV("got msg '%s' after encoder shutdown.",
69072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                  msg->debugString().c_str());
69172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
69272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mbuf != NULL) {
69372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->release();
69472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
69516e79115e497386eaf010af388627f94314a55a3Chong Zhang
69672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
69772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
69872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
69972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mInputBufferQueue.push_back(mbuf);
70072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
70172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        feedEncoderInputBuffers();
70272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
70372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
70472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
70572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatEncoderActivity:
70672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
70772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
70872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
70972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
71072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7111099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        int32_t cbID;
7121099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        CHECK(msg->findInt32("callbackID", &cbID));
7131099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        if (cbID == MediaCodec::CB_INPUT_AVAILABLE) {
7141099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
7151099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
7161099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7171099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mAvailEncoderInputIndices.push_back(index);
7181099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            feedEncoderInputBuffers();
7191099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) {
7201099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
7211099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t offset;
7221099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t size;
7231099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int64_t timeUs;
7241099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t flags;
7251099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7261099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
7271099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("offset", &offset));
7281099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("size", &size));
7291099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt64("timeUs", &timeUs));
7301099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("flags", &flags));
7311099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7321099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_EOS) {
7331099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mEncoder->releaseOutputBuffer(index);
7341099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
7351099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
7361099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
737f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
7381099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            sp<ABuffer> outbuf;
7391099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getOutputBuffer(index, &outbuf);
7401099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (err != OK || outbuf == NULL) {
7411099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
7421099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
7431099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
744f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
7451099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            MediaBuffer *mbuf = new MediaBuffer(outbuf->size());
7461099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            memcpy(mbuf->data(), outbuf->data(), outbuf->size());
74772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7481099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) {
7491099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                if (mIsVideo) {
7501099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t decodingTimeUs;
7511099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    if (mFlags & FLAG_USE_SURFACE_INPUT) {
7521099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // GraphicBufferSource is supposed to discard samples
7531099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // queued before start, and offset timeUs by start time
7541099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        CHECK_GE(timeUs, 0ll);
7551099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // TODO:
7561099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // Decoding time for surface source is unavailable,
7571099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // use presentation time for now. May need to move
7581099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // this logic into MediaCodec.
7591099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = timeUs;
7601099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    } else {
7611099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        CHECK(!mDecodingTimeQueue.empty());
7621099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = *(mDecodingTimeQueue.begin());
7631099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        mDecodingTimeQueue.erase(mDecodingTimeQueue.begin());
7641099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    }
7651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
76672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7671099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64,
7681099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, decodingTimeUs - timeUs);
7691099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                } else {
7701099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t driftTimeUs = 0;
7711099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#if DEBUG_DRIFT_TIME
7721099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    CHECK(!mDriftTimeQueue.empty());
7731099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    driftTimeUs = *(mDriftTimeQueue.begin());
7741099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mDriftTimeQueue.erase(mDriftTimeQueue.begin());
7751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs);
7761099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#endif // DEBUG_DRIFT_TIME
7771099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64,
7781099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, driftTimeUs);
7791099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                }
7801099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt64(kKeyTime, timeUs);
7811099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            } else {
7821099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true);
7831099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
7841099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
7851099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true);
7861099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
7871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mbuf->setObserver(this);
7881099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mbuf->add_ref();
7891099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7901099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            {
7911099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                Mutex::Autolock autoLock(mOutputBufferLock);
7921099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mOutputBufferQueue.push_back(mbuf);
7931099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mOutputBufferCond.signal();
7941099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
7951099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7961099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mEncoder->releaseOutputBuffer(index);
7971099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       } else if (cbID == MediaCodec::CB_ERROR) {
7981099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err;
7991099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("err", &err));
8001099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            ALOGE("Encoder (%s) reported error : 0x%x",
8011099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mIsVideo ? "video" : "audio", err);
8021099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            signalEOS();
8031099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       }
8041099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       break;
80572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
80672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStart:
80772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
8083f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
80972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
81072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
81172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<RefBase> obj;
81272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->findObject("meta", &obj));
81372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MetaData *params = static_cast<MetaData *>(obj.get());
81472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
81572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> response = new AMessage;
81672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->setInt32("err", onStart(params));
81772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->postReply(replyID);
81872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
81972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
82072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStop:
82172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
82216e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio");
82372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8243f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
82572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
82672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
82716e79115e497386eaf010af388627f94314a55a3Chong Zhang        if (mEncoderReachedEOS) {
82872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // if we already reached EOS, reply and return now
82916e79115e497386eaf010af388627f94314a55a3Chong Zhang            ALOGI("encoder (%s) already stopped",
83072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mIsVideo ? "video" : "audio");
83172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(replyID);
83272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
83372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
83472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
83572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.push_back(replyID);
83672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mStopping) {
83772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // nothing to do if we're already stopping, reply will be posted
83872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // to all when we're stopped.
83972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
84072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
84172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
84272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = true;
84372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
84472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // if using surface, signal source EOS and wait for EOS to come back.
84572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // otherwise, release encoder and post EOS if haven't done already
84672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
84772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mEncoder->signalEndOfInputStream();
84872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
84972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            signalEOS();
85072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
85172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
85272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
85372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPause:
85472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
85572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags && FLAG_USE_SURFACE_INPUT) {
85672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            suspend();
85772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
85872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
85972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->pause();
86072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
86172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
86272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
86372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    default:
86472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        TRESPASS();
86572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
86672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
86772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
86872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} // namespace android
869