SimpleDecodingSource.cpp revision 5bd99f9211c533058be9f41bc966be1f2f501f13
100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar/*
200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar * Copyright 2016, The Android Open Source Project
300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar *
400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar * Licensed under the Apache License, Version 2.0 (the "License");
500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar * you may not use this file except in compliance with the License.
600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar * You may obtain a copy of the License at
700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar *
800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar *     http://www.apache.org/licenses/LICENSE-2.0
900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar *
1000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar * Unless required by applicable law or agreed to in writing, software
1100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar * distributed under the License is distributed on an "AS IS" BASIS,
1200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar * See the License for the specific language governing permissions and
1400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar * limitations under the License.
1500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar */
1600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
1700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar#include <gui/Surface.h>
1800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
1900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar#include <media/ICrypto.h>
2000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar#include <media/stagefright/foundation/ABuffer.h>
2100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar#include <media/stagefright/foundation/ALooper.h>
2200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar#include <media/stagefright/foundation/AMessage.h>
2300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar#include <media/stagefright/foundation/AUtils.h>
2400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar#include <media/stagefright/MediaBuffer.h>
2500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar#include <media/stagefright/MediaCodecList.h>
2600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar#include <media/stagefright/MediaCodec.h>
2700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar#include <media/stagefright/MetaData.h>
2800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar#include <media/stagefright/SimpleDecodingSource.h>
2900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar#include <media/stagefright/Utils.h>
3000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
3100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnarusing namespace android;
3200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
3300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnarconst int64_t kTimeoutWaitForOutputUs = 500000; // 0.5 seconds
343ca8f9cc3024b3306bd3782fc7d234570051a534Lajos Molnarconst int64_t kTimeoutWaitForInputUs = 5000; // 5 milliseconds
3500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
3600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar//static
3700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnarsp<SimpleDecodingSource> SimpleDecodingSource::Create(
38963f181c57a26dd23bd9dff263614bbb38960888Lajos Molnar        const sp<IMediaSource> &source, uint32_t flags, const sp<ANativeWindow> &nativeWindow,
39963f181c57a26dd23bd9dff263614bbb38960888Lajos Molnar        const char *desiredCodec) {
4000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    sp<Surface> surface = static_cast<Surface*>(nativeWindow.get());
4100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    const char *mime = NULL;
4200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    sp<MetaData> meta = source->getFormat();
4300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    CHECK(meta->findCString(kKeyMIMEType, &mime));
4400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
4500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    sp<AMessage> format = new AMessage;
465bd99f9211c533058be9f41bc966be1f2f501f13Lajos Molnar    if (convertMetaDataToMessage(source->getFormat(), &format) != OK) {
475bd99f9211c533058be9f41bc966be1f2f501f13Lajos Molnar        return NULL;
485bd99f9211c533058be9f41bc966be1f2f501f13Lajos Molnar    }
4900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
5000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    Vector<AString> matchingCodecs;
5100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    MediaCodecList::findMatchingCodecs(
5200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            mime, false /* encoder */, flags, &matchingCodecs);
5300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
5400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    sp<ALooper> looper = new ALooper;
5500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    looper->setName("stagefright");
5600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    looper->start();
5700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
5800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    sp<MediaCodec> codec;
5900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
6000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    for (size_t i = 0; i < matchingCodecs.size(); ++i) {
6100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        const AString &componentName = matchingCodecs[i];
62963f181c57a26dd23bd9dff263614bbb38960888Lajos Molnar        if (desiredCodec != NULL && componentName.compare(desiredCodec)) {
63963f181c57a26dd23bd9dff263614bbb38960888Lajos Molnar            continue;
64963f181c57a26dd23bd9dff263614bbb38960888Lajos Molnar        }
6500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
6600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        ALOGV("Attempting to allocate codec '%s'", componentName.c_str());
6700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
6800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        codec = MediaCodec::CreateByComponentName(looper, componentName);
6900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        if (codec != NULL) {
7000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            ALOGI("Successfully allocated codec '%s'", componentName.c_str());
7100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
7200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            status_t err = codec->configure(format, surface, NULL /* crypto */, 0 /* flags */);
7300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            if (err == OK) {
7400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                err = codec->getOutputFormat(&format);
7500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            }
7600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            if (err == OK) {
7700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                return new SimpleDecodingSource(codec, source, looper, surface != NULL, format);
7800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            }
7900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
8000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            ALOGD("Failed to configure codec '%s'", componentName.c_str());
8100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            codec->release();
8200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            codec = NULL;
8300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        }
8400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
8500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
8600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    looper->stop();
8700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    ALOGE("No matching decoder! (mime: %s)", mime);
8800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    return NULL;
8900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar}
9000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
9100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos MolnarSimpleDecodingSource::SimpleDecodingSource(
9200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        const sp<MediaCodec> &codec, const sp<IMediaSource> &source, const sp<ALooper> &looper,
9300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        bool usingSurface, const sp<AMessage> &format)
9400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    : mCodec(codec),
9500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar      mSource(source),
9600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar      mLooper(looper),
9700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar      mUsingSurface(usingSurface),
9800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar      mProtectedState(format) {
9900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    mCodec->getName(&mComponentName);
10000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar}
10100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
10200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos MolnarSimpleDecodingSource::~SimpleDecodingSource() {
10300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    mCodec->release();
10400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    mLooper->stop();
10500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar}
10600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
10700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnarstatus_t SimpleDecodingSource::start(MetaData *params) {
10800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    (void)params;
10900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    Mutexed<ProtectedState>::Locked me(mProtectedState);
11000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    if (me->mState != INIT) {
11100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        return -EINVAL;
11200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
11300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    status_t res = mCodec->start();
11400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    if (res == OK) {
11500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        res = mSource->start();
11600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
11700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
11800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    if (res == OK) {
11900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        me->mState = STARTED;
12000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        me->mQueuedInputEOS = false;
12100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        me->mGotOutputEOS = false;
12200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    } else {
12300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        me->mState = ERROR;
12400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
12500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
12600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    return res;
12700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar}
12800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
12900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnarstatus_t SimpleDecodingSource::stop() {
13000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    Mutexed<ProtectedState>::Locked me(mProtectedState);
13100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    if (me->mState != STARTED) {
13200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        return -EINVAL;
13300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
13400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
13500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    // wait for any pending reads to complete
13600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    me->mState = STOPPING;
13700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    while (me->mReading) {
13800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        me.waitForCondition(me->mReadCondition);
13900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
14000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
14100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    status_t res1 = mCodec->stop();
14200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    if (res1 != OK) {
14300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        mCodec->release();
14400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
14500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    status_t res2 = mSource->stop();
14600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    if (res1 == OK && res2 == OK) {
14700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        me->mState = STOPPED;
14800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    } else {
14900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        me->mState = ERROR;
15000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
15100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    return res1 != OK ? res1 : res2;
15200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar}
15300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
15400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnarsp<MetaData> SimpleDecodingSource::getFormat() {
15500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    Mutexed<ProtectedState>::Locked me(mProtectedState);
15600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    if (me->mState == STARTED || me->mState == INIT) {
15700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        sp<MetaData> meta = new MetaData();
15800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        convertMessageToMetaData(me->mFormat, meta);
15900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        return meta;
16000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
16100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    return NULL;
16200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar}
16300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
16400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos MolnarSimpleDecodingSource::ProtectedState::ProtectedState(const sp<AMessage> &format)
16500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    : mReading(false),
16600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar      mFormat(format),
16700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar      mState(INIT),
16800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar      mQueuedInputEOS(false),
16900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar      mGotOutputEOS(false) {
17000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar}
17100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
17200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnarstatus_t SimpleDecodingSource::read(
17300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        MediaBuffer **buffer, const ReadOptions *options) {
17400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    *buffer = NULL;
17500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
17600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    Mutexed<ProtectedState>::Locked me(mProtectedState);
17700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    if (me->mState != STARTED) {
17800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        return ERROR_END_OF_STREAM;
17900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
18000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    me->mReading = true;
18100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
18200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    status_t res = doRead(me, buffer, options);
18300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
18400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    me.lock();
18500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    me->mReading = false;
18600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    if (me->mState != STARTED) {
18700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        me->mReadCondition.signal();
18800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
18900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
19000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    return res;
19100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar}
19200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
19300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnarstatus_t SimpleDecodingSource::doRead(
19400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        Mutexed<ProtectedState>::Locked &me, MediaBuffer **buffer, const ReadOptions *options) {
19500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    // |me| is always locked on entry, but is allowed to be unlocked on exit
19600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    CHECK_EQ(me->mState, STARTED);
19700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
19800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    size_t out_ix, in_ix, out_offset, out_size;
19900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    int64_t out_pts;
20000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    uint32_t out_flags;
20100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    status_t res;
20200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
20300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    // flush codec on seek
20400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    IMediaSource::ReadOptions::SeekMode mode;
20500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    if (options != NULL && options->getSeekTo(&out_pts, &mode)) {
20600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        me->mQueuedInputEOS = false;
20700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        me->mGotOutputEOS = false;
20800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        mCodec->flush();
20900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
21000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
21100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    if (me->mGotOutputEOS) {
21200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        return ERROR_END_OF_STREAM;
21300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
21400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
2153ca8f9cc3024b3306bd3782fc7d234570051a534Lajos Molnar    for (int retries = 0; ++retries; ) {
21600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        // If we fill all available input buffers, we should expect that
21700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        // the codec produces at least one output buffer. Also, the codec
21800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        // should produce an output buffer in at most 1 seconds. Retry a
21900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        // few times nonetheless.
22000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        while (!me->mQueuedInputEOS) {
2213ca8f9cc3024b3306bd3782fc7d234570051a534Lajos Molnar            // allow some time to get input buffer after flush
2223ca8f9cc3024b3306bd3782fc7d234570051a534Lajos Molnar            res = mCodec->dequeueInputBuffer(&in_ix, kTimeoutWaitForInputUs);
22300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            if (res == -EAGAIN) {
22400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                // no available input buffers
22500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                break;
22600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            }
22700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
22800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            sp<ABuffer> in_buffer;
22900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            if (res == OK) {
23000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                res = mCodec->getInputBuffer(in_ix, &in_buffer);
23100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            }
23200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
23300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            if (res != OK || in_buffer == NULL) {
23400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                ALOGW("[%s] could not get input buffer #%zu",
23500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                        mComponentName.c_str(), in_ix);
23600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                me->mState = ERROR;
23700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                return UNKNOWN_ERROR;
23800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            }
23900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
24000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            MediaBuffer *in_buf;
24100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            while (true) {
24200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                in_buf = NULL;
24300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                me.unlock();
24400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                res = mSource->read(&in_buf, options);
24500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                me.lock();
24600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                if (res != OK || me->mState != STARTED) {
24700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    if (in_buf != NULL) {
24800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                        in_buf->release();
24900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                        in_buf = NULL;
25000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    }
25100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
25200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    // queue EOS
25300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    me->mQueuedInputEOS = true;
25400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    if (mCodec->queueInputBuffer(
25500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                                 in_ix, 0 /* offset */, 0 /* size */,
25600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                                 0 /* pts */, MediaCodec::BUFFER_FLAG_EOS) != OK) {
25700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                        ALOGI("[%s] failed to queue input EOS", mComponentName.c_str());
25800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                        me->mState = ERROR;
25900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                        return UNKNOWN_ERROR;
26000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    }
26100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
26200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    // don't stop on EOS, but report error or EOS on stop
26300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    if (res != ERROR_END_OF_STREAM) {
26400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                        me->mState = ERROR;
26500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                        return res;
26600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    }
26700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    if (me->mState != STARTED) {
26800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                        return ERROR_END_OF_STREAM;
26900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    }
27000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    break;
27100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                }
27200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                if (in_buf == NULL) { // should not happen
27300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    continue;
27400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                } else if (in_buf->range_length() != 0) {
27500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    break;
27600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                }
27700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                in_buf->release();
27800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            }
27900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
28000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            if (in_buf != NULL) {
28100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                int64_t timestampUs = 0;
28200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                CHECK(in_buf->meta_data()->findInt64(kKeyTime, &timestampUs));
28300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                if (in_buf->range_length() > in_buffer->capacity()) {
28400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    ALOGW("'%s' received %zu input bytes for buffer of size %zu",
28500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                            mComponentName.c_str(),
28600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                            in_buf->range_length(), in_buffer->capacity());
28700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                }
28800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                memcpy(in_buffer->base(), (uint8_t *)in_buf->data() + in_buf->range_offset(),
28900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                       min(in_buf->range_length(), in_buffer->capacity()));
29000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
29100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                res = mCodec->queueInputBuffer(
29200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                        in_ix, 0 /* offset */, in_buf->range_length(),
29300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                        timestampUs, 0 /* flags */);
29400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                if (res != OK) {
29500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    ALOGI("[%s] failed to queue input buffer #%zu", mComponentName.c_str(), in_ix);
29600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    me->mState = ERROR;
29700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                }
29800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                in_buf->release();
29900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            }
30000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        }
30100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
30200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        me.unlock();
30300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        res = mCodec->dequeueOutputBuffer(
30400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                &out_ix, &out_offset, &out_size, &out_pts,
30500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                &out_flags, kTimeoutWaitForOutputUs /* timeoutUs */);
30600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        me.lock();
30700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        // abort read on stop
30800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        if (me->mState != STARTED) {
30900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            if (res == OK) {
31000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                mCodec->releaseOutputBuffer(out_ix);
31100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            }
31200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            return ERROR_END_OF_STREAM;
31300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        }
31400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
31500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        if (res == -EAGAIN) {
31600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            ALOGD("[%s] did not produce an output buffer. retry count: %d",
31700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                  mComponentName.c_str(), retries);
31800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            continue;
31900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        } else if (res == INFO_FORMAT_CHANGED) {
32000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            if (mCodec->getOutputFormat(&me->mFormat) != OK) {
32100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                me->mState = ERROR;
32200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                res = UNKNOWN_ERROR;
32300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            }
32400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            return res;
32500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        } else if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
32600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            ALOGV("output buffers changed");
32700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            continue;
32800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        } else if (res != OK) {
32900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            me->mState = ERROR;
33000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            return res;
33100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        }
33200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
33300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        sp<ABuffer> out_buffer;
33400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        res = mCodec->getOutputBuffer(out_ix, &out_buffer);
33500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        if (res != OK) {
33600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            ALOGW("[%s] could not get output buffer #%zu",
33700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                    mComponentName.c_str(), out_ix);
33800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            me->mState = ERROR;
33900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            return UNKNOWN_ERROR;
34000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        }
34100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        if (out_flags & MediaCodec::BUFFER_FLAG_EOS) {
34200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            me->mGotOutputEOS = true;
34300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            // return EOS immediately if last buffer is empty
34400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            if (out_size == 0) {
34500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                mCodec->releaseOutputBuffer(out_ix);
34600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar                return ERROR_END_OF_STREAM;
34700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            }
34800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        }
34900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
35000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        if (mUsingSurface && out_size > 0) {
35100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            *buffer = new MediaBuffer(0);
35200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            mCodec->renderOutputBufferAndRelease(out_ix);
35300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        } else {
35400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            *buffer = new MediaBuffer(out_size);
35500eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            CHECK_LE(out_buffer->size(), (*buffer)->size());
35600eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            memcpy((*buffer)->data(), out_buffer->data(), out_buffer->size());
35700eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            (*buffer)->meta_data()->setInt64(kKeyTime, out_pts);
35800eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar            mCodec->releaseOutputBuffer(out_ix);
35900eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        }
36000eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar        return OK;
36100eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    }
36200eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar
36300eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar    return TIMED_OUT;
36400eb2fdb2b8f108e74c32e03b2a0e5bab3f107b6Lajos Molnar}
365