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>
26bc8f53b8c1c220d9ce01526b6e3834f14af98ed5Dongwon Kang#include <media/MediaBufferHolder.h>
277e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim#include <media/MediaCodecBuffer.h>
28d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/MediaSource.h>
2972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ABuffer.h>
3072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ADebug.h>
3172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ALooper.h>
3272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/AMessage.h>
3372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaBuffer.h>
3472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodec.h>
3516fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar#include <media/stagefright/MediaCodecList.h>
36e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MediaCodecSource.h>
3772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaErrors.h>
38e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MetaData.h>
3972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/Utils.h>
4072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangnamespace android {
4272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnarconst int32_t kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
44b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnarconst int32_t kDefaultHwVideoEncoderFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
452cbf6cea23539bfe99e36d1d221de62255452e86Eino-Ville Talvalaconst int32_t kDefaultVideoEncoderDataSpace = HAL_DATASPACE_V0_BT709;
46c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
476a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarconst int kStopTimeoutUs = 300000; // allow 1 sec for shutting down encoder
48cf3205fab08adfdc9d5c0fef1cef54cab0074117Hangyu Kuang// allow maximum 1 sec for stop time offset. This limits the the delay in the
49cf3205fab08adfdc9d5c0fef1cef54cab0074117Hangyu Kuang// input source.
50cf3205fab08adfdc9d5c0fef1cef54cab0074117Hangyu Kuangconst int kMaxStopTimeOffsetUs = 1000000;
516a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
5272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstruct MediaCodecSource::Puller : public AHandler {
53090ef604f81447eab4aa0a5b45d6307482573560Chih-Hung Hsieh    explicit Puller(const sp<MediaSource> &source);
5472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5572e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    void interruptSource();
5672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t start(const sp<MetaData> &meta, const sp<AMessage> &notify);
5716e79115e497386eaf010af388627f94314a55a3Chong Zhang    void stop();
586a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    void stopSource();
5972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void pause();
6072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void resume();
61f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    status_t setStopTimeUs(int64_t stopTimeUs);
621889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    bool readBuffer(MediaBufferBase **buffer);
636a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
6472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprotected:
6572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual void onMessageReceived(const sp<AMessage> &msg);
6672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual ~Puller();
6772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprivate:
6972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    enum {
7072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStart = 'msta',
7172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStop,
7272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatPull,
73f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        kWhatSetStopTimeUs,
7472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    };
7572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaSource> mSource;
7772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> mNotify;
7872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<ALooper> mLooper;
7972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mIsAudio;
806a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
816a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    struct Queue {
826a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Queue()
836a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            : mReadPendingSince(0),
846a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar              mPaused(false),
856a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar              mPulling(false) { }
866a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        int64_t mReadPendingSince;
876a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        bool mPaused;
886a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        bool mPulling;
891889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang        Vector<MediaBufferBase *> mReadBuffers;
906a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
916a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        void flush();
926a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // if queue is empty, return false and set *|buffer| to NULL . Otherwise, pop
9372e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar        // buffer from front of the queue, place it into *|buffer| and return true.
941889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang        bool readBuffer(MediaBufferBase **buffer);
9572e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar        // add a buffer to the back of the queue
961889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang        void pushBuffer(MediaBufferBase *mbuf);
976a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    };
986a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Queue> mQueue;
9972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
10172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void schedulePull();
10272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void handleEOS();
10372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    DISALLOW_EVIL_CONSTRUCTORS(Puller);
10572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang};
10672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10772cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::Puller(const sp<MediaSource> &source)
10872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mSource(source),
10972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mLooper(new ALooper()),
1106a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar      mIsAudio(false)
1116a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar{
11272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MetaData> meta = source->getFormat();
11372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    const char *mime;
11472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(meta->findCString(kKeyMIMEType, &mime));
11572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mIsAudio = !strncasecmp(mime, "audio/", 6);
11772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->setName("pull_looper");
11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
12072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
12172cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::~Puller() {
12272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(id());
12372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->stop();
12472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
12572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1261889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kangvoid MediaCodecSource::Puller::Queue::pushBuffer(MediaBufferBase *mbuf) {
1276a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    mReadBuffers.push_back(mbuf);
1286a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
1296a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
1301889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kangbool MediaCodecSource::Puller::Queue::readBuffer(MediaBufferBase **mbuf) {
1316a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    if (mReadBuffers.empty()) {
1326a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        *mbuf = NULL;
1336a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        return false;
1346a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
1356a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    *mbuf = *mReadBuffers.begin();
1366a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    mReadBuffers.erase(mReadBuffers.begin());
1376a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    return true;
1386a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
1396a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
1406a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarvoid MediaCodecSource::Puller::Queue::flush() {
1411889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    MediaBufferBase *mbuf;
1426a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    while (readBuffer(&mbuf)) {
1436a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // there are no null buffers in the queue
1446a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        mbuf->release();
1456a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
1466a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
1476a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
1481889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kangbool MediaCodecSource::Puller::readBuffer(MediaBufferBase **mbuf) {
1496a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Queue>::Locked queue(mQueue);
1506a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    return queue->readBuffer(mbuf);
1516a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
1526a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
15372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::postSynchronouslyAndReturnError(
15472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
15572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
15672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
15772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
15972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
16072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
16172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
16272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
16372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
16472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
16572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
16672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
16772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
16872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
169f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuangstatus_t MediaCodecSource::Puller::setStopTimeUs(int64_t stopTimeUs) {
170f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    sp<AMessage> msg = new AMessage(kWhatSetStopTimeUs, this);
171f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    msg->setInt64("stop-time-us", stopTimeUs);
172f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    return postSynchronouslyAndReturnError(msg);
173f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang}
174f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
1756a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarstatus_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, const sp<AMessage> &notify) {
17672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("puller (%s) start", mIsAudio ? "audio" : "video");
17772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->start(
17872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* runOnCallingThread */,
17972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* canCallJava */,
18072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            PRIORITY_AUDIO);
18172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(this);
18272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mNotify = notify;
18372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1841d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStart, this);
18572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", meta);
18672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
18772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
18872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
18916e79115e497386eaf010af388627f94314a55a3Chong Zhangvoid MediaCodecSource::Puller::stop() {
1906a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    bool interrupt = false;
1916a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    {
1926a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // mark stopping before actually reaching kWhatStop on the looper, so the pulling will
1936a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // stop.
1946a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Mutexed<Queue>::Locked queue(mQueue);
1956a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        queue->mPulling = false;
1966a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        interrupt = queue->mReadPendingSince && (queue->mReadPendingSince < ALooper::GetNowUs() - 1000000);
1976a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        queue->flush(); // flush any unprocessed pulled buffers
1986a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
19916e79115e497386eaf010af388627f94314a55a3Chong Zhang
2006a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    if (interrupt) {
20172e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar        interruptSource();
2026a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
2036a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
20416e79115e497386eaf010af388627f94314a55a3Chong Zhang
20572e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnarvoid MediaCodecSource::Puller::interruptSource() {
20672e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    // call source->stop if read has been pending for over a second
20772e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    // We have to call this outside the looper as looper is pending on the read.
20872e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    mSource->stop();
20972e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar}
21072e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar
2116a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarvoid MediaCodecSource::Puller::stopSource() {
21272e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStop, this);
21372e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    (void)postSynchronouslyAndReturnError(msg);
21472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
21572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::pause() {
2176a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Queue>::Locked queue(mQueue);
2186a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    queue->mPaused = true;
21972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
22072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::resume() {
2226a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Queue>::Locked queue(mQueue);
2236a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    queue->mPaused = false;
22472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
22572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::schedulePull() {
2276a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    (new AMessage(kWhatPull, this))->post();
22872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
22972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::handleEOS() {
2316a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video");
2326a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    sp<AMessage> msg = mNotify->dup();
2336a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    msg->setInt32("eos", 1);
2346a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    msg->post();
23572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
23672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) {
23872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
23972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStart:
24072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
24172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<RefBase> obj;
24272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->findObject("meta", &obj));
24372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2446a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            {
2456a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                Mutexed<Queue>::Locked queue(mQueue);
2466a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                queue->mPulling = true;
2476a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            }
24872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->start(static_cast<MetaData *>(obj.get()));
25072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
25172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err == OK) {
25272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                schedulePull();
25372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
25472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
25572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<AMessage> response = new AMessage;
25672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->setInt32("err", err);
25772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2583f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
25972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
26072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->postReply(replyID);
26172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
26272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
26372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
264f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        case kWhatSetStopTimeUs:
265f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        {
266f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang            sp<AReplyToken> replyID;
267f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang            CHECK(msg->senderAwaitsResponse(&replyID));
268f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang            int64_t stopTimeUs;
269f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang            CHECK(msg->findInt64("stop-time-us", &stopTimeUs));
270f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang            status_t err = mSource->setStopTimeUs(stopTimeUs);
271f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
272f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang            sp<AMessage> response = new AMessage;
273f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang            response->setInt32("err", err);
274f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang            response->postReply(replyID);
275f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang            break;
276f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        }
277f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang
27872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStop:
27972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
2806a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            mSource->stop();
28172e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar
28272e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            sp<AMessage> response = new AMessage;
28372e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            response->setInt32("err", OK);
28472e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar
28572e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            sp<AReplyToken> replyID;
28672e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
28772e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            response->postReply(replyID);
28872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
28972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
29072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
29172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatPull:
29272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
2936a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            Mutexed<Queue>::Locked queue(mQueue);
2946a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue->mReadPendingSince = ALooper::GetNowUs();
2956a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            if (!queue->mPulling) {
2966a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                handleEOS();
29772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
29872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
29972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3006a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue.unlock();
3011889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang            MediaBufferBase *mbuf = NULL;
30272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->read(&mbuf);
3036a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue.lock();
30472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3056a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue->mReadPendingSince = 0;
3066a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            // if we need to discard buffer
3076a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            if (!queue->mPulling || queue->mPaused || err != OK) {
3086a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                if (mbuf != NULL) {
30972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf->release();
31072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf = NULL;
31172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
3126a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                if (queue->mPulling && err == OK) {
3136a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                    msg->post(); // if simply paused, keep pulling source
3146d6c21b8d2ed66007833dae0451b0a211c97e592Wonsik Kim                    break;
3156a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                } else if (err == ERROR_END_OF_STREAM) {
31672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGV("stream ended, mbuf %p", mbuf);
3176a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                } else if (err != OK) {
31872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGE("error %d reading stream.", err);
31972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
3206a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            }
32172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3226a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            if (mbuf != NULL) {
3236a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                queue->pushBuffer(mbuf);
32472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
32572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3266a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue.unlock();
32772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3286a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            if (mbuf != NULL) {
3296a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                mNotify->post();
3306a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                msg->post();
3316a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            } else {
3326a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                handleEOS();
3336a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            }
33472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
33572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
33672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
33772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        default:
33872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            TRESPASS();
33972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
34072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
34172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3426a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos MolnarMediaCodecSource::Output::Output()
3436a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    : mEncoderReachedEOS(false),
3446a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar      mErrorCode(OK) {
3456a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
3466a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
34772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang// static
34872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<MediaCodecSource> MediaCodecSource::Create(
34972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
35072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &format,
35172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
352addf2cbb120346ae42e78fa739245a353db5edadChong Zhang        const sp<PersistentSurface> &persistentSurface,
35372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags) {
354addf2cbb120346ae42e78fa739245a353db5edadChong Zhang    sp<MediaCodecSource> mediaSource = new MediaCodecSource(
355addf2cbb120346ae42e78fa739245a353db5edadChong Zhang            looper, format, source, persistentSurface, flags);
35672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mediaSource->init() == OK) {
35872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return mediaSource;
35972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
36072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return NULL;
36172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
36272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36361fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuangstatus_t MediaCodecSource::setInputBufferTimeOffset(int64_t timeOffsetUs) {
364d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    sp<AMessage> msg = new AMessage(kWhatSetInputBufferTimeOffset, mReflector);
365d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    msg->setInt64("time-offset-us", timeOffsetUs);
36661fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang    return postSynchronouslyAndReturnError(msg);
367d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim}
368d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim
369a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kimint64_t MediaCodecSource::getFirstSampleSystemTimeUs() {
370a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    sp<AMessage> msg = new AMessage(kWhatGetFirstSampleSystemTimeUs, mReflector);
371a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    sp<AMessage> response;
372a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    msg->postAndAwaitResponse(&response);
373a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    int64_t timeUs;
374a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    if (!response->findInt64("time-us", &timeUs)) {
375a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        timeUs = -1ll;
376a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    }
377a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    return timeUs;
378a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim}
379a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim
38072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::start(MetaData* params) {
3811d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStart, mReflector);
38272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", params);
38372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
38472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
38572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::stop() {
3871d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStop, mReflector);
3886a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    return postSynchronouslyAndReturnError(msg);
38972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
39072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
391764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang
392f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuangstatus_t MediaCodecSource::setStopTimeUs(int64_t stopTimeUs) {
393f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    sp<AMessage> msg = new AMessage(kWhatSetStopTimeUs, mReflector);
394764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    msg->setInt64("stop-time-us", stopTimeUs);
395764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    return postSynchronouslyAndReturnError(msg);
396764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang}
397764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang
398764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuangstatus_t MediaCodecSource::pause(MetaData* params) {
399764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    sp<AMessage> msg = new AMessage(kWhatPause, mReflector);
400764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    msg->setObject("meta", params);
401764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    msg->post();
40272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
40372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
40472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
405ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnarsp<MetaData> MediaCodecSource::getFormat() {
406ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    Mutexed<sp<MetaData>>::Locked meta(mMeta);
407ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    return *meta;
408ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar}
409ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar
41072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() {
41172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
41272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mGraphicBufferProducer;
41372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
41472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MediaCodecSource::read(
4161889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang        MediaBufferBase** buffer, const ReadOptions* /* options */) {
4176a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Output>::Locked output(mOutput);
41872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    *buffer = NULL;
4206a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    while (output->mBufferQueue.size() == 0 && !output->mEncoderReachedEOS) {
4216a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        output.waitForCondition(output->mCond);
42272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
4236a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    if (!output->mEncoderReachedEOS) {
4246a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        *buffer = *output->mBufferQueue.begin();
4256a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        output->mBufferQueue.erase(output->mBufferQueue.begin());
42672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
42772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
4286a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    return output->mErrorCode;
42972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
43072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4311889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kangvoid MediaCodecSource::signalBufferReturned(MediaBufferBase *buffer) {
43272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->setObserver(0);
43372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->release();
43472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
43572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43672cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::MediaCodecSource(
43772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
43872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &outputFormat,
43972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
440addf2cbb120346ae42e78fa739245a353db5edadChong Zhang        const sp<PersistentSurface> &persistentSurface,
44172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags)
44272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mLooper(looper),
44372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mOutputFormat(outputFormat),
44472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mMeta(new MetaData),
44572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFlags(flags),
44672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mIsVideo(false),
44772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStarted(false),
44872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStopping(false),
44972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mDoMoreWorkPending(false),
450c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mSetEncoderFormat(false),
451c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mEncoderFormat(0),
452c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mEncoderDataSpace(0),
453addf2cbb120346ae42e78fa739245a353db5edadChong Zhang      mPersistentSurface(persistentSurface),
454d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim      mInputBufferTimeOffsetUs(0),
455a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim      mFirstSampleSystemTimeUs(-1ll),
456a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim      mPausePending(false),
45772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFirstSampleTimeUs(-1ll),
4586a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar      mGeneration(0) {
45972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mLooper != NULL);
46072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
46272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mPuller = new Puller(source);
46372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
46472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
46572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46672cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::~MediaCodecSource() {
46772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    releaseEncoder();
46872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->stop();
47072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(mReflector->id());
47172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
47272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::init() {
47472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = initEncoder();
47572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
47772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        releaseEncoder();
47872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
47972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
48072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
48172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
48272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
48372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::initEncoder() {
48420db1647e6062631e93f8040a352950b5960dd8eWonsik Kim
48572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mReflector = new AHandlerReflector<MediaCodecSource>(this);
48672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(mReflector);
48772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
48872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper = new ALooper;
48972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->setName("codec_looper");
49072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->start();
49172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
49272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
49372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("create-input-buffers-suspended", 1);
49472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
49572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
49672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString outputMIME;
49772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &outputMIME));
49820db1647e6062631e93f8040a352950b5960dd8eWonsik Kim    mIsVideo = outputMIME.startsWithIgnoreCase("video/");
49972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
50020db1647e6062631e93f8040a352950b5960dd8eWonsik Kim    AString name;
50116fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar    status_t err = NO_INIT;
50220db1647e6062631e93f8040a352950b5960dd8eWonsik Kim    if (mOutputFormat->findString("testing-name", &name)) {
50320db1647e6062631e93f8040a352950b5960dd8eWonsik Kim        mEncoder = MediaCodec::CreateByComponentName(mCodecLooper, name);
50472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
50516fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector);
50616fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        mEncoder->setCallback(mEncoderActivityNotify);
50772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
50816fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        err = mEncoder->configure(
50916fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                    mOutputFormat,
51016fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                    NULL /* nativeWindow */,
51116fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                    NULL /* crypto */,
51216fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                    MediaCodec::CONFIGURE_FLAG_ENCODE);
51320db1647e6062631e93f8040a352950b5960dd8eWonsik Kim    } else {
51420db1647e6062631e93f8040a352950b5960dd8eWonsik Kim        Vector<AString> matchingCodecs;
51520db1647e6062631e93f8040a352950b5960dd8eWonsik Kim        MediaCodecList::findMatchingCodecs(
51620db1647e6062631e93f8040a352950b5960dd8eWonsik Kim                outputMIME.c_str(), true /* encoder */,
51720db1647e6062631e93f8040a352950b5960dd8eWonsik Kim                ((mFlags & FLAG_PREFER_SOFTWARE_CODEC) ? MediaCodecList::kPreferSoftwareCodecs : 0),
51820db1647e6062631e93f8040a352950b5960dd8eWonsik Kim                &matchingCodecs);
51920db1647e6062631e93f8040a352950b5960dd8eWonsik Kim
52020db1647e6062631e93f8040a352950b5960dd8eWonsik Kim        for (size_t ix = 0; ix < matchingCodecs.size(); ++ix) {
52120db1647e6062631e93f8040a352950b5960dd8eWonsik Kim            mEncoder = MediaCodec::CreateByComponentName(
52220db1647e6062631e93f8040a352950b5960dd8eWonsik Kim                    mCodecLooper, matchingCodecs[ix]);
52320db1647e6062631e93f8040a352950b5960dd8eWonsik Kim
52420db1647e6062631e93f8040a352950b5960dd8eWonsik Kim            if (mEncoder == NULL) {
52520db1647e6062631e93f8040a352950b5960dd8eWonsik Kim                continue;
52620db1647e6062631e93f8040a352950b5960dd8eWonsik Kim            }
527421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen
52820db1647e6062631e93f8040a352950b5960dd8eWonsik Kim            ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
52920db1647e6062631e93f8040a352950b5960dd8eWonsik Kim
53020db1647e6062631e93f8040a352950b5960dd8eWonsik Kim            mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector);
53120db1647e6062631e93f8040a352950b5960dd8eWonsik Kim            mEncoder->setCallback(mEncoderActivityNotify);
53220db1647e6062631e93f8040a352950b5960dd8eWonsik Kim
53320db1647e6062631e93f8040a352950b5960dd8eWonsik Kim            err = mEncoder->configure(
53420db1647e6062631e93f8040a352950b5960dd8eWonsik Kim                        mOutputFormat,
53520db1647e6062631e93f8040a352950b5960dd8eWonsik Kim                        NULL /* nativeWindow */,
53620db1647e6062631e93f8040a352950b5960dd8eWonsik Kim                        NULL /* crypto */,
53720db1647e6062631e93f8040a352950b5960dd8eWonsik Kim                        MediaCodec::CONFIGURE_FLAG_ENCODE);
53820db1647e6062631e93f8040a352950b5960dd8eWonsik Kim
53920db1647e6062631e93f8040a352950b5960dd8eWonsik Kim            if (err == OK) {
54020db1647e6062631e93f8040a352950b5960dd8eWonsik Kim                break;
54120db1647e6062631e93f8040a352950b5960dd8eWonsik Kim            }
54220db1647e6062631e93f8040a352950b5960dd8eWonsik Kim            mEncoder->release();
54320db1647e6062631e93f8040a352950b5960dd8eWonsik Kim            mEncoder = NULL;
54416fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        }
54516fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar    }
54672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
54772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
54872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
54972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
55072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
55172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->getOutputFormat(&mOutputFormat);
552ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    sp<MetaData> meta = new MetaData;
553ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    convertMessageToMetaData(mOutputFormat, meta);
554ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    mMeta.lock().set(meta);
55572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
55672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
55772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mIsVideo);
55872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
559addf2cbb120346ae42e78fa739245a353db5edadChong Zhang        if (mPersistentSurface != NULL) {
560e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // When using persistent surface, we are only interested in the
561e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // consumer, but have to use PersistentSurface as a wrapper to
562e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // pass consumer over messages (similar to BufferProducerWrapper)
563addf2cbb120346ae42e78fa739245a353db5edadChong Zhang            err = mEncoder->setInputSurface(mPersistentSurface);
564e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        } else {
565e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            err = mEncoder->createInputSurface(&mGraphicBufferProducer);
566e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        }
56772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
56872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
56972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
57072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
57172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
57272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
573c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    sp<AMessage> inputFormat;
574c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    int32_t usingSwReadOften;
575c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    mSetEncoderFormat = false;
576b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar    if (mEncoder->getInputFormat(&inputFormat) == OK) {
577c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        mSetEncoderFormat = true;
578b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        if (inputFormat->findInt32("using-sw-read-often", &usingSwReadOften)
579b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar                && usingSwReadOften) {
580b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            // this is a SW encoder; signal source to allocate SW readable buffers
581b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            mEncoderFormat = kDefaultSwVideoEncoderFormat;
582b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        } else {
583b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            mEncoderFormat = kDefaultHwVideoEncoderFormat;
584b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        }
585b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        if (!inputFormat->findInt32("android._dataspace", &mEncoderDataSpace)) {
586b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            mEncoderDataSpace = kDefaultVideoEncoderDataSpace;
587b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        }
588b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        ALOGV("setting dataspace %#x, format %#x", mEncoderDataSpace, mEncoderFormat);
589c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    }
590c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
5911099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan    err = mEncoder->start();
59272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
59372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
59472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
59572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
59672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5976a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    {
5986a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Mutexed<Output>::Locked output(mOutput);
5996a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        output->mEncoderReachedEOS = false;
6006a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        output->mErrorCode = OK;
6016a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
60272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
60372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
60472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
60572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
60672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::releaseEncoder() {
60772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder == NULL) {
60872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return;
60972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
61072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->release();
61272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder.clear();
61372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
61472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::postSynchronouslyAndReturnError(
61672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
61772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
61872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
61972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
62172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
62272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
62372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
62572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
62672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
62772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
62972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
63072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
63172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalEOS(status_t err) {
6326a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    bool reachedEOS = false;
6336a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    {
6346a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Mutexed<Output>::Locked output(mOutput);
6356a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        reachedEOS = output->mEncoderReachedEOS;
6366a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (!reachedEOS) {
6376a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio");
63872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // release all unread media buffers
6391889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang            for (List<MediaBufferBase*>::iterator it = output->mBufferQueue.begin();
6406a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                    it != output->mBufferQueue.end(); it++) {
64172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                (*it)->release();
64272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
6436a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output->mBufferQueue.clear();
6446a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output->mEncoderReachedEOS = true;
6456a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output->mErrorCode = err;
6466a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output->mCond.signal();
6476a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
6486a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            reachedEOS = true;
6496a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output.unlock();
6506a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            releaseEncoder();
65172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
65272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
6536a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
6546a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    if (mStopping && reachedEOS) {
65516e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio");
656522e43188628dc30287e3f8c69b779ecc885e7c2Ray Essick        if (mPuller != NULL) {
657522e43188628dc30287e3f8c69b779ecc885e7c2Ray Essick            mPuller->stopSource();
658522e43188628dc30287e3f8c69b779ecc885e7c2Ray Essick        }
6596a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
66072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // posting reply to everyone that's waiting
6613f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        List<sp<AReplyToken>>::iterator it;
66272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        for (it = mStopReplyIDQueue.begin();
66372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                it != mStopReplyIDQueue.end(); it++) {
66472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(*it);
66572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
66672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.clear();
66772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = false;
6686a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        ++mGeneration;
66972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
67072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
67172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
672764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuangvoid MediaCodecSource::resume(int64_t resumeStartTimeUs) {
67372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
67472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
67572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
67672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", false);
677764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        if (resumeStartTimeUs > 0) {
678764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            params->setInt64("drop-start-time-us", resumeStartTimeUs);
67972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
68072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
68172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
68272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
68372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
68472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::feedEncoderInputBuffers() {
6851889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang    MediaBufferBase* mbuf = NULL;
6866a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    while (!mAvailEncoderInputIndices.empty() && mPuller->readBuffer(&mbuf)) {
68772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t bufferIndex = *mAvailEncoderInputIndices.begin();
68872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
68972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
69072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t timeUs = 0ll;
69172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags = 0;
69272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t size = 0;
69372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
69472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf != NULL) {
6953d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen            CHECK(mbuf->meta_data().findInt64(kKeyTime, &timeUs));
696a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            if (mFirstSampleSystemTimeUs < 0ll) {
697a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                mFirstSampleSystemTimeUs = systemTime() / 1000;
698a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                if (mPausePending) {
699a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                    mPausePending = false;
700764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang                    onPause(mFirstSampleSystemTimeUs);
701a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                    mbuf->release();
702a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                    mAvailEncoderInputIndices.push_back(bufferIndex);
703a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                    return OK;
704a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                }
705a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            }
706a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim
707d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim            timeUs += mInputBufferTimeOffsetUs;
70872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
70972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // push decoding time for video, or drift time for audio
71072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
71172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDecodingTimeQueue.push_back(timeUs);
71272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
71372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME
71472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mFirstSampleTimeUs < 0ll) {
71572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mFirstSampleTimeUs = timeUs;
71672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
71772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                int64_t driftTimeUs = 0;
7183d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                if (mbuf->meta_data().findInt64(kKeyDriftTime, &driftTimeUs)
71972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        && driftTimeUs) {
72072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs;
72172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
72272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDriftTimeQueue.push_back(driftTimeUs);
72372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME
72472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
72572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7267e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim            sp<MediaCodecBuffer> inbuf;
7271099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
728e36e1034c2938559c96d1e765b3c75380c83ff6bHaynes Mathew George
729e36e1034c2938559c96d1e765b3c75380c83ff6bHaynes Mathew George            if (err != OK || inbuf == NULL || inbuf->data() == NULL
730e36e1034c2938559c96d1e765b3c75380c83ff6bHaynes Mathew George                    || mbuf->data() == NULL || mbuf->size() == 0) {
7311099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->release();
7321099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
7331099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
7341099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
7351099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
73672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            size = mbuf->size();
73772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7381099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            memcpy(inbuf->data(), mbuf->data(), size);
73972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
74072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
74172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // video encoder will release MediaBuffer when done
74272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // with underlying data.
743bc8f53b8c1c220d9ce01526b6e3834f14af98ed5Dongwon Kang                inbuf->meta()->setObject("mediaBufferHolder", new MediaBufferHolder(mbuf));
744bc8f53b8c1c220d9ce01526b6e3834f14af98ed5Dongwon Kang                mbuf->release();
74572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
74672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->release();
74772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
74872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
74972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            flags = MediaCodec::BUFFER_FLAG_EOS;
75072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
75172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
75272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        status_t err = mEncoder->queueInputBuffer(
75372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                bufferIndex, 0, size, timeUs, flags);
75472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
75572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
75672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
75772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
75872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
75972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
76072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
76172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
76272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
76372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::onStart(MetaData *params) {
76472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStopping) {
76572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("Failed to start while we're stopping");
76672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return INVALID_OPERATION;
76772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
768764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    int64_t startTimeUs;
769764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    if (params == NULL || !params->findInt64(kKeyTime, &startTimeUs)) {
770764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        startTimeUs = -1ll;
771764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    }
77272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
77372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStarted) {
77472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
775a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (mPausePending) {
776a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            mPausePending = false;
777a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            return OK;
778a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        }
7794cca134f0a775808458622490886d775c59bcc54Wonsik Kim        if (mIsVideo) {
7804cca134f0a775808458622490886d775c59bcc54Wonsik Kim            mEncoder->requestIDRFrame();
7814cca134f0a775808458622490886d775c59bcc54Wonsik Kim        }
78272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
783764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            resume(startTimeUs);
78472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
78572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
78672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->resume();
78772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
78872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
78972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
79072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
79172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio");
79272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
79372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = OK;
79472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
79572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
796764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        if (mEncoder != NULL) {
797764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            sp<AMessage> params = new AMessage;
798764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            params->setInt32("drop-input-frames", false);
799764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            if (startTimeUs >= 0) {
800764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang                params->setInt64("skip-frames-before", startTimeUs);
801764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            }
802764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            mEncoder->setParameters(params);
80372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
80472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else {
80572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mPuller != NULL);
806c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        sp<MetaData> meta = params;
807c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        if (mSetEncoderFormat) {
808c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            if (meta == NULL) {
809c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar                meta = new MetaData;
810c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            }
811c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            meta->setInt32(kKeyPixelFormat, mEncoderFormat);
812c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            meta->setInt32(kKeyColorSpace, mEncoderDataSpace);
813c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        }
814c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
8151d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> notify = new AMessage(kWhatPullerNotify, mReflector);
816c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        err = mPuller->start(meta.get(), notify);
81772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
81872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
81972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
82072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
82172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
82272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio");
82372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
82472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mStarted = true;
82572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
82672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
82772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
828764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuangvoid MediaCodecSource::onPause(int64_t pauseStartTimeUs) {
829764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    if ((mFlags & FLAG_USE_SURFACE_INPUT) && (mEncoder != NULL)) {
830764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        sp<AMessage> params = new AMessage;
831764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        params->setInt32("drop-input-frames", true);
832764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        params->setInt64("drop-start-time-us", pauseStartTimeUs);
833764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        mEncoder->setParameters(params);
834a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    } else {
835a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        CHECK(mPuller != NULL);
836a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        mPuller->pause();
837a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    }
838a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim}
839a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim
84072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
84172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
84272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPullerNotify:
84372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
8446a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        int32_t eos = 0;
8456a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (msg->findInt32("eos", &eos) && eos) {
8466a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("puller (%s) reached EOS", mIsVideo ? "video" : "audio");
84716e79115e497386eaf010af388627f94314a55a3Chong Zhang            signalEOS();
8486a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            break;
84972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
85072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
85172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
8526a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("got msg '%s' after encoder shutdown.", msg->debugString().c_str());
85372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
85472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
85572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
85672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        feedEncoderInputBuffers();
85772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
85872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
85972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatEncoderActivity:
86072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
86172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
86272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
86372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
86472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        int32_t cbID;
8661099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        CHECK(msg->findInt32("callbackID", &cbID));
8671099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        if (cbID == MediaCodec::CB_INPUT_AVAILABLE) {
8681099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
8691099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
8701099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
8711099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mAvailEncoderInputIndices.push_back(index);
8721099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            feedEncoderInputBuffers();
87358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        } else if (cbID == MediaCodec::CB_OUTPUT_FORMAT_CHANGED) {
87458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            status_t err = mEncoder->getOutputFormat(&mOutputFormat);
87558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            if (err != OK) {
87658fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                signalEOS(err);
87758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                break;
87858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            }
879ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar            sp<MetaData> meta = new MetaData;
880ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar            convertMessageToMetaData(mOutputFormat, meta);
881ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar            mMeta.lock().set(meta);
8821099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) {
8831099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
8841099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t offset;
8851099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t size;
8861099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int64_t timeUs;
8871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t flags;
8881099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
8891099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
8901099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("offset", &offset));
8911099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("size", &size));
8921099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt64("timeUs", &timeUs));
8931099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("flags", &flags));
8941099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
8951099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_EOS) {
8961099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mEncoder->releaseOutputBuffer(index);
8971099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
8981099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
8991099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
900f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
9017e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim            sp<MediaCodecBuffer> outbuf;
9021099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getOutputBuffer(index, &outbuf);
903e36e1034c2938559c96d1e765b3c75380c83ff6bHaynes Mathew George            if (err != OK || outbuf == NULL || outbuf->data() == NULL
904e36e1034c2938559c96d1e765b3c75380c83ff6bHaynes Mathew George                || outbuf->size() == 0) {
9051099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
9061099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
9071099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
908f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
9091889c3edad32995c0cf26ae2248fe7c957b7ec84Dongwon Kang            MediaBufferBase *mbuf = new MediaBuffer(outbuf->size());
91001d1e525584d037b80d7c9ab79010fd2a5b9a870Andy Hung            mbuf->setObserver(this);
911a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            mbuf->add_ref();
91272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9131099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) {
9141099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                if (mIsVideo) {
9151099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t decodingTimeUs;
9161099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    if (mFlags & FLAG_USE_SURFACE_INPUT) {
917a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                        if (mFirstSampleSystemTimeUs < 0ll) {
918a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                            mFirstSampleSystemTimeUs = systemTime() / 1000;
919a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                            if (mPausePending) {
920a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                                mPausePending = false;
921764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang                                onPause(mFirstSampleSystemTimeUs);
922a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                                mbuf->release();
923a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                                break;
924a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                            }
925a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                        }
92661fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang                        // Timestamp offset is already adjusted in GraphicBufferSource.
927e35600eb62d4a2dc2dd0cc8c0d0d177cec7ed1ccWonsik Kim                        // GraphicBufferSource is supposed to discard samples
928e35600eb62d4a2dc2dd0cc8c0d0d177cec7ed1ccWonsik Kim                        // queued before start, and offset timeUs by start time
929e35600eb62d4a2dc2dd0cc8c0d0d177cec7ed1ccWonsik Kim                        CHECK_GE(timeUs, 0ll);
9301099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // TODO:
9311099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // Decoding time for surface source is unavailable,
9321099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // use presentation time for now. May need to move
9331099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // this logic into MediaCodec.
9341099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = timeUs;
9351099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    } else {
9361099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        CHECK(!mDecodingTimeQueue.empty());
9371099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = *(mDecodingTimeQueue.begin());
9381099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        mDecodingTimeQueue.erase(mDecodingTimeQueue.begin());
9391099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    }
9403d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    mbuf->meta_data().setInt64(kKeyDecodingTime, decodingTimeUs);
94172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9421099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64,
9431099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, decodingTimeUs - timeUs);
9441099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                } else {
9451099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t driftTimeUs = 0;
9461099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#if DEBUG_DRIFT_TIME
9471099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    CHECK(!mDriftTimeQueue.empty());
9481099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    driftTimeUs = *(mDriftTimeQueue.begin());
9491099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mDriftTimeQueue.erase(mDriftTimeQueue.begin());
9503d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                    mbuf->meta_data().setInt64(kKeyDriftTime, driftTimeUs);
9511099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#endif // DEBUG_DRIFT_TIME
9521099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64,
9531099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, driftTimeUs);
9541099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                }
9553d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                mbuf->meta_data().setInt64(kKeyTime, timeUs);
9561099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            } else {
9573d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                mbuf->meta_data().setInt64(kKeyTime, 0ll);
9583d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                mbuf->meta_data().setInt32(kKeyIsCodecConfig, true);
9591099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
9601099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
9613d21ae3fad5a894cf15f2e7e7a1d54d0f3d19db0Marco Nelissen                mbuf->meta_data().setInt32(kKeyIsSyncFrame, true);
9621099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
963a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            memcpy(mbuf->data(), outbuf->data(), outbuf->size());
9641099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
9651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            {
9666a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                Mutexed<Output>::Locked output(mOutput);
9676a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                output->mBufferQueue.push_back(mbuf);
9686a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                output->mCond.signal();
9691099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
9701099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
9711099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mEncoder->releaseOutputBuffer(index);
9721099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       } else if (cbID == MediaCodec::CB_ERROR) {
9731099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err;
9741099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("err", &err));
9751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            ALOGE("Encoder (%s) reported error : 0x%x",
9761099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mIsVideo ? "video" : "audio", err);
977c68689dfd6fa3b880a0d8e75408b582b389630f8Praveen Chavan            if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
978c68689dfd6fa3b880a0d8e75408b582b389630f8Praveen Chavan                mStopping = true;
979c68689dfd6fa3b880a0d8e75408b582b389630f8Praveen Chavan                mPuller->stop();
980c68689dfd6fa3b880a0d8e75408b582b389630f8Praveen Chavan            }
9811099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            signalEOS();
9821099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       }
9831099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       break;
98472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
98572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStart:
98672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
9873f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
98872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
98972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
99072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<RefBase> obj;
99172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->findObject("meta", &obj));
99272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MetaData *params = static_cast<MetaData *>(obj.get());
99372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
99472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> response = new AMessage;
99572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->setInt32("err", onStart(params));
99672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->postReply(replyID);
99772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
99872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
99972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStop:
100072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
100116e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio");
100272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10033f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
100472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
100572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10066a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (mOutput.lock()->mEncoderReachedEOS) {
100772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // if we already reached EOS, reply and return now
100816e79115e497386eaf010af388627f94314a55a3Chong Zhang            ALOGI("encoder (%s) already stopped",
100972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mIsVideo ? "video" : "audio");
101072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(replyID);
101172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
101272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
101372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
101472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.push_back(replyID);
101572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mStopping) {
101672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // nothing to do if we're already stopping, reply will be posted
101772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // to all when we're stopped.
101872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
101972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
102072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
102172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = true;
102272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1023f72cefddf378909f360998852e41f49042711299Hangyu Kuang        int64_t timeoutUs = kStopTimeoutUs;
102472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // if using surface, signal source EOS and wait for EOS to come back.
10256a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // otherwise, stop puller (which also clears the input buffer queue)
10266a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // and wait for the EOS message. We cannot call source->stop() because
10276a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // the encoder may still be processing input buffers.
102872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
102972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mEncoder->signalEndOfInputStream();
1030f72cefddf378909f360998852e41f49042711299Hangyu Kuang            // Increase the timeout if there is delay in the GraphicBufferSource
1031f72cefddf378909f360998852e41f49042711299Hangyu Kuang            sp<AMessage> inputFormat;
1032f72cefddf378909f360998852e41f49042711299Hangyu Kuang            int64_t stopTimeOffsetUs;
1033f72cefddf378909f360998852e41f49042711299Hangyu Kuang            if (mEncoder->getInputFormat(&inputFormat) == OK &&
1034f72cefddf378909f360998852e41f49042711299Hangyu Kuang                    inputFormat->findInt64("android._stop-time-offset-us", &stopTimeOffsetUs) &&
1035f72cefddf378909f360998852e41f49042711299Hangyu Kuang                    stopTimeOffsetUs > 0) {
1036cf3205fab08adfdc9d5c0fef1cef54cab0074117Hangyu Kuang                if (stopTimeOffsetUs > kMaxStopTimeOffsetUs) {
1037cf3205fab08adfdc9d5c0fef1cef54cab0074117Hangyu Kuang                    ALOGW("Source stopTimeOffsetUs %lld too large, limit at %lld us",
1038cf3205fab08adfdc9d5c0fef1cef54cab0074117Hangyu Kuang                        (long long)stopTimeOffsetUs, (long long)kMaxStopTimeOffsetUs);
1039cf3205fab08adfdc9d5c0fef1cef54cab0074117Hangyu Kuang                    stopTimeOffsetUs = kMaxStopTimeOffsetUs;
1040cf3205fab08adfdc9d5c0fef1cef54cab0074117Hangyu Kuang                }
1041f72cefddf378909f360998852e41f49042711299Hangyu Kuang                timeoutUs += stopTimeOffsetUs;
1042cf3205fab08adfdc9d5c0fef1cef54cab0074117Hangyu Kuang            } else {
1043cf3205fab08adfdc9d5c0fef1cef54cab0074117Hangyu Kuang                // Use kMaxStopTimeOffsetUs if stop time offset is not provided by input source
1044cf3205fab08adfdc9d5c0fef1cef54cab0074117Hangyu Kuang                timeoutUs = kMaxStopTimeOffsetUs;
1045f72cefddf378909f360998852e41f49042711299Hangyu Kuang            }
104672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
10476a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            mPuller->stop();
104872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
10496a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
10506a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // complete stop even if encoder/puller stalled
10516a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        sp<AMessage> timeoutMsg = new AMessage(kWhatStopStalled, mReflector);
10526a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        timeoutMsg->setInt32("generation", mGeneration);
1053f72cefddf378909f360998852e41f49042711299Hangyu Kuang        timeoutMsg->post(timeoutUs);
105472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
105572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
10566a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
10576a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    case kWhatStopStalled:
10586a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    {
10596a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        int32_t generation;
10606a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        CHECK(msg->findInt32("generation", &generation));
10616a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (generation != mGeneration) {
10626a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar             break;
10636a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        }
10646a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
10656a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
10666a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("source (%s) stopping", mIsVideo ? "video" : "audio");
106772e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            mPuller->interruptSource();
10686a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
10696a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        }
10706a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        signalEOS();
1071764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        break;
10726a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
10736a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
107472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPause:
107572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
1076a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (mFirstSampleSystemTimeUs < 0) {
1077a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            mPausePending = true;
107872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
1079764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            sp<RefBase> obj;
1080764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            CHECK(msg->findObject("meta", &obj));
1081764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            MetaData *params = static_cast<MetaData *>(obj.get());
1082764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            int64_t pauseStartTimeUs = -1;
1083764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            if (params == NULL || !params->findInt64(kKeyTime, &pauseStartTimeUs)) {
1084764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang                pauseStartTimeUs = -1ll;
1085764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            }
1086764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            onPause(pauseStartTimeUs);
108772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
108872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
108972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
1090d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    case kWhatSetInputBufferTimeOffset:
1091d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    {
1092d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        sp<AReplyToken> replyID;
1093d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        CHECK(msg->senderAwaitsResponse(&replyID));
109461fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang        status_t err = OK;
1095d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        CHECK(msg->findInt64("time-offset-us", &mInputBufferTimeOffsetUs));
1096d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim
109761fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang        // Propagate the timestamp offset to GraphicBufferSource.
10986d332d2cdf6e62c2c20ebff220868fe9e3ed7f44Chong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
109961fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang            sp<AMessage> params = new AMessage;
110061fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang            params->setInt64("time-offset-us", mInputBufferTimeOffsetUs);
110161fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang            err = mEncoder->setParameters(params);
110261fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang        }
110361fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang
1104d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        sp<AMessage> response = new AMessage;
110561fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang        response->setInt32("err", err);
1106d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        response->postReply(replyID);
1107d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        break;
1108d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
1109f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang    case kWhatSetStopTimeUs:
1110764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    {
1111764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        sp<AReplyToken> replyID;
1112764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        CHECK(msg->senderAwaitsResponse(&replyID));
1113764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        status_t err = OK;
1114764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        int64_t stopTimeUs;
1115764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        CHECK(msg->findInt64("stop-time-us", &stopTimeUs));
1116764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang
1117f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        // Propagate the stop time to GraphicBufferSource.
1118764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
1119764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            sp<AMessage> params = new AMessage;
1120764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            params->setInt64("stop-time-us", stopTimeUs);
1121764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang            err = mEncoder->setParameters(params);
1122f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang        } else {
1123f8754cc59cdea9026ee4e1c821a6c362c55da7f8Hangyu Kuang            err = mPuller->setStopTimeUs(stopTimeUs);
1124764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        }
1125764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang
1126764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        sp<AMessage> response = new AMessage;
1127764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        response->setInt32("err", err);
1128764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        response->postReply(replyID);
1129764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang        break;
1130764d945bfdb9dec60f2b482fbf6c5e83824ed950Hangyu Kuang    }
1131a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    case kWhatGetFirstSampleSystemTimeUs:
1132a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    {
1133a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        sp<AReplyToken> replyID;
1134a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        CHECK(msg->senderAwaitsResponse(&replyID));
1135a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim
1136a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        sp<AMessage> response = new AMessage;
1137a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        response->setInt64("time-us", mFirstSampleSystemTimeUs);
1138a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        response->postReply(replyID);
1139a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        break;
1140a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    }
114172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    default:
114272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        TRESPASS();
114372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
114472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
114572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
114672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} // namespace android
1147