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