/*
 * Copyright (C) 2019 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 "C2Decoder"

#include "C2Decoder.h"

int32_t C2Decoder::createCodec2Component(string compName, AMediaFormat *format) {
    ALOGV("In %s", __func__);
    mListener.reset(new CodecListener(
            [this](std::list<std::unique_ptr<C2Work>> &workItems) { handleWorkDone(workItems); }));
    if (!mListener) return -1;

    const char *mime = nullptr;
    AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
    if (!mime) {
        ALOGE("Error in AMediaFormat_getString");
        return -1;
    }
    // Configure the plugin with Input properties
    std::vector<C2Param *> configParam;
    if (!strncmp(mime, "audio/", 6)) {
        int32_t sampleRate, numChannels;
        AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &sampleRate);
        AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &numChannels);
        C2StreamSampleRateInfo::output sampleRateInfo(0u, sampleRate);
        C2StreamChannelCountInfo::output channelCountInfo(0u, numChannels);
        configParam.push_back(&sampleRateInfo);
        configParam.push_back(&channelCountInfo);

    } else {
        int32_t width, height;
        AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &width);
        AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &height);
        C2StreamPictureSizeInfo::input inputSize(0u, width, height);
        configParam.push_back(&inputSize);
    }

    int64_t sTime = mStats->getCurTime();
    mComponent = mClient->CreateComponentByName(compName.c_str(), mListener, &mClient);
    if (mComponent == nullptr) {
        ALOGE("Create component failed for %s", compName.c_str());
        return -1;
    }
    std::vector<std::unique_ptr<C2SettingResult>> failures;
    int32_t status = mComponent->config(configParam, C2_DONT_BLOCK, &failures);
    if (failures.size() != 0) {
        ALOGE("Invalid Configuration");
        return -1;
    }

    status |= mComponent->start();
    int64_t eTime = mStats->getCurTime();
    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
    mStats->setInitTime(timeTaken);
    return status;
}

int32_t C2Decoder::decodeFrames(uint8_t *inputBuffer, vector<AMediaCodecBufferInfo> &frameInfo) {
    ALOGV("In %s", __func__);
    typedef std::unique_lock<std::mutex> ULock;
    c2_status_t status = C2_OK;
    mStats->setStartTime();
    while (1) {
        if (mNumInputFrame == frameInfo.size()) break;
        std::unique_ptr<C2Work> work;
        // Prepare C2Work
        {
            ULock l(mQueueLock);
            if (mWorkQueue.empty()) mQueueCondition.wait_for(l, MAX_RETRY * TIME_OUT);
            if (!mWorkQueue.empty()) {
                mStats->addInputTime();
                work.swap(mWorkQueue.front());
                mWorkQueue.pop_front();
            } else {
                cout << "Wait for generating C2Work exceeded timeout" << endl;
                return -1;
            }
        }

        uint32_t flags = frameInfo[mNumInputFrame].flags;
        if (flags == AMEDIACODEC_BUFFER_FLAG_CODEC_CONFIG) {
            flags = C2FrameData::FLAG_CODEC_CONFIG;
        }
        if (mNumInputFrame == (frameInfo.size() - 1)) {
            flags |= C2FrameData::FLAG_END_OF_STREAM;
        }
        work->input.flags = (C2FrameData::flags_t)flags;
        work->input.ordinal.timestamp = frameInfo[mNumInputFrame].presentationTimeUs;
        work->input.ordinal.frameIndex = mNumInputFrame;
        work->input.buffers.clear();
        int size = frameInfo[mNumInputFrame].size;
        int alignedSize = ALIGN(size, PAGE_SIZE);
        if (size) {
            std::shared_ptr<C2LinearBlock> block;
            status = mLinearPool->fetchLinearBlock(
                    alignedSize, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE}, &block);
            if (status != C2_OK || block == nullptr) {
                cout << "C2LinearBlock::map() failed : " << status << endl;
                return status;
            }

            C2WriteView view = block->map().get();
            if (view.error() != C2_OK) {
                cout << "C2LinearBlock::map() failed : " << view.error() << endl;
                return view.error();
            }
            memcpy(view.base(), inputBuffer + mOffset, size);
            work->input.buffers.emplace_back(new LinearBuffer(block, size));
            mStats->addFrameSize(size);
        }
        work->worklets.clear();
        work->worklets.emplace_back(new C2Worklet);

        std::list<std::unique_ptr<C2Work>> items;
        items.push_back(std::move(work));
        // queue() invokes process() function of C2 Plugin.
        status = mComponent->queue(&items);
        if (status != C2_OK) {
            ALOGE("queue failed");
            return status;
        }
        ALOGV("Frame #%d size = %d queued", mNumInputFrame, size);
        mNumInputFrame++;
        mOffset += size;
    }
    return status;
}

void C2Decoder::deInitCodec() {
    ALOGV("In %s", __func__);
    if (!mComponent) return;

    int64_t sTime = mStats->getCurTime();
    mComponent->stop();
    mComponent->release();
    mComponent = nullptr;
    int64_t eTime = mStats->getCurTime();
    int64_t timeTaken = mStats->getTimeDiff(sTime, eTime);
    mStats->setDeInitTime(timeTaken);
}

void C2Decoder::dumpStatistics(string inputReference, int64_t durationUs, string componentName,
                               string statsFile) {
    string operation = "c2decode";
    string mode = "async";
    mStats->dumpStatistics(operation, inputReference, durationUs, componentName, mode, statsFile);
}

void C2Decoder::resetDecoder() {
    mOffset = 0;
    mNumInputFrame = 0;
    if (mStats) mStats->reset();
}
