/* 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: chongliang.cao $
 * $Date: 2015/11/24 $
 * $RCSfile: venc_if.h,v $
 * $Revision: #2 $
 *
 *---------------------------------------------------------------------------*/

/** @file venc_if.h
 *  Public interface of software program stream demux driver
 */


#ifndef VENC_IF_H
#define VENC_IF_H

//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------
//#include "drv_common.h"
#include "x_common.h"
#include "x_typedef.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"
#ifdef CC_ATV_PVR_SUPPORT
#include "drv_vbi.h"
#endif

//#define VENC_TIME_PROFILE
#ifdef VENC_TIME_PROFILE
#include "x_timer.h"
#endif


//-----------------------------------------------------------------------------
// Macro definitions
//-----------------------------------------------------------------------------

//return value
#define VENC_OK                     (0)
#define VENC_FAIL                   (1)
#define VENC_NO_MEMORY              (2)
#define VENC_DEV_BUSY               (3)
#define VENC_INV_HANDLE             (4)
#define VENC_INV_ARG                (5)
#define VENC_INTERNAL_ERR           (6)
#define VENC_NOT_IMPL               (7)
#define VENC_WAIT_YUV               (8)

#define VENC_COMM    (0x000)
#define VENC_H264    (0x100)

// parameter flag
#define VENC_PRAM_FLAG_RES              (1L<<0)
#define VENC_PRAM_FLAG_FRAMERATE        (1L<<1)
#define VENC_PRAM_FLAG_BITRATE          (1L<<2)

// ctrl flag
#define VENC_CTRL_FLAG_INSERT_KEYFRAME  (1L<<0)

// real time parameter flag
#define VENC_RT_PARM_FLAG_RES               (1L<<0)
#define VENC_RT_PARM_FLAG_BITRATE           (1L<<1)
#define VENC_RT_PARM_FLAG_FRAMERATE         (1L<<2)
#define VENC_RT_PARM_FLAG_PIXAL             (1L<<3)

// real time ctrl flag
#define VENC_RT_CTRL_FLAG_INSERT_KEYFRAME   (1L<<0)

#define VENC_OUT_PIC_MEMBERS\
    UINT32 u4Type;\
    UINT32 u4Pts;\
    UINT32 u4Addr;\
    UINT32 u4Size;\
    UINT32 u4RStart;\
    UINT32 u4REnd;


//-----------------------------------------------------------------------------
// Type definitions
//-----------------------------------------------------------------------------

typedef VOID * VENC_HANDLE;
#define VENC_NULL_HANDLE  ((VOID*)0 )


typedef enum
{
    VENC_PROFILE_VPHONE = 0,    //VIDEO PHONE, ex. skype
    VENC_PROFILE_PVR,           //ATV PVR
    VENC_PROFILE_MS,            //Multiscreen interaction
    VENC_PROFILE_EMU,           //FOR EMULATION OR IC VERIFICATION
    VENC_PROFILE_SLT,           // for SLT
    VENC_PROFILE_MSI_OSTG,      //Multiscreen interaction with output stage
    VENC_PROFILE_CUST,
    VENC_PROFILE_MAX
} VENC_PROFILE_T;


typedef enum
{
    VENC_PIX_FMT_PSCAN = 0,     // DI format
    VENC_PIX_FMT_NV12,          //420 with two planes, the Y plane is first. ex.emulation
    VENC_PIX_FMT_B16X32,        //BLOCK MODE 16 X 32
    VENC_PIX_FMT_B64X32,        //BLOCK MODE 64 X 32
    VENC_PIX_FMT_NV21,          //420 with two planes, the Y plane is first.vuvuvuvuvu ex.emulation
    VENC_PIX_FMT_YV12,          //420 with two planes, the Y plane is first.u uuuu v vvvvv ex.emulation
    VENC_PIX_FMT_MAX
} VENC_PIX_FMT_T;

typedef struct
{
    UINT32 u4YAddr;
    UINT32 u4CAddr;
    UINT32 u4Pts;
    BOOL fgRzSrc;
#ifdef CC_ATV_PVR_SUPPORT
    VBI_PVR_NOTIFY_DATA rCC_Data;
    VBI_PVR_NOTIFY_DATA rAFD_Data;
#endif
#ifdef VENC_TIME_PROFILE
    HAL_TIME_T rTimeHwS;
#endif
} VENC_IN_PIC_T;

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

typedef struct
{
    VENC_OUT_PIC_MEMBERS
} VENC_OUT_PIC_T;


typedef enum
{
    VENC_PRAM_FRAMERATE    = VENC_COMM + 1,
    VENC_PRAM_BITRATE      ,//= VENC_COMM + 2,
    VENC_PRAM_RESOLUTION   ,//= VENC_COMM + 3,
    VENC_PRAM_PROFILELEVEL,
    VENC_PRAM_ADDAUD,
    VENC_PRAM_WIDTH,
    VENC_PRAM_HEIGHT,
    VENC_PRAM_NUM,
    VENC_PRAM_ASPECTRATIOIDC,
    VENC_PRAM_PERIOD_OF_INTRA_FRAMES,
    VENC_PRAM_PIX_FMT,
    VENC_PRAM_MAX
} VENC_PRAM_T;


typedef enum
{
    VENC_CTRL_SYNC_MODE,
    VENC_CTRL_PIX_FMT,
    VENC_CTRL_BUFF,
    VENC_CTRL_OUT_CB,
    VENC_CTRL_RZ,
    VENC_CTRL_GET_THUMBNAIL,
    VENC_CTRL_MAX
} VENC_CTRL_T;


// VENC_CTRL_SYNC_MODE
typedef enum
{
    VENC_SMODE_SYNC,    // only sync api is work.
    VENC_SMODE_ASYNC,   //
    VENC_SMODE_DUAL,    //both sync api and async api  are work.
    VENC_SMODE_MAX
} VENC_SMODE_T;


typedef struct
{
    UINT16 u2Width;
    UINT16 u2Height;
} VENC_PRAM_RES_T;
typedef struct
{
    VENC_PIX_FMT_T ePixFmt;
    UINT16 u2Pitch;
} VENC_PRAM_PIXFMT_T;


// VENC_CTRL_PIX_FMT
typedef struct
{
    VENC_PIX_FMT_T ePixFmt;
    UINT16 u2Pitch;
} VENC_CTRL_PIXFMT_T;


// VENC_CTRL_BUFF
typedef struct
{
    UINT32 u4Addr;
    UINT32 u4Size;
} VENC_CTRL_BUFF_T;


// VENC_CTRL_OUT_CB
typedef struct
{
    VOID* pvData;
    VOID  (*cb)(VOID *, VENC_IN_PIC_T *, VENC_OUT_PIC_T *, UINT32);
} VENC_CTRL_OUTCB_T;


// VENC_CTRL_RZ
typedef struct
{
    BOOL fgResizeSrc;
    UINT32 u4GfxConfig;
    UINT32 u4GfxTmpY;
    UINT32 u4GfxTmpC;
    UINT32 u4SrcPitch;
    UINT32 u4SrcWidth;
    UINT32 u4SrcHeight;
    VOID *pvIn;
    VOID *pvOut;
} VENC_CTRL_RZ_T;


// VENC_CTRL_GET_THUMBNAIL
typedef struct
{
    UINT32 u4Width;
    UINT32 u4Height;
    VOID *pvTag;
    VOID (*cb)(VOID *pvTag, UINT32 u4PhyAddr);
} VENC_CTRL_THUMBNAIL_T;


typedef struct
{
    UINT32 u4Flag;
    UINT16 u2Width;
    UINT16 u2Height;
    UINT16 u2Pitch;
    UINT32 u4Bitrate;
    UINT8  u1Framerate;
	VENC_PIX_FMT_T ePixFmt;
} VENC_RT_PARM_T;


typedef struct
{
    UINT32 u4Flag;
} VENC_RT_CTRL_T;


//H264 PART
typedef enum
{
    VENC_H264_PIC_TYPE_SPS = 0x01,
    VENC_H264_PIC_TYPE_PPS = 0x02,
    VENC_H264_PIC_TYPE_SEI = 0x04,
    VENC_H264_PIC_TYPE_IDR = 0x10,
    VENC_H264_PIC_TYPE_I   = 0x20,
    VENC_H264_PIC_TYPE_P   = 0x30,
    VENC_H264_PIC_TYPE_B   = 0x40,
    VENC_H264_PIC_TYPE_MAX
} VENC_H264_PIC_TYPE;


typedef enum
{
    VENC_H264_PRAM_PROFILE_LEVEL  = VENC_H264 + 1,
    VENC_H264_PRAM_2              = VENC_H264 + 2,
    VENC_H264_PRAM_MAX
} VENC_H264_PRAM_T;


typedef enum
{
    VENC_H264_CTRL_1    = VENC_H264 + 1,
    VENC_H264_CTRL_2    = VENC_H264 + 2,
    VENC_H264_CTRL_3    = VENC_H264 + 3,
    VENC_H264_CTRL_MAX
} VENC_H264_CTRL_T;

typedef struct
{
    UINT16 u2Profile;
    UINT16 u2Level;
} VENC_H264_PRAM_PL_T;

typedef struct
{
    UINT32 u4SarIdc;
    UINT32 u4SarWidth;
    UINT32 u4SarHeight;
} VENC_H264_SAR_INFO_T;

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

VENC_HANDLE VENC_Open(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 *ptCtrl);
UINT32 VENC_SetRtCtrlAsync(VENC_HANDLE hEnc, VENC_RT_CTRL_T *ptCtrl);
UINT32 VENC_UnlockBuf(VENC_HANDLE hEnc, UINT32 u4Addr, UINT32 u4Size);
//BOOL VENC_CkgenOnOff(BOOL fgEnable);

//-----------------------------------------------------------------------------
// usage
//-----------------------------------------------------------------------------
/*
//######example 1:
//##skype: IPPPPPP.... mode
// USE SYNC MODE

VENC_HANDLE hVEnc;
UINT32 u4Value;

hVEnc = VENC_Open(VENC_H264, VENC_PROFILE_VPHONE, FALSE);

if (VENC_NULL_HANDLE == hVEnc)
{
    Printf("Open venc fail!\n");
    return;
}

//30 frame per sec.
u4Value = 30;
if (VENC_OK != VENC_SetParam(hVEnc, VENC_PRAM_FRAMERATE, (VOID*)&u4Framerate))
{
    Printf("Set parameter error!\n");
    return;
}

//200k
u4Value = 204800;
if (VENC_OK != VENC_SetParam(hVEnc, VENC_PRAM_BITRATE, (VOID*)&u4Value))
{
    Printf("Set parameter error!\n");
    return;
}

//352*288
VENC_PRAM_RES_T res;
res.u2Width = 352;
res.u2Height= 288;
if (VENC_OK != VENC_SetParam(hVEnc, VENC_PRAM_RESOLUTION, (VOID*)&res))
{
    Printf("Set parameter error!\n");
    return;
}

//PIX FORMATE
VENC_CTRL_PIXFMT_T pix;
pix.ePixFmt  = VENC_PIX_FMT_NV12;
pix.u2Pitch   = 352;
if (VENC_OK != VENC_SetCtrl(hVEnc, VENC_CTRL_PIX_FMT, (VOID*)&pix))
{
    Printf("Set ctrl error!\n");
    return;
}

//SYNC MODE
u4Val = (UINT32)VENC_SMODE_SYNC;
if (VENC_OK != VENC_SetCtrl(hVEnc, VENC_CTRL_SYNC_MODE, (VOID*)&u4Val))
{
    Printf("Set ctrl error!\n");
    return;
}


//Working Buffer
VENC_CTRL_BUFF_T buff;
buff.u4Addr  = 0x00001234;
buff.u4Size   = 0x00005678;
if (VENC_OK != VENC_SetCtrl(hVEnc, VENC_CTRL_BUFF, (VOID*)&buff))
{
    Printf("Set ctrl error!\n");
    return;
}


//Init
if (VENC_OK != VENC_Init(hVEnc))
{
    Printf("Init fail!\n");
    return;
}


//Run
if (VENC_OK != VENC_Run(hVEnc))
{
    Printf("Run fail!\n");
    return;
}

//encoder frames
while (doing)
{
    UINT32 u4Ret;
    VENC_IN_PIC_T rIn;
    VENC_OUT_PIC_T rOut;

    get_frame_from_camera;

    rIn.u4YAddr  = Y_data;
    rIn.u4CAddr = C_data;

    if (use extra buffer)
    {
        rOut.u4Addr = 0x23456789; //use
        rOut.u4Size  = 0x20000;      //use
        rOut.u4RStart = 0               // line buffer
        rOut.u4REnd  = 0                // line buffer
    }
    else
    {
        rOut.u4Addr = 0; //use
        rOut.u4Size  = 0;      //use
    }

    if (VENC_OK == (u4Ret= VENC_EncFrameSync(hVEnc, &rIn, &rOut)))
    {
         process encode from rOut.u4Addr;
         VENC_UnlockBuf(hVEnc, &rOut);
     }
    else
    {
        Printf("Encode frame fail, errCode:%d\n", u4Ret);
    }

}

//Stop
if (VENC_OK != VENC_Stop(hVEnc))
{
    Printf("Stop fail!\n");
    return;
}

//Close
if (VENC_OK != VENC_Close(hVEnc))
{
    Printf("Close fail!\n");
    return;
}



//######example 2:
//##skype: IPPPPPP.... mode
// USE ASYNC MODE

VENC_HANDLE hVEnc;
UINT32 u4Value;

hVEnc = VENC_Open(VENC_H264, VENC_PROFILE_VPHONE, FALSE);

if (VENC_NULL_HANDLE == hVEnc)
{
    Printf("Open venc fail!\n");
    return;
}

//30 frame per sec.
u4Value = 30;
if (VENC_OK != VENC_SetParam(hVEnc, VENC_PRAM_FRAMERATE, (VOID*)&u4Framerate))
{
    Printf("Set parameter error!\n");
    return;
}

//200k
u4Value = 204800;
if (VENC_OK != VENC_SetParam(hVEnc, VENC_PRAM_BITRATE, (VOID*)&u4Value))
{
    Printf("Set parameter error!\n");
    return;
}

//352*288
VENC_PRAM_RES_T res;
res.u2Width = 352;
res.u2Height= 288;
if (VENC_OK != VENC_SetParam(hVEnc, VENC_PRAM_RESOLUTION, (VOID*)&res))
{
    Printf("Set parameter error!\n");
    return;
}

//PIX FORMATE
VENC_CTRL_PIXFMT_T pix;
pix.ePixFmt  = VENC_PIX_FMT_NV12;
pix.u2Pitch   = 352;
if (VENC_OK != VENC_SetCtrl(hVEnc, VENC_CTRL_PIX_FMT, (VOID*)&pix))
{
    Printf("Set ctrl error!\n");
    return;
}

//SYNC MODE
u4Val = (UINT32)VENC_SMODE_ASYNC;
if (VENC_OK != VENC_SetCtrl(hVEnc, VENC_CTRL_SYNC_MODE, (VOID*)&u4Val))
{
    Printf("Set ctrl error!\n");
    return;
}


//Working Buffer
VENC_CTRL_BUFF_T buff;
buff.u4Addr  = 0x00001234;
buff.u4Size   = 0x00005678;
if (VENC_OK != VENC_SetCtrl(hVEnc, VENC_CTRL_BUFF, (VOID*)&buff))
{
    Printf("Set ctrl error!\n");
    return;
}


//Output Callback
HOST_T  rHost;
rHost.host = HOST;
rHost.hVEnc = hVEnc;

VOID demo_cb(VOID *pvArg, VENC_OUT_PIC_T * ptOut)
{
    HOST_T * pHost = (HOST_T)pvArg;

    process encode from ptOut->u4Addr;

    VENC_UnlockBuf(hVEnc, ptOut);
}

VENC_CTRL_OUTCB_T rCb;
rCb.pvData = (VOID *)&rHost;
rCb.cb        = demo_cb;

if (VENC_OK != VENC_SetCtrl(hVEnc, VENC_CTRL_OUT_CB, (VOID*)&rCb))
{
    Printf("Set ctrl error!\n");
    return;
}


//Init
if (VENC_OK != VENC_Init(hVEnc))
{
    Printf("Init fail!\n");
    return;
}


//Run
if (VENC_OK != VENC_Run(hVEnc))
{
    Printf("Run fail!\n");
    return;
}

//encoder frames
while (doing)
{
    UINT32 u4Ret;
    VENC_IN_PIC_T rIn;
    VENC_OUT_PIC_T rOut;

    get_frame_from_camera;

    rIn.u4YAddr  = Y_data;
    rIn.u4CAddr = C_data;

    if (use extra buffer)
    {
        rOut.u4Addr = 0x23456789; //use
        rOut.u4Size  = 0x20000;      //use
        rOut.u4RStart = 0               // line buffer
        rOut.u4REnd  = 0                // line buffer
    }
    else
    {
        rOut.u4Addr = 0; //use
        rOut.u4Size  = 0;      //use
    }

    if (VENC_OK == (u4Ret= VENC_EncFrameAsync(hVEnc, &rIn, &rOut)))
    {
        VENC_UnlockBuf(hVEnc, ptOut);
    }
    else
    {
        Printf("Encode frame fail, errCode:%d\n", u4Ret);
    }

}



//Stop
if (VENC_OK != VENC_Stop(hVEnc))
{
    Printf("Stop fail!\n");
    return;
}

//Close
if (VENC_OK != VENC_Close(hVEnc))
{
    Printf("Close fail!\n");
    return;
}



//######example 3:
//##prv: BBPBBP... mode
// only support async mode, when need to generate B type Frame
// please ref example 2

hVEnc = VENC_Open(VENC_H264, VENC_PROFILE_PVR, FALSE);

if (VENC_NULL_HANDLE == hVEnc)
{
    Printf("Open venc error!\n");
    return;
}

...


*/

#endif // VENC_IF_H


