////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2006-2009 MStar Semiconductor, Inc.
// All rights reserved.
//
// Unless otherwise stipulated in writing, any and all information contained
// herein regardless in any format shall remain the sole proprietary of
// MStar Semiconductor Inc. and be kept in strict confidence
// (ˇ§MStar Confidential Informationˇ¨) by the recipient.
// Any unauthorized act including without limitation unauthorized disclosure,
// copying, use, reproduction, sale, distribution, modification, disassembling,
// reverse engineering and compiling of the contents of MStar Confidential
// Information is unlawful and strictly prohibited. MStar hereby reserves the
// rights to any and all damages, losses, costs and expenses resulting therefrom.
//
////////////////////////////////////////////////////////////////////////////////

#include <config.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>

#include <pthread.h>

#include <directfb.h>

#include <direct/types.h>
#include <direct/mem.h>
#include <direct/memcpy.h>
#include <direct/messages.h>
#include <direct/thread.h>
#include <direct/util.h>

#include <idirectfb.h>

#include <core/surface.h>
#include <core/gfxcard.h>

#include <display/idirectfbsurface.h>

#include <media/idirectfbdatabuffer.h>
#include <media/idirectfbimageprovider.h>

#include <misc/gfx_util.h>

#include <MsCommon.h>
#include  <apiGFX.h>
#include  <apiGOP.h>
#include  <drvMMIO.h>

#include <drvXC_IOPort.h>
#include <drvTVEncoder.h>
#include <drvMVOP.h>
#include <apiXC.h>
#include <apiPNL.h>

#define VECAPTURE_QUALITY_REFINE 1
#define VECAPTURE_ALL_USE_VE_DRIVER 1 //Skip gop driver with IOC functions, all use VE driver APIs

static DFBResult Probe( IDirectFBImageProvider_ProbeContext *ctx );

static DFBResult
Construct( IDirectFBImageProvider *thiz,
           ... );


#include <direct/interface_implementation.h>

DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, VEC )
void AddvecImageProviderInterface()
{
}


/*****************************************************************************/




#if VECAPTURE_ALL_USE_VE_DRIVER
typedef struct {
     int                            ref;      /* reference counter */

     IDirectFBSurface               *destination;
     DFBRectangle                   dest_rect;
     CoreSurface                    *source;
     CardState                      state;
     CoreDFB                        *core;

     DIRenderCallback               callback;
     void                           *callback_ctx;

     E_XC_SOURCE_TO_VE              eSourceToVE;
     MS_VE_INPUT_SRC_TYPE           eSourceToIP;
     MS_WINDOW_TYPE                 stCapWin;
     MS_U16                         u16OutputHSize;
     MS_U16                         u16OutputVSize;
     MS_VE_VECAPTURESTATE           stVECapState;



     DFBSurfacePixelFormat          vec_capture_format;

     /*
     u16                           vec_capture_x;
     u16                           vec_capture_y;
     u16                           vec_capture_w;
     u16                           vec_capture_h;
     u8                            vec_capture_alphavalue;
     u8                            vec_csc_enable;
     */
     unsigned long                 vec_capture_addr;
     unsigned int                  vec_capture_pitch;

} IDirectFBImageProvider_VEC_data;
#else
typedef struct {
     int                            ref;      /* reference counter */

     IDirectFBSurface               *destination;
     DFBRectangle                   dest_rect;
     CoreSurface                    *source;
     CardState                      state;
     CoreDFB                        *core;

     DIRenderCallback               callback;
     void                           *callback_ctx;

     E_XC_SOURCE_TO_VE              eSourceToVE;
     MS_WINDOW_TYPE                 stCapWin;
     MS_U16                         u16OutputHSize;
     MS_U16                         u16OutputVSize;
     MS_GOP_VECAPTURESTATE          stVECapState;



     DFBSurfacePixelFormat          vec_capture_format;

     /*
     u16                           vec_capture_x;
     u16                           vec_capture_y;
     u16                           vec_capture_w;
     u16                           vec_capture_h;
     u8                            vec_capture_alphavalue;
     u8                            vec_csc_enable;
     */
     unsigned long                 vec_capture_addr;
     unsigned int                  vec_capture_pitch;

} IDirectFBImageProvider_VEC_data;
#endif //VECAPTURE_ALL_USE_VE_DRIVER
#define VECERRORMSG(x, ...) \
     D_ERROR( "IDirectFBImageProvider_VEC: " #x "!\n", ## __VA_ARGS__ )

#define VECDEBUGMSG(x, ...) \
     D_DEBUG( "IDirectFBImageProvider_VEC: " #x "!\n", ## __VA_ARGS__ )



static const int gconst_vecapture_pitch = 1440;

/*****************************************************************************
** Local Functions
*****************************************************************************/
#if VECAPTURE_ALL_USE_VE_DRIVER
static bool vecConvertToVEInputSrc(IDirectFBImageProvider_VEC_data *data, const char *value)
{
     if(strcmp (value, "DTV" ) == 0)
         data->eSourceToIP = MS_VE_SRC_DTV;
     else
     if(strcmp (value, "ATV" ) == 0)
         data->eSourceToIP = MS_VE_SRC_ATV;
     else
     if(strcmp(value,"AV")==0)
        data->eSourceToIP = MS_VE_SRC_CVBS0;
     else
     if(strcmp(value,"SV")==0)
        data->eSourceToIP = MS_VE_SRC_SVIDEO;
     else
     if(strcmp(value,"VGA")==0)
        data->eSourceToIP = MS_VE_SRC_DSUB;
     else
     if(strcmp(value,"COMP")==0)
        data->eSourceToIP = MS_VE_SRC_COMP;
     else
     if(strcmp(value,"HDMI")==0)
        data->eSourceToIP = MS_VE_SRC_HDMI_A;
     else
     if(strcmp(value,"STORAGE")==0)
        data->eSourceToIP = MS_VE_SRC_DTV; //For mm, use DTV temporary
     else
     {
        data->eSourceToIP = MS_VE_SRC_NONE;
        printf("VEC: Unknown Src type[%s]\n", value);
        return false;
     }
    printf("VEC: Src type convert: [%s] -> %u\n", value, data->eSourceToIP);
    return true;
}
#endif //#if VECAPTURE_ALL_USE_VE_DRIVER

static bool vecConfig( IDirectFBImageProvider_VEC_data *data, const char *name, const char *value )
{
     if(strcmp (name, "vec_capture_src" ) == 0)
     {
         if(strcmp(value,"OP2")==0)
            data->eSourceToVE = E_XC_OP2;
         else
         if(strcmp(value,"OVERLAP")==0)
            data->eSourceToVE = E_XC_OVERLAP;
         else
#if VECAPTURE_ALL_USE_VE_DRIVER
         if(strcmp (value, "IP_SUB" ) == 0)
             data->eSourceToVE = E_XC_IP_SUB;
         else
#endif
         if(strcmp (value, "IP" ) == 0)
             data->eSourceToVE = E_XC_IP;
         else
         if(strcmp (value, "VOP2" ) == 0)
             data->eSourceToVE = E_XC_VOP2;
         else
         if(strcmp(value,"BRI")==0)
            data->eSourceToVE = E_XC_BRI;
         else
         if(strcmp(value,"GAM")==0)
            data->eSourceToVE = E_XC_GAM;
         else
         if(strcmp(value,"DITHER")==0)
            data->eSourceToVE = E_XC_DITHER;
         else
             return false;
     } else
#if VECAPTURE_ALL_USE_VE_DRIVER
     if(strcmp (name, "vec_capture_inputsrc" ) == 0)
     {
        return vecConvertToVEInputSrc(data, value);
     } else
#endif
     if(strcmp (name, "vec_capture_x" ) == 0)
     {
         if(value)
         {
             char *error;
             unsigned long val = strtoul( value, &error, 10 );
             if (*error)
                return false;

             data->stCapWin.x = val;
         }else
             return false;
     } else
     if(strcmp (name, "vec_capture_y" ) == 0)
     {
         if(value)
         {
             char *error;
             unsigned long val = strtoul( value, &error, 10 );
             if (*error)
                return false;

             data->stCapWin.y = val;
         }else
             return false;
     } else
     if(strcmp (name, "vec_capture_w" ) == 0)
     {
         if(value)
         {
             char *error;
             unsigned long val = strtoul( value, &error, 10 );
             if (*error)
                return false;

             data->stCapWin.width = val;
         }else
             return false;
     } else
     if(strcmp (name, "vec_capture_h" ) == 0)
     {
         if(value)
         {
             char *error;
             unsigned long val = strtoul( value, &error, 10 );
             if (*error)
                return false;

             data->stCapWin.height = val;
         }else
             return false;
     } else
     if(strcmp (name, "vec_output_h" ) == 0)
     {
         if(value)
         {
             char *error;
             unsigned long val = strtoul( value, &error, 10 );
             if (*error)
                return false;

             data->u16OutputHSize = val;
         }else
             return false;
     } else
     if(strcmp (name, "vec_output_v" ) == 0)
     {
         if(value)
         {
             char *error;
             unsigned long val = strtoul( value, &error, 10 );
             if (*error)
                return false;

             data->u16OutputVSize = val;
         }else
             return false;
     }else
     if(strcmp (name, "vec_capture_addr" ) == 0)
     {
         if(value)
         {
             char *error;
             unsigned long val = strtoul( value, &error, 16 );
             if (*error)
                return false;

             data->vec_capture_addr = val;
         }else
             return false;
     }

     return true;
}

static bool
parseFile (IDirectFBImageProvider_VEC_data *data, const char *filename)
{
     FILE *in;
     char line[400];

     in = fopen (filename, "r");
     if (in == 0)
     {
          D_DEBUG( "DirectFB/VEC: Loading gopc file failed.\n");
          return false;
     }

     while (fgets( line, 400, in ))
     {
         char *name = line;
         char *comment = strchr( line, '#');
         char *value;

         if (comment)
         {
            *comment = 0;
         }

         value = strchr( line, '=' );

         if (value)
         {
            *value = 0;
            value++;
            direct_trim( &value );
         }

         direct_trim( &name );

         if ((!*name) || (*name == '#'))
            continue;

         vecConfig(data, name, value );
     }

     fclose (in);

     return true;
}

#if VECAPTURE_ALL_USE_VE_DRIVER
static bool
vecInit(IDirectFBImageProvider_VEC_data *data)
{
    MS_VE_Output_CAPTURE VECapture;

    //printf("\nget the op screen\n");
    //MDrv_VE_SetDbgLevel(1);
    printf("\nImage Capture:  Output width is %d, height is %d\n",data->u16OutputHSize, data->u16OutputVSize);
    printf("VEC Source is %d\n", data->eSourceToVE);

    if(data->eSourceToVE==E_XC_OP2||data->eSourceToVE==E_XC_OVERLAP)
    {
        MS_PNL_DST_DispInfo dstDispInfo;
        MS_U32 width;
        MS_U32 height;
        MS_Switch_VE_Src_Info SwitchInputSrc;
        MS_VE_Set_Mode_Type SetModeType;
        MS_VE_Output_Ctrl OutputCtrl;
        MApi_PNL_GetDstInfo(&dstDispInfo, sizeof(MS_PNL_DST_DispInfo));
        width  = dstDispInfo.DEHEND - dstDispInfo.DEHST + 1;
        height = dstDispInfo.DEVEND - dstDispInfo.DEVST + 1;

#if VECAPTURE_QUALITY_REFINE
        MS_VE_CusScalingInfo stVECusScalingInfo;
        stVECusScalingInfo.bHCusScalingEnable = TRUE;
        stVECusScalingInfo.bVCusScalingEnable = TRUE;
        stVECusScalingInfo.u16HScalingsrc = width;
        stVECusScalingInfo.u16HScalingdst = data->u16OutputHSize;
        stVECusScalingInfo.u16VScalingsrc = height;
        stVECusScalingInfo.u16VScalingdst= data->u16OutputVSize;
        MDrv_VE_Set_Customer_Scaling(&stVECusScalingInfo);
#endif
        VECapture.bVECapture = TRUE;
        VECapture.u16Width = data->u16OutputHSize;
        VECapture.u16height= data->u16OutputVSize;
        VECapture.u32MiuBaseAddr = data->vec_capture_addr;
        VECapture.u32MemSize     = gconst_vecapture_pitch*data->u16OutputVSize*3;

        MDrv_VE_InitVECapture(&VECapture);
        MApi_XC_SetOutputCapture(ENABLE, data->eSourceToVE);     // Enable op2 to ve path
        SetModeType.u16H_CapSize     = width;
        SetModeType.u16V_CapSize     = height;
        SetModeType.u16H_CapStart    = dstDispInfo.DEHST;
        SetModeType.u16V_CapStart    = dstDispInfo.DEVST;
        SetModeType.u16H_SC_CapSize  = width;
        SetModeType.u16V_SC_CapSize  = height;
        SetModeType.u16H_SC_CapStart = dstDispInfo.DEHST;
        SetModeType.u16V_SC_CapStart = dstDispInfo.DEVST;
        SetModeType.bHDuplicate      = FALSE;
        SetModeType.bSrcInterlace    = FALSE;
        SetModeType.u16InputVFreq    = MApi_XC_GetOutputVFreqX100()/10;

        SwitchInputSrc.InputSrcType  = MS_VE_SRC_SCALER; // Set source of VE to scaler_OP.
        MDrv_VE_SwitchInputSource(&SwitchInputSrc);
        MDrv_VE_SetMode(&SetModeType);
        OutputCtrl.bEnable = TRUE;
        OutputCtrl.OutputType = MS_VE_OUT_CAPTURE;
        MDrv_VE_SetOutputCtrl(&OutputCtrl);

        return true;
    }
    else if(data->eSourceToVE==E_XC_IP_SUB)
    {
        VECapture.bVECapture = TRUE;
        VECapture.u16Width = data->u16OutputHSize;
        VECapture.u16height= data->u16OutputVSize;
        VECapture.u32MiuBaseAddr = data->vec_capture_addr;
        VECapture.u32MemSize     = gconst_vecapture_pitch*data->u16OutputVSize*3;
        MDrv_VE_InitVECapture(&VECapture);

        MApi_XC_SetOutputCapture(ENABLE, data->eSourceToVE);     // Enable ip to ve path
    }
    else
    {
        return false;
    }




    return true;
}


static bool EnaVECapture(IDirectFBImageProvider_VEC_data *data)
{
    bool bRet =false;
    if(data->stVECapState.bEnable)
    {
        if(data->eSourceToVE==E_XC_IP_SUB) //For IP capture, need reconfig VE for different input signals
        {
            //Skip enable vec for sub_ip capture in DFB
            //Because some ve config code is not added here
            /*MS_VE_InputSrc_Info VeInputSrc;
            MS_VE_Set_Mode_Type SetModeType;
            MS_VE_Output_Ctrl OutputCtrl;
            XC_ApiStatus DrvStatus;
            MApi_XC_GetStatus(&DrvStatus, SUB_WINDOW);
#if VECAPTURE_QUALITY_REFINE
            MS_VE_CusScalingInfo stVECusScalingInfo;
            stVECusScalingInfo.bHCusScalingEnable = TRUE;
            stVECusScalingInfo.bVCusScalingEnable = TRUE;
            stVECusScalingInfo.u16HScalingsrc = DrvStatus.stCapWin.width;
            stVECusScalingInfo.u16HScalingdst = data->u16OutputHSize;
            stVECusScalingInfo.u16VScalingsrc = DrvStatus.stCapWin.height;
            stVECusScalingInfo.u16VScalingdst= data->u16OutputVSize;
            MDrv_VE_Set_Customer_Scaling(&stVECusScalingInfo);
#endif
            SetModeType.u16H_CapSize     = DrvStatus.stCapWin.width;
            SetModeType.u16V_CapSize     = DrvStatus.stCapWin.height;
            SetModeType.u16H_CapStart    = DrvStatus.stCapWin.x;
            SetModeType.u16V_CapStart    = DrvStatus.stCapWin.y;
            SetModeType.u16H_SC_CapSize  = DrvStatus.stCapWin.width;
            SetModeType.u16V_SC_CapSize  = DrvStatus.stCapWin.height;
            SetModeType.u16H_SC_CapStart = DrvStatus.stCapWin.x;
            SetModeType.u16V_SC_CapStart = DrvStatus.stCapWin.y;
            SetModeType.bHDuplicate      = FALSE;
            SetModeType.bSrcInterlace    = DrvStatus.bInterlace;
            SetModeType.u16InputVFreq    = DrvStatus.u16InputVFreq;

            VeInputSrc.u16Version = VE_INPUTSRC_INFO_VERSION; // Set source of VE to scaler_sub.
            VeInputSrc.eInputSrcType = MS_VE_SRC_SUB;
            VeInputSrc.eInputSrcOfMixedSrc = data->eSourceToIP;
            MDrv_VE_SetInputSource(&VeInputSrc);
            MDrv_VE_SetMode(&SetModeType);
            OutputCtrl.bEnable = TRUE;
            OutputCtrl.OutputType = MS_VE_OUT_CAPTURE;
            MDrv_VE_SetOutputCtrl(&OutputCtrl);*/
        }
        else
        {
            bRet = MDrv_VE_EnaVECapture(&(data->stVECapState));
        }
    }
    else
    {
        MS_VE_Output_CAPTURE VECapture;
        VECapture.bVECapture = FALSE;
        MDrv_VE_InitVECapture(&VECapture);
        bRet = MDrv_VE_EnaVECapture(&(data->stVECapState));
    }


    if((bRet == TRUE) && (data->stVECapState.u8Result == TRUE))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}


static bool
vecOpen(IDirectFBImageProvider_VEC_data *data)
{
   data->stVECapState.u16Version = VE_VECAPTURESTATE_VERSION;
   data->stVECapState.u16Length  = sizeof(MS_VE_VECAPTURESTATE);
   data->stVECapState.bEnable = TRUE;
   return EnaVECapture(data);

}

static bool
vecClose(IDirectFBImageProvider_VEC_data *data)
{
#if VECAPTURE_QUALITY_REFINE
    MS_VE_CusScalingInfo stVECusScalingInfo;
    stVECusScalingInfo.bHCusScalingEnable = FALSE;
    stVECusScalingInfo.bVCusScalingEnable = FALSE;
    MDrv_VE_Set_Customer_Scaling(&stVECusScalingInfo);
#endif
    data->stVECapState.u16Version = VE_VECAPTURESTATE_VERSION;
    data->stVECapState.u16Length  = sizeof(MS_VE_VECAPTURESTATE);
    data->stVECapState.bEnable = FALSE;
    return EnaVECapture(data);


}

static bool
vecOneFrameDone(IDirectFBImageProvider_VEC_data *data)
{

    bool bRet;
    data->stVECapState.u16Version = VE_VECAPTURESTATE_VERSION;
    data->stVECapState.u16Length  = sizeof(MS_VE_VECAPTURESTATE);
    data->stVECapState.u8FrameCount = 1;
    bRet = MDrv_VE_VECaptureWaitOnFrame(&(data->stVECapState));
    if((bRet == TRUE) && (data->stVECapState.u8Result == TRUE))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }

}
#else
static bool
vecInit(IDirectFBImageProvider_VEC_data *data)
{
    MS_Switch_VE_Src_Info SwitchInputSrc;
    MS_VE_Set_Mode_Type SetModeType;
    MS_VE_Output_CAPTURE VECapture;
    MS_VE_Output_Ctrl OutputCtrl;


    MS_PNL_DST_DispInfo dstDispInfo;
    MS_U32 width  = 0;
    MS_U32 height = 0;
    //should modify by the format
    int bytes_per_pixel = 2;
     //printf("\nget the op screen\n");

    MApi_PNL_GetDstInfo(&dstDispInfo, sizeof(MS_PNL_DST_DispInfo));
    width  = dstDispInfo.DEHEND - dstDispInfo.DEHST + 1;
    height = dstDispInfo.DEVEND - dstDispInfo.DEVST + 1;

    printf("\nthe Output width is %d, height is %d\n",data->u16OutputHSize, data->u16OutputVSize);
    printf("VEC Source is %d\n", data->eSourceToVE);

    if(data->eSourceToVE==E_XC_OP2||data->eSourceToVE==E_XC_OVERLAP)
    {
#if VECAPTURE_QUALITY_REFINE
        MS_VE_CusScalingInfo stVECusScalingInfo;
        stVECusScalingInfo.bHCusScalingEnable = TRUE;
        stVECusScalingInfo.bVCusScalingEnable = TRUE;
        stVECusScalingInfo.u16HScalingsrc = width;
        stVECusScalingInfo.u16HScalingdst = data->u16OutputHSize;
        stVECusScalingInfo.u16VScalingsrc = height;
        stVECusScalingInfo.u16VScalingdst= data->u16OutputVSize;
        MDrv_VE_Set_Customer_Scaling(&stVECusScalingInfo);
#endif
        VECapture.bVECapture = TRUE;
        VECapture.u16Width = data->u16OutputHSize;
        VECapture.u16height= data->u16OutputVSize;
        VECapture.u32MiuBaseAddr = data->vec_capture_addr;
        VECapture.u32MemSize     = gconst_vecapture_pitch*data->u16OutputVSize*3;

        MDrv_VE_InitVECapture(&VECapture);
        MApi_XC_SetOutputCapture(ENABLE, data->eSourceToVE);     // Enable op2 to ve path
        SetModeType.u16H_CapSize     = width;
        SetModeType.u16V_CapSize     = height;
        SetModeType.u16H_CapStart    = dstDispInfo.DEHST;
        SetModeType.u16V_CapStart    = dstDispInfo.DEVST;
        SetModeType.u16H_SC_CapSize  = width;
        SetModeType.u16V_SC_CapSize  = height;
        SetModeType.u16H_SC_CapStart = dstDispInfo.DEHST;
        SetModeType.u16V_SC_CapStart = dstDispInfo.DEVST;
        SetModeType.bHDuplicate      = FALSE;
        SetModeType.bSrcInterlace    = FALSE;
        SwitchInputSrc.InputSrcType  = MS_VE_SRC_SCALER; // Set source of VE to scaler.
        SetModeType.u16InputVFreq    = MApi_XC_GetOutputVFreqX100()/10;

        MDrv_VE_SwitchInputSource(&SwitchInputSrc);
        MDrv_VE_SetMode(&SetModeType);
        OutputCtrl.bEnable = TRUE;
        OutputCtrl.OutputType = MS_VE_OUT_CAPTURE;
        MDrv_VE_SetOutputCtrl(&OutputCtrl);

        return true;
    }
    else
    {
        return false;
    }




    return true;
}


static bool EnaVECapture(PMS_GOP_VECAPTURESTATE pstVECapState)
{
    E_GOP_API_Result eRet;
    MS_VE_Output_CAPTURE VECapture;

    if(pstVECapState->bEnable)
    {
        eRet = MApi_GOP_EnaVECapture(pstVECapState);
    }
    else
    {
        VECapture.bVECapture = FALSE;
        MDrv_VE_InitVECapture(&VECapture);
        eRet = MApi_GOP_EnaVECapture(pstVECapState);
    }


    if(eRet == GOP_API_SUCCESS)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}


static bool
vecOpen(IDirectFBImageProvider_VEC_data *data)
{
   data->stVECapState.bEnable = TRUE;
   return EnaVECapture(&(data->stVECapState));

}

static bool
vecClose(IDirectFBImageProvider_VEC_data *data)
{

#if VECAPTURE_QUALITY_REFINE
    MS_VE_CusScalingInfo stVECusScalingInfo;
    stVECusScalingInfo.bHCusScalingEnable = FALSE;
    stVECusScalingInfo.bVCusScalingEnable = FALSE;
    MDrv_VE_Set_Customer_Scaling(&stVECusScalingInfo);
#endif
    data->stVECapState.bEnable = FALSE;
    return EnaVECapture(&(data->stVECapState));


}

static bool
vecOneFrameDone(IDirectFBImageProvider_VEC_data *data)
{

    E_GOP_API_Result eRet;

    data->stVECapState.u8FrameCount = 1;
    eRet = MApi_GOP_VECaptureWaitOnFrame(&(data->stVECapState));
    if((eRet == GOP_API_SUCCESS))
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }

}
#endif //VECAPTURE_ALL_USE_VE_DRIVER
/*****************************************************************************
** Interface
*****************************************************************************/

static void
IDirectFBImageProvider_VEC_Destruct( IDirectFBImageProvider *thiz )
{
     IDirectFBImageProvider_VEC_data *data = thiz->priv;

     dfb_surface_unref( data->source );

     dfb_state_set_destination( &data->state,  NULL );
     dfb_state_set_source( &data->state,  NULL );
     dfb_state_destroy(&data->state);

     DIRECT_DEALLOCATE_INTERFACE( thiz );
}

static DirectResult
IDirectFBImageProvider_VEC_AddRef( IDirectFBImageProvider *thiz )
{
     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_VEC )

     data->ref++;

     return DFB_OK;
}

static DirectResult
IDirectFBImageProvider_VEC_Release( IDirectFBImageProvider *thiz )
{
     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_VEC )

     if (--data->ref == 0)
          IDirectFBImageProvider_VEC_Destruct( thiz );

     return DFB_OK;
}

static DFBResult
IDirectFBImageProvider_VEC_GetSurfaceDescription( IDirectFBImageProvider *thiz,
                                                  DFBSurfaceDescription  *desc )
{
     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_VEC )

     if (!desc)
          return DFB_INVARG;

     if (!data->source)
          return DFB_FAILURE;

     desc->flags       = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
     desc->width       = data->u16OutputHSize;
     desc->height      = data->u16OutputVSize;
     desc->pixelformat = data->source->config.format;

     return DFB_OK;
}

static DFBResult
IDirectFBImageProvider_VEC_GetImageDescription( IDirectFBImageProvider *thiz,
                                                 DFBImageDescription   *desc )
{
     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_VEC )

     desc->caps = DICAPS_NONE;

     return DFB_OK;
}


static DFBResult
IDirectFBImageProvider_VEC_RenderTo( IDirectFBImageProvider *thiz,
                                     IDirectFBSurface       *destination,
                                     const DFBRectangle     *dest_rect )
{
     IDirectFBSurface_data *dst_data;
     DFBRectangle           rect = { 0, 0, 0, 0 };

     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_VEC )

     if (!destination)
          return DFB_INVARG;

     dst_data = destination->priv;
     if ((!dst_data) || (!dst_data->surface))
          return DFB_DESTROYED;

     if (dest_rect) {
          if ((dest_rect->w < 1) || (dest_rect->h < 1))
               return DFB_INVARG;

          rect = *dest_rect;
          rect.x += dst_data->area.wanted.x;
          rect.y += dst_data->area.wanted.y;
     }else
          rect = dst_data->area.wanted;

     /* save for later blitting operation */
     data->dest_rect = rect;

     //open GOPCapture HW:


    if(false == vecInit(data))
        return DFB_FAILURE;

     /* build the clip rectangle */
     if (!dfb_rectangle_intersect( &rect, &dst_data->area.current ))
          return DFB_INVARG;

     /* put the destination clip into the state */
     DFBRegion clip = {rect.x, rect.y, rect.x + rect.w - 1,rect.y + rect.h - 1};
     dfb_state_set_clip(&data->state, &clip);
     dfb_state_set_destination( &data->state,  dst_data->surface );

     if (data->destination)
          data->destination->Release( data->destination );

     destination->AddRef( destination );
     data->destination = destination;

     //Start DWin Interrupt:
     vecOpen(data);
     while(1)
     {
        if(vecOneFrameDone(data))
        {
            break;
        }
        else
        {

        }
     }
     vecClose(data);

     {
        DFBRectangle   rect, drect;
        bool xmirror_enable = false;
        bool ymirror_enable = false;

        if(dst_data->state.blit_xmirror_enabled)
        {
            xmirror_enable = true;
        }

        if(dst_data->state.blit_ymirror_enabled)
        {
            ymirror_enable = true;
        }

        rect.x = 0;
        rect.y = 0;
        rect.w = data->u16OutputHSize;
        rect.h = data->u16OutputVSize;

        drect = data->dest_rect;

        dfb_state_set_blit_xmirror_enabled( &data->state, xmirror_enable);
        dfb_state_set_blit_ymirror_enabled( &data->state, ymirror_enable);

        dfb_gfxcard_stretchblit( &rect, &drect, &data->state );

        if (data->callback)
             data->callback (&rect, data->callback_ctx);
     }
    dfb_state_set_destination( &data->state, NULL );
    destination->Release( destination );
     return DFB_OK;
}

static DFBResult
IDirectFBImageProvider_VEC_SetRenderCallback( IDirectFBImageProvider *thiz,
                                              DIRenderCallback        callback,
                                              void                   *context )
{
     DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_VEC)

     data->callback     = callback;
     data->callback_ctx = context;

     return DFB_OK;
}


/*
Wrap the IDirectFBImageProvider_GOPC_xxx to _IDirectFBImageProvider_GOPC_xxx for safe call
*/


static DirectResult
_IDirectFBImageProvider_VEC_AddRef( IDirectFBImageProvider *thiz )
{
    DFBResult ret = DFB_OK;
    DFB_GLOBAL_LOCK(DFB_LOCK_FOR_EXEC);
    ret = IDirectFBImageProvider_VEC_AddRef(thiz);
    DFB_GLOBAL_UNLOCK(DFB_LOCK_FOR_EXEC);
    return ret;
}

static DirectResult
_IDirectFBImageProvider_VEC_Release( IDirectFBImageProvider *thiz )
{
    DFBResult ret = DFB_OK;
    DFB_GLOBAL_LOCK(DFB_LOCK_FOR_EXEC);
    ret = IDirectFBImageProvider_VEC_Release(thiz);
    DFB_GLOBAL_UNLOCK(DFB_LOCK_FOR_EXEC);
    return ret;
}

static DFBResult
_IDirectFBImageProvider_VEC_GetSurfaceDescription( IDirectFBImageProvider *thiz,
                                                  DFBSurfaceDescription  *desc )
{
    DFBResult ret = DFB_OK;
    DFB_GLOBAL_LOCK(DFB_LOCK_FOR_EXEC);
    ret = IDirectFBImageProvider_VEC_GetSurfaceDescription(thiz,desc);
    DFB_GLOBAL_UNLOCK(DFB_LOCK_FOR_EXEC);
    return ret;
}

static DFBResult
_IDirectFBImageProvider_VEC_GetImageDescription( IDirectFBImageProvider *thiz,
                                                 DFBImageDescription   *desc )
{
    DFBResult ret = DFB_OK;
    DFB_GLOBAL_LOCK(DFB_LOCK_FOR_EXEC);
    ret = IDirectFBImageProvider_VEC_GetImageDescription(thiz,desc);
    DFB_GLOBAL_UNLOCK(DFB_LOCK_FOR_EXEC);
    return ret;
}


static DFBResult
_IDirectFBImageProvider_VEC_RenderTo( IDirectFBImageProvider *thiz,
                                     IDirectFBSurface       *destination,
                                     const DFBRectangle     *dest_rect )
{
    DFBResult ret = DFB_OK;
    DFB_GLOBAL_LOCK(DFB_LOCK_FOR_EXEC);
    ret = IDirectFBImageProvider_VEC_RenderTo(thiz,destination,dest_rect);
    DFB_GLOBAL_UNLOCK(DFB_LOCK_FOR_EXEC);
    return ret;
}

static DFBResult
_IDirectFBImageProvider_VEC_SetRenderCallback( IDirectFBImageProvider *thiz,
                                              DIRenderCallback        callback,
                                              void                   *context )
{
    DFBResult ret = DFB_OK;
    DFB_GLOBAL_LOCK(DFB_LOCK_FOR_EXEC);
    ret = IDirectFBImageProvider_VEC_SetRenderCallback(thiz,callback,context);
    DFB_GLOBAL_UNLOCK(DFB_LOCK_FOR_EXEC);
    return ret;
}

 static u32 _mstarGFXAddr(u32 cpuPhysicalAddr, u32 mst_miu1_cpu_offset, u32 mst_miu1_hal_offset)
{
   if(cpuPhysicalAddr >= mst_miu1_cpu_offset)
      return (cpuPhysicalAddr-mst_miu1_cpu_offset+mst_miu1_hal_offset);
    else
      return (cpuPhysicalAddr-dfb_config->mst_miu0_cpu_offset+dfb_config->mst_miu0_hal_offset);

   return cpuPhysicalAddr;
}

static  u32 _mstarCPUPhyAddr(u32 halPhysicalAddr, u32 mst_miu1_cpu_offset, u32 mst_miu1_hal_offset)
{
    if(halPhysicalAddr >= mst_miu1_hal_offset)
        return mst_miu1_cpu_offset + halPhysicalAddr - mst_miu1_hal_offset;
    else
        return dfb_config->mst_miu0_cpu_offset + halPhysicalAddr - dfb_config->mst_miu0_hal_offset;

    return halPhysicalAddr;
}



/* exported symbols */
static DFBResult
Probe( IDirectFBImageProvider_ProbeContext *ctx )
{
    if (ctx->filename) {
          if (strstr( ctx->filename, ".vec" ) ||
              strstr( ctx->filename, ".VEC" ))
          {
               if (access( ctx->filename, F_OK ) == 0)
                    return DFB_OK;
          }
     }

     return DFB_UNSUPPORTED;
}

static DFBResult
Construct( IDirectFBImageProvider *thiz,
           ... )
{
     IDirectFBDataBuffer *buffer;
     IDirectFBDataBuffer_data *buffer_data;
     CoreDFB             *core;
     va_list              tag;
     CoreSurfaceBufferLock ret_lock;
     DFBSurfacePixelFormat capture_fmt;
     GraphicsDeviceInfo device_info;
     u16 alignfactor =0;
     DFBResult ret;

     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBImageProvider_VEC )

     va_start( tag, thiz );
     buffer = va_arg( tag, IDirectFBDataBuffer * );
     core = va_arg( tag, CoreDFB * );
     va_end( tag );

     data->ref    = 1;
     data->core = core;

     buffer_data = (IDirectFBDataBuffer_data*) buffer->priv;

     data->eSourceToVE = E_XC_OP2;
     data->u16OutputHSize = 720;
     data->u16OutputVSize = 480;
     data->vec_capture_format = DSPF_UYVY;

     if(parseFile(data, buffer_data->filename) == false)
     {
          D_DEBUG( "DirectFB/VEC: Loading gopc file failed.\n");
          DIRECT_DEALLOCATE_INTERFACE( thiz );
          return DFB_FAILURE;
     }

     //Create Capture Surface:
     dfb_gfxcard_get_device_info( &device_info );


     capture_fmt = data->vec_capture_format;
     alignfactor = (u16)(device_info.limits.surface_byteoffset_alignment/2);
     //Alignment check for GOP Write, if alignfactor:data->gopc_capture_w == 0, we don't have to enlarge additional 8 pixel
     data->u16OutputHSize = data->u16OutputHSize +(alignfactor-( (data->u16OutputHSize % alignfactor == 0)? alignfactor:data->u16OutputHSize % alignfactor));
     if(data->u16OutputHSize < alignfactor)
        data->u16OutputHSize = alignfactor;

    if(1)
    {
#if 1
        int min_pitch;
        CoreSurfaceConfig config;
        CoreSurfaceTypeFlags type = CSTF_NONE;
        DFBSurfacePixelFormat format =  capture_fmt;
        //DFBSurfacePixelFormat format =  DSPF_UYVY;
        printf("\nthe format is DSPF_UYVY\n");
        printf("\nthe data->vec_capture_addr is %x\n",data->vec_capture_addr);
        int width = data->u16OutputHSize;
        int height = data->u16OutputVSize;

        // min_pitch = DFB_BYTES_PER_LINE(format, width);
        min_pitch=gconst_vecapture_pitch;

        config.flags  = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS;
        config.size.w = width;
        config.size.h = height;
        config.format = format;
        config.caps   = DSCAPS_DOUBLE;

        config.preallocated[0].addr  = (void *)_mstarCPUPhyAddr(data->vec_capture_addr,dfb_config->mst_miu1_cpu_offset, dfb_config->mst_miu1_hal_offset);
        config.preallocated[0].pitch = min_pitch;
        printf("\nthe config.preallocated[0].addr is %x\n",config.preallocated[0].addr );
        config.preallocated[1].addr  = config.preallocated[0].addr + min_pitch * data->u16OutputVSize;
        config.preallocated[1].pitch = min_pitch;


        config.flags |= CSCONF_PREALLOCATED_IN_VIDEO;
        type = CSTF_PREALLOCATED_IN_VIDEO;

        ret = dfb_surface_create( data->core, &config, type, CSTF_INTERNAL, NULL, &(data->source) );

#else

        ret = dfb_surface_create_simple( data->core, data->u16OutputHSize,
                         data->u16OutputVSize,
                         capture_fmt, DSCAPS_VIDEOONLY|DSCAPS_TRIPLE, CSTF_INTERNAL, 0, NULL,
                         &(data->source));
#endif
    }
     if(DFB_OK != ret)
     {
          D_DEBUG( "DirectFB/GOPC: Create Capture Surface Failed!\n");
          DIRECT_DEALLOCATE_INTERFACE( thiz );
          return ret;
     }


     dfb_surface_lock_buffer(data->source, CSBR_FRONT, CSAID_ACCEL0, CSAF_WRITE, &ret_lock);

     data->vec_capture_addr = _mstarGFXAddr(ret_lock.phys, dfb_config->mst_miu1_cpu_offset, dfb_config->mst_miu1_hal_offset);
     data->vec_capture_pitch = ret_lock.pitch;
     dfb_surface_unlock_buffer(data->source, &ret_lock);

     dfb_state_init(&data->state, NULL);

     dfb_state_set_source(&data->state, data->source);

     thiz->AddRef = _IDirectFBImageProvider_VEC_AddRef;
     thiz->Release = _IDirectFBImageProvider_VEC_Release;
     thiz->RenderTo = _IDirectFBImageProvider_VEC_RenderTo;
     thiz->SetRenderCallback = _IDirectFBImageProvider_VEC_SetRenderCallback;
     thiz->GetImageDescription = _IDirectFBImageProvider_VEC_GetImageDescription;
     thiz->GetSurfaceDescription = _IDirectFBImageProvider_VEC_GetSurfaceDescription;


     return DFB_OK;
}
