MediaCodecSource.cpp revision 090ef604f81447eab4aa0a5b45d6307482573560
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>
332e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar#include <media/stagefright/MediaCodecList.h>
34e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MediaCodecSource.h>
3572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaErrors.h>
3672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaSource.h>
37e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MetaData.h>
38e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/PersistentSurface.h>
3972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/Utils.h>
4072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangnamespace android {
4272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnarconst int kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
44c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnarconst int kDefaultSwVideoEncoderDataSpace = HAL_DATASPACE_BT709;
45c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
46ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnarconst int kStopTimeoutUs = 300000; // allow 1 sec for shutting down encoder
47ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
4872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstruct MediaCodecSource::Puller : public AHandler {
49090ef604f81447eab4aa0a5b45d6307482573560Chih-Hung Hsieh    explicit Puller(const sp<MediaSource> &source);
5072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t start(const sp<MetaData> &meta, const sp<AMessage> &notify);
5216e79115e497386eaf010af388627f94314a55a3Chong Zhang    void stop();
53ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    void stopSource();
5472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void pause();
5572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void resume();
5672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
57ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    bool readBuffer(MediaBuffer **buffer);
58ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
5972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprotected:
6072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual void onMessageReceived(const sp<AMessage> &msg);
6172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual ~Puller();
6272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprivate:
6472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    enum {
6572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStart = 'msta',
6672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStop,
6772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatPull,
6872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    };
6972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaSource> mSource;
7172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> mNotify;
7272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<ALooper> mLooper;
7372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mIsAudio;
74ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
75ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    struct Queue {
76ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        Queue()
77ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            : mReadPendingSince(0),
78ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar              mPaused(false),
79ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar              mPulling(false) { }
80ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        int64_t mReadPendingSince;
81ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        bool mPaused;
82ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        bool mPulling;
83ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        Vector<MediaBuffer *> mReadBuffers;
84ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
85ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        void flush();
86ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        // if queue is empty, return false and set *|buffer| to NULL . Otherwise, pop
87ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        // buffer from front of the queue, place it into *|buffer| and return true.
88ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        bool readBuffer(MediaBuffer **buffer);
89ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        // add a buffer to the back of the queue
90ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        void pushBuffer(MediaBuffer *mbuf);
91ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    };
92ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    Mutexed<Queue> mQueue;
9372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
9572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void schedulePull();
9672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void handleEOS();
9772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    DISALLOW_EVIL_CONSTRUCTORS(Puller);
9972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang};
10072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10172cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::Puller(const sp<MediaSource> &source)
10272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mSource(source),
10372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mLooper(new ALooper()),
104ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar      mIsAudio(false)
105ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar{
10672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MetaData> meta = source->getFormat();
10772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    const char *mime;
10872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(meta->findCString(kKeyMIMEType, &mime));
10972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mIsAudio = !strncasecmp(mime, "audio/", 6);
11172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->setName("pull_looper");
11372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
11472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11572cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::~Puller() {
11672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(id());
11772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->stop();
11872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
120ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnarvoid MediaCodecSource::Puller::Queue::pushBuffer(MediaBuffer *mbuf) {
121ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    mReadBuffers.push_back(mbuf);
122ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar}
123ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
124ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnarbool MediaCodecSource::Puller::Queue::readBuffer(MediaBuffer **mbuf) {
125ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    if (mReadBuffers.empty()) {
126ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        *mbuf = NULL;
127ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        return false;
128ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    }
129ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    *mbuf = *mReadBuffers.begin();
130ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    mReadBuffers.erase(mReadBuffers.begin());
131ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    return true;
132ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar}
133ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
134ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnarvoid MediaCodecSource::Puller::Queue::flush() {
135ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    MediaBuffer *mbuf;
136ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    while (readBuffer(&mbuf)) {
137ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        // there are no null buffers in the queue
138ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        mbuf->release();
139ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    }
140ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar}
141ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
142ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnarbool MediaCodecSource::Puller::readBuffer(MediaBuffer **mbuf) {
143ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    Mutexed<Queue>::Locked queue(mQueue);
144ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    return queue->readBuffer(mbuf);
145ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar}
146ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
14772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::postSynchronouslyAndReturnError(
14872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
14972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
15072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
15172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
15372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
15472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
15572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
15772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
15872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
15972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
16072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
16172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
16272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
163ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnarstatus_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, const sp<AMessage> &notify) {
16472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("puller (%s) start", mIsAudio ? "audio" : "video");
16572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->start(
16672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* runOnCallingThread */,
16772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* canCallJava */,
16872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            PRIORITY_AUDIO);
16972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(this);
17072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mNotify = notify;
17172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1721d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStart, this);
17372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", meta);
17472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
17572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
17672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
17716e79115e497386eaf010af388627f94314a55a3Chong Zhangvoid MediaCodecSource::Puller::stop() {
178ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    bool interrupt = false;
179ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    {
180ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        // mark stopping before actually reaching kWhatStop on the looper, so the pulling will
181ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        // stop.
182ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        Mutexed<Queue>::Locked queue(mQueue);
183ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        queue->mPulling = false;
184ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        interrupt = queue->mReadPendingSince && (queue->mReadPendingSince < ALooper::GetNowUs() - 1000000);
185ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        queue->flush(); // flush any unprocessed pulled buffers
186ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    }
18716e79115e497386eaf010af388627f94314a55a3Chong Zhang
188ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    if (interrupt) {
189ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        // call source->stop if read has been pending for over a second
190ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        // TODO: we should really call this if kWhatStop has not returned for more than a second.
191ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        mSource->stop();
192ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    }
193ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar}
19416e79115e497386eaf010af388627f94314a55a3Chong Zhang
195ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnarvoid MediaCodecSource::Puller::stopSource() {
1961d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatStop, this))->post();
19772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
19872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
19972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::pause() {
200ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    Mutexed<Queue>::Locked queue(mQueue);
201ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    queue->mPaused = true;
20272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
20372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::resume() {
205ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    Mutexed<Queue>::Locked queue(mQueue);
206ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    queue->mPaused = false;
20772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
20872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::schedulePull() {
210ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    (new AMessage(kWhatPull, this))->post();
21172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
21272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::handleEOS() {
214ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video");
215ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    sp<AMessage> msg = mNotify->dup();
216ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    msg->setInt32("eos", 1);
217ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    msg->post();
21872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
21972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) {
22172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
22272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStart:
22372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
22472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<RefBase> obj;
22572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->findObject("meta", &obj));
22672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
227ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            {
228ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                Mutexed<Queue>::Locked queue(mQueue);
229ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                queue->mPulling = true;
230ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            }
23172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->start(static_cast<MetaData *>(obj.get()));
23372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err == OK) {
23572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                schedulePull();
23672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
23772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<AMessage> response = new AMessage;
23972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->setInt32("err", err);
24072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2413f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
24272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
24372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->postReply(replyID);
24472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
24572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
24672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStop:
24872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
249ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            mSource->stop();
25072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
25172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
25272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
25372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatPull:
25472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
255ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            Mutexed<Queue>::Locked queue(mQueue);
256ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            queue->mReadPendingSince = ALooper::GetNowUs();
257ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            if (!queue->mPulling) {
258ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                handleEOS();
25972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
26072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
26172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
262ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            queue.unlock();
263ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            MediaBuffer *mbuf = NULL;
26472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->read(&mbuf);
265ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            queue.lock();
26672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
267ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            queue->mReadPendingSince = 0;
268ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            // if we need to discard buffer
269ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            if (!queue->mPulling || queue->mPaused || err != OK) {
270ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                if (mbuf != NULL) {
27172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf->release();
27272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf = NULL;
27372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
274ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                if (queue->mPulling && err == OK) {
275ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                    msg->post(); // if simply paused, keep pulling source
276ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                } else if (err == ERROR_END_OF_STREAM) {
27772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGV("stream ended, mbuf %p", mbuf);
278ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                } else if (err != OK) {
27972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGE("error %d reading stream.", err);
28072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
281ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            }
28272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
283ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            if (mbuf != NULL) {
284ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                queue->pushBuffer(mbuf);
28572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
28672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
287ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            queue.unlock();
28872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
289ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            if (mbuf != NULL) {
290ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                mNotify->post();
291ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                msg->post();
292ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            } else {
293ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                handleEOS();
294ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            }
29572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
29672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
29772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
29872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        default:
29972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            TRESPASS();
30072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
30172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
30272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
303ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos MolnarMediaCodecSource::Output::Output()
304ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    : mEncoderReachedEOS(false),
305ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar      mErrorCode(OK) {
306ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar}
307ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
30872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang// static
30972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<MediaCodecSource> MediaCodecSource::Create(
31072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
31172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &format,
31272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
313e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        const sp<IGraphicBufferConsumer> &consumer,
31472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags) {
31572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaCodecSource> mediaSource =
316e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            new MediaCodecSource(looper, format, source, consumer, flags);
31772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
31872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mediaSource->init() == OK) {
31972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return mediaSource;
32072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
32172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return NULL;
32272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
32372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
32472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::start(MetaData* params) {
3251d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStart, mReflector);
32672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", params);
32772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
32872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
32972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
33072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::stop() {
3311d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStop, mReflector);
332ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    return postSynchronouslyAndReturnError(msg);
33372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
33472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
33572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::pause() {
3361d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPause, mReflector))->post();
33772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
33872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
33972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
34072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() {
34172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
34272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mGraphicBufferProducer;
34372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
34472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
34584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MediaCodecSource::read(
34684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        MediaBuffer** buffer, const ReadOptions* /* options */) {
347ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    Mutexed<Output>::Locked output(mOutput);
34872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
34972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    *buffer = NULL;
350ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    while (output->mBufferQueue.size() == 0 && !output->mEncoderReachedEOS) {
351ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        output.waitForCondition(output->mCond);
35272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
353ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    if (!output->mEncoderReachedEOS) {
354ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        *buffer = *output->mBufferQueue.begin();
355ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        output->mBufferQueue.erase(output->mBufferQueue.begin());
35672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
35772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
358ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    return output->mErrorCode;
35972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
36072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) {
36272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->setObserver(0);
36372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->release();
36472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
36572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36672cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::MediaCodecSource(
36772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
36872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &outputFormat,
36972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
370e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        const sp<IGraphicBufferConsumer> &consumer,
37172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags)
37272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mLooper(looper),
37372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mOutputFormat(outputFormat),
37472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mMeta(new MetaData),
37572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFlags(flags),
37672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mIsVideo(false),
37772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStarted(false),
37872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStopping(false),
37972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mDoMoreWorkPending(false),
380c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mSetEncoderFormat(false),
381c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mEncoderFormat(0),
382c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mEncoderDataSpace(0),
383e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang      mGraphicBufferConsumer(consumer),
38472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFirstSampleTimeUs(-1ll),
385ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar      mGeneration(0) {
38672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mLooper != NULL);
38772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString mime;
38972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &mime));
39072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!strncasecmp("video/", mime.c_str(), 6)) {
39272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mIsVideo = true;
39372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
39472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
39672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mPuller = new Puller(source);
39772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
39872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
39972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40072cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::~MediaCodecSource() {
40172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    releaseEncoder();
40272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->stop();
40472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(mReflector->id());
40572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
40672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::init() {
40872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = initEncoder();
40972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
41172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        releaseEncoder();
41272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
41372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
41572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
41672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::initEncoder() {
41872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mReflector = new AHandlerReflector<MediaCodecSource>(this);
41972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(mReflector);
42072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper = new ALooper;
42272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->setName("codec_looper");
42372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->start();
42472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_METADATA_INPUT) {
42672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("store-metadata-in-buffers", 1);
42772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
42872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
43072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("create-input-buffers-suspended", 1);
43172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
43272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString outputMIME;
43472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &outputMIME));
43572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4362e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar    Vector<AString> matchingCodecs;
4372e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar    MediaCodecList::findMatchingCodecs(
4382e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar            outputMIME.c_str(), true /* encoder */,
4392e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar            ((mFlags & FLAG_PREFER_SOFTWARE_CODEC) ? MediaCodecList::kPreferSoftwareCodecs : 0),
4402e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar            &matchingCodecs);
44172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4422e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar    status_t err = NO_INIT;
4432e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar    for (size_t ix = 0; ix < matchingCodecs.size(); ++ix) {
4442e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar        mEncoder = MediaCodec::CreateByComponentName(
4452e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar                mCodecLooper, matchingCodecs[ix]);
4462e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar
4472e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar        if (mEncoder == NULL) {
4482e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar            continue;
4492e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar        }
4502e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar
4512e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar        ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
45272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4532e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar        mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector);
4542e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar        mEncoder->setCallback(mEncoderActivityNotify);
45572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4562e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar        err = mEncoder->configure(
4572e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar                    mOutputFormat,
4582e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar                    NULL /* nativeWindow */,
4592e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar                    NULL /* crypto */,
4602e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar                    MediaCodec::CONFIGURE_FLAG_ENCODE);
461421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen
4622e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar        if (err == OK) {
4632e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar            break;
4642e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar        }
4652e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar        mEncoder->release();
4662e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar        mEncoder = NULL;
4672e18508d33b845ef77676559d3bb70acc37b39eeLajos Molnar    }
46872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
47072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
47172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
47272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->getOutputFormat(&mOutputFormat);
47472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    convertMessageToMetaData(mOutputFormat, mMeta);
47572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
47772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mIsVideo);
47872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
479e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        if (mGraphicBufferConsumer != NULL) {
480e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // When using persistent surface, we are only interested in the
481e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // consumer, but have to use PersistentSurface as a wrapper to
482e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // pass consumer over messages (similar to BufferProducerWrapper)
4838f469e18c307cb9dc0d16ed9225972aa8be4516fChong Zhang            err = mEncoder->setInputSurface(
484e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang                    new PersistentSurface(NULL, mGraphicBufferConsumer));
485e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        } else {
486e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            err = mEncoder->createInputSurface(&mGraphicBufferProducer);
487e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        }
48872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
48972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
49072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
49172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
49272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
49372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
494c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    sp<AMessage> inputFormat;
495c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    int32_t usingSwReadOften;
496c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    mSetEncoderFormat = false;
497c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    if (mEncoder->getInputFormat(&inputFormat) == OK
498c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            && inputFormat->findInt32("using-sw-read-often", &usingSwReadOften)
499c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            && usingSwReadOften) {
500c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        // this is a SW encoder; signal source to allocate SW readable buffers
501c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        mSetEncoderFormat = true;
502c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        mEncoderFormat = kDefaultSwVideoEncoderFormat;
503c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        mEncoderDataSpace = kDefaultSwVideoEncoderDataSpace;
504c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    }
505c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
5061099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan    err = mEncoder->start();
50772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
50872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
50972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
51072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
51172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
512ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    {
513ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        Mutexed<Output>::Locked output(mOutput);
514ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        output->mEncoderReachedEOS = false;
515ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        output->mErrorCode = OK;
516ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    }
51772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
51872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
51972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
52072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
52172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::releaseEncoder() {
52272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder == NULL) {
52372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return;
52472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
52572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
52672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->release();
52772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder.clear();
52872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
52972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
53072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::postSynchronouslyAndReturnError(
53172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
53272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
53372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
53472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
53572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
53672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
53772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
53872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
53972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
54072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
54172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
54272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
54372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
54472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
54572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
54672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalEOS(status_t err) {
547ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    bool reachedEOS = false;
548ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    {
549ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        Mutexed<Output>::Locked output(mOutput);
550ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        reachedEOS = output->mEncoderReachedEOS;
551ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        if (!reachedEOS) {
552ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio");
55372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // release all unread media buffers
554ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            for (List<MediaBuffer*>::iterator it = output->mBufferQueue.begin();
555ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                    it != output->mBufferQueue.end(); it++) {
55672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                (*it)->release();
55772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
558ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            output->mBufferQueue.clear();
559ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            output->mEncoderReachedEOS = true;
560ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            output->mErrorCode = err;
561ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            output->mCond.signal();
562ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
563ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            reachedEOS = true;
564ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            output.unlock();
565ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            releaseEncoder();
56672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
56772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
568ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
569ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    if (mStopping && reachedEOS) {
57016e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio");
571ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        mPuller->stopSource();
572ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
57372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // posting reply to everyone that's waiting
5743f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        List<sp<AReplyToken>>::iterator it;
57572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        for (it = mStopReplyIDQueue.begin();
57672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                it != mStopReplyIDQueue.end(); it++) {
57772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(*it);
57872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
57972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.clear();
58072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = false;
581ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        ++mGeneration;
58272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
58372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
58472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
58572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::suspend() {
58672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
58772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
58872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
58972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", true);
59072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
59172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
59272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
59372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
59472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::resume(int64_t skipFramesBeforeUs) {
59572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
59672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
59772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
59872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", false);
59972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (skipFramesBeforeUs > 0) {
60072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            params->setInt64("skip-frames-before", skipFramesBeforeUs);
60172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
60272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
60372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
60472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
60572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
60672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::feedEncoderInputBuffers() {
607ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    MediaBuffer* mbuf = NULL;
608ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    while (!mAvailEncoderInputIndices.empty() && mPuller->readBuffer(&mbuf)) {
60972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t bufferIndex = *mAvailEncoderInputIndices.begin();
61072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
61172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t timeUs = 0ll;
61372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags = 0;
61472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t size = 0;
61572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf != NULL) {
61772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
61872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // push decoding time for video, or drift time for audio
62072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
62172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDecodingTimeQueue.push_back(timeUs);
62272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
62372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME
62472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mFirstSampleTimeUs < 0ll) {
62572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mFirstSampleTimeUs = timeUs;
62672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
62772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                int64_t driftTimeUs = 0;
62972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs)
63072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        && driftTimeUs) {
63172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs;
63272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
63372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDriftTimeQueue.push_back(driftTimeUs);
63472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME
63572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
63672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6371099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            sp<ABuffer> inbuf;
6381099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
6391099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (err != OK || inbuf == NULL) {
6401099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->release();
6411099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
6421099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
6431099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
6441099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
64572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            size = mbuf->size();
64672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6471099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            memcpy(inbuf->data(), mbuf->data(), size);
64872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
64972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
65072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // video encoder will release MediaBuffer when done
65172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // with underlying data.
6521099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                inbuf->setMediaBufferBase(mbuf);
65372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
65472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->release();
65572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
65672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
65772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            flags = MediaCodec::BUFFER_FLAG_EOS;
65872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
65972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
66072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        status_t err = mEncoder->queueInputBuffer(
66172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                bufferIndex, 0, size, timeUs, flags);
66272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
66372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
66472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
66572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
66672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
66772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
66872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
66972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
67072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
67172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::onStart(MetaData *params) {
67272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStopping) {
67372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("Failed to start while we're stopping");
67472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return INVALID_OPERATION;
67572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
67672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
67772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStarted) {
67872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
67972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
68072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            resume();
68172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
68272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
68372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->resume();
68472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
68572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
68672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
68772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
68872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio");
68972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
69072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = OK;
69172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
69272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
69372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t startTimeUs;
69472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
69572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            startTimeUs = -1ll;
69672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
69772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        resume(startTimeUs);
69872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else {
69972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mPuller != NULL);
700c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        sp<MetaData> meta = params;
701c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        if (mSetEncoderFormat) {
702c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            if (meta == NULL) {
703c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar                meta = new MetaData;
704c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            }
705c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            meta->setInt32(kKeyPixelFormat, mEncoderFormat);
706c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            meta->setInt32(kKeyColorSpace, mEncoderDataSpace);
707c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        }
708c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
7091d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> notify = new AMessage(kWhatPullerNotify, mReflector);
710c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        err = mPuller->start(meta.get(), notify);
71172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
71272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
71372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
71472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
71572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
71672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio");
71772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
71872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mStarted = true;
71972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
72072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
72172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
72272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
72372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
72472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPullerNotify:
72572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
726ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        int32_t eos = 0;
727ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        if (msg->findInt32("eos", &eos) && eos) {
728ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            ALOGV("puller (%s) reached EOS", mIsVideo ? "video" : "audio");
72916e79115e497386eaf010af388627f94314a55a3Chong Zhang            signalEOS();
730ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            break;
73172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
73272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
73372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
734ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            ALOGV("got msg '%s' after encoder shutdown.", msg->debugString().c_str());
73572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
73672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
73772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
73872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        feedEncoderInputBuffers();
73972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
74072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
74172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatEncoderActivity:
74272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
74372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
74472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
74572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
74672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7471099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        int32_t cbID;
7481099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        CHECK(msg->findInt32("callbackID", &cbID));
7491099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        if (cbID == MediaCodec::CB_INPUT_AVAILABLE) {
7501099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
7511099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
7521099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7531099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mAvailEncoderInputIndices.push_back(index);
7541099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            feedEncoderInputBuffers();
7551099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) {
7561099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
7571099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t offset;
7581099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t size;
7591099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int64_t timeUs;
7601099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t flags;
7611099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7621099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
7631099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("offset", &offset));
7641099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("size", &size));
7651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt64("timeUs", &timeUs));
7661099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("flags", &flags));
7671099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7681099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_EOS) {
7691099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mEncoder->releaseOutputBuffer(index);
7701099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
7711099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
7721099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
773f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
7741099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            sp<ABuffer> outbuf;
7751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getOutputBuffer(index, &outbuf);
7761099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (err != OK || outbuf == NULL) {
7771099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
7781099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
7791099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
780f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
7811099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            MediaBuffer *mbuf = new MediaBuffer(outbuf->size());
7821099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            memcpy(mbuf->data(), outbuf->data(), outbuf->size());
78372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7841099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) {
7851099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                if (mIsVideo) {
7861099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t decodingTimeUs;
7871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    if (mFlags & FLAG_USE_SURFACE_INPUT) {
7881099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // GraphicBufferSource is supposed to discard samples
7891099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // queued before start, and offset timeUs by start time
7901099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        CHECK_GE(timeUs, 0ll);
7911099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // TODO:
7921099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // Decoding time for surface source is unavailable,
7931099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // use presentation time for now. May need to move
7941099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // this logic into MediaCodec.
7951099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = timeUs;
7961099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    } else {
7971099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        CHECK(!mDecodingTimeQueue.empty());
7981099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = *(mDecodingTimeQueue.begin());
7991099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        mDecodingTimeQueue.erase(mDecodingTimeQueue.begin());
8001099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    }
8011099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
80272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8031099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64,
8041099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, decodingTimeUs - timeUs);
8051099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                } else {
8061099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t driftTimeUs = 0;
8071099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#if DEBUG_DRIFT_TIME
8081099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    CHECK(!mDriftTimeQueue.empty());
8091099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    driftTimeUs = *(mDriftTimeQueue.begin());
8101099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mDriftTimeQueue.erase(mDriftTimeQueue.begin());
8111099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs);
8121099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#endif // DEBUG_DRIFT_TIME
8131099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64,
8141099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, driftTimeUs);
8151099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                }
8161099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt64(kKeyTime, timeUs);
8171099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            } else {
8181099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true);
8191099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
8201099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
8211099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true);
8221099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
8231099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mbuf->setObserver(this);
8241099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mbuf->add_ref();
8251099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
8261099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            {
827ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                Mutexed<Output>::Locked output(mOutput);
828ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                output->mBufferQueue.push_back(mbuf);
829ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar                output->mCond.signal();
8301099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
8311099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
8321099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mEncoder->releaseOutputBuffer(index);
8331099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       } else if (cbID == MediaCodec::CB_ERROR) {
8341099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err;
8351099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("err", &err));
8361099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            ALOGE("Encoder (%s) reported error : 0x%x",
8371099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mIsVideo ? "video" : "audio", err);
8381099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            signalEOS();
8391099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       }
8401099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       break;
84172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
84272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStart:
84372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
8443f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
84572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
84672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
84772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<RefBase> obj;
84872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->findObject("meta", &obj));
84972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MetaData *params = static_cast<MetaData *>(obj.get());
85072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
85172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> response = new AMessage;
85272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->setInt32("err", onStart(params));
85372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->postReply(replyID);
85472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
85572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
85672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStop:
85772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
85816e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio");
85972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8603f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
86172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
86272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
863ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        if (mOutput.lock()->mEncoderReachedEOS) {
86472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // if we already reached EOS, reply and return now
86516e79115e497386eaf010af388627f94314a55a3Chong Zhang            ALOGI("encoder (%s) already stopped",
86672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mIsVideo ? "video" : "audio");
86772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(replyID);
86872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
86972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
87072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
87172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.push_back(replyID);
87272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mStopping) {
87372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // nothing to do if we're already stopping, reply will be posted
87472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // to all when we're stopped.
87572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
87672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
87772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
87872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = true;
87972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
88072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // if using surface, signal source EOS and wait for EOS to come back.
881ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        // otherwise, stop puller (which also clears the input buffer queue)
882ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        // and wait for the EOS message. We cannot call source->stop() because
883ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        // the encoder may still be processing input buffers.
88472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
88572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mEncoder->signalEndOfInputStream();
88672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
887ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            mPuller->stop();
88872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
889ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
890ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        // complete stop even if encoder/puller stalled
891ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        sp<AMessage> timeoutMsg = new AMessage(kWhatStopStalled, mReflector);
892ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        timeoutMsg->setInt32("generation", mGeneration);
893ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        timeoutMsg->post(kStopTimeoutUs);
89472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
89572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
896ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
897ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    case kWhatStopStalled:
898ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    {
899ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        int32_t generation;
900ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        CHECK(msg->findInt32("generation", &generation));
901ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        if (generation != mGeneration) {
902ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar             break;
903ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        }
904ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
905ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
906ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            ALOGV("source (%s) stopping", mIsVideo ? "video" : "audio");
907ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            mPuller->stopSource();
908ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar            ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
909ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        }
910ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        signalEOS();
911ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar    }
912ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar
91372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPause:
91472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
915ea1a45dbdf7fd6f435f92d20a95f432cf3f147b5Lajos Molnar        if (mFlags & FLAG_USE_SURFACE_INPUT) {
91672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            suspend();
91772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
91872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
91972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->pause();
92072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
92172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
92272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
92372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    default:
92472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        TRESPASS();
92572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
92672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
92772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
92872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} // namespace android
929