/*
 * Copyright 2016, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "SimpleDecodingSource"
#include <utils/Log.h>

#include <gui/Surface.h>

#include <mediadrm/ICrypto.h>
#include <media/MediaCodecBuffer.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaCodecList.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/SimpleDecodingSource.h>
#include <media/stagefright/Utils.h>

using namespace android;

const int64_t kTimeoutWaitForOutputUs = 500000; // 0.5 seconds
const int64_t kTimeoutWaitForInputUs = 0; // don't wait
const int kTimeoutMaxRetries = 20;

//static
sp<SimpleDecodingSource> SimpleDecodingSource::Create(
        const sp<MediaSource> &source, uint32_t flags) {
    return SimpleDecodingSource::Create(source, flags, nullptr, nullptr);
}

//static
sp<SimpleDecodingSource> SimpleDecodingSource::Create(
        const sp<MediaSource> &source, uint32_t flags, const sp<ANativeWindow> &nativeWindow,
        const char *desiredCodec, bool skipMediaCodecList) {
    sp<Surface> surface = static_cast<Surface*>(nativeWindow.get());
    const char *mime = NULL;
    sp<MetaData> meta = source->getFormat();
    CHECK(meta->findCString(kKeyMIMEType, &mime));

    sp<AMessage> format = new AMessage;
    if (convertMetaDataToMessage(source->getFormat(), &format) != OK) {
        return NULL;
    }

    Vector<AString> matchingCodecs;
    MediaCodecList::findMatchingCodecs(
            mime, false /* encoder */, flags, &matchingCodecs);

    sp<ALooper> looper = new ALooper;
    looper->setName("stagefright");
    looper->start();

    sp<MediaCodec> codec;
    auto configure = [=](const sp<MediaCodec> &codec, const AString &componentName)
            -> sp<SimpleDecodingSource> {
        if (codec != NULL) {
            ALOGI("Successfully allocated codec '%s'", componentName.c_str());

            status_t err = codec->configure(format, surface, NULL /* crypto */, 0 /* flags */);
            sp<AMessage> outFormat;
            if (err == OK) {
                err = codec->getOutputFormat(&outFormat);
            }
            if (err == OK) {
                return new SimpleDecodingSource(codec, source, looper,
                        surface != NULL,
                        strcmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS) == 0,
                        outFormat);
            }

            ALOGD("Failed to configure codec '%s'", componentName.c_str());
            codec->release();
        }
        return NULL;
    };

    if (skipMediaCodecList) {
        codec = MediaCodec::CreateByComponentName(looper, desiredCodec);
        return configure(codec, desiredCodec);
    }

    for (size_t i = 0; i < matchingCodecs.size(); ++i) {
        const AString &componentName = matchingCodecs[i];
        if (desiredCodec != NULL && componentName.compare(desiredCodec)) {
            continue;
        }

        ALOGV("Attempting to allocate codec '%s'", componentName.c_str());

        codec = MediaCodec::CreateByComponentName(looper, componentName);
        sp<SimpleDecodingSource> res = configure(codec, componentName);
        if (res != NULL) {
            return res;
        } else {
            codec = NULL;
        }
    }

    looper->stop();
    ALOGE("No matching decoder! (mime: %s)", mime);
    return NULL;
}

SimpleDecodingSource::SimpleDecodingSource(
        const sp<MediaCodec> &codec, const sp<MediaSource> &source, const sp<ALooper> &looper,
        bool usingSurface, bool isVorbis, const sp<AMessage> &format)
    : mCodec(codec),
      mSource(source),
      mLooper(looper),
      mUsingSurface(usingSurface),
      mIsVorbis(isVorbis),
      mProtectedState(format) {
    mCodec->getName(&mComponentName);
}

SimpleDecodingSource::~SimpleDecodingSource() {
    mCodec->release();
    mLooper->stop();
}

status_t SimpleDecodingSource::start(MetaData *params) {
    (void)params;
    Mutexed<ProtectedState>::Locked me(mProtectedState);
    if (me->mState != INIT) {
        return -EINVAL;
    }
    status_t res = mCodec->start();
    if (res == OK) {
        res = mSource->start();
    }

    if (res == OK) {
        me->mState = STARTED;
        me->mQueuedInputEOS = false;
        me->mGotOutputEOS = false;
    } else {
        me->mState = ERROR;
    }

    return res;
}

status_t SimpleDecodingSource::stop() {
    Mutexed<ProtectedState>::Locked me(mProtectedState);
    if (me->mState != STARTED) {
        return -EINVAL;
    }

    // wait for any pending reads to complete
    me->mState = STOPPING;
    while (me->mReading) {
        me.waitForCondition(me->mReadCondition);
    }

    status_t res1 = mCodec->stop();
    if (res1 != OK) {
        mCodec->release();
    }
    status_t res2 = mSource->stop();
    if (res1 == OK && res2 == OK) {
        me->mState = STOPPED;
    } else {
        me->mState = ERROR;
    }
    return res1 != OK ? res1 : res2;
}

sp<MetaData> SimpleDecodingSource::getFormat() {
    Mutexed<ProtectedState>::Locked me(mProtectedState);
    if (me->mState == STARTED || me->mState == INIT) {
        sp<MetaData> meta = new MetaData();
        convertMessageToMetaData(me->mFormat, meta);
        return meta;
    }
    return NULL;
}

SimpleDecodingSource::ProtectedState::ProtectedState(const sp<AMessage> &format)
    : mReading(false),
      mFormat(format),
      mState(INIT),
      mQueuedInputEOS(false),
      mGotOutputEOS(false) {
}

status_t SimpleDecodingSource::read(
        MediaBufferBase **buffer, const ReadOptions *options) {
    *buffer = NULL;

    Mutexed<ProtectedState>::Locked me(mProtectedState);
    if (me->mState != STARTED) {
        return ERROR_END_OF_STREAM;
    }
    me->mReading = true;

    status_t res = doRead(me, buffer, options);

    me.lock();
    me->mReading = false;
    if (me->mState != STARTED) {
        me->mReadCondition.signal();
    }

    return res;
}

status_t SimpleDecodingSource::doRead(
        Mutexed<ProtectedState>::Locked &me, MediaBufferBase **buffer, const ReadOptions *options) {
    // |me| is always locked on entry, but is allowed to be unlocked on exit
    CHECK_EQ(me->mState, STARTED);

    size_t out_ix, in_ix, out_offset, out_size;
    int64_t out_pts;
    uint32_t out_flags;
    status_t res;

    // flush codec on seek
    MediaSource::ReadOptions::SeekMode mode;
    if (options != NULL && options->getSeekTo(&out_pts, &mode)) {
        me->mQueuedInputEOS = false;
        me->mGotOutputEOS = false;
        mCodec->flush();
    }

    if (me->mGotOutputEOS) {
        return ERROR_END_OF_STREAM;
    }

    for (int retries = 0; retries < kTimeoutMaxRetries; ++retries) {
        // If we fill all available input buffers, we should expect that
        // the codec produces at least one output buffer. Also, the codec
        // should produce an output buffer in at most 1 seconds. Retry a
        // few times nonetheless.
        while (!me->mQueuedInputEOS) {
            // allow some time to get input buffer after flush
            res = mCodec->dequeueInputBuffer(&in_ix, kTimeoutWaitForInputUs);
            if (res == -EAGAIN) {
                // no available input buffers
                break;
            }

            sp<MediaCodecBuffer> in_buffer;
            if (res == OK) {
                res = mCodec->getInputBuffer(in_ix, &in_buffer);
            }

            if (res != OK || in_buffer == NULL) {
                ALOGW("[%s] could not get input buffer #%zu",
                        mComponentName.c_str(), in_ix);
                me->mState = ERROR;
                return UNKNOWN_ERROR;
            }

            MediaBufferBase *in_buf;
            while (true) {
                in_buf = NULL;
                me.unlock();
                res = mSource->read(&in_buf, options);
                me.lock();
                if (res != OK || me->mState != STARTED) {
                    if (in_buf != NULL) {
                        in_buf->release();
                        in_buf = NULL;
                    }

                    // queue EOS
                    me->mQueuedInputEOS = true;
                    if (mCodec->queueInputBuffer(
                                 in_ix, 0 /* offset */, 0 /* size */,
                                 0 /* pts */, MediaCodec::BUFFER_FLAG_EOS) != OK) {
                        ALOGI("[%s] failed to queue input EOS", mComponentName.c_str());
                        me->mState = ERROR;
                        return UNKNOWN_ERROR;
                    }

                    // don't stop on EOS, but report error or EOS on stop
                    if (res != ERROR_END_OF_STREAM) {
                        me->mState = ERROR;
                        return res;
                    }
                    if (me->mState != STARTED) {
                        return ERROR_END_OF_STREAM;
                    }
                    break;
                }
                if (in_buf == NULL) { // should not happen
                    continue;
                } else if (in_buf->range_length() != 0) {
                    break;
                }
                in_buf->release();
            }

            if (in_buf != NULL) {
                int64_t timestampUs = 0;
                CHECK(in_buf->meta_data().findInt64(kKeyTime, &timestampUs));
                if (in_buf->range_length() + (mIsVorbis ? 4 : 0) > in_buffer->capacity()) {
                    ALOGW("'%s' received %zu input bytes for buffer of size %zu",
                            mComponentName.c_str(),
                            in_buf->range_length() + (mIsVorbis ? 4 : 0), in_buffer->capacity());
                }
                size_t cpLen = min(in_buf->range_length(), in_buffer->capacity());
                memcpy(in_buffer->base(), (uint8_t *)in_buf->data() + in_buf->range_offset(),
                        cpLen);

                if (mIsVorbis) {
                    int32_t numPageSamples;
                    if (!in_buf->meta_data().findInt32(kKeyValidSamples, &numPageSamples)) {
                        numPageSamples = -1;
                    }
                    if (cpLen + sizeof(numPageSamples) <= in_buffer->capacity()) {
                        memcpy(in_buffer->base() + cpLen, &numPageSamples, sizeof(numPageSamples));
                        cpLen += sizeof(numPageSamples);
                    } else {
                        ALOGW("Didn't have enough space to copy kKeyValidSamples");
                    }
                }

                res = mCodec->queueInputBuffer(
                        in_ix, 0 /* offset */, cpLen,
                        timestampUs, 0 /* flags */);
                if (res != OK) {
                    ALOGI("[%s] failed to queue input buffer #%zu", mComponentName.c_str(), in_ix);
                    me->mState = ERROR;
                }
                in_buf->release();
            }
        }

        me.unlock();
        res = mCodec->dequeueOutputBuffer(
                &out_ix, &out_offset, &out_size, &out_pts,
                &out_flags, kTimeoutWaitForOutputUs /* timeoutUs */);
        me.lock();
        // abort read on stop
        if (me->mState != STARTED) {
            if (res == OK) {
                mCodec->releaseOutputBuffer(out_ix);
            }
            return ERROR_END_OF_STREAM;
        }

        if (res == -EAGAIN) {
            ALOGD("[%s] did not produce an output buffer. retry count: %d",
                  mComponentName.c_str(), retries);
            continue;
        } else if (res == INFO_FORMAT_CHANGED) {
            if (mCodec->getOutputFormat(&me->mFormat) != OK) {
                me->mState = ERROR;
                res = UNKNOWN_ERROR;
            }
            return res;
        } else if (res == INFO_OUTPUT_BUFFERS_CHANGED) {
            ALOGV("output buffers changed");
            continue;
        } else if (res != OK) {
            me->mState = ERROR;
            return res;
        }

        sp<MediaCodecBuffer> out_buffer;
        res = mCodec->getOutputBuffer(out_ix, &out_buffer);
        if (res != OK) {
            ALOGW("[%s] could not get output buffer #%zu",
                    mComponentName.c_str(), out_ix);
            me->mState = ERROR;
            return UNKNOWN_ERROR;
        }
        if (out_flags & MediaCodec::BUFFER_FLAG_EOS) {
            me->mGotOutputEOS = true;
            // return EOS immediately if last buffer is empty
            if (out_size == 0) {
                mCodec->releaseOutputBuffer(out_ix);
                return ERROR_END_OF_STREAM;
            }
        }

        if (mUsingSurface && out_size > 0) {
            *buffer = new MediaBuffer(0);
            mCodec->renderOutputBufferAndRelease(out_ix);
        } else {
            *buffer = new MediaBuffer(out_size);
            CHECK_LE(out_buffer->size(), (*buffer)->size());
            memcpy((*buffer)->data(), out_buffer->data(), out_buffer->size());
            (*buffer)->meta_data().setInt64(kKeyTime, out_pts);
            mCodec->releaseOutputBuffer(out_ix);
        }
        return OK;
    }

    return TIMED_OUT;
}
