 /*
  * =====================================================================================
  *
  *      Copyright (c) 2008-2018 Allwinner Technology Co. Ltd.
  *      All rights reserved.
  *
  *       Filename:  omx_venc_linux_adapter.c
  *
  *    Description:
  *
  *        Version:  1.0
  *        Created:  2018/08
  *       Revision:  none
  *       Compiler:  gcc
  *
  *         Author:  SWC-PPD
  *      Company: Allwinner Technology Co. Ltd.
  *
  *       History :
  *        Author : AL3
  *        Date   : 2013/05/05
  *    Comment : complete the design code
  *
  * =====================================================================================
  */
#include "omx_venc_adapter.h"
#include "AWOMX_VideoIndexExtension.h"

OMX_ERRORTYPE getDefaultParameter(AwOmxVenc* impl, OMX_IN OMX_INDEXTYPE eParamIndex,
                                           OMX_IN OMX_PTR pParamData)
{
    CEDARC_UNUSE(impl);
    CEDARC_UNUSE(eParamIndex);
    CEDARC_UNUSE(pParamData);
    loge("getDefaultParameter. UnsupportedIndex %d. unkonwn param %p\n", eParamIndex, pParamData);
    OMX_ERRORTYPE eError = OMX_ErrorUnsupportedIndex;
    return eError;
}
OMX_ERRORTYPE setDefaultParameter(AwOmxVenc* impl, OMX_IN OMX_INDEXTYPE eParamIndex,
                                           OMX_IN OMX_PTR pParamData)
{
    logd("setDefaultParameter. Index %d. Param %p\n", eParamIndex, pParamData);
    OMX_ERRORTYPE eError = OMX_ErrorNone;
    AW_VIDEO_EXTENSIONS_INDEXTYPE param = (AW_VIDEO_EXTENSIONS_INDEXTYPE) eParamIndex;
    switch (param)
    {
        case AWOMX_IndexVendorUseAwBuffer:
            if(pParamData!=NULL) {
                OMX_AW_BUFFER_PARAM* data = (OMX_AW_BUFFER_PARAM* ) pParamData;
                impl->m_useAwBuffer = data->useAwBuffer;
                impl->m_bufferFdNum = data->nFdNum;
                logd("use aw buffer = %d, fd num = %d", impl->m_useAwBuffer, impl->m_bufferFdNum);
            }
            break;
        case AWOMX_IndexVendorSetVencCsdMode:
            if(pParamData!=NULL) {
                int* mode = (int*)pParamData;
                impl->m_CsdMode = *mode < VIDEO_ENC_CSD_MODE_NUM ? *mode : 0;
                logd("set csd mode = %d", impl->m_CsdMode);
            }
            break;
        default:
            eError = OMX_ErrorUnsupportedIndex;
            break;
    }

    return eError;
}

void getAndAddInputBuffer(AwOmxVenc* impl, OMX_BUFFERHEADERTYPE* pInBufHdr,
                                    VencInputBuffer* sInputBuffer)
{
    logv("function %s. line %d.", __FUNCTION__, __LINE__);
    int result = -1;
    OmxPrivateBuffer *private;
    int index = 0;
    sInputBuffer->nFlag = 0;
    sInputBuffer->nPts = pInBufHdr->nTimeStamp;
    sInputBuffer->nID = (unsigned long)pInBufHdr;
    sInputBuffer->nShareBufFd = -1;

    if (pInBufHdr->nFlags & OMX_BUFFERFLAG_EOS)
    {
        sInputBuffer->nFlag |= VENC_BUFFERFLAG_EOS;
    }

    private = (OmxPrivateBuffer*) pInBufHdr->pPlatformPrivate;

    for (; index < NUM_MAX_IN_BUFFERS; index++)
    {
        if (impl->mInputBufInfo[index].nShareFd == private->nShareBufFd)
            break;
    }

    if (index >= NUM_MAX_IN_BUFFERS)
    {
        index = 0;
        for (; index < NUM_MAX_IN_BUFFERS; index++)
        {
            if (impl->mInputBufInfo[index].nShareFd == 0)
            {
                impl->mInputBufInfo[index].nShareFd = private->nShareBufFd;
                impl->mInputBufInfo[index].nFdNums  = impl->m_bufferFdNum;
                break;
            }
        }
        if (index >= NUM_MAX_IN_BUFFERS)
        {
            loge("buffer count too large");
            goto exit;
        }
        struct user_iommu_param iommu_buffer;
        iommu_buffer.fd = private->nShareBufFd;
        VideoEncoderGetVeIommuAddr(impl->m_encoder, &iommu_buffer);
        impl->mInputBufInfo[index].nBufPhyAddr = (uintptr_t)iommu_buffer.iommu_addr;
        if(impl->m_bufferFdNum > 1) {
            memset(&iommu_buffer, 0x00, sizeof(struct user_iommu_param));
            iommu_buffer.fd = private->nShareBufFd + 1; //fd of next plane
            VideoEncoderGetVeIommuAddr(impl->m_encoder, &iommu_buffer);
            impl->mInputBufInfo[index].nBufPhyCAddr = (uintptr_t)iommu_buffer.iommu_addr;
            logd("get inputbuffer phyC with fd = %d", private->nShareBufFd+1);
        }
    }

    sInputBuffer->pAddrPhyY = (unsigned char*)impl->mInputBufInfo[index].nBufPhyAddr;
    if(impl->m_bufferFdNum > 1)
        sInputBuffer->pAddrPhyC = (unsigned char*)impl->mInputBufInfo[index].nBufPhyCAddr;
    else
        sInputBuffer->pAddrPhyC = sInputBuffer->pAddrPhyY + impl->m_sInPortDefType.format.video.nStride *
                                    ALIGN_16B(impl->m_sInPortDefType.format.video.nFrameHeight);
    logv("using fd %d addrPhyY %p addrPhyC %p", private->nShareBufFd, sInputBuffer->pAddrPhyY, sInputBuffer->pAddrPhyC);

    result = AddOneInputBuffer(impl->m_encoder, sInputBuffer);
    if (result!=0)
    {
        impl->mInputBufferStep = OMX_VENC_STEP_ADD_BUFFER_TO_ENC;
    }
    else
    {
        impl->mInputBufferStep = OMX_VENC_STEP_GET_INPUTBUFFER;
    }

exit:
    logv("exit with result %d", result);
}

void getInputBufferFromBufHdr (AwOmxVenc* impl, OMX_BUFFERHEADERTYPE* pInBufHdr,
                                                                VencInputBuffer* sInputBuffer)
{
    logv("function %s. line %d.", __FUNCTION__, __LINE__);
    if (impl->mVideoExtParams.bEnableCropping)
    {
        if (impl->mVideoExtParams.ui16CropLeft ||
            impl->mVideoExtParams.ui16CropTop)
        {
            sInputBuffer->bEnableCorp = 1;
            sInputBuffer->sCropInfo.nLeft =
                impl->mVideoExtParams.ui16CropLeft;
            sInputBuffer->sCropInfo.nWidth =
                impl->m_sOutPortDefType.format.video.nFrameWidth -
                impl->mVideoExtParams.ui16CropLeft -
                impl->mVideoExtParams.ui16CropRight;
            sInputBuffer->sCropInfo.nTop =
                impl->mVideoExtParams.ui16CropTop;
            sInputBuffer->sCropInfo.nHeight =
                impl->m_sOutPortDefType.format.video.nFrameHeight -
                impl->mVideoExtParams.ui16CropTop -
                impl->mVideoExtParams.ui16CropBottom;
        }
    }
    memcpy(sInputBuffer->pAddrVirY,
           pInBufHdr->pBuffer + pInBufHdr->nOffset, impl->mSizeY);
    memcpy(sInputBuffer->pAddrVirC,
           pInBufHdr->pBuffer + pInBufHdr->nOffset + impl->mSizeY, impl->mSizeC);
    impl->mSizeY = 0;
    impl->mSizeC = 0;

}

void getInputBufferFromBufHdrWithoutCrop(AwOmxVenc* impl, OMX_BUFFERHEADERTYPE* pInBufHdr,
                                                                VencInputBuffer* sInputBuffer)
{
    logd("function %s. line %d.", __FUNCTION__, __LINE__);
    memcpy(sInputBuffer->pAddrVirY,
           pInBufHdr->pBuffer + pInBufHdr->nOffset, impl->mSizeY);
    memcpy(sInputBuffer->pAddrVirC,
           pInBufHdr->pBuffer + pInBufHdr->nOffset + impl->mSizeY, impl->mSizeC);
    impl->mSizeY = 0;
    impl->mSizeC = 0;
}

void determineVencColorFormat(AwOmxVenc* impl)
{
    switch (impl->m_sInPortFormatType.eColorFormat)
    {
        case OMX_COLOR_FormatYUV420SemiPlanar:
        {
            logv("color format: VENC_PIXEL_YUV420SP");
            impl->m_vencColorFormat = VENC_PIXEL_YUV420SP;
            break;
        }
        case OMX_COLOR_FormatYVU420SemiPlanar:
        {
            logv("color format: VENC_PIXEL_YVU420SP");
            impl->m_vencColorFormat = VENC_PIXEL_YVU420SP;
            break;
        }
        case OMX_COLOR_FormatYVU420Planar:
        {
            logv("color format: VENC_PIXEL_YVU420P");
            impl->m_vencColorFormat = VENC_PIXEL_YVU420P;
            break;
        }
        default:
        {
            logw("determine none format!!!!!!!!!!!");
            break;
        }

    }
}

void determineVencBufStrideIfNecessary(AwOmxVenc* impl, VencBaseConfig* pBaseConfig)
{
    CEDARC_UNUSE(impl);
    CEDARC_UNUSE(pBaseConfig);
    //do nothing.
}

int deparseEncInputBuffer(int nIonFd,
                                VideoEncoder *pEncoder,
                                OMXInputBufferInfoT *pInputBufInfo)
{
    OMX_S32 i;
    int ret;
    for(i=0; i<NUM_MAX_IN_BUFFERS; i++)
    {
        OMXInputBufferInfoT *p;
        p = pInputBufInfo + i;

        if(p->nShareFd > 0)
        {
            if(CdcIonGetMemType() == MEMORY_IOMMU)
            {
                logd("remove fd %d, num = %d", p->nShareFd, p->nFdNums);
                struct user_iommu_param iommu_buffer;
                iommu_buffer.fd = p->nShareFd;
                iommu_buffer.iommu_addr = (unsigned int)p->nBufPhyAddr;
                VideoEncoderFreeVeIommuAddr(pEncoder, &iommu_buffer);
                if(p->nFdNums > 1) {
                    memset(&iommu_buffer, 0x00, sizeof(struct user_iommu_param));
                    iommu_buffer.fd = p->nShareFd + 1;
                    iommu_buffer.iommu_addr = (unsigned int)p->nBufPhyCAddr;
                    VideoEncoderFreeVeIommuAddr(pEncoder, &iommu_buffer);
                }
            }
            memset(p, 0x00, sizeof(OMXInputBufferInfoT));
        }
    }
    return 0;
}

void updateOmxDebugFlag(AwOmxVenc* impl)
{
    impl->bSaveStreamFlag = OMX_FALSE;
    impl->bOpenStatisticFlag = OMX_FALSE;
    impl->bShowFrameSizeFlag = OMX_FALSE;
    #if SAVE_BITSTREAM
    impl->bSaveStreamFlag = OMX_TRUE;
    #endif
    #if OPEN_STATISTICS
    impl->bOpenStatisticFlag = OMX_TRUE;
    #endif
    #if PRINTF_FRAME_SIZE
    impl->bShowFrameSizeFlag = OMX_TRUE;
    #endif
}

