/* INTEL CONFIDENTIAL
* Copyright (c) 2012 Intel Corporation.  All rights reserved.
*
* The source code contained or described herein and all documents
* related to the source code ("Material") are owned by Intel
* Corporation or its suppliers or licensors.  Title to the
* Material remains with Intel Corporation or its suppliers and
* licensors.  The Material contains trade secrets and proprietary
* and confidential information of Intel or its suppliers and
* licensors. The Material is protected by worldwide copyright and
* trade secret laws and treaty provisions.  No part of the Material
* may be used, copied, reproduced, modified, published, uploaded,
* posted, transmitted, distributed, or disclosed in any way without
* Intel's prior express written permission.
*
* No license under any patent, copyright, trade secret or other
* intellectual property right is granted to or conferred upon you
* by disclosure or delivery of the Materials, either expressly, by
* implication, inducement, estoppel or otherwise. Any license
* under such intellectual property rights must be express and
* approved by Intel in writing.
*
*/

#include "VideoDecoderVP8.h"
#include "VideoDecoderTrace.h"
#include <string.h>

VideoDecoderVP8::VideoDecoderVP8(const char *mimeType)
    : VideoDecoderBase(mimeType, VBP_VP8) {
    invalidateReferenceFrames(0);
    invalidateReferenceFrames(1);
}

VideoDecoderVP8::~VideoDecoderVP8() {
    stop();
}

void VideoDecoderVP8::invalidateReferenceFrames(int toggle) {
    ReferenceFrameBuffer *p = mRFBs[toggle];
    for (int i = 0; i < VP8_REF_SIZE; i++) {
        p->index = (uint32_t) -1;
        p->surfaceBuffer = NULL;
        p++;
    }
}

void VideoDecoderVP8::clearAsReference(int toggle, int ref_type) {
    ReferenceFrameBuffer ref = mRFBs[toggle][ref_type];
    if (ref.surfaceBuffer) {
        ref.surfaceBuffer->asReferernce = false;
    }
}

void VideoDecoderVP8::updateFormatInfo(vbp_data_vp8 *data) {
    int32_t width = data->codec_data->frame_width;
    int32_t height = data->codec_data->frame_height;
    ITRACE("updateFormatInfo: current size: %d x %d, new size: %d x %d",
            mVideoFormatInfo.width, mVideoFormatInfo.height, width, height);

    if ((mVideoFormatInfo.width != width ||
            mVideoFormatInfo.height != height) &&
            width && height) {
        mVideoFormatInfo.width = width;
        mVideoFormatInfo.height = height;
        mSizeChanged = true;
        ITRACE("Video size is changed.");
    }

    mVideoFormatInfo.cropLeft = data->codec_data->crop_left;
    mVideoFormatInfo.cropRight = data->codec_data->crop_right;
    mVideoFormatInfo.cropTop = data->codec_data->crop_top;
    mVideoFormatInfo.cropBottom = data->codec_data->crop_bottom;
    ITRACE("Cropping: left = %d, top = %d, right = %d, bottom = %d", data->codec_data->crop_left, data->codec_data->crop_top, data->codec_data->crop_bottom);

    mVideoFormatInfo.valid = true;
}

Decode_Status VideoDecoderVP8::startVA(vbp_data_vp8 *data) {
    updateFormatInfo(data);

    VAProfile vaProfile = VAProfileVP8Version0_3;
    if (data->codec_data->version_num > 3) {
        return DECODE_PARSER_FAIL;
    }

    return VideoDecoderBase::setupVA(VP8_SURFACE_NUMBER + VP8_REF_SIZE, vaProfile);
}

Decode_Status VideoDecoderVP8::start(VideoConfigBuffer *buffer) {
    Decode_Status status;

    status = VideoDecoderBase::start(buffer);
    CHECK_STATUS("VideoDecoderBase::start");

    // We don't want base class to manage reference.
    VideoDecoderBase::ManageReference(false);

    if (buffer->data == NULL || buffer->size == 0) {
        WTRACE("No config data to start VA.");
        return DECODE_SUCCESS;
    }

    vbp_data_vp8 *data = NULL;
    status = VideoDecoderBase::parseBuffer(buffer->data, buffer->size, true, (void**)&data);
    CHECK_STATUS("VideoDecoderBase::parseBuffer");

    status = startVA(data);
    return status;
}

void VideoDecoderVP8::stop(void) {
    VideoDecoderBase::stop();

    invalidateReferenceFrames(0);
    invalidateReferenceFrames(1);
}

void VideoDecoderVP8::flush(void) {
    VideoDecoderBase::flush();

    invalidateReferenceFrames(0);
    invalidateReferenceFrames(1);
}

Decode_Status VideoDecoderVP8::decode(VideoDecodeBuffer *buffer) {
    Decode_Status status;
    vbp_data_vp8 *data = NULL;
    if (buffer == NULL) {
        ETRACE("VideoDecodeBuffer is NULL.");
        return DECODE_INVALID_DATA;
    }

    status = VideoDecoderBase::parseBuffer(
                 buffer->data,
                 buffer->size,
                 false,
                 (void**)&data);
    CHECK_STATUS("VideoDecoderBase::parseBuffer");

    mShowFrame = data->codec_data->show_frame;

    if (!mVAStarted) {
        status = startVA(data);
        CHECK_STATUS("startVA");
    }

    status = decodeFrame(buffer, data);

    return status;
}

Decode_Status VideoDecoderVP8::decodeFrame(VideoDecodeBuffer* buffer, vbp_data_vp8 *data) {
    Decode_Status status;
    mCurrentPTS = buffer->timeStamp;
    if (0 == data->num_pictures || NULL == data->pic_data) {
        WTRACE("Number of pictures is 0.");
        return DECODE_SUCCESS;
    }

    if (VP8_KEY_FRAME == data->codec_data->frame_type) {
        if (mSizeChanged) {
            mSizeChanged = false;
            return DECODE_FORMAT_CHANGE;
        } else {
            updateFormatInfo(data);
            if (mSizeChanged == true) {
                mSizeChanged = false;
                return DECODE_FORMAT_CHANGE;
            }
        }
    }

    if (data->codec_data->frame_type == VP8_SKIPPED_FRAME) {
        // Do nothing for skip frame as the last frame will be rendered agian by natively
        return DECODE_SUCCESS;
    }

    status = acquireSurfaceBuffer();
    CHECK_STATUS("acquireSurfaceBuffer");

    // set referenceFrame to true if frame decoded is I/P frame, false otherwise.
    int frameType = data->codec_data->frame_type;
    mAcquiredBuffer->referenceFrame = (frameType == VP8_KEY_FRAME || frameType == VP8_INTER_FRAME);
    // assume it is frame picture.
    mAcquiredBuffer->renderBuffer.scanFormat = VA_FRAME_PICTURE;
    mAcquiredBuffer->renderBuffer.timeStamp = buffer->timeStamp;
    mAcquiredBuffer->renderBuffer.flag = 0;
    if (buffer->flag & WANT_DECODE_ONLY) {
        mAcquiredBuffer->renderBuffer.flag |= WANT_DECODE_ONLY;
    }


    // Here data->num_pictures is always equal to 1
    for (int index = 0; index < data->num_pictures; index++) {
        status = decodePicture(data, index);
        if (status != DECODE_SUCCESS) {
            endDecodingFrame(true);
            return status;
        }
    }

    if (frameType != VP8_SKIPPED_FRAME) {
        updateReferenceFrames(data);
    }

    // if sample is successfully decoded, call outputSurfaceBuffer(); otherwise
    // call releaseSurfacebuffer();
    status = outputSurfaceBuffer();
    return status;
}

Decode_Status VideoDecoderVP8::decodePicture(vbp_data_vp8 *data, int32_t picIndex) {
    VAStatus vaStatus = VA_STATUS_SUCCESS;
    Decode_Status status;
    uint32_t bufferIDCount = 0;
    VABufferID bufferIDs[5];

    vbp_picture_data_vp8 *picData = &(data->pic_data[picIndex]);
    VAPictureParameterBufferVP8 *picParams = picData->pic_parms;

    status = setReference(picParams, picIndex);
    CHECK_STATUS("setReference");

    vaStatus = vaBeginPicture(mVADisplay, mVAContext, mAcquiredBuffer->renderBuffer.surface);
    CHECK_VA_STATUS("vaBeginPicture");
    // setting mDecodingFrame to true so vaEndPicture will be invoked to end the picture decoding.
    mDecodingFrame = true;

    vaStatus = vaCreateBuffer(
                   mVADisplay,
                   mVAContext,
                   VAPictureParameterBufferType,
                   sizeof(VAPictureParameterBufferVP8),
                   1,
                   picParams,
                   &bufferIDs[bufferIDCount]);
    CHECK_VA_STATUS("vaCreatePictureParameterBuffer");
    bufferIDCount++;

    vaStatus = vaCreateBuffer(
                   mVADisplay,
                   mVAContext,
                   VAProbabilityBufferType,
                   sizeof(VAProbabilityDataBufferVP8),
                   1,
                   data->prob_data,
                   &bufferIDs[bufferIDCount]);
    CHECK_VA_STATUS("vaCreateProbabilityBuffer");
    bufferIDCount++;

    vaStatus = vaCreateBuffer(
                   mVADisplay,
                   mVAContext,
                   VAIQMatrixBufferType,
                   sizeof(VAIQMatrixBufferVP8),
                   1,
                   data->IQ_matrix_buf,
                   &bufferIDs[bufferIDCount]);
    CHECK_VA_STATUS("vaCreateIQMatrixBuffer");
    bufferIDCount++;

    /* Here picData->num_slices is always equal to 1 */
    for (uint32_t i = 0; i < picData->num_slices; i++) {
        vaStatus = vaCreateBuffer(
                       mVADisplay,
                       mVAContext,
                       VASliceParameterBufferType,
                       sizeof(VASliceParameterBufferVP8),
                       1,
                       &(picData->slc_data[i].slc_parms),
                       &bufferIDs[bufferIDCount]);
        CHECK_VA_STATUS("vaCreateSliceParameterBuffer");
        bufferIDCount++;

        vaStatus = vaCreateBuffer(
                       mVADisplay,
                       mVAContext,
                       VASliceDataBufferType,
                       picData->slc_data[i].slice_size, //size
                       1,        //num_elements
                       picData->slc_data[i].buffer_addr + picData->slc_data[i].slice_offset,
                       &bufferIDs[bufferIDCount]);
        CHECK_VA_STATUS("vaCreateSliceDataBuffer");
        bufferIDCount++;
    }

    vaStatus = vaRenderPicture(
                   mVADisplay,
                   mVAContext,
                   bufferIDs,
                   bufferIDCount);
    CHECK_VA_STATUS("vaRenderPicture");

    vaStatus = vaEndPicture(mVADisplay, mVAContext);
    mDecodingFrame = false;
    CHECK_VA_STATUS("vaEndPicture");

    return DECODE_SUCCESS;
}

Decode_Status VideoDecoderVP8::setReference(VAPictureParameterBufferVP8 *picParam, int32_t picIndex) {
    int frameType = picParam->pic_fields.bits.key_frame;
    switch (frameType) {
    case VP8_KEY_FRAME:
        picParam->last_ref_frame = VA_INVALID_SURFACE;
        picParam->alt_ref_frame = VA_INVALID_SURFACE;
        picParam->golden_ref_frame = VA_INVALID_SURFACE;
        break;
    case VP8_INTER_FRAME:
        if (mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer   == NULL ||
                mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer    == NULL ||
                mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer == NULL) {
            return DECODE_NO_REFERENCE;
        }
        //mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer = mLastReference;
        picParam->last_ref_frame = mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer->renderBuffer.surface;
        picParam->alt_ref_frame = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer->renderBuffer.surface;
        picParam->golden_ref_frame = mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer->renderBuffer.surface;
        break;
    case VP8_SKIPPED_FRAME:
        // will never happen here
        break;
    default:
        return DECODE_PARSER_FAIL;
    }

    return DECODE_SUCCESS;
}

void VideoDecoderVP8::updateReferenceFrames(vbp_data_vp8 *data) {
    /* Refresh last frame reference buffer using the currently reconstructed frame */
    refreshLastReference(data);

    /* Refresh golden frame reference buffer using the currently reconstructed frame */
    refreshGoldenReference(data);

    /* Refresh alternative frame reference buffer using the currently reconstructed frame */
    refreshAltReference(data);

    /* Update reference frames */
    for (int i = 0; i < VP8_REF_SIZE; i++) {
        VideoSurfaceBuffer *p = mRFBs[1][i].surfaceBuffer;
        int j;
        for (j = 0; j < VP8_REF_SIZE; j++) {
            if (p == mRFBs[0][j].surfaceBuffer) {
                break;
            }
        }
        if (j == VP8_REF_SIZE) {
            clearAsReference(1, i);
        }
    }
}

void VideoDecoderVP8::refreshLastReference(vbp_data_vp8 *data) {
    /* Save previous last reference */
    mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer = mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer;
    mRFBs[1][VP8_LAST_REF_PIC].index = mRFBs[0][VP8_LAST_REF_PIC].index;

    /* For key frame, this is always true */
    if (data->codec_data->refresh_last_frame) {
        mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer = mAcquiredBuffer;
        mRFBs[0][VP8_LAST_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface;
        mRFBs[0][VP8_LAST_REF_PIC].surfaceBuffer->asReferernce = true;
    }
}

void VideoDecoderVP8::refreshGoldenReference(vbp_data_vp8 *data) {
    /* Save previous golden reference */
    mRFBs[1][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer;
    mRFBs[1][VP8_GOLDEN_REF_PIC].index = mRFBs[0][VP8_GOLDEN_REF_PIC].index;

    if (data->codec_data->golden_copied != BufferCopied_NoneToGolden) {
        if (data->codec_data->golden_copied == BufferCopied_LastToGolden) {
            /* LastFrame is copied to GoldenFrame */
            mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer;
            mRFBs[0][VP8_GOLDEN_REF_PIC].index = mRFBs[1][VP8_LAST_REF_PIC].index;
        } else if (data->codec_data->golden_copied == BufferCopied_AltRefToGolden) {
            /* AltRefFrame is copied to GoldenFrame */
            mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer;
            mRFBs[0][VP8_GOLDEN_REF_PIC].index = mRFBs[0][VP8_ALT_REF_PIC].index;
        }
    }

    /* For key frame, this is always true */
    if (data->codec_data->refresh_golden_frame) {
        mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer = mAcquiredBuffer;
        mRFBs[0][VP8_GOLDEN_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface;
        mRFBs[0][VP8_GOLDEN_REF_PIC].surfaceBuffer->asReferernce = true;
    }
}

void VideoDecoderVP8::refreshAltReference(vbp_data_vp8 *data) {
    /* Save previous alternative reference */
    mRFBs[1][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer;
    mRFBs[1][VP8_ALT_REF_PIC].index = mRFBs[0][VP8_ALT_REF_PIC].index;

    if (data->codec_data->altref_copied != BufferCopied_NoneToAltRef) {
        if (data->codec_data->altref_copied == BufferCopied_LastToAltRef) {
            /* LastFrame is copied to AltRefFrame */
            mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[1][VP8_LAST_REF_PIC].surfaceBuffer;
            mRFBs[0][VP8_ALT_REF_PIC].index = mRFBs[1][VP8_LAST_REF_PIC].index;
        } else if (data->codec_data->altref_copied == BufferCopied_GoldenToAltRef) {
            /* GoldenFrame is copied to AltRefFrame */
            mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mRFBs[1][VP8_GOLDEN_REF_PIC].surfaceBuffer;
            mRFBs[0][VP8_ALT_REF_PIC].index = mRFBs[1][VP8_GOLDEN_REF_PIC].index;
        }
    }

    /* For key frame, this is always true */
    if (data->codec_data->refresh_alt_frame) {
        mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer = mAcquiredBuffer;
        mRFBs[0][VP8_ALT_REF_PIC].index = mAcquiredBuffer->renderBuffer.surface;
        mRFBs[0][VP8_ALT_REF_PIC].surfaceBuffer->asReferernce = true;
    }
}


Decode_Status VideoDecoderVP8::checkHardwareCapability(VAProfile profile) {
    VAStatus vaStatus;
    VAConfigAttrib cfgAttribs[2];
    cfgAttribs[0].type = VAConfigAttribMaxPictureWidth;
    cfgAttribs[1].type = VAConfigAttribMaxPictureHeight;
    vaStatus = vaGetConfigAttributes(mVADisplay, VAProfileVP8Version0_3,
            VAEntrypointVLD, cfgAttribs, 2);
    CHECK_VA_STATUS("vaGetConfigAttributes");
    if (cfgAttribs[0].value * cfgAttribs[1].value < (uint32_t)mVideoFormatInfo.width * (uint32_t)mVideoFormatInfo.height) {
        ETRACE("hardware supports resolution %d * %d smaller than the clip resolution %d * %d",
                cfgAttribs[0].value, cfgAttribs[1].value, mVideoFormatInfo.width, mVideoFormatInfo.height);
        return DECODE_DRIVER_FAIL;
    }

    return DECODE_SUCCESS;
}

