/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

/*-----------------------------------------------------------------------------
 *
 * $Author$
 * $Date$
 * $RCSfile: venc_drvif.h,v $
 * $Revision$
 *
 *---------------------------------------------------------------------------*/

/** @file venc_drvif.h
 *  Public interface of video encoder
 */


#ifndef VENC_DRVIF_H
#define VENC_DRVIF_H

//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------
#include "venc_if.h"

/*lint -save -e961 */
#include "x_common.h"
#include "x_typedef.h"
#include "x_timer.h"
#include "x_assert.h"
#include "x_os.h"
#include "x_bim.h"
#include "x_clksrc.h"
#include "x_hal_5381.h"
#include "x_hal_926.h"
#include "def_venc.h"

//-----------------------------------------------------------------------------
// Configurations
//-----------------------------------------------------------------------------
#define VENC_RAVEN_DRIVER //Used in Venc_cmd.c

#define INPUT_BUF_FROM_SCALER //defined for scaler, undefined for DI.

//#define CC_EMULATION
//#define VENC_EMU_RAVEN

#ifdef CC_EMULATION
#define VENC_EMU
#endif

#ifdef VENC_EMU
//#define USB_SUPPORT
//#define VENC_CYCLE
//#define VENC_DRAM_PROFILE
//#define VENC_MT8580_PATTERN

#ifndef VENC_DRAM_PROFILE
#if defined(CC_MT5396) || defined(CC_MT5398) // MT5368 doesn't have channel B
#define DRAM_CHANNEL_AB_TEST
#endif
#endif

#if defined(VENC_CYCLE) || defined(VENC_DRAM_PROFILE)
#define VENC_LIGHT_LOG
#endif

#ifdef USB_SUPPORT
//#define SINGLE_FILE_SUPPORT
#endif

#endif

//#define VENC_DUMP_BS // tmp for dump
//#define VENC_FRAME_CTRL_BY_DRV


//-----------------------------------------------------------------------------
// Constant definitions
//-----------------------------------------------------------------------------

#define VENC_CMDQ_SIZE       (16)
#define VENC_CMDQ_PRIORITY   (255)

#define VENC_FRMQ_SIZE       (16 + VENC_CMDQ_SIZE)
#define VENC_FRMQ_PRIORITY   VENC_CMDQ_PRIORITY

#define VENC_STACK_SIZE      (16384)
#define VENC_THREAD_PRIORITY (50)

#define VENC_MAX_FRAME_BUFFER_NUM (8)

#define QVGA_WIDTH (320)
#define QVGA_HEIGHT (240)

#define VENC_DEV_USED (0xa4)

#define VENC_RESIZE_BUF_N (2)
#define VENC_RESIZE_BUF_SZ (1920*1088 * 3 / 2)
#define VENC_RESIZE_BUF_TOTAL (VENC_RESIZE_BUF_SZ * VENC_RESIZE_BUF_N)

#ifdef CC_USE_DDI
#define VENC_THUMBNAIL_SIZE (240*144*4)
#else
#define VENC_THUMBNAIL_SIZE (160*120*4)
#endif

//-----------------------------------------------------------------------------
// Macro definitions
//-----------------------------------------------------------------------------
#define VENC_ALIGN_MASK(VAL, MSK) (((VAL) + (MSK)) & (~(MSK)))

#define VENC_OBJECT_TO_HANDLE(object) ((VENC_HANDLE)(object))
#define VENC_HANDLE_TO_OBJECT(h,o)    ((o*)(h))


#define VENC_CHK_OK_BREAK(ret)                  \
if ((ret) != VENC_OK)                           \
{                                               \
    LOG(0, "%s(%d)\n", __FUNCTION__, __LINE__); \
    ASSERT(0);                                  \
    break;                                      \
}

#define VENC_SUPPORT_ASYNC_MODE(m) ( VENC_SMODE_ASYNC == (m) || VENC_SMODE_DUAL == (m))

#define _VEncInitSyncCmdFlag(obj)                                         \
do {                                                                      \
    INT32 i4Ret = x_sema_lock(obj->hEncSyncSema, X_SEMA_OPTION_NOWAIT);   \
    LOG(5, "%s(%d): init sync cmd %d\n", __FUNCTION__, __LINE__, i4Ret);  \
    UNUSED(i4Ret);                                                        \
} while (0)

#define _VEncWaitSyncCmdDone(obj)                                         \
do {                                                                      \
    VERIFY(x_sema_lock(obj->hEncSyncSema, X_SEMA_OPTION_WAIT) == OSR_OK); \
    LOG(5, "%s(%d): wait sync cmd\n", __FUNCTION__, __LINE__);            \
} while (0)

#define _VEncNotifySyncCmdDone(obj)                                       \
do {                                                                      \
    VERIFY(x_sema_unlock(obj->hEncSyncSema) == OSR_OK);                   \
    LOG(5, "%s(%d): notify sync cmd\n", __FUNCTION__, __LINE__);          \
} while (0)


#define VENC_LINK_FOR_EACH_OBJECT(o) for (o=_ptVEncObjHead->next; o; o = o->next)
#define VENC_FOR_EACH_HANDLE(h) for (h=VENC_OBJECT_TO_HANDLE(_ptVEncObjHead->next); h!= VENC_NULL_HANDLE; h = VENC_OBJECT_TO_HANDLE(VENC_HANDLE_TO_OBJECT(h,VENC_OBJECT_T)->next))

// from h264api

#if 1
#define VENC_BFRAME_MAX  (2)

// bad macro name ...
#define VENC_RAVEN_SRCBUF_CNT     (2)
#ifdef __MODEL_slt__
#define VENC_RAVEN_BSBUF_CNT      (3)
#else
#define VENC_RAVEN_BSBUF_CNT      (3)
#endif
#endif

#define VENC_RAVEN_REF_CNT        (3)

// max number of objects that we support: VENC_MAX_OBJECT_NUM - 1,so set 33 to support 32  maxhandle
#define VENC_MAX_OBJECT_NUM 33

#define VENC_RAVEN_RECREFBUF_CNT VENC_RAVEN_SRCBUF_CNT
#define VENC_RAVEN_COLMV_BUF_CNT VENC_RAVEN_SRCBUF_CNT


//#ifdef VENC_EMU
#define REZ_REC_N 256
//#endif
//-----------------------------------------------------------------------------
// Type definitions
//-----------------------------------------------------------------------------
typedef enum
{
    BS_BUF_EMPTY,
    BS_BUF_ENCODING,
    BS_BUF_COPYING
}VENC_BS_BUF_STATUS;

typedef enum
{
    VENC_CTRL_INT_GET_BS_INFO = VENC_CTRL_MAX + 1,
    VENC_CTRL_INT_GET_STATE,
    VENC_CTRL_INT_GET_NAME,
    VENC_CTRL_INT_GET_TYPE,
    VENC_CTRL_INT_GET_BUFFER,
#ifdef CC_VENC_RM_SUPPORT
	VENC_CTRL_INT_GET_PRIORITY,
#endif
    VENC_CTRL_INT_MAX
}VENC_CTRL_INT_T;


typedef enum
{
    VENC_CMD_START_ASYNC = 0x01,  // start
    VENC_CMD_STOP_ASYNC  = 0x02,  // stop
    VENC_CMD_EXIT_ASYNC  = 0x03,  // thread exit

    VENC_CMD_START_SYNC  = 0x11,  // start
    VENC_CMD_STOP_SYNC   = 0x12,  // stop
    VENC_CMD_EXIT_SYNC   = 0x13,  // thread exit

    VENC_CMD_UNKNOWN     = 0xFF
} VENC_CMD_T;



typedef enum
{
    VENC_STATE_STOP,        // stop
    VENC_STATE_RUN,         // run
    VENC_STATE_UNKNOWN
} VENC_STATE_T;


typedef enum
{
    VENC_ENC_STATE_IDLE,
    VENC_ENC_STATE_ENC,
    VENC_ENC_STATE_MAX
} VENC_ENC_STATE_T;


typedef enum
{
    VENC_FRMQ_TYPE_FRM,
    VENC_FRMQ_TYPE_DUMMY,
    VENC_FRMQ_TYPE_CMD,
    VENC_FRMQ_TYPE_RT_PARM,
    VENC_FRMQ_TYPE_RT_CTRL,
    VENC_FRMQ_TYPE_MAX
} VENC_FRMQ_TYPE_T;

// from h264api
#if 1
typedef struct
{
    UINT32              u4OutputBuf[VENC_RAVEN_BSBUF_CNT];
    UINT32              u4OutputBufSize;
    UINT32              u4RamCodeBuf;
    UINT32              u4RCInfoBuf;
    UINT32              au4SrcBufY[VENC_RAVEN_REF_CNT];
    UINT32              au4SrcBufC[VENC_RAVEN_REF_CNT];
    UINT32              au4SrcBufV[VENC_RAVEN_SRCBUF_CNT];
    UINT32              au4ColMvInfoBuf[VENC_RAVEN_REF_CNT];

    UINT32              u4InputBufY; // input buffer is maintained by front module
    UINT32              u4InputBufC; // so, we do not alloc input buf here. Just alloc these three variables.
    UINT32              u4InputBufV;

    UINT32              u4TSVCSyntaxBuf;
    UINT32              u4TSVCPrefixNALUBuf;
} VENC_RAVEN_HW_BUF_T;


typedef enum
{
    VENC_REZ_STATE_IDLE,
    VENC_REZ_STATE_REZ,
    VENC_REZ_STATE_MAX
} VENC_REZ_STATE_T;


typedef struct
{
    UINT32 u4CosAddr;
}VENC_COS_PIC_PRAM_T;


// forward declaration for _VENC_CTRL_BASE
struct _VENC_REZ_OBJ_T;
struct _VENC_BUFMGR_BASE_T;


typedef struct _VENC_CTRL_BASE
{
    //Coarse
    VENC_REZ_STATE_T eRezFrmState;
    VENC_STATE_T     eRezCmdState;
    HANDLE_T    hRezThread;
    HANDLE_T    hRezCmdQ;
    HANDLE_T    hRezFrmQ;
    UINT16      u2SrcWidth;
    UINT16      u2SrcHeidht;
    UINT16      u2DesWidth;
    UINT16      u2DesHeidht;
    UINT16      u2DesPitch;
    BOOL        fgCoarse;
    struct _VENC_REZ_OBJ_T *ptRezObj;
    struct _VENC_BUFMGR_BASE_T *ptCoarseBuffMgr;

    //encode flow
    UINT32      u4FrameNo;
    BOOL        fg1stHeader;
    BOOL        fgSkipHeaderOnce;
    BOOL        fgKeyframe;
    UINT8       u1RepeatHeader;
    BOOL        fgWriteSEI;
    BOOL        fgForceIDR;
    BOOL        fgReqAddAud;
	BOOL        fgSecure;
    VENC_H264_PIC_TYPE eType;
    UINT8       u1BFrameNo;
    UINT8       u1BFrmIdx;
    UINT32     u4RecordSize;
    UINT32     u4RecordAddr;
    #if defined(CC_S_PLATFORM) && (defined(CC_WK_CUST) || defined(CC_HK_CUST) || defined(CC_CP_CUST))
    VENC_PIX_FMT_T ePixFmt;
    #endif
    VENC_IN_PIC_T  uaIn[VENC_BFRAME_MAX];
    VENC_OUT_PIC_T uaOut[VENC_BFRAME_MAX];
    VENC_COS_PIC_PRAM_T uaPram[VENC_BFRAME_MAX];

    UINT8 u1BSeqIdx;
    UINT8 u1RefSeqIdx;

    UINT32 u4FrefCSAddr;
    UINT32 u4BrefCSAddr;

    UINT16 u2IDRFrmPeriod;
    UINT16 u2IDRFrmIdx;

    UINT16 u2IFrmPeriod;
    UINT16 u2IFrmIdx;

    UINT32 u4RCUAddr;
    UINT32 u4RCUCodeSize;

    //working buffer
    UINT32 u4CFrmBuffAddr[7];
    UINT32 u4YFrmBuffAddr[2];
    UINT32 u4UVFrmBuffAddr[2];

    UINT32 u4InitWp;
    UINT32 u4BsSa;
    UINT32 u4BsSz;
    UINT32 u4BsEa;
    UINT32 u4NaluBufSa;
    UINT32 u4NaluBufSz;
    UINT32 u4NaluBufEa;
    UINT32 u4NaluBufWp;
    UINT32 u4AudNaluBufSa;
    UINT32 u4AudNaluBufSz;
    UINT32 u4AudNaluBufEa;
    UINT32 u4AudNaluBufWp;
    UINT32 u4RomCodeAddr;
    UINT32 u4UpperInfoMBAddr;
    UINT32 u4ColInfoAddr;
    UINT32 u4CSInfoAddr;
    UINT32 u4NextCpSa;
    UINT32 u4Rp;
    UINT32 u4DumpInfoAddr;
    UPTR u4ThumbnailYuv420;
    UPTR u4ThumbnailARGB;

    BOOL   fgEMUDirectMode;

    VENC_RAVEN_HW_BUF_T rHwBuf;
    //VENC_RAVEN_CRC_T    rCrc;
    VENC_BS_BUF_STATUS rBsBufStatus[VENC_RAVEN_BSBUF_CNT];

    //debug info
    UINT32 u4SPScrc;
    UINT32 u4PPScrc;
    UINT32 u4FRMcrc;

    UINT32 u4PingPongNo;
} VENC_CTRL_BASE_T;
#endif // from h264api

typedef struct
{
    UINT32 data;
}VENC_PIC_PRAM_T;

typedef struct
{
    VENC_FRMQ_TYPE_T eType;
    union{
        struct {
            VENC_IN_PIC_T    tIn;
            VENC_OUT_PIC_T   tOut;
            VENC_PIC_PRAM_T  tPram;
        }frm;
        VENC_RT_PARM_T tRTParm;
        VENC_RT_CTRL_T tRTCtrl;
    }u;
}VENC_FRMQ_DATA_T;

struct _VENC_OBJECT_TYPE_T;

typedef struct _VENC_OBJECT_T
{
    //link list
    // legacy
    struct _VENC_OBJECT_T *next;

    struct _VENC_OBJECT_T *prNext;

    // an object-type pointer, this object was created by this object-type
    struct _VENC_OBJECT_TYPE_T *prObjectType;

    UINT32 u4Id;

    UINT32 u4HalLock;

    BOOL    fgInterlace;
    BOOL    fgConstQualityMode;
    UINT8   u1Used;
    UINT16  u2Pitch;

    //variable
    UINT8   u1aName[7];
    UINT8   u1Framerate;

    // for dynamic framerate change
    UINT32  u4LastPts;
    // we support run-time resolution change,
    // but the resolution can not larger than u2MaxWidth*u2MaxHeight
    // u2MaxWidth and u2MaxHeight are initialized in (*Init) callback function
    UINT16  u2MaxWidth;
    UINT16  u2MaxHeight;
    UINT16  u2Width;
    UINT16  u2Height;
    UINT32  u4Type;
    UINT32  u4Bitrate;
    UINT32  u4PeriodOfIntraFrames;
    UINT32  u4FixedQpValue;
    UINT32  u4GOPValue;
    UINT32  u4FrameCnt;
    VENC_HANDLE hParam;

    //resize source
    BOOL fgResizeSrc;
    UINT32 u4GfxConfig;
    UINT32 u4GfxTmpY;
    UINT32 u4GfxTmpC;
    UINT32 u4SrcPitch;
    UINT32 u4SrcWidth;
    UINT32 u4SrcHeight;
    VOID *pvIn;
    VOID *pvOut;

    //working buffer
    UPTR u4BuffAddr;
    UINT32 u4BuffSize;
    UINT32 u4UsedSize;
    UPTR u4BuffPtr;
    VENC_HANDLE hVencFbmHandle;
    // for debug: cli will use these
    UPTR u4YAddr;
    UPTR u4CAddr;
    UPTR u4VAddr;
    UINT32 u4DumpIndex;
    UINT32 u4DumpFlag;
    UINT32 u4DumpResv;
#ifdef CC_VENC_RM_SUPPORT
	PFN_VENC_RM_CB pfRMnty;
	UINT32 u4Priority;
	HANDLE_T hWaitKickSema;
	UCHAR ucBlockAsNoResource;	//Block as no resource to encoder.
#endif

#ifdef VENC_DRAM_PROFILE
    // Dram info
    UINT32                u4DramTotalCycle;
    UINT32                u4FrmCnt;
#endif

    VENC_PIX_FMT_T   ePixFmt;
    VENC_SMODE_T     eSMode;

    VENC_STATE_T     eState;
    VENC_ENC_STATE_T eEncState;
    VENC_PROFILE_T eProfile;

    HANDLE_T    hEncThread;
    VOID        (*pfnEncMainLoop)(VOID *);
    HANDLE_T    hEncCmdQ;
    HANDLE_T    hEncSyncSema;
    HANDLE_T    hEncFrmQ;
    VENC_HANDLE hCtrl;

    // get thumbnail
    BOOL fgGetThumbnail;
    UINT32 u4ThumbnailWidth;
    UINT32 u4ThumbnailPitch;
    UINT32 u4ThumbnailHeight;
    VOID *pvThumbnailTag;
    VOID (*pfnThumbnailCb)(VOID *pvTag, UPTR u4PhyAddr);

    //output callback
    VOID *pvCallbackData;
    VOID (*OutputCallback)(VOID *, VENC_IN_PIC_T *, VENC_OUT_PIC_T *, UINT32);

    //function
    UINT32      (*Close)          (struct _VENC_OBJECT_T *);
    VENC_HANDLE (*CreateParam)    (struct _VENC_OBJECT_T *, VENC_PROFILE_T, BOOL fgInterlace);
    UINT32      (*SetParam)       (struct _VENC_OBJECT_T *, UINT32, VOID *);
    UINT32      (*GetParam)       (struct _VENC_OBJECT_T *, UINT32, VOID *);
    VENC_HANDLE (*CreateCtrl)     (struct _VENC_OBJECT_T *, VENC_PROFILE_T);
    UINT32      (*SetCtrl)        (struct _VENC_OBJECT_T *, UINT32, VOID *);
    UINT32      (*GetCtrl)        (struct _VENC_OBJECT_T *, UINT32, VOID *);
    UINT32      (*Init)           (struct _VENC_OBJECT_T *);
    UINT32      (*Run)            (struct _VENC_OBJECT_T *);
    UINT32      (*Stop)           (struct _VENC_OBJECT_T *);
    UINT32      (*EncSeqHdrSync)  (struct _VENC_OBJECT_T *, VENC_OUT_PIC_T *, VOID*);
    UINT32      (*EncFrameSync)   (struct _VENC_OBJECT_T *, VENC_IN_PIC_T *, VENC_OUT_PIC_T *, VOID*);
    UINT32      (*EncFrameAsync)  (struct _VENC_OBJECT_T *, VENC_IN_PIC_T *, VENC_OUT_PIC_T *, VOID*);
    UINT32      (*SetRtParamSync) (struct _VENC_OBJECT_T *, VENC_RT_PARM_T *);
    UINT32      (*SetRtParamAsync)(struct _VENC_OBJECT_T *, VENC_RT_PARM_T *);
    UINT32      (*SetRtCtrlSync)  (struct _VENC_OBJECT_T *, VENC_RT_CTRL_T *);
    UINT32      (*SetRtCtrlAsync) (struct _VENC_OBJECT_T *, VENC_RT_CTRL_T *);
    UINT32      (*UnlockBuf)      (struct _VENC_OBJECT_T *, UINT32, UINT32);

    // dump this object's status
    VOID        (*Dump)           (struct _VENC_OBJECT_T *prObject /*, CHAR *pcOutputBuffer, UINT32 u4OutputBufferSize*/);

    UINT8  u1HierPLayerCount;
} VENC_OBJECT_T;


struct _VENC_OBJECT_TYPE_OPERATIONS_T;
typedef struct _VENC_OBJECT_TYPE_OPERATIONS_T VENC_OBJECT_TYPE_OPERATIONS_T;

struct _VENC_OBJECT_TYPE_T;
typedef struct _VENC_OBJECT_TYPE_T VENC_OBJECT_TYPE_T;


// codec operations
struct _VENC_OBJECT_TYPE_OPERATIONS_T
{
    // create an instance of this codec
    VENC_OBJECT_T *(*Open)(VENC_OBJECT_TYPE_T *prObjectType);

    // before we create the first instance, we should start the hardware encoder
    UINT32 (*Load)(VENC_OBJECT_TYPE_T *prObjectType);

    // after we destroy the last instance, we should stop the hardware encoder
    UINT32 (*Unload)(VENC_OBJECT_TYPE_T *prObjectType);
};


// codec information
struct _VENC_OBJECT_TYPE_T
{
    VENC_OBJECT_TYPE_T *prNext;

    UINT32 u4HalLock;

    // codec type: h264/h265/vp8/vp9 ...
    UINT32 u4Type;

    // codec name
    CHAR szName[16];

    // this codec's instances' head
    VENC_OBJECT_T *prHead;

    // codec's operations
    const VENC_OBJECT_TYPE_OPERATIONS_T *prOperations;
#ifdef CC_VENC_RM_SUPPORT
	PFN_VENC_RM_CB pfnRmCb;
#endif
};


typedef struct
{
    UINT32 u4YAddr;
    UINT32 u4UVAddr;
}VENC_FRM_BUFF_T;


typedef struct _VENC_OBJECT_HEAD_T
{
    //link list
    struct _VENC_OBJECT_T *next;
}VENC_OBJECT_HEAD_T;

extern VENC_OBJECT_HEAD_T *_ptVEncObjHead;

typedef struct
{
    UINT32 u4Addr;
    UINT32 u4Size;
    UINT32 u4Wp;
    UINT32 u4Rp;
}VENC_CTRL_BS_INFO;

typedef struct
{
    VENC_STATE_T     eState;
    VENC_ENC_STATE_T eEncState;
}VENC_CTRL_STATE;

//-----------------------------------------------------------------------------
// Prototype of Inter-file functions
//-----------------------------------------------------------------------------
UINT32 _VENC_Open(VENC_HANDLE *phEnc, UINT32 u4Type, VENC_PROFILE_T eProfile, BOOL fgInterlace);
UINT32 _VENC_Close(VENC_HANDLE hEnc);
UINT32 _VENC_Init(VENC_HANDLE hEnc);
UINT32 _VENC_Run(VENC_HANDLE hEnc);
UINT32 _VENC_Stop(VENC_HANDLE hEnc);
UINT32 _VENC_SetParam(VENC_HANDLE hEnc, UINT32 u4Type, VOID *pvArg);
UINT32 _VENC_GetParam(VENC_HANDLE hEnc, UINT32 u4Type, VOID *pvArg);
UINT32 _VENC_SetCtrl(VENC_HANDLE hEnc, UINT32 u4Type, VOID *pvArg);
UINT32 _VENC_GetCtrl(VENC_HANDLE hEnc, UINT32 u4Type, VOID *pvArg);
UINT32 _VENC_EncSeqHdrSync(VENC_HANDLE hEnc, VENC_OUT_PIC_T *ptOut);
UINT32 _VENC_EncFrameSync(VENC_HANDLE hEnc, VENC_IN_PIC_T *ptIn, VENC_OUT_PIC_T *ptOut);
UINT32 _VENC_EncFrameAsync(VENC_HANDLE hEnc, VENC_IN_PIC_T *ptIn, VENC_OUT_PIC_T *ptOut);
UINT32 _VENC_SetRtParamSync(VENC_HANDLE hEnc, VENC_RT_PARM_T *ptParm);
UINT32 _VENC_SetRtParamAsync(VENC_HANDLE hEnc, VENC_RT_PARM_T *ptParm);
UINT32 _VENC_SetRtCtrlSync(VENC_HANDLE hEnc, VENC_RT_CTRL_T *ptParm);
UINT32 _VENC_SetRtCtrlAsync(VENC_HANDLE hEnc, VENC_RT_CTRL_T *ptParm);
UINT32 _VENC_UnlockBuf(VENC_HANDLE hEnc, UINT32 u4Addr, UINT32 u4Size);
#ifdef CC_VENC_RM_SUPPORT
VENC_OBJECT_TYPE_T* _VENC_GetObjTypeInfo(void);
VOID _VENC_RMKickRet(UCHAR ucEsId, VENC_RM_BLOCK_E eCond);
VENC_OBJECT_T* _VENC_GetObjInfo(UCHAR ucEsId);
#endif

#if 0
UINT32 _VENC_ReceiveCmd(VENC_OBJECT_T *pObj, VOID *pvData);
VOID   _VENC_ProcessCmd(VENC_OBJECT_T *pObj, UINT32 u4Cmd, BOOL *pfgRun);
VOID   _VENC_SendFrm(VENC_OBJECT_T *pObj, VENC_FRMQ_DATA_T *prFrm);
#endif
#ifdef VENC_DRAM_PROFILE
VOID _VENC_DramAccessByteStart(VENC_OBJECT_T *this);
VOID _VENC_DramAccessByteEnd(VENC_OBJECT_T *this);
#endif


//-----------------------------------------------------------------------------
// Prototype  of public functions
//-----------------------------------------------------------------------------

typedef struct _VENC_BITS_BUFFER
{
    UINT32  i_data;
    UINT8   bit_left;
    UINT8   *p_data;
} VENC_BITS_BUFFER;


#define BITS_BUFFER rBitsBuff
#define PBITS_BUFFER prBitsBuff
#define PUT_BIT_START(buff) VENC_BITS_BUFFER BITS_BUFFER,*PBITS_BUFFER;PBITS_BUFFER=&BITS_BUFFER;BITS_BUFFER.i_data=0;if(!buff){ASSERT(buff);return VENC_INV_ARG;}inti_bits_buffer(PBITS_BUFFER,buff);
#define PUT_BIT_END(size) bits_flush(PBITS_BUFFER);size=BITS_BUFFER.i_data
#define PUT_BIT(val, n)    put_bits(PBITS_BUFFER, n, val)
#define ALIGN_BIT()    bits_align(PBITS_BUFFER)
#define PUT_BIT_UE(val)    put_bits(PBITS_BUFFER, bits_ue_size(val), val+1)
#define PUT_BIT_SE(val)    put_bits(PBITS_BUFFER, bits_se_size(val), bits_se_to_ue(val))

/*
put bit function
max 32 bit
*/
extern void put_bits(VENC_BITS_BUFFER *p_buffer, UINT8 count, UINT32 bits);
extern void inti_bits_buffer(VENC_BITS_BUFFER *p_buffer, UINT8 *p_addr);
extern void bits_align(VENC_BITS_BUFFER *p_buffer );
extern void bits_flush(VENC_BITS_BUFFER *p_buffer );
//exp-golomb code from spec 9.1
extern UINT8 bits_ue_size(UINT32 value);
extern UINT8 bits_se_size(INT32 value);
extern UINT32 bits_se_to_ue(INT32 value);

VOID vVencStartDebugEncode(VENC_OBJECT_T *prObject, VENC_IN_PIC_T *prIn, VENC_OUT_PIC_T *prOut, VOID* pvPram);

VOID vVencStopDebugEncode(VENC_OBJECT_T *prObject, VENC_IN_PIC_T *prIn, VENC_OUT_PIC_T *prOut, VOID* pvPram);

VOID vVencDumpObjectStream(VENC_OBJECT_T *prObject, VENC_IN_PIC_T *prIn, VENC_OUT_PIC_T *prOut, UINT32 u4DumpFlag);

VENC_OBJECT_T *prVencFindObjectByHandle(VENC_HANDLE hVencHandle);

// register a codec object type
extern UINT32 u4VencRegisterObjectType(VENC_OBJECT_TYPE_T *prObjectType, UINT32 u4Type);

// Unregister a codec object type
extern UINT32 u4VencUnregisterObjectType(VENC_OBJECT_TYPE_T *prObjectType);

extern VENC_OBJECT_T *prVencGetObjectByIndex(UINT32 u4ObjectIndex);

// init venc module
extern UINT32 u4VencInitModule(VOID);

// deinit venc module
extern UINT32 u4VencDeinitModule(VOID);

/**
 * Allocate working buffer
 * We got a whole buffer pool from the fbm
 */
VOID *pvVencAllocWorkingBuffer(VENC_OBJECT_T *prObject, UINT32 u4Size, UINT32 u4Align);

/** DUMMY */
VOID vVencFreeWorkingBuffer(VENC_OBJECT_T *prObject, UINT32 u4Addr);

/** Allocate an output buffer for encoding (spin), buffer status will be set to encoding */
UINT32 u4VencAllocOutputBuffer(VENC_OBJECT_T *prObject, VENC_OUT_PIC_T *prOut);

/** Lock this output buffer for copying */
UINT32 u4VencLockOutputBuffer(VENC_OBJECT_T *prObject, UINT32 u4Addr);

/** Free this buffer to the pool (3?), buffer status will be reset to empty */
UINT32 u4VencFreeOutputBuffer(VENC_OBJECT_T *prObject, UINT32 u4Addr);

/** flush output buffer, do callback */
VOID vVencFlushOutputBuffer(VENC_OBJECT_T *prObject,
        VENC_IN_PIC_T *prIn,
        VENC_OUT_PIC_T *prOut,
        VOID *pvArg);

/** EOS output buffer, do callback */
VOID vVencSendEOSFrame(VENC_OBJECT_T *prObject,
        VENC_IN_PIC_T *prIn,
        VENC_OUT_PIC_T *prOut,
        VOID *pvArg);
UINT32 u4VencAppendOutputBuffer(VENC_OUT_PIC_T *prTo, const VENC_OUT_PIC_T *prFrom);

#endif // VENC_DRVIF_H


