/*
 * Copyright (C) 2011 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 "SoftVorbis"
#include <utils/Log.h>

#include "SoftVorbis.h"

#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>

extern "C" {
    #include <Tremolo/codec_internal.h>

    int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb);
    int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb);
    int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb);
}

namespace android {

template<class T>
static void InitOMXParams(T *params) {
    params->nSize = sizeof(T);
    params->nVersion.s.nVersionMajor = 1;
    params->nVersion.s.nVersionMinor = 0;
    params->nVersion.s.nRevision = 0;
    params->nVersion.s.nStep = 0;
}

SoftVorbis::SoftVorbis(
        const char *name,
        const OMX_CALLBACKTYPE *callbacks,
        OMX_PTR appData,
        OMX_COMPONENTTYPE **component)
    : SimpleSoftOMXComponent(name, callbacks, appData, component),
      mInputBufferCount(0),
      mState(NULL),
      mVi(NULL),
      mAnchorTimeUs(0),
      mNumFramesOutput(0),
      mNumFramesLeftOnPage(-1),
      mSawInputEos(false),
      mSignalledOutputEos(false),
      mOutputPortSettingsChange(NONE) {
    initPorts();
    CHECK_EQ(initDecoder(), (status_t)OK);
}

SoftVorbis::~SoftVorbis() {
    if (mState != NULL) {
        vorbis_dsp_clear(mState);
        delete mState;
        mState = NULL;
    }

    if (mVi != NULL) {
        vorbis_info_clear(mVi);
        delete mVi;
        mVi = NULL;
    }
}

void SoftVorbis::initPorts() {
    OMX_PARAM_PORTDEFINITIONTYPE def;
    InitOMXParams(&def);

    def.nPortIndex = 0;
    def.eDir = OMX_DirInput;
    def.nBufferCountMin = kNumBuffers;
    def.nBufferCountActual = def.nBufferCountMin;
    def.nBufferSize = 8192;
    def.bEnabled = OMX_TRUE;
    def.bPopulated = OMX_FALSE;
    def.eDomain = OMX_PortDomainAudio;
    def.bBuffersContiguous = OMX_FALSE;
    def.nBufferAlignment = 1;

    def.format.audio.cMIMEType =
        const_cast<char *>(MEDIA_MIMETYPE_AUDIO_VORBIS);

    def.format.audio.pNativeRender = NULL;
    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
    def.format.audio.eEncoding = OMX_AUDIO_CodingVORBIS;

    addPort(def);

    def.nPortIndex = 1;
    def.eDir = OMX_DirOutput;
    def.nBufferCountMin = kNumBuffers;
    def.nBufferCountActual = def.nBufferCountMin;
    def.nBufferSize = kMaxNumSamplesPerBuffer * sizeof(int16_t);
    def.bEnabled = OMX_TRUE;
    def.bPopulated = OMX_FALSE;
    def.eDomain = OMX_PortDomainAudio;
    def.bBuffersContiguous = OMX_FALSE;
    def.nBufferAlignment = 2;

    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
    def.format.audio.pNativeRender = NULL;
    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;

    addPort(def);
}

status_t SoftVorbis::initDecoder() {
    return OK;
}

OMX_ERRORTYPE SoftVorbis::internalGetParameter(
        OMX_INDEXTYPE index, OMX_PTR params) {
    switch (index) {
        case OMX_IndexParamAudioVorbis:
        {
            OMX_AUDIO_PARAM_VORBISTYPE *vorbisParams =
                (OMX_AUDIO_PARAM_VORBISTYPE *)params;

            if (vorbisParams->nPortIndex != 0) {
                return OMX_ErrorUndefined;
            }

            vorbisParams->nBitRate = 0;
            vorbisParams->nMinBitRate = 0;
            vorbisParams->nMaxBitRate = 0;
            vorbisParams->nAudioBandWidth = 0;
            vorbisParams->nQuality = 3;
            vorbisParams->bManaged = OMX_FALSE;
            vorbisParams->bDownmix = OMX_FALSE;

            if (!isConfigured()) {
                vorbisParams->nChannels = 1;
                vorbisParams->nSampleRate = 44100;
            } else {
                vorbisParams->nChannels = mVi->channels;
                vorbisParams->nSampleRate = mVi->rate;
                vorbisParams->nBitRate = mVi->bitrate_nominal;
                vorbisParams->nMinBitRate = mVi->bitrate_lower;
                vorbisParams->nMaxBitRate = mVi->bitrate_upper;
            }

            return OMX_ErrorNone;
        }

        case OMX_IndexParamAudioPcm:
        {
            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;

            if (pcmParams->nPortIndex != 1) {
                return OMX_ErrorUndefined;
            }

            pcmParams->eNumData = OMX_NumericalDataSigned;
            pcmParams->eEndian = OMX_EndianBig;
            pcmParams->bInterleaved = OMX_TRUE;
            pcmParams->nBitPerSample = 16;
            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;

            if (!isConfigured()) {
                pcmParams->nChannels = 1;
                pcmParams->nSamplingRate = 44100;
            } else {
                pcmParams->nChannels = mVi->channels;
                pcmParams->nSamplingRate = mVi->rate;
            }

            return OMX_ErrorNone;
        }

        default:
            return SimpleSoftOMXComponent::internalGetParameter(index, params);
    }
}

OMX_ERRORTYPE SoftVorbis::internalSetParameter(
        OMX_INDEXTYPE index, const OMX_PTR params) {
    switch (index) {
        case OMX_IndexParamStandardComponentRole:
        {
            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
                (const OMX_PARAM_COMPONENTROLETYPE *)params;

            if (strncmp((const char *)roleParams->cRole,
                        "audio_decoder.vorbis",
                        OMX_MAX_STRINGNAME_SIZE - 1)) {
                return OMX_ErrorUndefined;
            }

            return OMX_ErrorNone;
        }

        case OMX_IndexParamAudioVorbis:
        {
            const OMX_AUDIO_PARAM_VORBISTYPE *vorbisParams =
                (const OMX_AUDIO_PARAM_VORBISTYPE *)params;

            if (vorbisParams->nPortIndex != 0) {
                return OMX_ErrorUndefined;
            }

            return OMX_ErrorNone;
        }

        default:
            return SimpleSoftOMXComponent::internalSetParameter(index, params);
    }
}

bool SoftVorbis::isConfigured() const {
    return mInputBufferCount >= 2;
}

static void makeBitReader(
        const void *data, size_t size,
        ogg_buffer *buf, ogg_reference *ref, oggpack_buffer *bits) {
    buf->data = (uint8_t *)data;
    buf->size = size;
    buf->refcount = 1;
    buf->ptr.owner = NULL;

    ref->buffer = buf;
    ref->begin = 0;
    ref->length = size;
    ref->next = NULL;

    oggpack_readinit(bits, ref);
}

void SoftVorbis::onQueueFilled(OMX_U32 portIndex) {
    List<BufferInfo *> &inQueue = getPortQueue(0);
    List<BufferInfo *> &outQueue = getPortQueue(1);

    if (mOutputPortSettingsChange != NONE) {
        return;
    }

    if (portIndex == 0 && mInputBufferCount < 2) {
        BufferInfo *info = *inQueue.begin();
        OMX_BUFFERHEADERTYPE *header = info->mHeader;

        const uint8_t *data = header->pBuffer + header->nOffset;
        size_t size = header->nFilledLen;

        ogg_buffer buf;
        ogg_reference ref;
        oggpack_buffer bits;

        makeBitReader(
                (const uint8_t *)data + 7, size - 7,
                &buf, &ref, &bits);

        if (mInputBufferCount == 0) {
            CHECK(mVi == NULL);
            mVi = new vorbis_info;
            vorbis_info_init(mVi);

            CHECK_EQ(0, _vorbis_unpack_info(mVi, &bits));
        } else {
            CHECK_EQ(0, _vorbis_unpack_books(mVi, &bits));

            CHECK(mState == NULL);
            mState = new vorbis_dsp_state;
            CHECK_EQ(0, vorbis_dsp_init(mState, mVi));

            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
            mOutputPortSettingsChange = AWAITING_DISABLED;
        }

        inQueue.erase(inQueue.begin());
        info->mOwnedByUs = false;
        notifyEmptyBufferDone(header);

        ++mInputBufferCount;

        return;
    }

    while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
        BufferInfo *inInfo = NULL;
        OMX_BUFFERHEADERTYPE *inHeader = NULL;
        if (!inQueue.empty()) {
            inInfo = *inQueue.begin();
            inHeader = inInfo->mHeader;
        }

        BufferInfo *outInfo = *outQueue.begin();
        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;

        int32_t numPageSamples = 0;

        if (inHeader) {
            if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
                mSawInputEos = true;
            }

            if (inHeader->nFilledLen || !mSawInputEos) {
                CHECK_GE(inHeader->nFilledLen, sizeof(numPageSamples));
                memcpy(&numPageSamples,
                       inHeader->pBuffer
                        + inHeader->nOffset + inHeader->nFilledLen - 4,
                       sizeof(numPageSamples));

                if (inHeader->nOffset == 0) {
                    mAnchorTimeUs = inHeader->nTimeStamp;
                    mNumFramesOutput = 0;
                }

                inHeader->nFilledLen -= sizeof(numPageSamples);;
            }
        }

        if (numPageSamples >= 0) {
            mNumFramesLeftOnPage = numPageSamples;
        }

        ogg_buffer buf;
        buf.data = inHeader ? inHeader->pBuffer + inHeader->nOffset : NULL;
        buf.size = inHeader ? inHeader->nFilledLen : 0;
        buf.refcount = 1;
        buf.ptr.owner = NULL;

        ogg_reference ref;
        ref.buffer = &buf;
        ref.begin = 0;
        ref.length = buf.size;
        ref.next = NULL;

        ogg_packet pack;
        pack.packet = &ref;
        pack.bytes = ref.length;
        pack.b_o_s = 0;
        pack.e_o_s = 0;
        pack.granulepos = 0;
        pack.packetno = 0;

        int numFrames = 0;

        outHeader->nFlags = 0;
        int err = vorbis_dsp_synthesis(mState, &pack, 1);
        if (err != 0) {
            // FIXME temporary workaround for log spam
#if !defined(__arm__) && !defined(__aarch64__)
            ALOGV("vorbis_dsp_synthesis returned %d", err);
#else
            ALOGW("vorbis_dsp_synthesis returned %d", err);
#endif
        } else {
            numFrames = vorbis_dsp_pcmout(
                    mState, (int16_t *)outHeader->pBuffer,
                    (kMaxNumSamplesPerBuffer / mVi->channels));

            if (numFrames < 0) {
                ALOGE("vorbis_dsp_pcmout returned %d", numFrames);
                numFrames = 0;
            }
        }

        if (mNumFramesLeftOnPage >= 0) {
            if (numFrames > mNumFramesLeftOnPage) {
                ALOGV("discarding %d frames at end of page",
                     numFrames - mNumFramesLeftOnPage);
                numFrames = mNumFramesLeftOnPage;
                if (mSawInputEos) {
                    outHeader->nFlags = OMX_BUFFERFLAG_EOS;
                    mSignalledOutputEos = true;
                }
            }
            mNumFramesLeftOnPage -= numFrames;
        }

        outHeader->nFilledLen = numFrames * sizeof(int16_t) * mVi->channels;
        outHeader->nOffset = 0;

        outHeader->nTimeStamp =
            mAnchorTimeUs
                + (mNumFramesOutput * 1000000ll) / mVi->rate;

        mNumFramesOutput += numFrames;

        if (inHeader) {
            inInfo->mOwnedByUs = false;
            inQueue.erase(inQueue.begin());
            inInfo = NULL;
            notifyEmptyBufferDone(inHeader);
            inHeader = NULL;
        }

        outInfo->mOwnedByUs = false;
        outQueue.erase(outQueue.begin());
        outInfo = NULL;
        notifyFillBufferDone(outHeader);
        outHeader = NULL;

        ++mInputBufferCount;
    }
}

void SoftVorbis::onPortFlushCompleted(OMX_U32 portIndex) {
    if (portIndex == 0 && mState != NULL) {
        // Make sure that the next buffer output does not still
        // depend on fragments from the last one decoded.

        mNumFramesOutput = 0;
        vorbis_dsp_restart(mState);
    }
}

void SoftVorbis::onReset() {
    mInputBufferCount = 0;
    mNumFramesOutput = 0;
    if (mState != NULL) {
        vorbis_dsp_clear(mState);
        delete mState;
        mState = NULL;
    }

    if (mVi != NULL) {
        vorbis_info_clear(mVi);
        delete mVi;
        mVi = NULL;
    }

    mSawInputEos = false;
    mSignalledOutputEos = false;
    mOutputPortSettingsChange = NONE;
}

void SoftVorbis::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
    if (portIndex != 1) {
        return;
    }

    switch (mOutputPortSettingsChange) {
        case NONE:
            break;

        case AWAITING_DISABLED:
        {
            CHECK(!enabled);
            mOutputPortSettingsChange = AWAITING_ENABLED;
            break;
        }

        default:
        {
            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
            CHECK(enabled);
            mOutputPortSettingsChange = NONE;
            break;
        }
    }
}

}  // namespace android

android::SoftOMXComponent *createSoftOMXComponent(
        const char *name, const OMX_CALLBACKTYPE *callbacks,
        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
    return new android::SoftVorbis(name, callbacks, appData, component);
}
