
#include "mcfw/src_linux/mcfw_api/usecases/multich_common.h"
#include "mcfw/src_linux/mcfw_api/usecases/multich_ipcbits.h"
#include "demos/mcfw_api_demos/multich_usecase/ti_mcfw_ipnc_main.h"


/* =============================================================================
 * Externs
 * ============================================================================= */

/* Merge Link for camera streams */
//#define NUM_DUP_LINK           (3)
#define NUM_MERGE_LINK              (1)
#define CAM_STREAM_MERGE_IDX        (0)
//#define HDMIDIS_DUP_IDX        (0)
/* =============================================================================
 * Use case code
 * ============================================================================= */
static SystemVideo_Ivahd2ChMap_Tbl systemVid_encDecIvaChMapTbl = {
    .isPopulated = 1,
    .ivaMap[0] = {
                  .EncNumCh = 2,
                  .EncChList = {0, 1},
                  .DecNumCh = 2,
                  .DecChList = {0, 1},
                  },

};



static Void SetIpcFramesOutInQueInfo(System_LinkQueInfo *inQueInfo)
{
    Int i;

    inQueInfo->numCh =2;// gVencModuleContext.vencConfig.numPrimaryChn;
    for (i = 0; i < inQueInfo->numCh; i++)
    {
        inQueInfo->chInfo[i].bufType = SYSTEM_BUF_TYPE_VIDFRAME;
        inQueInfo->chInfo[i].dataFormat = SYSTEM_DF_YUV420SP_UV;
        inQueInfo->chInfo[i].memType    = SYSTEM_MT_NONTILEDMEM;
        inQueInfo->chInfo[i].scanFormat = SYSTEM_SF_PROGRESSIVE;
        inQueInfo->chInfo[i].startX     = 0;
        inQueInfo->chInfo[i].startY     = 0;
        inQueInfo->chInfo[i].width      = 1920;
        inQueInfo->chInfo[i].height     = 1080;
        inQueInfo->chInfo[i].pitch[0]   = 1920;
        inQueInfo->chInfo[i].pitch[1]   = 0;
        inQueInfo->chInfo[i].pitch[2]   = 0;
    }
}

Void multich_create_uw_fullftr()
{
	Int32 i;
	// VPSS ---->A8
	//A8--->c674
    System_LinkInfo framesProducerLinkInfo;
	//A8--->VIDEO
    CameraLink_CreateParams cameraPrm;
    UInt32 mergeId[NUM_MERGE_LINK];
    MergeLink_CreateParams mergePrm[NUM_MERGE_LINK];
	//VPSS ---->A8
	IpcFramesOutLinkRTOS_CreateParams ipcFramesOutVpssToHostPrm;
	IpcFramesInLinkHLOS_CreateParams ipcFramesInHostPrm;
    //A8--->M3Video
	UInt32 ipcInVideoFrameId;
	
	IpcFramesOutLinkHLOS_CreateParams  ipcFramesOutHostPrm;
    IpcFramesInLinkRTOS_CreateParams   ipcFramesInVideoFromHostPrm;
    
	EncLink_CreateParams encPrm;
    //M3Video --->A8
	IpcBitsOutLinkRTOS_CreateParams ipcBitsOutVideoToHostPrm;
    IpcBitsInLinkHLOS_CreateParams ipcBitsInHostPrm;

    CameraLink_VipInstParams *pCameraInstPrm;
    CameraLink_OutParams *pCameraOutPrm;

	/* IPC struct init */
	MULTICH_INIT_STRUCT(IpcFramesOutLinkRTOS_CreateParams, ipcFramesOutVpssToHostPrm);
	MULTICH_INIT_STRUCT(IpcFramesInLinkHLOS_CreateParams, ipcFramesInHostPrm);
	MULTICH_INIT_STRUCT(IpcFramesOutLinkHLOS_CreateParams, ipcFramesOutHostPrm);
	MULTICH_INIT_STRUCT(IpcFramesInLinkRTOS_CreateParams,  ipcFramesInVideoFromHostPrm);

	MULTICH_INIT_STRUCT(IpcBitsOutLinkRTOS_CreateParams, ipcBitsOutVideoToHostPrm);
	MULTICH_INIT_STRUCT(IpcBitsInLinkHLOS_CreateParams, ipcBitsInHostPrm);

    MultiCh_detectBoard();
    System_linkControl(SYSTEM_LINK_ID_M3VPSS, SYSTEM_M3VPSS_CMD_RESET_VIDEO_DEVICES, NULL, 0, TRUE);
    System_linkControl(SYSTEM_LINK_ID_M3VIDEO, SYSTEM_COMMON_CMD_SET_CH2IVAHD_MAP_TBL,
                       &systemVid_encDecIvaChMapTbl, sizeof(SystemVideo_Ivahd2ChMap_Tbl), TRUE);

	gVcamModuleContext.cameraId = SYSTEM_LINK_ID_CAMERA;
    mergeId[CAM_STREAM_MERGE_IDX] = SYSTEM_VPSS_LINK_ID_MERGE_0;
	gVcamModuleContext.ipcFramesOutVpssToHostId  = SYSTEM_VPSS_LINK_ID_IPC_FRAMES_OUT_0;
	gVcamModuleContext.ipcFramesInHostId = SYSTEM_HOST_LINK_ID_IPC_FRAMES_IN_0;
	
    ipcInVideoFrameId = SYSTEM_VIDEO_LINK_ID_IPC_FRAMES_IN_0;//SYSTEM_VIDEO_LINK_ID_IPC_IN_M3_0;
	gVcamModuleContext.ipcFramesOutHostId = SYSTEM_HOST_LINK_ID_IPC_FRAMES_OUT_0; 
	
	gVencModuleContext.encId = SYSTEM_LINK_ID_VENC_0;

	gVencModuleContext.ipcBitsOutRTOSId = SYSTEM_VIDEO_LINK_ID_IPC_BITS_OUT_0;
    gVencModuleContext.ipcBitsInHLOSId = SYSTEM_HOST_LINK_ID_IPC_BITS_IN_0;

	/* Camera Link params */
	CameraLink_CreateParams_Init(&cameraPrm);
	cameraPrm.captureMode = CAMERA_LINK_CAPMODE_ISIF;
	cameraPrm.outQueParams[0].nextLink  = mergeId[CAM_STREAM_MERGE_IDX];
	cameraPrm.outQueParams[1].nextLink  = mergeId[CAM_STREAM_MERGE_IDX];

	/* This is for TVP5158 Audio Channels - Change it to 16 if there are 16
	 * audio channels connected in cascade */
	cameraPrm.numAudioChannels = 0;
	cameraPrm.numVipInst = 1;

	cameraPrm.tilerEnable = FALSE;
	cameraPrm.vsEnable = FALSE;

	pCameraInstPrm = &cameraPrm.vipInst[0];
	pCameraInstPrm->vipInstId = SYSTEM_CAMERA_INST_VP_CSI2;
	pCameraInstPrm->videoDecoderId = MultiCh_getSensorId(gUI_mcfw_config.sensorId);
	pCameraInstPrm->inDataFormat = SYSTEM_DF_YUV420SP_UV;
	pCameraInstPrm->sensorOutWidth  = 1920;
	pCameraInstPrm->sensorOutHeight = 1080;
	pCameraInstPrm->standard = SYSTEM_STD_1080P_24;//SYSTEM_STD_1080P_30;
	pCameraInstPrm->numOutput = 2;

	/* First stream */
	pCameraOutPrm = &pCameraInstPrm->outParams[0];
	pCameraOutPrm->dataFormat = SYSTEM_DF_YUV420SP_UV;
	pCameraOutPrm->scEnable = FALSE;
	pCameraOutPrm->scOutWidth = 1920;
	pCameraOutPrm->scOutHeight = 1080;
	pCameraOutPrm->outQueId = 0;

	/* second stream */
	pCameraOutPrm = &pCameraInstPrm->outParams[1];
	pCameraOutPrm->dataFormat = SYSTEM_DF_YUV420SP_UV;
	pCameraOutPrm->scEnable = FALSE;
	pCameraOutPrm->scOutWidth = 1920;//720;
	pCameraOutPrm->scOutHeight = 1080;//480;
	pCameraOutPrm->outQueId = 1;

	/* 2A config*/
	cameraPrm.t2aConfig.n2A_vendor = gUI_mcfw_config.n2A_vendor;
	cameraPrm.t2aConfig.n2A_mode = gUI_mcfw_config.n2A_mode;

    mergePrm[CAM_STREAM_MERGE_IDX].numInQue = 2;
    mergePrm[CAM_STREAM_MERGE_IDX].inQueParams[0].prevLinkId = gVcamModuleContext.cameraId;
    mergePrm[CAM_STREAM_MERGE_IDX].inQueParams[0].prevLinkQueId = 0;
    mergePrm[CAM_STREAM_MERGE_IDX].inQueParams[1].prevLinkId = gVcamModuleContext.cameraId;
    mergePrm[CAM_STREAM_MERGE_IDX].inQueParams[1].prevLinkQueId = 1;
    mergePrm[CAM_STREAM_MERGE_IDX].outQueParams.nextLink = gVcamModuleContext.ipcFramesOutVpssToHostId;
    mergePrm[CAM_STREAM_MERGE_IDX].notifyNextLink = TRUE;

	//set Frames out vpss to host link info
	ipcFramesOutVpssToHostPrm.baseCreateParams.noNotifyMode = TRUE;
	ipcFramesOutVpssToHostPrm.baseCreateParams.notifyNextLink = FALSE;
	ipcFramesOutVpssToHostPrm.baseCreateParams.notifyPrevLink = FALSE;
	ipcFramesOutVpssToHostPrm.baseCreateParams.inQueParams.prevLinkId =  mergeId[CAM_STREAM_MERGE_IDX];
	ipcFramesOutVpssToHostPrm.baseCreateParams.inQueParams.prevLinkQueId = 0;
	ipcFramesOutVpssToHostPrm.baseCreateParams.outQueParams[0].nextLink = gVcamModuleContext.ipcFramesInHostId;
	ipcFramesOutVpssToHostPrm.baseCreateParams.numOutQue=1;
	ipcFramesOutVpssToHostPrm.baseCreateParams.notifyProcessLink=FALSE;

	ipcFramesInHostPrm.baseCreateParams.noNotifyMode = TRUE;
	ipcFramesInHostPrm.baseCreateParams.notifyNextLink = FALSE;
	ipcFramesInHostPrm.baseCreateParams.notifyPrevLink = FALSE;//TRUE;
	ipcFramesInHostPrm.baseCreateParams.inQueParams.prevLinkId = gVcamModuleContext.ipcFramesOutVpssToHostId;
	ipcFramesInHostPrm.baseCreateParams.inQueParams.prevLinkQueId = 0;
	ipcFramesInHostPrm.baseCreateParams.outQueParams[0].nextLink = SYSTEM_LINK_ID_INVALID;;
	ipcFramesInHostPrm.baseCreateParams.numOutQue = 1;
	ipcFramesInHostPrm.exportOnlyPhyAddr = TRUE;
	
	ipcFramesInHostPrm.cbCtx = &gVcamModuleContext;
	ipcFramesInHostPrm.cbFxn = Vcam_ipcFramesInCbFxn;

	//A8 Frames to M3Video set
	ipcFramesOutHostPrm.baseCreateParams.noNotifyMode = TRUE;
	ipcFramesOutHostPrm.baseCreateParams.notifyNextLink = FALSE;//TRUE;
	ipcFramesOutHostPrm.baseCreateParams.notifyPrevLink = FALSE;
	ipcFramesOutHostPrm.baseCreateParams.numOutQue = 1;
	ipcFramesOutHostPrm.baseCreateParams.inQueParams.prevLinkId = SYSTEM_LINK_ID_INVALID;
	ipcFramesOutHostPrm.baseCreateParams.inQueParams.prevLinkQueId = 0;
	ipcFramesOutHostPrm.baseCreateParams.outQueParams[0].nextLink = ipcInVideoFrameId;
	SetIpcFramesOutInQueInfo(&ipcFramesOutHostPrm.inQueInfo);
	
	ipcFramesInVideoFromHostPrm.baseCreateParams.noNotifyMode = TRUE;
	ipcFramesInVideoFromHostPrm.baseCreateParams.notifyNextLink = FALSE;
	ipcFramesInVideoFromHostPrm.baseCreateParams.notifyPrevLink = FALSE;
	ipcFramesInVideoFromHostPrm.baseCreateParams.numOutQue = 1;
	ipcFramesInVideoFromHostPrm.baseCreateParams.inQueParams.prevLinkId = gVcamModuleContext.ipcFramesOutHostId;
	ipcFramesInVideoFromHostPrm.baseCreateParams.inQueParams.prevLinkQueId = 0;
	ipcFramesInVideoFromHostPrm.baseCreateParams.outQueParams[0].nextLink = gVencModuleContext.encId;
	
	// init encode params
    /* Video Encoder Link params */
	MULTICH_INIT_STRUCT(EncLink_CreateParams, encPrm);
	{
	    encPrm.numBufPerCh[0] = 4; //D1
	    encPrm.numBufPerCh[1] = 4; //CIF]]
	
		EncLink_ChCreateParams *pLinkChPrm;
        EncLink_ChDynamicParams *pLinkDynPrm;
        VENC_CHN_DYNAMIC_PARAM_S *pDynPrm;
        VENC_CHN_PARAMS_S *pChPrm;

		for (i = 0; i < VENC_PRIMARY_CHANNELS; i++)
		{
			pLinkChPrm  = &encPrm.chCreateParams[i];
			pLinkDynPrm = &pLinkChPrm->defaultDynamicParams;

			pChPrm      = &gVencModuleContext.vencConfig.encChannelParams[i];
			pDynPrm     = &pChPrm->dynamicParam;
	//		if( i==1)
				pLinkChPrm->format = IVIDEO_H264HP;
	//		else
	//			pLinkChPrm->format = IVIDEO_MJPEG;

			pLinkChPrm->profile                 = gVencModuleContext.vencConfig.h264Profile[i];
			pLinkChPrm->dataLayout              = IVIDEO_PROGRESSIVE;
			pLinkChPrm->fieldMergeEncodeEnable  = FALSE;
			pLinkChPrm->enableAnalyticinfo      = pChPrm->enableAnalyticinfo;
			pLinkChPrm->maxBitRate              = pChPrm->maxBitRate;
			pLinkChPrm->encodingPreset          = pChPrm->encodingPreset;
			pLinkChPrm->rateControlPreset       = IVIDEO_USER_DEFINED; //pChPrm->rcType;
			pLinkChPrm->enableHighSpeed         = FALSE;
			pLinkChPrm->enableWaterMarking      = pChPrm->enableWaterMarking;
			pLinkChPrm->StreamPreset            = gUI_mcfw_config.StreamPreset[i];

			pLinkDynPrm->intraFrameInterval     = pDynPrm->intraFrameInterval;
			pLinkDynPrm->targetBitRate          = pDynPrm->targetBitRate;
			pLinkDynPrm->interFrameInterval     = 1;
			pLinkDynPrm->mvAccuracy             = IVIDENC2_MOTIONVECTOR_QUARTERPEL;
			pLinkDynPrm->inputFrameRate         = pDynPrm->inputFrameRate;
			pLinkDynPrm->rcAlg                  = pDynPrm->rcAlg;
			pLinkDynPrm->qpMin                  = pDynPrm->qpMin;
			pLinkDynPrm->qpMax                  = pDynPrm->qpMax;
			pLinkDynPrm->qpInit                 = pDynPrm->qpInit;
			pLinkDynPrm->vbrDuration            = pDynPrm->vbrDuration;
			pLinkDynPrm->vbrSensitivity         = pDynPrm->vbrSensitivity;

//			encPrm.numBufPerCh[i] = 4;
//			gVencModuleContext.encFormat[i] = pLinkChPrm->format;
		}
	}

    /* Video Encoder Framerate */
    encPrm.chCreateParams[0].defaultDynamicParams.inputFrameRate = 25;
    encPrm.chCreateParams[1].defaultDynamicParams.inputFrameRate = 25;
	encPrm.vsEnable = gUI_mcfw_config.vsEnable;
	encPrm.isVaUseCase = 0;
/*	
    for (i = VENC_PRIMARY_CHANNELS; i < (VENC_CHN_MAX - 1); i++)
    {
        encPrm.chCreateParams[i].format = IVIDEO_MJPEG;
        encPrm.chCreateParams[i].profile = 0;
        encPrm.chCreateParams[i].dataLayout = IVIDEO_PROGRESSIVE;
        encPrm.chCreateParams[i].fieldMergeEncodeEnable = FALSE;
        encPrm.chCreateParams[i].defaultDynamicParams.intraFrameInterval = 0;
        encPrm.chCreateParams[i].encodingPreset = 0;
        encPrm.chCreateParams[i].enableAnalyticinfo = 0;
        encPrm.chCreateParams[i].enableWaterMarking = 0;
        encPrm.chCreateParams[i].defaultDynamicParams.inputFrameRate = 25;
        encPrm.chCreateParams[i].rateControlPreset = 0;
        encPrm.chCreateParams[i].defaultDynamicParams.targetBitRate = 100 * 1000;
        encPrm.chCreateParams[i].defaultDynamicParams.interFrameInterval = 0;
        encPrm.chCreateParams[i].defaultDynamicParams.mvAccuracy = 0;
    }
*/
	encPrm.inQueParams.prevLinkId = ipcInVideoFrameId;
    encPrm.inQueParams.prevLinkQueId = 0;
    encPrm.outQueParams.nextLink = gVencModuleContext.ipcBitsOutRTOSId;

	/* IPC Bits Out VIDEO Link params */
	ipcBitsOutVideoToHostPrm.baseCreateParams.noNotifyMode = TRUE;//FALSE;
	ipcBitsOutVideoToHostPrm.baseCreateParams.notifyNextLink = FALSE;
	ipcBitsOutVideoToHostPrm.baseCreateParams.notifyPrevLink = FALSE;
    ipcBitsOutVideoToHostPrm.baseCreateParams.inQueParams.prevLinkId = gVencModuleContext.encId;
    ipcBitsOutVideoToHostPrm.baseCreateParams.inQueParams.prevLinkQueId = 0;
    ipcBitsOutVideoToHostPrm.baseCreateParams.numOutQue = 1;
    ipcBitsOutVideoToHostPrm.baseCreateParams.outQueParams[0].nextLink = gVencModuleContext.ipcBitsInHLOSId;
    MultiCh_ipcBitsInitCreateParams_BitsOutRTOS(&ipcBitsOutVideoToHostPrm, TRUE);

    /* IPC Bits In HOST Link params */
	ipcBitsInHostPrm.baseCreateParams.noNotifyMode = TRUE;//FALSE;
	ipcBitsInHostPrm.baseCreateParams.notifyNextLink = FALSE;
	ipcBitsInHostPrm.baseCreateParams.notifyPrevLink = FALSE;//TRUE;
    ipcBitsInHostPrm.baseCreateParams.inQueParams.prevLinkId = gVencModuleContext.ipcBitsOutRTOSId;
    ipcBitsInHostPrm.baseCreateParams.inQueParams.prevLinkQueId = 0;
    MultiCh_ipcBitsInitCreateParams_BitsInHLOS(&ipcBitsInHostPrm);

    /* Links Creation */
    /* Camera Link */
    System_linkCreate(gVcamModuleContext.cameraId, &cameraPrm, sizeof(cameraPrm));
    System_linkControl(gVcamModuleContext.cameraId, CAMERA_LINK_CMD_DETECT_VIDEO, NULL, 0, TRUE);
    /* Merge Link */
    System_linkCreate(mergeId[CAM_STREAM_MERGE_IDX], &mergePrm[CAM_STREAM_MERGE_IDX], sizeof(mergePrm[CAM_STREAM_MERGE_IDX]));
	
	//out yuv 420 1080P to A8
	System_linkCreate(gVcamModuleContext.ipcFramesOutVpssToHostId, &ipcFramesOutVpssToHostPrm, sizeof(ipcFramesOutVpssToHostPrm));
	System_linkCreate(gVcamModuleContext.ipcFramesInHostId, &ipcFramesInHostPrm, sizeof(ipcFramesInHostPrm));

	System_linkGetInfo(gVcamModuleContext.ipcFramesInHostId,&framesProducerLinkInfo);
	OSA_assert(framesProducerLinkInfo.numQue == 1);
	ipcFramesOutHostPrm.inQueInfo = framesProducerLinkInfo.queInfo[0];
	//A8 out yuv420 to M3Video
	System_linkCreate(gVcamModuleContext.ipcFramesOutHostId, &ipcFramesOutHostPrm, sizeof(ipcFramesOutHostPrm));
	System_linkCreate(ipcInVideoFrameId, &ipcFramesInVideoFromHostPrm, sizeof(ipcFramesInVideoFromHostPrm));

	// Video Encoder Link
    System_linkCreate(gVencModuleContext.encId, &encPrm, sizeof(encPrm));

	//M3Video to A8
	System_linkCreate(gVencModuleContext.ipcBitsOutRTOSId, &ipcBitsOutVideoToHostPrm, sizeof(ipcBitsOutVideoToHostPrm));
	System_linkCreate(gVencModuleContext.ipcBitsInHLOSId, &ipcBitsInHostPrm, sizeof(ipcBitsInHostPrm));

	//start Links
    System_linkStart(gVencModuleContext.ipcBitsInHLOSId);
    System_linkStart(gVencModuleContext.ipcBitsOutRTOSId);
    System_linkStart(gVencModuleContext.encId);

    System_linkStart(ipcInVideoFrameId);

    System_linkStart(gVcamModuleContext.ipcFramesOutHostId);
    System_linkStart(gVcamModuleContext.ipcFramesInHostId);
    System_linkStart(gVcamModuleContext.ipcFramesOutVpssToHostId);
       
	System_linkStart(mergeId[CAM_STREAM_MERGE_IDX]);
	System_linkStart(gVcamModuleContext.cameraId);

}

Void multich_delete_uw_fullftr()
{
    UInt32 mergeId[NUM_MERGE_LINK];

    /* display link */
	System_linkDelete(gVcamModuleContext.ipcFramesInHostId);
	System_linkDelete(gVcamModuleContext.ipcFramesOutVpssToHostId);

    /* Merge Link */
    System_linkDelete(mergeId[CAM_STREAM_MERGE_IDX]);

    /* Camera Link */
    System_linkDelete(gVcamModuleContext.cameraId);

    /* Print the HWI, SWI and all tasks load */
    /* Reset the accumulated timer ticks */
    MultiCh_prfLoadCalcEnable(FALSE, TRUE, FALSE);

    OSA_printf("USECASE TEARDOWN DONE\n");
}
