MediaCodecSource.cpp revision 7e34bf5af26f8752d4786d3098740cdf51e2438f
172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang/*
272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Copyright 2014, The Android Open Source Project
372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *
472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Licensed under the Apache License, Version 2.0 (the "License");
572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * you may not use this file except in compliance with the License.
672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * You may obtain a copy of the License at
772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *
872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *     http://www.apache.org/licenses/LICENSE-2.0
972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *
1072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Unless required by applicable law or agreed to in writing, software
1172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * distributed under the License is distributed on an "AS IS" BASIS,
1272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * See the License for the specific language governing permissions and
1472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * limitations under the License.
1572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang */
1672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang//#define LOG_NDEBUG 0
1872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#define LOG_TAG "MediaCodecSource"
1972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#define DEBUG_DRIFT_TIME 0
20a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
21a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
22a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
23e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <gui/IGraphicBufferConsumer.h>
2472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/IGraphicBufferProducer.h>
2572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/Surface.h>
2672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/ICrypto.h>
277e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim#include <media/MediaCodecBuffer.h>
2872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ABuffer.h>
2972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ADebug.h>
3072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ALooper.h>
3172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/AMessage.h>
3272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaBuffer.h>
3372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodec.h>
3416fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar#include <media/stagefright/MediaCodecList.h>
35e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MediaCodecSource.h>
3672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaErrors.h>
3772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaSource.h>
38e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MetaData.h>
39e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/PersistentSurface.h>
4072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/Utils.h>
4172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangnamespace android {
4372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnarconst int32_t kDefaultSwVideoEncoderFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
45b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnarconst int32_t kDefaultHwVideoEncoderFormat = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
462cbf6cea23539bfe99e36d1d221de62255452e86Eino-Ville Talvalaconst int32_t kDefaultVideoEncoderDataSpace = HAL_DATASPACE_V0_BT709;
47c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
486a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarconst int kStopTimeoutUs = 300000; // allow 1 sec for shutting down encoder
496a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
5072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstruct MediaCodecSource::Puller : public AHandler {
51090ef604f81447eab4aa0a5b45d6307482573560Chih-Hung Hsieh    explicit Puller(const sp<MediaSource> &source);
5272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5372e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    void interruptSource();
5472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t start(const sp<MetaData> &meta, const sp<AMessage> &notify);
5516e79115e497386eaf010af388627f94314a55a3Chong Zhang    void stop();
566a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    void stopSource();
5772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void pause();
5872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void resume();
5972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
606a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    bool readBuffer(MediaBuffer **buffer);
616a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
6272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprotected:
6372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual void onMessageReceived(const sp<AMessage> &msg);
6472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual ~Puller();
6572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprivate:
6772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    enum {
6872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStart = 'msta',
6972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStop,
7072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatPull,
7172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    };
7272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaSource> mSource;
7472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> mNotify;
7572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<ALooper> mLooper;
7672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mIsAudio;
776a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
786a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    struct Queue {
796a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Queue()
806a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            : mReadPendingSince(0),
816a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar              mPaused(false),
826a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar              mPulling(false) { }
836a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        int64_t mReadPendingSince;
846a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        bool mPaused;
856a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        bool mPulling;
866a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Vector<MediaBuffer *> mReadBuffers;
876a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
886a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        void flush();
896a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // if queue is empty, return false and set *|buffer| to NULL . Otherwise, pop
9072e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar        // buffer from front of the queue, place it into *|buffer| and return true.
916a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        bool readBuffer(MediaBuffer **buffer);
9272e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar        // add a buffer to the back of the queue
936a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        void pushBuffer(MediaBuffer *mbuf);
946a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    };
956a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Queue> mQueue;
9672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
9872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void schedulePull();
9972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void handleEOS();
10072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    DISALLOW_EVIL_CONSTRUCTORS(Puller);
10272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang};
10372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10472cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::Puller(const sp<MediaSource> &source)
10572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mSource(source),
10672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mLooper(new ALooper()),
1076a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar      mIsAudio(false)
1086a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar{
10972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MetaData> meta = source->getFormat();
11072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    const char *mime;
11172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(meta->findCString(kKeyMIMEType, &mime));
11272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mIsAudio = !strncasecmp(mime, "audio/", 6);
11472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->setName("pull_looper");
11672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
11772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11872cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::~Puller() {
11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(id());
12072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->stop();
12172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
12272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1236a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarvoid MediaCodecSource::Puller::Queue::pushBuffer(MediaBuffer *mbuf) {
1246a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    mReadBuffers.push_back(mbuf);
1256a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
1266a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
1276a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarbool MediaCodecSource::Puller::Queue::readBuffer(MediaBuffer **mbuf) {
1286a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    if (mReadBuffers.empty()) {
1296a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        *mbuf = NULL;
1306a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        return false;
1316a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
1326a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    *mbuf = *mReadBuffers.begin();
1336a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    mReadBuffers.erase(mReadBuffers.begin());
1346a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    return true;
1356a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
1366a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
1376a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarvoid MediaCodecSource::Puller::Queue::flush() {
1386a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    MediaBuffer *mbuf;
1396a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    while (readBuffer(&mbuf)) {
1406a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // there are no null buffers in the queue
1416a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        mbuf->release();
1426a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
1436a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
1446a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
1456a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarbool MediaCodecSource::Puller::readBuffer(MediaBuffer **mbuf) {
1466a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Queue>::Locked queue(mQueue);
1476a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    return queue->readBuffer(mbuf);
1486a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
1496a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
15072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::postSynchronouslyAndReturnError(
15172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
15272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
15372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
15472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
15672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
15772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
15872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
16072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
16172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
16272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
16372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
16472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
16572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1666a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarstatus_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, const sp<AMessage> &notify) {
16772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("puller (%s) start", mIsAudio ? "audio" : "video");
16872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->start(
16972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* runOnCallingThread */,
17072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* canCallJava */,
17172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            PRIORITY_AUDIO);
17272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(this);
17372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mNotify = notify;
17472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1751d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStart, this);
17672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", meta);
17772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
17872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
17972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
18016e79115e497386eaf010af388627f94314a55a3Chong Zhangvoid MediaCodecSource::Puller::stop() {
1816a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    bool interrupt = false;
1826a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    {
1836a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // mark stopping before actually reaching kWhatStop on the looper, so the pulling will
1846a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // stop.
1856a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Mutexed<Queue>::Locked queue(mQueue);
1866a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        queue->mPulling = false;
1876a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        interrupt = queue->mReadPendingSince && (queue->mReadPendingSince < ALooper::GetNowUs() - 1000000);
1886a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        queue->flush(); // flush any unprocessed pulled buffers
1896a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
19016e79115e497386eaf010af388627f94314a55a3Chong Zhang
1916a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    if (interrupt) {
19272e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar        interruptSource();
1936a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
1946a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
19516e79115e497386eaf010af388627f94314a55a3Chong Zhang
19672e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnarvoid MediaCodecSource::Puller::interruptSource() {
19772e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    // call source->stop if read has been pending for over a second
19872e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    // We have to call this outside the looper as looper is pending on the read.
19972e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    mSource->stop();
20072e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar}
20172e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar
2026a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarvoid MediaCodecSource::Puller::stopSource() {
20372e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStop, this);
20472e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    (void)postSynchronouslyAndReturnError(msg);
20572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
20672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::pause() {
2086a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Queue>::Locked queue(mQueue);
2096a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    queue->mPaused = true;
21072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
21172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::resume() {
2136a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Queue>::Locked queue(mQueue);
2146a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    queue->mPaused = false;
21572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
21672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::schedulePull() {
2186a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    (new AMessage(kWhatPull, this))->post();
21972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
22072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::handleEOS() {
2226a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video");
2236a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    sp<AMessage> msg = mNotify->dup();
2246a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    msg->setInt32("eos", 1);
2256a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    msg->post();
22672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
22772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) {
22972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
23072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStart:
23172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
23272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<RefBase> obj;
23372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->findObject("meta", &obj));
23472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2356a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            {
2366a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                Mutexed<Queue>::Locked queue(mQueue);
2376a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                queue->mPulling = true;
2386a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            }
23972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->start(static_cast<MetaData *>(obj.get()));
24172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err == OK) {
24372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                schedulePull();
24472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
24572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<AMessage> response = new AMessage;
24772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->setInt32("err", err);
24872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2493f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
25072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
25172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->postReply(replyID);
25272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
25372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
25472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
25572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStop:
25672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
2576a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            mSource->stop();
25872e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar
25972e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            sp<AMessage> response = new AMessage;
26072e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            response->setInt32("err", OK);
26172e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar
26272e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            sp<AReplyToken> replyID;
26372e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
26472e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            response->postReply(replyID);
26572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
26672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
26772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
26872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatPull:
26972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
2706a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            Mutexed<Queue>::Locked queue(mQueue);
2716a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue->mReadPendingSince = ALooper::GetNowUs();
2726a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            if (!queue->mPulling) {
2736a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                handleEOS();
27472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
27572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
27672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2776a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue.unlock();
2786a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            MediaBuffer *mbuf = NULL;
27972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->read(&mbuf);
2806a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue.lock();
28172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2826a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue->mReadPendingSince = 0;
2836a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            // if we need to discard buffer
2846a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            if (!queue->mPulling || queue->mPaused || err != OK) {
2856a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                if (mbuf != NULL) {
28672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf->release();
28772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf = NULL;
28872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
2896a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                if (queue->mPulling && err == OK) {
2906a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                    msg->post(); // if simply paused, keep pulling source
2916d6c21b8d2ed66007833dae0451b0a211c97e592Wonsik Kim                    break;
2926a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                } else if (err == ERROR_END_OF_STREAM) {
29372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGV("stream ended, mbuf %p", mbuf);
2946a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                } else if (err != OK) {
29572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGE("error %d reading stream.", err);
29672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
2976a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            }
29872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2996a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            if (mbuf != NULL) {
3006a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                queue->pushBuffer(mbuf);
30172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
30272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3036a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue.unlock();
30472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3056a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            if (mbuf != NULL) {
3066a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                mNotify->post();
3076a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                msg->post();
3086a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            } else {
3096a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                handleEOS();
3106a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            }
31172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
31272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
31372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
31472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        default:
31572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            TRESPASS();
31672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
31772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
31872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3196a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos MolnarMediaCodecSource::Output::Output()
3206a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    : mEncoderReachedEOS(false),
3216a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar      mErrorCode(OK) {
3226a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
3236a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
32472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang// static
32572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<MediaCodecSource> MediaCodecSource::Create(
32672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
32772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &format,
32872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
329e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        const sp<IGraphicBufferConsumer> &consumer,
33072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags) {
33172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaCodecSource> mediaSource =
332e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            new MediaCodecSource(looper, format, source, consumer, flags);
33372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
33472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mediaSource->init() == OK) {
33572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return mediaSource;
33672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
33772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return NULL;
33872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
33972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
34061fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuangstatus_t MediaCodecSource::setInputBufferTimeOffset(int64_t timeOffsetUs) {
341d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    sp<AMessage> msg = new AMessage(kWhatSetInputBufferTimeOffset, mReflector);
342d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    msg->setInt64("time-offset-us", timeOffsetUs);
34361fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang    return postSynchronouslyAndReturnError(msg);
344d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim}
345d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim
346a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kimint64_t MediaCodecSource::getFirstSampleSystemTimeUs() {
347a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    sp<AMessage> msg = new AMessage(kWhatGetFirstSampleSystemTimeUs, mReflector);
348a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    sp<AMessage> response;
349a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    msg->postAndAwaitResponse(&response);
350a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    int64_t timeUs;
351a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    if (!response->findInt64("time-us", &timeUs)) {
352a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        timeUs = -1ll;
353a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    }
354a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    return timeUs;
355a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim}
356a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim
35772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::start(MetaData* params) {
3581d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStart, mReflector);
35972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", params);
36072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
36172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
36272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::stop() {
3641d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStop, mReflector);
3656a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    return postSynchronouslyAndReturnError(msg);
36672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
36772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
36872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::pause() {
3691d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPause, mReflector))->post();
37072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
37172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
37272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
373ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnarsp<MetaData> MediaCodecSource::getFormat() {
374ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    Mutexed<sp<MetaData>>::Locked meta(mMeta);
375ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    return *meta;
376ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar}
377ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar
37872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() {
37972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
38072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mGraphicBufferProducer;
38172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
38272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MediaCodecSource::read(
38484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        MediaBuffer** buffer, const ReadOptions* /* options */) {
3856a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Output>::Locked output(mOutput);
38672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    *buffer = NULL;
3886a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    while (output->mBufferQueue.size() == 0 && !output->mEncoderReachedEOS) {
3896a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        output.waitForCondition(output->mCond);
39072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
3916a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    if (!output->mEncoderReachedEOS) {
3926a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        *buffer = *output->mBufferQueue.begin();
3936a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        output->mBufferQueue.erase(output->mBufferQueue.begin());
39472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
39572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
3966a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    return output->mErrorCode;
39772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
39872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) {
40072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->setObserver(0);
40172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->release();
40272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
40372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
40472cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::MediaCodecSource(
40572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
40672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &outputFormat,
40772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
408e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        const sp<IGraphicBufferConsumer> &consumer,
40972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags)
41072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mLooper(looper),
41172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mOutputFormat(outputFormat),
41272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mMeta(new MetaData),
41372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFlags(flags),
41472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mIsVideo(false),
41572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStarted(false),
41672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStopping(false),
41772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mDoMoreWorkPending(false),
418c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mSetEncoderFormat(false),
419c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mEncoderFormat(0),
420c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mEncoderDataSpace(0),
421e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang      mGraphicBufferConsumer(consumer),
422d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim      mInputBufferTimeOffsetUs(0),
423a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim      mFirstSampleSystemTimeUs(-1ll),
424a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim      mPausePending(false),
42572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFirstSampleTimeUs(-1ll),
4266a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar      mGeneration(0) {
42772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mLooper != NULL);
42872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString mime;
43072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &mime));
43172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!strncasecmp("video/", mime.c_str(), 6)) {
43372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mIsVideo = true;
43472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
43572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
43772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mPuller = new Puller(source);
43872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
43972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
44072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44172cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::~MediaCodecSource() {
44272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    releaseEncoder();
44372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->stop();
44572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(mReflector->id());
44672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
44772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::init() {
44972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = initEncoder();
45072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
45172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
45272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        releaseEncoder();
45372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
45472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
45572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
45672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
45772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
45872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::initEncoder() {
45972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mReflector = new AHandlerReflector<MediaCodecSource>(this);
46072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(mReflector);
46172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper = new ALooper;
46372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->setName("codec_looper");
46472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->start();
46572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
46772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("create-input-buffers-suspended", 1);
46872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
46972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString outputMIME;
47172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &outputMIME));
47272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47316fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar    Vector<AString> matchingCodecs;
47416fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar    MediaCodecList::findMatchingCodecs(
47516fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar            outputMIME.c_str(), true /* encoder */,
47616fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar            ((mFlags & FLAG_PREFER_SOFTWARE_CODEC) ? MediaCodecList::kPreferSoftwareCodecs : 0),
47716fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar            &matchingCodecs);
47872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47916fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar    status_t err = NO_INIT;
48016fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar    for (size_t ix = 0; ix < matchingCodecs.size(); ++ix) {
48116fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        mEncoder = MediaCodec::CreateByComponentName(
48216fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                mCodecLooper, matchingCodecs[ix]);
48316fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar
48416fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        if (mEncoder == NULL) {
48516fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar            continue;
48616fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        }
48716fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar
48816fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
48972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
49016fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector);
49116fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        mEncoder->setCallback(mEncoderActivityNotify);
49272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
49316fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        err = mEncoder->configure(
49416fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                    mOutputFormat,
49516fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                    NULL /* nativeWindow */,
49616fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                    NULL /* crypto */,
49716fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                    MediaCodec::CONFIGURE_FLAG_ENCODE);
498421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen
49916fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        if (err == OK) {
50016fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar            break;
50116fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        }
50216fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        mEncoder->release();
50316fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        mEncoder = NULL;
50416fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar    }
50572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
50672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
50772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
50872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
50972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
51072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->getOutputFormat(&mOutputFormat);
511ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    sp<MetaData> meta = new MetaData;
512ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    convertMessageToMetaData(mOutputFormat, meta);
513ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    mMeta.lock().set(meta);
51472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
51572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
51672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mIsVideo);
51772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
518e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        if (mGraphicBufferConsumer != NULL) {
519e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // When using persistent surface, we are only interested in the
520e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // consumer, but have to use PersistentSurface as a wrapper to
521e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // pass consumer over messages (similar to BufferProducerWrapper)
5228f469e18c307cb9dc0d16ed9225972aa8be4516fChong Zhang            err = mEncoder->setInputSurface(
523e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang                    new PersistentSurface(NULL, mGraphicBufferConsumer));
524e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        } else {
525e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            err = mEncoder->createInputSurface(&mGraphicBufferProducer);
526e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        }
52772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
52872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
52972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
53072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
53172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
53272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
533c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    sp<AMessage> inputFormat;
534c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    int32_t usingSwReadOften;
535c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    mSetEncoderFormat = false;
536b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar    if (mEncoder->getInputFormat(&inputFormat) == OK) {
537c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        mSetEncoderFormat = true;
538b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        if (inputFormat->findInt32("using-sw-read-often", &usingSwReadOften)
539b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar                && usingSwReadOften) {
540b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            // this is a SW encoder; signal source to allocate SW readable buffers
541b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            mEncoderFormat = kDefaultSwVideoEncoderFormat;
542b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        } else {
543b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            mEncoderFormat = kDefaultHwVideoEncoderFormat;
544b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        }
545b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        if (!inputFormat->findInt32("android._dataspace", &mEncoderDataSpace)) {
546b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            mEncoderDataSpace = kDefaultVideoEncoderDataSpace;
547b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        }
548b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        ALOGV("setting dataspace %#x, format %#x", mEncoderDataSpace, mEncoderFormat);
549c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    }
550c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
5511099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan    err = mEncoder->start();
55272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
55372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
55472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
55572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
55672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5576a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    {
5586a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Mutexed<Output>::Locked output(mOutput);
5596a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        output->mEncoderReachedEOS = false;
5606a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        output->mErrorCode = OK;
5616a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
56272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
56372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
56472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
56572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
56672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::releaseEncoder() {
56772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder == NULL) {
56872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return;
56972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
57072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
57172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->release();
57272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder.clear();
57372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
57472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
57572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::postSynchronouslyAndReturnError(
57672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
57772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
57872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
57972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
58072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
58172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
58272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
58372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
58472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
58572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
58672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
58772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
58872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
58972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
59072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
59172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalEOS(status_t err) {
5926a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    bool reachedEOS = false;
5936a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    {
5946a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Mutexed<Output>::Locked output(mOutput);
5956a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        reachedEOS = output->mEncoderReachedEOS;
5966a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (!reachedEOS) {
5976a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio");
59872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // release all unread media buffers
5996a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            for (List<MediaBuffer*>::iterator it = output->mBufferQueue.begin();
6006a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                    it != output->mBufferQueue.end(); it++) {
60172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                (*it)->release();
60272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
6036a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output->mBufferQueue.clear();
6046a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output->mEncoderReachedEOS = true;
6056a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output->mErrorCode = err;
6066a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output->mCond.signal();
6076a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
6086a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            reachedEOS = true;
6096a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output.unlock();
6106a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            releaseEncoder();
61172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
61272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
6136a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
6146a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    if (mStopping && reachedEOS) {
61516e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio");
6166a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        mPuller->stopSource();
6176a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
61872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // posting reply to everyone that's waiting
6193f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        List<sp<AReplyToken>>::iterator it;
62072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        for (it = mStopReplyIDQueue.begin();
62172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                it != mStopReplyIDQueue.end(); it++) {
62272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(*it);
62372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
62472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.clear();
62572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = false;
6266a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        ++mGeneration;
62772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
62872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
62972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
63072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::suspend() {
63172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
63272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
63372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
63472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", true);
63572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
63672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
63772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
63872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
63972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::resume(int64_t skipFramesBeforeUs) {
64072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
64172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
64272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
64372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", false);
64472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (skipFramesBeforeUs > 0) {
64572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            params->setInt64("skip-frames-before", skipFramesBeforeUs);
64672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
64772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
64872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
64972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
65072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
65172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::feedEncoderInputBuffers() {
6526a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    MediaBuffer* mbuf = NULL;
6536a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    while (!mAvailEncoderInputIndices.empty() && mPuller->readBuffer(&mbuf)) {
65472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t bufferIndex = *mAvailEncoderInputIndices.begin();
65572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
65672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
65772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t timeUs = 0ll;
65872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags = 0;
65972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t size = 0;
66072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
66172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf != NULL) {
66272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
663a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            if (mFirstSampleSystemTimeUs < 0ll) {
664a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                mFirstSampleSystemTimeUs = systemTime() / 1000;
665a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                if (mPausePending) {
666a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                    mPausePending = false;
667a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                    onPause();
668a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                    mbuf->release();
669a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                    mAvailEncoderInputIndices.push_back(bufferIndex);
670a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                    return OK;
671a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                }
672a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            }
673a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim
674d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim            timeUs += mInputBufferTimeOffsetUs;
67572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
67672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // push decoding time for video, or drift time for audio
67772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
67872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDecodingTimeQueue.push_back(timeUs);
67972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
68072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME
68172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mFirstSampleTimeUs < 0ll) {
68272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mFirstSampleTimeUs = timeUs;
68372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
68472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                int64_t driftTimeUs = 0;
68572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs)
68672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        && driftTimeUs) {
68772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs;
68872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
68972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDriftTimeQueue.push_back(driftTimeUs);
69072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME
69172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
69272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6937e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim            sp<MediaCodecBuffer> inbuf;
6941099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
6951099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (err != OK || inbuf == NULL) {
6961099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->release();
6971099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
6981099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
6991099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
7001099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
70172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            size = mbuf->size();
70272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7031099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            memcpy(inbuf->data(), mbuf->data(), size);
70472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
70572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
70672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // video encoder will release MediaBuffer when done
70772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // with underlying data.
7081099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                inbuf->setMediaBufferBase(mbuf);
70972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
71072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->release();
71172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
71272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
71372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            flags = MediaCodec::BUFFER_FLAG_EOS;
71472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
71572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
71672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        status_t err = mEncoder->queueInputBuffer(
71772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                bufferIndex, 0, size, timeUs, flags);
71872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
71972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
72072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
72172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
72272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
72372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
72472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
72572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
72672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
72772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::onStart(MetaData *params) {
72872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStopping) {
72972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("Failed to start while we're stopping");
73072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return INVALID_OPERATION;
73172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
73272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
73372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStarted) {
73472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
735a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (mPausePending) {
736a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            mPausePending = false;
737a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            return OK;
738a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        }
7394cca134f0a775808458622490886d775c59bcc54Wonsik Kim        if (mIsVideo) {
7404cca134f0a775808458622490886d775c59bcc54Wonsik Kim            mEncoder->requestIDRFrame();
7414cca134f0a775808458622490886d775c59bcc54Wonsik Kim        }
74272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
74372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            resume();
74472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
74572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
74672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->resume();
74772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
74872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
74972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
75072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
75172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio");
75272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
75372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = OK;
75472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
75572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
75672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t startTimeUs;
75772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
75872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            startTimeUs = -1ll;
75972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
76072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        resume(startTimeUs);
76172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else {
76272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mPuller != NULL);
763c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        sp<MetaData> meta = params;
764c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        if (mSetEncoderFormat) {
765c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            if (meta == NULL) {
766c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar                meta = new MetaData;
767c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            }
768c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            meta->setInt32(kKeyPixelFormat, mEncoderFormat);
769c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            meta->setInt32(kKeyColorSpace, mEncoderDataSpace);
770c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        }
771c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
7721d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> notify = new AMessage(kWhatPullerNotify, mReflector);
773c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        err = mPuller->start(meta.get(), notify);
77472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
77572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
77672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
77772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
77872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
77972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio");
78072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
78172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mStarted = true;
78272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
78372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
78472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
785a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kimvoid MediaCodecSource::onPause() {
786a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    if (mFlags & FLAG_USE_SURFACE_INPUT) {
787a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        suspend();
788a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    } else {
789a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        CHECK(mPuller != NULL);
790a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        mPuller->pause();
791a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    }
792a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim}
793a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim
79472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
79572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
79672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPullerNotify:
79772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
7986a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        int32_t eos = 0;
7996a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (msg->findInt32("eos", &eos) && eos) {
8006a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("puller (%s) reached EOS", mIsVideo ? "video" : "audio");
80116e79115e497386eaf010af388627f94314a55a3Chong Zhang            signalEOS();
8026a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            break;
80372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
80472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
80572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
8066a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("got msg '%s' after encoder shutdown.", msg->debugString().c_str());
80772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
80872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
80972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
81072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        feedEncoderInputBuffers();
81172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
81272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
81372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatEncoderActivity:
81472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
81572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
81672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
81772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
81872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8191099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        int32_t cbID;
8201099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        CHECK(msg->findInt32("callbackID", &cbID));
8211099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        if (cbID == MediaCodec::CB_INPUT_AVAILABLE) {
8221099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
8231099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
8241099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
8251099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mAvailEncoderInputIndices.push_back(index);
8261099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            feedEncoderInputBuffers();
82758fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        } else if (cbID == MediaCodec::CB_OUTPUT_FORMAT_CHANGED) {
82858fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            status_t err = mEncoder->getOutputFormat(&mOutputFormat);
82958fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            if (err != OK) {
83058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                signalEOS(err);
83158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                break;
83258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            }
833ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar            sp<MetaData> meta = new MetaData;
834ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar            convertMessageToMetaData(mOutputFormat, meta);
835ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar            mMeta.lock().set(meta);
8361099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) {
8371099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
8381099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t offset;
8391099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t size;
8401099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int64_t timeUs;
8411099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t flags;
8421099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
8431099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
8441099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("offset", &offset));
8451099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("size", &size));
8461099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt64("timeUs", &timeUs));
8471099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("flags", &flags));
8481099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
8491099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_EOS) {
8501099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mEncoder->releaseOutputBuffer(index);
8511099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
8521099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
8531099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
854f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
8557e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim            sp<MediaCodecBuffer> outbuf;
8561099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getOutputBuffer(index, &outbuf);
8571099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (err != OK || outbuf == NULL) {
8581099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
8591099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
8601099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
861f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
8621099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            MediaBuffer *mbuf = new MediaBuffer(outbuf->size());
863a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            mbuf->add_ref();
86472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) {
8661099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                if (mIsVideo) {
8671099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t decodingTimeUs;
8681099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    if (mFlags & FLAG_USE_SURFACE_INPUT) {
869a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                        if (mFirstSampleSystemTimeUs < 0ll) {
870a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                            mFirstSampleSystemTimeUs = systemTime() / 1000;
871a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                            if (mPausePending) {
872a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                                mPausePending = false;
873a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                                onPause();
874a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                                mbuf->release();
875a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                                break;
876a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                            }
877a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim                        }
87861fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang                        // Timestamp offset is already adjusted in GraphicBufferSource.
879e35600eb62d4a2dc2dd0cc8c0d0d177cec7ed1ccWonsik Kim                        // GraphicBufferSource is supposed to discard samples
880e35600eb62d4a2dc2dd0cc8c0d0d177cec7ed1ccWonsik Kim                        // queued before start, and offset timeUs by start time
881e35600eb62d4a2dc2dd0cc8c0d0d177cec7ed1ccWonsik Kim                        CHECK_GE(timeUs, 0ll);
8821099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // TODO:
8831099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // Decoding time for surface source is unavailable,
8841099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // use presentation time for now. May need to move
8851099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // this logic into MediaCodec.
8861099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = timeUs;
8871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    } else {
8881099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        CHECK(!mDecodingTimeQueue.empty());
8891099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = *(mDecodingTimeQueue.begin());
8901099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        mDecodingTimeQueue.erase(mDecodingTimeQueue.begin());
8911099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    }
8921099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
89372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8941099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64,
8951099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, decodingTimeUs - timeUs);
8961099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                } else {
8971099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t driftTimeUs = 0;
8981099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#if DEBUG_DRIFT_TIME
8991099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    CHECK(!mDriftTimeQueue.empty());
9001099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    driftTimeUs = *(mDriftTimeQueue.begin());
9011099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mDriftTimeQueue.erase(mDriftTimeQueue.begin());
9021099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs);
9031099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#endif // DEBUG_DRIFT_TIME
9041099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64,
9051099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, driftTimeUs);
9061099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                }
9071099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt64(kKeyTime, timeUs);
9081099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            } else {
9091099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true);
9101099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
9111099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
9121099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true);
9131099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
914a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            memcpy(mbuf->data(), outbuf->data(), outbuf->size());
9151099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mbuf->setObserver(this);
9161099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
9171099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            {
9186a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                Mutexed<Output>::Locked output(mOutput);
9196a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                output->mBufferQueue.push_back(mbuf);
9206a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                output->mCond.signal();
9211099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
9221099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
9231099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mEncoder->releaseOutputBuffer(index);
9241099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       } else if (cbID == MediaCodec::CB_ERROR) {
9251099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err;
9261099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("err", &err));
9271099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            ALOGE("Encoder (%s) reported error : 0x%x",
9281099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mIsVideo ? "video" : "audio", err);
9291099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            signalEOS();
9301099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       }
9311099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       break;
93272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
93372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStart:
93472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
9353f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
93672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
93772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
93872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<RefBase> obj;
93972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->findObject("meta", &obj));
94072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MetaData *params = static_cast<MetaData *>(obj.get());
94172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
94272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> response = new AMessage;
94372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->setInt32("err", onStart(params));
94472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->postReply(replyID);
94572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
94672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
94772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStop:
94872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
94916e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio");
95072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9513f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
95272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
95372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9546a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (mOutput.lock()->mEncoderReachedEOS) {
95572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // if we already reached EOS, reply and return now
95616e79115e497386eaf010af388627f94314a55a3Chong Zhang            ALOGI("encoder (%s) already stopped",
95772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mIsVideo ? "video" : "audio");
95872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(replyID);
95972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
96072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
96172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
96272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.push_back(replyID);
96372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mStopping) {
96472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // nothing to do if we're already stopping, reply will be posted
96572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // to all when we're stopped.
96672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
96772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
96872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
96972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = true;
97072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
97172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // if using surface, signal source EOS and wait for EOS to come back.
9726a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // otherwise, stop puller (which also clears the input buffer queue)
9736a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // and wait for the EOS message. We cannot call source->stop() because
9746a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // the encoder may still be processing input buffers.
97572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
97672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mEncoder->signalEndOfInputStream();
97772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
9786a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            mPuller->stop();
97972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
9806a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
9816a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // complete stop even if encoder/puller stalled
9826a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        sp<AMessage> timeoutMsg = new AMessage(kWhatStopStalled, mReflector);
9836a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        timeoutMsg->setInt32("generation", mGeneration);
9846a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        timeoutMsg->post(kStopTimeoutUs);
98572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
98672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
9876a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
9886a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    case kWhatStopStalled:
9896a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    {
9906a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        int32_t generation;
9916a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        CHECK(msg->findInt32("generation", &generation));
9926a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (generation != mGeneration) {
9936a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar             break;
9946a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        }
9956a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
9966a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
9976a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("source (%s) stopping", mIsVideo ? "video" : "audio");
99872e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            mPuller->interruptSource();
9996a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
10006a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        }
10016a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        signalEOS();
10026a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
10036a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
100472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPause:
100572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
1006a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        if (mFirstSampleSystemTimeUs < 0) {
1007a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            mPausePending = true;
100872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
1009a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim            onPause();
101072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
101172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
101272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
1013d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    case kWhatSetInputBufferTimeOffset:
1014d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    {
1015d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        sp<AReplyToken> replyID;
1016d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        CHECK(msg->senderAwaitsResponse(&replyID));
101761fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang        status_t err = OK;
1018d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        CHECK(msg->findInt64("time-offset-us", &mInputBufferTimeOffsetUs));
1019d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim
102061fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang        // Propagate the timestamp offset to GraphicBufferSource.
10216d332d2cdf6e62c2c20ebff220868fe9e3ed7f44Chong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
102261fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang            sp<AMessage> params = new AMessage;
102361fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang            params->setInt64("time-offset-us", mInputBufferTimeOffsetUs);
102461fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang            err = mEncoder->setParameters(params);
102561fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang        }
102661fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang
1027d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        sp<AMessage> response = new AMessage;
102861fcfd1b0b58dff9284ede8dc49749ca7395856dHangyu Kuang        response->setInt32("err", err);
1029d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        response->postReply(replyID);
1030d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        break;
1031d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
1032a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    case kWhatGetFirstSampleSystemTimeUs:
1033a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    {
1034a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        sp<AReplyToken> replyID;
1035a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        CHECK(msg->senderAwaitsResponse(&replyID));
1036a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim
1037a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        sp<AMessage> response = new AMessage;
1038a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        response->setInt64("time-us", mFirstSampleSystemTimeUs);
1039a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        response->postReply(replyID);
1040a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim        break;
1041a5aeb87eabfda3cb385eed405b843bdcb64252beWonsik Kim    }
104272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    default:
104372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        TRESPASS();
104472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
104572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
104672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
104772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} // namespace android
1048