172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang/*
272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Copyright 2014, The Android Open Source Project
372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *
472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Licensed under the Apache License, Version 2.0 (the "License");
572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * you may not use this file except in compliance with the License.
672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * You may obtain a copy of the License at
772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *
872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *     http://www.apache.org/licenses/LICENSE-2.0
972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang *
1072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * Unless required by applicable law or agreed to in writing, software
1172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * distributed under the License is distributed on an "AS IS" BASIS,
1272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * See the License for the specific language governing permissions and
1472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang * limitations under the License.
1572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang */
1672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang//#define LOG_NDEBUG 0
1872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#define LOG_TAG "MediaCodecSource"
1972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#define DEBUG_DRIFT_TIME 0
20a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
21a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h>
22a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn
23e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <gui/IGraphicBufferConsumer.h>
2472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/IGraphicBufferProducer.h>
2572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <gui/Surface.h>
2672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/ICrypto.h>
2772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ABuffer.h>
2872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ADebug.h>
2972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/ALooper.h>
3072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/foundation/AMessage.h>
3172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaBuffer.h>
3272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaCodec.h>
3316fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar#include <media/stagefright/MediaCodecList.h>
34e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MediaCodecSource.h>
3572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaErrors.h>
3672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/MediaSource.h>
37e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/MetaData.h>
38e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang#include <media/stagefright/PersistentSurface.h>
3972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#include <media/stagefright/Utils.h>
4072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
4172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangnamespace android {
4272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
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
486a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
4972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstruct MediaCodecSource::Puller : public AHandler {
5072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    Puller(const sp<MediaSource> &source);
5172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5272e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    void interruptSource();
5372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t start(const sp<MetaData> &meta, const sp<AMessage> &notify);
5416e79115e497386eaf010af388627f94314a55a3Chong Zhang    void stop();
556a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    void stopSource();
5672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void pause();
5772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void resume();
5872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
596a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    bool readBuffer(MediaBuffer **buffer);
606a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
6172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprotected:
6272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual void onMessageReceived(const sp<AMessage> &msg);
6372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    virtual ~Puller();
6472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangprivate:
6672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    enum {
6772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStart = 'msta',
6872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatStop,
6972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        kWhatPull,
7072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    };
7172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaSource> mSource;
7372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> mNotify;
7472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<ALooper> mLooper;
7572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    bool mIsAudio;
766a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
776a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    struct Queue {
786a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Queue()
796a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            : mReadPendingSince(0),
806a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar              mPaused(false),
816a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar              mPulling(false) { }
826a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        int64_t mReadPendingSince;
836a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        bool mPaused;
846a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        bool mPulling;
856a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Vector<MediaBuffer *> mReadBuffers;
866a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
876a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        void flush();
886a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // if queue is empty, return false and set *|buffer| to NULL . Otherwise, pop
8972e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar        // buffer from front of the queue, place it into *|buffer| and return true.
906a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        bool readBuffer(MediaBuffer **buffer);
9172e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar        // add a buffer to the back of the queue
926a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        void pushBuffer(MediaBuffer *mbuf);
936a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    };
946a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Queue> mQueue;
9572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t postSynchronouslyAndReturnError(const sp<AMessage> &msg);
9772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void schedulePull();
9872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    void handleEOS();
9972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    DISALLOW_EVIL_CONSTRUCTORS(Puller);
10172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang};
10272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
10372cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::Puller(const sp<MediaSource> &source)
10472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mSource(source),
10572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mLooper(new ALooper()),
1066a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar      mIsAudio(false)
1076a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar{
10872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MetaData> meta = source->getFormat();
10972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    const char *mime;
11072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(meta->findCString(kKeyMIMEType, &mime));
11172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mIsAudio = !strncasecmp(mime, "audio/", 6);
11372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->setName("pull_looper");
11572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
11672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
11772cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::Puller::~Puller() {
11872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(id());
11972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->stop();
12072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
12172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1226a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarvoid MediaCodecSource::Puller::Queue::pushBuffer(MediaBuffer *mbuf) {
1236a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    mReadBuffers.push_back(mbuf);
1246a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
1256a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
1266a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarbool MediaCodecSource::Puller::Queue::readBuffer(MediaBuffer **mbuf) {
1276a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    if (mReadBuffers.empty()) {
1286a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        *mbuf = NULL;
1296a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        return false;
1306a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
1316a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    *mbuf = *mReadBuffers.begin();
1326a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    mReadBuffers.erase(mReadBuffers.begin());
1336a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    return true;
1346a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
1356a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
1366a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarvoid MediaCodecSource::Puller::Queue::flush() {
1376a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    MediaBuffer *mbuf;
1386a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    while (readBuffer(&mbuf)) {
1396a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // there are no null buffers in the queue
1406a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        mbuf->release();
1416a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
1426a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
1436a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
1446a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarbool MediaCodecSource::Puller::readBuffer(MediaBuffer **mbuf) {
1456a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Queue>::Locked queue(mQueue);
1466a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    return queue->readBuffer(mbuf);
1476a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
1486a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
14972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::Puller::postSynchronouslyAndReturnError(
15072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
15172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
15272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
15372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
15572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
15672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
15772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
15872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
15972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
16072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
16172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
16272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
16372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
16472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1656a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarstatus_t MediaCodecSource::Puller::start(const sp<MetaData> &meta, const sp<AMessage> &notify) {
16672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGV("puller (%s) start", mIsAudio ? "audio" : "video");
16772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->start(
16872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* runOnCallingThread */,
16972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            false /* canCallJava */,
17072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            PRIORITY_AUDIO);
17172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(this);
17272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mNotify = notify;
17372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
1741d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStart, this);
17572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", meta);
17672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
17772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
17872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
17916e79115e497386eaf010af388627f94314a55a3Chong Zhangvoid MediaCodecSource::Puller::stop() {
1806a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    bool interrupt = false;
1816a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    {
1826a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // mark stopping before actually reaching kWhatStop on the looper, so the pulling will
1836a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // stop.
1846a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Mutexed<Queue>::Locked queue(mQueue);
1856a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        queue->mPulling = false;
1866a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        interrupt = queue->mReadPendingSince && (queue->mReadPendingSince < ALooper::GetNowUs() - 1000000);
1876a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        queue->flush(); // flush any unprocessed pulled buffers
1886a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
18916e79115e497386eaf010af388627f94314a55a3Chong Zhang
1906a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    if (interrupt) {
19172e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar        interruptSource();
1926a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
1936a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
19416e79115e497386eaf010af388627f94314a55a3Chong Zhang
19572e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnarvoid MediaCodecSource::Puller::interruptSource() {
19672e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    // call source->stop if read has been pending for over a second
19772e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    // We have to call this outside the looper as looper is pending on the read.
19872e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    mSource->stop();
19972e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar}
20072e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar
2016a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnarvoid MediaCodecSource::Puller::stopSource() {
20272e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStop, this);
20372e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar    (void)postSynchronouslyAndReturnError(msg);
20472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
20572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
20672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::pause() {
2076a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Queue>::Locked queue(mQueue);
2086a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    queue->mPaused = true;
20972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
21072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::resume() {
2126a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Queue>::Locked queue(mQueue);
2136a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    queue->mPaused = false;
21472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
21572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
21672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::schedulePull() {
2176a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    (new AMessage(kWhatPull, this))->post();
21872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
21972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::handleEOS() {
2216a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    ALOGV("puller (%s) posting EOS", mIsAudio ? "audio" : "video");
2226a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    sp<AMessage> msg = mNotify->dup();
2236a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    msg->setInt32("eos", 1);
2246a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    msg->post();
22572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
22672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
22772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::Puller::onMessageReceived(const sp<AMessage> &msg) {
22872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
22972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStart:
23072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
23172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<RefBase> obj;
23272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->findObject("meta", &obj));
23372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2346a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            {
2356a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                Mutexed<Queue>::Locked queue(mQueue);
2366a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                queue->mPulling = true;
2376a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            }
23872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
23972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->start(static_cast<MetaData *>(obj.get()));
24072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (err == OK) {
24272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                schedulePull();
24372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
24472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
24572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            sp<AMessage> response = new AMessage;
24672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->setInt32("err", err);
24772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2483f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar            sp<AReplyToken> replyID;
24972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(msg->senderAwaitsResponse(&replyID));
25072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            response->postReply(replyID);
25172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
25272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
25372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
25472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatStop:
25572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
2566a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            mSource->stop();
25772e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar
25872e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            sp<AMessage> response = new AMessage;
25972e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            response->setInt32("err", OK);
26072e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar
26172e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            sp<AReplyToken> replyID;
26272e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            CHECK(msg->senderAwaitsResponse(&replyID));
26372e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            response->postReply(replyID);
26472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
26572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
26672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
26772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        case kWhatPull:
26872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        {
2696a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            Mutexed<Queue>::Locked queue(mQueue);
2706a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue->mReadPendingSince = ALooper::GetNowUs();
2716a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            if (!queue->mPulling) {
2726a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                handleEOS();
27372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                break;
27472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
27572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2766a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue.unlock();
2776a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            MediaBuffer *mbuf = NULL;
27872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            status_t err = mSource->read(&mbuf);
2796a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue.lock();
28072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2816a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue->mReadPendingSince = 0;
2826a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            // if we need to discard buffer
2836a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            if (!queue->mPulling || queue->mPaused || err != OK) {
2846a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                if (mbuf != NULL) {
28572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf->release();
28672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mbuf = NULL;
28772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
2886a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                if (queue->mPulling && err == OK) {
2896a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                    msg->post(); // if simply paused, keep pulling source
2906d6c21b8d2ed66007833dae0451b0a211c97e592Wonsik Kim                    break;
2916a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                } else if (err == ERROR_END_OF_STREAM) {
29272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGV("stream ended, mbuf %p", mbuf);
2936a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                } else if (err != OK) {
29472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    ALOGE("error %d reading stream.", err);
29572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
2966a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            }
29772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
2986a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            if (mbuf != NULL) {
2996a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                queue->pushBuffer(mbuf);
30072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
30172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3026a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            queue.unlock();
30372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3046a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            if (mbuf != NULL) {
3056a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                mNotify->post();
3066a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                msg->post();
3076a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            } else {
3086a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                handleEOS();
3096a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            }
31072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
31172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
31272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
31372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        default:
31472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            TRESPASS();
31572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
31672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
31772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
3186a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos MolnarMediaCodecSource::Output::Output()
3196a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    : mEncoderReachedEOS(false),
3206a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar      mErrorCode(OK) {
3216a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar}
3226a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
32372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang// static
32472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<MediaCodecSource> MediaCodecSource::Create(
32572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
32672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &format,
32772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
328e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        const sp<IGraphicBufferConsumer> &consumer,
32972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags) {
33072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<MediaCodecSource> mediaSource =
331e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            new MediaCodecSource(looper, format, source, consumer, flags);
33272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
33372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mediaSource->init() == OK) {
33472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return mediaSource;
33572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
33672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return NULL;
33772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
33872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
339d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kimvoid MediaCodecSource::setInputBufferTimeOffset(int64_t timeOffsetUs) {
340d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    sp<AMessage> msg = new AMessage(kWhatSetInputBufferTimeOffset, mReflector);
341d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    msg->setInt64("time-offset-us", timeOffsetUs);
342d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    postSynchronouslyAndReturnError(msg);
343d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim}
344d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim
34572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::start(MetaData* params) {
3461d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStart, mReflector);
34772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    msg->setObject("meta", params);
34872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return postSynchronouslyAndReturnError(msg);
34972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
35072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::stop() {
3521d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    sp<AMessage> msg = new AMessage(kWhatStop, mReflector);
3536a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    return postSynchronouslyAndReturnError(msg);
35472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
35572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
35672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::pause() {
3571d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar    (new AMessage(kWhatPause, mReflector))->post();
35872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
35972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
36072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
361ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnarsp<MetaData> MediaCodecSource::getFormat() {
362ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    Mutexed<sp<MetaData>>::Locked meta(mMeta);
363ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    return *meta;
364ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar}
365ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar
36672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangsp<IGraphicBufferProducer> MediaCodecSource::getGraphicBufferProducer() {
36772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
36872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return mGraphicBufferProducer;
36972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
37072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MediaCodecSource::read(
37284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        MediaBuffer** buffer, const ReadOptions* /* options */) {
3736a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    Mutexed<Output>::Locked output(mOutput);
37472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
37572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    *buffer = NULL;
3766a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    while (output->mBufferQueue.size() == 0 && !output->mEncoderReachedEOS) {
3776a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        output.waitForCondition(output->mCond);
37872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
3796a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    if (!output->mEncoderReachedEOS) {
3806a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        *buffer = *output->mBufferQueue.begin();
3816a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        output->mBufferQueue.erase(output->mBufferQueue.begin());
38272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
38372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
3846a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    return output->mErrorCode;
38572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
38672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
38772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalBufferReturned(MediaBuffer *buffer) {
38872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->setObserver(0);
38972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    buffer->release();
39072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
39172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
39272cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::MediaCodecSource(
39372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<ALooper> &looper,
39472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &outputFormat,
39572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<MediaSource> &source,
396e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        const sp<IGraphicBufferConsumer> &consumer,
39772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags)
39872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    : mLooper(looper),
39972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mOutputFormat(outputFormat),
40072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mMeta(new MetaData),
40172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFlags(flags),
40272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mIsVideo(false),
40372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStarted(false),
40472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mStopping(false),
40572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mDoMoreWorkPending(false),
406c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mSetEncoderFormat(false),
407c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mEncoderFormat(0),
408c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar      mEncoderDataSpace(0),
409e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang      mGraphicBufferConsumer(consumer),
410d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim      mInputBufferTimeOffsetUs(0),
41172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang      mFirstSampleTimeUs(-1ll),
4126a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar      mGeneration(0) {
41372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mLooper != NULL);
41472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString mime;
41672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &mime));
41772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
41872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!strncasecmp("video/", mime.c_str(), 6)) {
41972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mIsVideo = true;
42072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
42172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
42372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mPuller = new Puller(source);
42472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
42572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
42672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
42772cecca17d735db6532c45f0a7e10c47ee6f065aChong ZhangMediaCodecSource::~MediaCodecSource() {
42872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    releaseEncoder();
42972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->stop();
43172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->unregisterHandler(mReflector->id());
43272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
43372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::init() {
43572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = initEncoder();
43672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
43772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
43872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        releaseEncoder();
43972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
44072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
44272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
44372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::initEncoder() {
44572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mReflector = new AHandlerReflector<MediaCodecSource>(this);
44672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mLooper->registerHandler(mReflector);
44772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
44872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper = new ALooper;
44972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->setName("codec_looper");
45072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mCodecLooper->start();
45172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
45272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
45372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mOutputFormat->setInt32("create-input-buffers-suspended", 1);
45472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
45572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
45672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    AString outputMIME;
45772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mOutputFormat->findString("mime", &outputMIME));
45872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
45916fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar    Vector<AString> matchingCodecs;
46016fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar    MediaCodecList::findMatchingCodecs(
46116fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar            outputMIME.c_str(), true /* encoder */,
46216fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar            ((mFlags & FLAG_PREFER_SOFTWARE_CODEC) ? MediaCodecList::kPreferSoftwareCodecs : 0),
46316fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar            &matchingCodecs);
46472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
46516fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar    status_t err = NO_INIT;
46616fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar    for (size_t ix = 0; ix < matchingCodecs.size(); ++ix) {
46716fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        mEncoder = MediaCodec::CreateByComponentName(
46816fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                mCodecLooper, matchingCodecs[ix]);
46916fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar
47016fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        if (mEncoder == NULL) {
47116fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar            continue;
47216fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        }
47316fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar
47416fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        ALOGV("output format is '%s'", mOutputFormat->debugString(0).c_str());
47572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47616fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, mReflector);
47716fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        mEncoder->setCallback(mEncoderActivityNotify);
47872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
47916fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        err = mEncoder->configure(
48016fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                    mOutputFormat,
48116fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                    NULL /* nativeWindow */,
48216fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                    NULL /* crypto */,
48316fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar                    MediaCodec::CONFIGURE_FLAG_ENCODE);
484421f47ca9c2dcc78584b2bb609c3755483b55155Marco Nelissen
48516fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        if (err == OK) {
48616fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar            break;
48716fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        }
48816fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        mEncoder->release();
48916fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar        mEncoder = NULL;
49016fcc47c113e63efa69f5af5decf1ad46ec653a9Lajos Molnar    }
49172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
49272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
49372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
49472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
49572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
49672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->getOutputFormat(&mOutputFormat);
497ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    sp<MetaData> meta = new MetaData;
498ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    convertMessageToMetaData(mOutputFormat, meta);
499ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar    mMeta.lock().set(meta);
50072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
50172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
50272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mIsVideo);
50372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
504e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        if (mGraphicBufferConsumer != NULL) {
505e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // When using persistent surface, we are only interested in the
506e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // consumer, but have to use PersistentSurface as a wrapper to
507e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            // pass consumer over messages (similar to BufferProducerWrapper)
5088f469e18c307cb9dc0d16ed9225972aa8be4516fChong Zhang            err = mEncoder->setInputSurface(
509e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang                    new PersistentSurface(NULL, mGraphicBufferConsumer));
510e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        } else {
511e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang            err = mEncoder->createInputSurface(&mGraphicBufferProducer);
512e2a2dfcbf0c9d6bb7139263ecf0d8e53b4ca1049Chong Zhang        }
51372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
51472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
51572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
51672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
51772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
51872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
519c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    sp<AMessage> inputFormat;
520c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    int32_t usingSwReadOften;
521c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    mSetEncoderFormat = false;
522b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar    if (mEncoder->getInputFormat(&inputFormat) == OK) {
523c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        mSetEncoderFormat = true;
524b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        if (inputFormat->findInt32("using-sw-read-often", &usingSwReadOften)
525b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar                && usingSwReadOften) {
526b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            // this is a SW encoder; signal source to allocate SW readable buffers
527b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            mEncoderFormat = kDefaultSwVideoEncoderFormat;
528b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        } else {
529b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            mEncoderFormat = kDefaultHwVideoEncoderFormat;
530b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        }
531b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        if (!inputFormat->findInt32("android._dataspace", &mEncoderDataSpace)) {
532b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar            mEncoderDataSpace = kDefaultVideoEncoderDataSpace;
533b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        }
534b77d03b62cb743d0faf74b54aa466b4d220b5e61Lajos Molnar        ALOGV("setting dataspace %#x, format %#x", mEncoderDataSpace, mEncoderFormat);
535c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar    }
536c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
5371099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan    err = mEncoder->start();
53872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
53972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
54072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
54172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
54272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
5436a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    {
5446a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Mutexed<Output>::Locked output(mOutput);
5456a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        output->mEncoderReachedEOS = false;
5466a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        output->mErrorCode = OK;
5476a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
54872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
54972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
55072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
55172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
55272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::releaseEncoder() {
55372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder == NULL) {
55472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return;
55572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
55672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
55772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder->release();
55872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mEncoder.clear();
55972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
56072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
56172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::postSynchronouslyAndReturnError(
56272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        const sp<AMessage> &msg) {
56372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    sp<AMessage> response;
56472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = msg->postAndAwaitResponse(&response);
56572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
56672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (err != OK) {
56772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return err;
56872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
56972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
57072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (!response->findInt32("err", &err)) {
57172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        err = OK;
57272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
57372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
57472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return err;
57572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
57672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
57772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::signalEOS(status_t err) {
5786a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    bool reachedEOS = false;
5796a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    {
5806a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        Mutexed<Output>::Locked output(mOutput);
5816a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        reachedEOS = output->mEncoderReachedEOS;
5826a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (!reachedEOS) {
5836a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio");
58472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // release all unread media buffers
5856a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            for (List<MediaBuffer*>::iterator it = output->mBufferQueue.begin();
5866a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                    it != output->mBufferQueue.end(); it++) {
58772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                (*it)->release();
58872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
5896a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output->mBufferQueue.clear();
5906a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output->mEncoderReachedEOS = true;
5916a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output->mErrorCode = err;
5926a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output->mCond.signal();
5936a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
5946a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            reachedEOS = true;
5956a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            output.unlock();
5966a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            releaseEncoder();
59772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
59872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
5996a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
6006a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    if (mStopping && reachedEOS) {
60116e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio");
6026a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        mPuller->stopSource();
6036a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
60472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // posting reply to everyone that's waiting
6053f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        List<sp<AReplyToken>>::iterator it;
60672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        for (it = mStopReplyIDQueue.begin();
60772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                it != mStopReplyIDQueue.end(); it++) {
60872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(*it);
60972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
61072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.clear();
61172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = false;
6126a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        ++mGeneration;
61372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
61472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
61572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
61672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::suspend() {
61772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
61872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
61972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
62072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", true);
62172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
62272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
62372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
62472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
62572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::resume(int64_t skipFramesBeforeUs) {
62672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    CHECK(mFlags & FLAG_USE_SURFACE_INPUT);
62772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mEncoder != NULL) {
62872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> params = new AMessage;
62972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        params->setInt32("drop-input-frames", false);
63072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (skipFramesBeforeUs > 0) {
63172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            params->setInt64("skip-frames-before", skipFramesBeforeUs);
63272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
63372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mEncoder->setParameters(params);
63472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
63572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
63672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
63772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::feedEncoderInputBuffers() {
6386a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    MediaBuffer* mbuf = NULL;
6396a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    while (!mAvailEncoderInputIndices.empty() && mPuller->readBuffer(&mbuf)) {
64072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t bufferIndex = *mAvailEncoderInputIndices.begin();
64172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mAvailEncoderInputIndices.erase(mAvailEncoderInputIndices.begin());
64272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
64372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t timeUs = 0ll;
64472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        uint32_t flags = 0;
64572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        size_t size = 0;
64672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
64772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mbuf != NULL) {
64872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
649d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim            timeUs += mInputBufferTimeOffsetUs;
65072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
65172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // push decoding time for video, or drift time for audio
65272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
65372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDecodingTimeQueue.push_back(timeUs);
65472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
65572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#if DEBUG_DRIFT_TIME
65672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mFirstSampleTimeUs < 0ll) {
65772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mFirstSampleTimeUs = timeUs;
65872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
65972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
66072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                int64_t driftTimeUs = 0;
66172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                if (mbuf->meta_data()->findInt64(kKeyDriftTime, &driftTimeUs)
66272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                        && driftTimeUs) {
66372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    driftTimeUs = timeUs - mFirstSampleTimeUs - driftTimeUs;
66472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                }
66572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mDriftTimeQueue.push_back(driftTimeUs);
66672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang#endif // DEBUG_DRIFT_TIME
66772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
66872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6691099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            sp<ABuffer> inbuf;
6701099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getInputBuffer(bufferIndex, &inbuf);
6711099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (err != OK || inbuf == NULL) {
6721099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->release();
6731099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
6741099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
6751099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
6761099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
67772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            size = mbuf->size();
67872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
6791099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            memcpy(inbuf->data(), mbuf->data(), size);
68072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
68172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            if (mIsVideo) {
68272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // video encoder will release MediaBuffer when done
68372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                // with underlying data.
6841099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                inbuf->setMediaBufferBase(mbuf);
68572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            } else {
68672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                mbuf->release();
68772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            }
68872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
68972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            flags = MediaCodec::BUFFER_FLAG_EOS;
69072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
69172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
69272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        status_t err = mEncoder->queueInputBuffer(
69372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                bufferIndex, 0, size, timeUs, flags);
69472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
69572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
69672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
69772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
69872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
69972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
70072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
70172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
70272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
70372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangstatus_t MediaCodecSource::onStart(MetaData *params) {
70472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStopping) {
70572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGE("Failed to start while we're stopping");
70672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return INVALID_OPERATION;
70772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
70872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
70972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mStarted) {
71072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        ALOGI("MediaCodecSource (%s) resuming", mIsVideo ? "video" : "audio");
7114cca134f0a775808458622490886d775c59bcc54Wonsik Kim        if (mIsVideo) {
7124cca134f0a775808458622490886d775c59bcc54Wonsik Kim            mEncoder->requestIDRFrame();
7134cca134f0a775808458622490886d775c59bcc54Wonsik Kim        }
71472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
71572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            resume();
71672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
71772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
71872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->resume();
71972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
72072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        return OK;
72172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
72272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
72372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) starting", mIsVideo ? "video" : "audio");
72472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
72572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    status_t err = OK;
72672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
72772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    if (mFlags & FLAG_USE_SURFACE_INPUT) {
72872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        int64_t startTimeUs;
72972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (!params || !params->findInt64(kKeyTime, &startTimeUs)) {
73072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            startTimeUs = -1ll;
73172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
73272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        resume(startTimeUs);
73372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    } else {
73472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(mPuller != NULL);
735c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        sp<MetaData> meta = params;
736c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        if (mSetEncoderFormat) {
737c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            if (meta == NULL) {
738c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar                meta = new MetaData;
739c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            }
740c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            meta->setInt32(kKeyPixelFormat, mEncoderFormat);
741c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar            meta->setInt32(kKeyColorSpace, mEncoderDataSpace);
742c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        }
743c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar
7441d15ab58bf8239069ef343de6cb21aabf3ef7d78Lajos Molnar        sp<AMessage> notify = new AMessage(kWhatPullerNotify, mReflector);
745c93a13669ce1b5a9e6527b4c86c9d8f5e92be828Lajos Molnar        err = mPuller->start(meta.get(), notify);
74672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (err != OK) {
74772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            return err;
74872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
74972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
75072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
75172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    ALOGI("MediaCodecSource (%s) started", mIsVideo ? "video" : "audio");
75272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
75372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    mStarted = true;
75472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    return OK;
75572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
75672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
75772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhangvoid MediaCodecSource::onMessageReceived(const sp<AMessage> &msg) {
75872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    switch (msg->what()) {
75972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPullerNotify:
76072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
7616a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        int32_t eos = 0;
7626a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (msg->findInt32("eos", &eos) && eos) {
7636a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("puller (%s) reached EOS", mIsVideo ? "video" : "audio");
76416e79115e497386eaf010af388627f94314a55a3Chong Zhang            signalEOS();
7656a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            break;
76672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
76772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
76872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
7696a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("got msg '%s' after encoder shutdown.", msg->debugString().c_str());
77072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
77172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
77272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
77372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        feedEncoderInputBuffers();
77472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
77572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
77672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatEncoderActivity:
77772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
77872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mEncoder == NULL) {
77972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
78072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
78172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
7821099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        int32_t cbID;
7831099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        CHECK(msg->findInt32("callbackID", &cbID));
7841099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        if (cbID == MediaCodec::CB_INPUT_AVAILABLE) {
7851099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
7861099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
7871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
7881099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mAvailEncoderInputIndices.push_back(index);
7891099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            feedEncoderInputBuffers();
79058fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar        } else if (cbID == MediaCodec::CB_OUTPUT_FORMAT_CHANGED) {
79158fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            status_t err = mEncoder->getOutputFormat(&mOutputFormat);
79258fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            if (err != OK) {
79358fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                signalEOS(err);
79458fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar                break;
79558fb7c6e1a9244dd7215a647388c440d8d75851bLajos Molnar            }
796ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar            sp<MetaData> meta = new MetaData;
797ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar            convertMessageToMetaData(mOutputFormat, meta);
798ee0eba046f666303741a5a5f70afad17030cc8b1Lajos Molnar            mMeta.lock().set(meta);
7991099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan        } else if (cbID == MediaCodec::CB_OUTPUT_AVAILABLE) {
8001099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t index;
8011099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t offset;
8021099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            size_t size;
8031099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int64_t timeUs;
8041099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            int32_t flags;
8051099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
8061099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("index", &index));
8071099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("offset", &offset));
8081099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findSize("size", &size));
8091099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt64("timeUs", &timeUs));
8101099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("flags", &flags));
8111099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
8121099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_EOS) {
8131099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mEncoder->releaseOutputBuffer(index);
8141099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
8151099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
8161099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
817f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
8181099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            sp<ABuffer> outbuf;
8191099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err = mEncoder->getOutputBuffer(index, &outbuf);
8201099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (err != OK || outbuf == NULL) {
8211099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                signalEOS();
8221099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                break;
8231099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
824f2a64852a4a48c5a3d8a08ffcda20d6884586672Chong Zhang
8251099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            MediaBuffer *mbuf = new MediaBuffer(outbuf->size());
8261099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            memcpy(mbuf->data(), outbuf->data(), outbuf->size());
82772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8281099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (!(flags & MediaCodec::BUFFER_FLAG_CODECCONFIG)) {
8291099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                if (mIsVideo) {
8301099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t decodingTimeUs;
8311099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    if (mFlags & FLAG_USE_SURFACE_INPUT) {
832d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim                        // Time offset is not applied at
833d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim                        // feedEncoderInputBuffer() in surface input case.
834d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim                        timeUs += mInputBufferTimeOffsetUs;
8351099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // GraphicBufferSource is supposed to discard samples
8361099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // queued before start, and offset timeUs by start time
8371099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        CHECK_GE(timeUs, 0ll);
8381099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // TODO:
8391099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // Decoding time for surface source is unavailable,
8401099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // use presentation time for now. May need to move
8411099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        // this logic into MediaCodec.
8421099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = timeUs;
8431099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    } else {
8441099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        CHECK(!mDecodingTimeQueue.empty());
8451099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        decodingTimeUs = *(mDecodingTimeQueue.begin());
8461099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                        mDecodingTimeQueue.erase(mDecodingTimeQueue.begin());
8471099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    }
8481099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mbuf->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
84972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
8501099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[video] time %" PRId64 " us (%.2f secs), dts/pts diff %" PRId64,
8511099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, decodingTimeUs - timeUs);
8521099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                } else {
8531099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    int64_t driftTimeUs = 0;
8541099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#if DEBUG_DRIFT_TIME
8551099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    CHECK(!mDriftTimeQueue.empty());
8561099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    driftTimeUs = *(mDriftTimeQueue.begin());
8571099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mDriftTimeQueue.erase(mDriftTimeQueue.begin());
8581099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mbuf->meta_data()->setInt64(kKeyDriftTime, driftTimeUs);
8591099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan#endif // DEBUG_DRIFT_TIME
8601099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    ALOGV("[audio] time %" PRId64 " us (%.2f secs), drift %" PRId64,
8611099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                            timeUs, timeUs / 1E6, driftTimeUs);
8621099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                }
8631099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt64(kKeyTime, timeUs);
8641099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            } else {
8651099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt32(kKeyIsCodecConfig, true);
8661099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
8671099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            if (flags & MediaCodec::BUFFER_FLAG_SYNCFRAME) {
8681099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                mbuf->meta_data()->setInt32(kKeyIsSyncFrame, true);
8691099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
8701099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mbuf->setObserver(this);
8711099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mbuf->add_ref();
8721099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
8731099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            {
8746a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                Mutexed<Output>::Locked output(mOutput);
8756a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                output->mBufferQueue.push_back(mbuf);
8766a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar                output->mCond.signal();
8771099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            }
8781099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan
8791099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            mEncoder->releaseOutputBuffer(index);
8801099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       } else if (cbID == MediaCodec::CB_ERROR) {
8811099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            status_t err;
8821099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            CHECK(msg->findInt32("err", &err));
8831099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            ALOGE("Encoder (%s) reported error : 0x%x",
8841099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan                    mIsVideo ? "video" : "audio", err);
8851099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan            signalEOS();
8861099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       }
8871099188151eb63af24ecf542b58d4257bbb8236aPraveen Chavan       break;
88872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
88972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStart:
89072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
8913f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
89272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
89372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
89472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<RefBase> obj;
89572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->findObject("meta", &obj));
89672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        MetaData *params = static_cast<MetaData *>(obj.get());
89772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
89872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        sp<AMessage> response = new AMessage;
89972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->setInt32("err", onStart(params));
90072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        response->postReply(replyID);
90172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
90272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
90372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatStop:
90472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
90516e79115e497386eaf010af388627f94314a55a3Chong Zhang        ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio");
90672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9073f27436a9346f043f52265da1e6a74cde2bffd4dLajos Molnar        sp<AReplyToken> replyID;
90872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        CHECK(msg->senderAwaitsResponse(&replyID));
90972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
9106a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (mOutput.lock()->mEncoderReachedEOS) {
91172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // if we already reached EOS, reply and return now
91216e79115e497386eaf010af388627f94314a55a3Chong Zhang            ALOGI("encoder (%s) already stopped",
91372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang                    mIsVideo ? "video" : "audio");
91472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            (new AMessage)->postReply(replyID);
91572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
91672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
91772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
91872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopReplyIDQueue.push_back(replyID);
91972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mStopping) {
92072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // nothing to do if we're already stopping, reply will be posted
92172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            // to all when we're stopped.
92272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            break;
92372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
92472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
92572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        mStopping = true;
92672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
92772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        // if using surface, signal source EOS and wait for EOS to come back.
9286a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // otherwise, stop puller (which also clears the input buffer queue)
9296a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // and wait for the EOS message. We cannot call source->stop() because
9306a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // the encoder may still be processing input buffers.
93172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        if (mFlags & FLAG_USE_SURFACE_INPUT) {
93272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mEncoder->signalEndOfInputStream();
93372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
9346a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            mPuller->stop();
93572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
9366a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
9376a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        // complete stop even if encoder/puller stalled
9386a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        sp<AMessage> timeoutMsg = new AMessage(kWhatStopStalled, mReflector);
9396a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        timeoutMsg->setInt32("generation", mGeneration);
9406a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        timeoutMsg->post(kStopTimeoutUs);
94172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
94272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
9436a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
9446a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    case kWhatStopStalled:
9456a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    {
9466a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        int32_t generation;
9476a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        CHECK(msg->findInt32("generation", &generation));
9486a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (generation != mGeneration) {
9496a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar             break;
9506a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        }
9516a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
9526a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        if (!(mFlags & FLAG_USE_SURFACE_INPUT)) {
9536a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("source (%s) stopping", mIsVideo ? "video" : "audio");
95472e9ab92e0dbee8d19ae2ec92ecd0a172b231b44Lajos Molnar            mPuller->interruptSource();
9556a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar            ALOGV("source (%s) stopped", mIsVideo ? "video" : "audio");
9566a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        }
9576a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar        signalEOS();
9586a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar    }
9596a3a56fbcd6c01c3895f14e43858971b0edca9b2Lajos Molnar
96072cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    case kWhatPause:
96172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    {
962d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        if (mFlags & FLAG_USE_SURFACE_INPUT) {
96372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            suspend();
96472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        } else {
96572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            CHECK(mPuller != NULL);
96672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang            mPuller->pause();
96772cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        }
96872cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        break;
96972cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
970d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    case kWhatSetInputBufferTimeOffset:
971d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    {
972d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        sp<AReplyToken> replyID;
973d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        CHECK(msg->senderAwaitsResponse(&replyID));
974d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim
975d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        CHECK(msg->findInt64("time-offset-us", &mInputBufferTimeOffsetUs));
976d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim
977d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        sp<AMessage> response = new AMessage;
978d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        response->postReply(replyID);
979d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim        break;
980d008275796ac4cccf85fefce53cef733a49bc1faWonsik Kim    }
98172cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    default:
98272cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang        TRESPASS();
98372cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang    }
98472cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang}
98572cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang
98672cecca17d735db6532c45f0a7e10c47ee6f065aChong Zhang} // namespace android
987