////////////////////////////////////////////////////////////////////////////////
//
// 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 <drvXC_IOPort.h>
#include  <apiXC.h>
#include <drvXC_HDMI_if.h>
#include <apiXC_DWIN.h>

#include <apiPNL.h>


static DFBResult Probe( IDirectFBImageProvider_ProbeContext *ctx );

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


#include <direct/interface_implementation.h>

DIRECT_INTERFACE_IMPLEMENTATION( IDirectFBImageProvider, GOPC )
void AddGopcImageProviderInterface()
{
}
/*****************************************************************************/
typedef enum{
IMG_DWIN_SRC_OP = 0,
IMG_DWIN_SRC_MVOP,
IMG_DWIN_SRC_FRAME,
IMG_DWIN_SRC_IP,
IMG_DWIN_SRC_FRAME_WITHOSD,
IMG_DWIN_SRC_IP_NOSCALE
}IMG_DWIN_SRC;


typedef struct {
     int                            ref;      /* reference counter */

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

     DIRenderCallback               callback;
     void                           *callback_ctx;

     IMG_DWIN_SRC           gopc_capture_src;
     EN_GOP_DWIN_SCAN_MODE         gopc_capture_scan_type;
     EN_GOP_DWIN_DATA_FMT          gopc_capture_format;
     u16                           gopc_capture_x;
     u16                           gopc_capture_y;
     u16                           gopc_capture_w;
     u16                           gopc_capture_h;
     u8                            gopc_capture_alphavalue;
     u8                            gopc_csc_enable;
     unsigned long                 gopc_capture_addr;
     unsigned int                  gopc_capture_pitch;
     u16                           alignfactor;
     u16                           ori_capture_x;
     u16                           ori_capture_y;       
     u16                           ori_capture_w;
     u16                           ori_capture_h;      
     ST_XC_DIP_WINPROPERTY stDIPWinProperty;
     SCALER_DIP_WIN eWindow;      // DWIN1_WINDOW;
} IDirectFBImageProvider_GOPC_data;

#define GOPCERRORMSG(x, ...) \
     D_ERROR( "IDirectFBImageProvider_GOPC: " #x "!\n", ## __VA_ARGS__ )

#define GOPCDEBUGMSG(x, ...) \
     D_DEBUG( "IDirectFBImageProvider_GOPC: " #x "!\n", ## __VA_ARGS__ )

/*****************************************************************************
** Local Functions
*****************************************************************************/
static bool gopcConfig( IDirectFBImageProvider_GOPC_data *data, const char *name, const char *value )
{
     if(strcmp (name, "gopc_capture_src" ) == 0)
     {
         if(strcmp (value, "DWIN_SRC_OP" ) == 0)
             data->gopc_capture_src = IMG_DWIN_SRC_OP;
         else
         if(strcmp (value, "DWIN_SRC_MVOP" ) == 0)
             data->gopc_capture_src = IMG_DWIN_SRC_MVOP;
         else
         if(strcmp (value, "DWIN_SRC_FRAME" ) == 0)
             data->gopc_capture_src = IMG_DWIN_SRC_FRAME;
        else 
	  if(strcmp (value, "DWIN_SRC_IP" ) == 0)
		data->gopc_capture_src = IMG_DWIN_SRC_IP;
	  else 
	  if(strcmp (value, "DWIN_SRC_FRAME_WITHOSD" ) == 0)
		data->gopc_capture_src = IMG_DWIN_SRC_FRAME_WITHOSD;
	  else
	  if(strcmp (value, "DWIN_SRC_IP_NOSCALE" ) == 0)
		data->gopc_capture_src = IMG_DWIN_SRC_IP_NOSCALE;
	  else   
             return false;
     } else
     if(strcmp (name, "gopc_capture_scan_type" ) == 0)
     {
         if(strcmp (value, "DWIN_SCAN_MODE_PROGRESSIVE" ) == 0)
             data->gopc_capture_scan_type = DWIN_SCAN_MODE_PROGRESSIVE;
         else
         if(strcmp (value, "DWIN_SCAN_MODE_extern" ) == 0)
             data->gopc_capture_scan_type = DWIN_SCAN_MODE_extern;
         else
             return false;
     } else
     if(strcmp (name, "gopc_capture_format" ) == 0)
     {
         if(strcmp (value, "DWIN_DATA_FMT_UV7Y8" ) == 0)
             data->gopc_capture_format = DWIN_DATA_FMT_UV7Y8;
         else
         if(strcmp (value, "DWIN_DATA_FMT_UV8Y8" ) == 0)
             data->gopc_capture_format = DWIN_DATA_FMT_UV8Y8;
         else
         if(strcmp (value, "DWIN_DATA_FMT_ARGB8888" ) == 0)
             data->gopc_capture_format = DWIN_DATA_FMT_ARGB8888;
         else
         if(strcmp (value, "DWIN_DATA_FMT_RGB565" ) == 0)
             data->gopc_capture_format = DWIN_DATA_FMT_RGB565;
         else
             return false;
     } else
     if(strcmp (name, "gopc_capture_x" ) == 0)
     {
         if(value)
         {
             char *error;
             unsigned long val = strtoul( value, &error, 10 );
             if (*error)
                return false;

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

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

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

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

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

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

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

     return true;
}

static bool
parseFile (IDirectFBImageProvider_GOPC_data *data, const char *filename)
{
     FILE *in = NULL;
     char line[400] = {0};

     in = fopen (filename, "r");
     if (in == 0)
     {
          D_DEBUG( "DirectFB/GOPC: 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;
            direct_trim( &value );
         }

         direct_trim( &name );

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

         gopcConfig(data, name, value );
     }

     fclose (in);

     return true;
}

#define GOP_PIXEL_ALIGNMENT_FACTOR					0x0F
#define GOP_PIXEL_ALIGNMENT_SHIFT					4UL

static bool gopcUpdateDWinProperty(IDirectFBImageProvider_GOPC_data *data)
{
    GOP_DwinProperty stProperty;
    int bytes_per_pixel;
    XC_ApiStatus xcStatus;
    int align_x = data->gopc_capture_x,   align_w = data->gopc_capture_w;
    int align_y = data->gopc_capture_y,   align_h = data->gopc_capture_h;
	int auto_h_scaling_down = 0;

	switch(data->gopc_capture_format)
	   {
		   case DWIN_DATA_FMT_ARGB8888:
			   bytes_per_pixel = 4;
			   break;
		   default:
			   bytes_per_pixel = 2;
			   break;
	   }


	   align_w = data->gopc_capture_w& ~(data->alignfactor - 1);

	   if(data->gopc_capture_src == IMG_DWIN_SRC_FRAME || data->gopc_capture_src == IMG_DWIN_SRC_FRAME_WITHOSD)
	   {
		   MS_PNL_DST_DispInfo dstDispInfo;
		   MS_U32 width  = 0;
		   MS_U32 height = 0;

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

		   align_x = (data->gopc_capture_x + data->alignfactor - 1 ) & ~(data->alignfactor - 1);

		   if (width && height )
		   {
			   if((width < data->gopc_capture_w + data->gopc_capture_x) ||
				  (height < data->gopc_capture_h + data->gopc_capture_y))
			   {
				   printf("!!!ALERT: capture size overanged ! \n");
				   return false;
			   }
			   if(align_x + align_w > data->gopc_capture_w + data->gopc_capture_x)
			   {
				   align_w -= data->alignfactor;
				   if(align_w < 0)
					   align_w = 0;
			   }
		   }
		   else
		   {
			   printf("Error! MApi_PNL_GetDstInfo fail \n");
		   }
	   }
	   else if(data->gopc_capture_src == IMG_DWIN_SRC_OP)
	   {
		   align_x = (data->gopc_capture_x) & ~(data->alignfactor - 1);
		   if (MApi_XC_GetStatus(&xcStatus, MAIN_WINDOW))
		   {
			   if(xcStatus.stDispWin.width < align_w + align_x)
			   {
				   align_x = (u16)(xcStatus.stDispWin.width * align_x * 1.0 / align_w ) & ~(data->alignfactor - 1);
				   align_w = xcStatus.stDispWin.width - align_x;
				   if(align_w < 0)
					   align_w = 0;
				   printf("Capture resize: XC display w=%d, h=%d ,align x= %d, w = %d \n",xcStatus.stDispWin.width,xcStatus.stDispWin.height,align_x,align_w);
			   }
			   if(xcStatus.stDispWin.height < data->gopc_capture_h + data->gopc_capture_y)
			   {
				   align_y = (u16)(xcStatus.stDispWin.height * data->gopc_capture_y * 1.0 / data->gopc_capture_h );
				   align_h = xcStatus.stDispWin.height - align_y;
				   printf("XC display w=%d, h=%d, cap_y=%d,cap_h=%d \n",xcStatus.stDispWin.width,xcStatus.stDispWin.height,align_y,align_h);
			   }
		   }
		   else
		   {
			   printf("Error! Cannot get XC Status! \n");
		   }
	   }
	   else if(data->gopc_capture_src == IMG_DWIN_SRC_IP || data->gopc_capture_src == IMG_DWIN_SRC_IP_NOSCALE)
	   {
		   INPUT_SOURCE_TYPE_t enInputSourceType;
		   MS_BOOL	bRet = FALSE;
		   
		   memset(&xcStatus, 0, sizeof(XC_ApiStatus));
		   bRet = MApi_XC_GetStatus(&xcStatus, MAIN_WINDOW);

		   /* judge situation for 1.no signal  */
		   if ( (bRet==FALSE) || (xcStatus.stCapWin.width == 0) || (xcStatus.stCapWin.height==0) )
			   return false;

		   if(xcStatus.bBluescreenEnabled == TRUE) {
			   return false;
		   }

		   // Width should not be larger than 1920
		   if (data->gopc_capture_src == IMG_DWIN_SRC_IP)
		   {
		       if (xcStatus.stCapWin.width > 1920) {
			       xcStatus.stCapWin.width = 1920;
		       }
		   }
		   if (IsSrcTypeHDMI(xcStatus.enInputSourceType)) 
		   {
			   MS_WINDOW_TYPE stDEWin;
			   memset(&stDEWin, 0, sizeof(MS_WINDOW_TYPE));
			   if ( MApi_XC_GetHdmiSyncMode() == HDMI_SYNC_DE) 
			   {
				   MApi_XC_GetDEWindow(&stDEWin, MAIN_WINDOW);
			   } else 
			   {
				   MApi_XC_GetDEWidthHeightInDEByPassMode(&(stDEWin.width),&(stDEWin.height), MAIN_WINDOW);
			   }

			   if (stDEWin.width == 720) 
			   {
				   //For 576i/480i or 288P/240P Hduplicate mode in HDMI
				   if (((xcStatus.bInterlace == TRUE) && (stDEWin.height < 600)) ||
					   ((xcStatus.bInterlace == FALSE) && (stDEWin.height < 300))
					  ) 
				   {
					   MS_U8 u8CurHDMIPixelRep = MDrv_HDMI_Get_Pixel_Repetition();
					   xcStatus.stCapWin.width <<= u8CurHDMIPixelRep;
				   }
			   }
		   }
		   else if(xcStatus.bHDuplicate) 
		   {
			  MS_U8 ratio = 1; // double duplicate        	            
			  data->gopc_capture_x <<= ratio;              	            
			  data->gopc_capture_w <<= ratio;              	            
			  align_w = data->gopc_capture_w& ~(data->alignfactor - 1);	            	            	             
		   } 		   

		   if(data->gopc_capture_src == IMG_DWIN_SRC_IP_NOSCALE) // fine tune the x and width to capture the MAX picture in the IMG_DWIN_SRC_IP_NOSCALE
		   {	                                                           
			  data->ori_capture_x = data->gopc_capture_x; 
			  data->ori_capture_y = data->gopc_capture_y;
			  data->ori_capture_w = data->gopc_capture_w;
			  data->ori_capture_h = data->gopc_capture_h; 
			  align_x = (data->gopc_capture_x) & ~(data->alignfactor - 1);
			  align_w = (data->gopc_capture_w + (data->gopc_capture_x - align_x) + data->alignfactor - 1) & ~(data->alignfactor - 1); 
			  if (align_w > xcStatus.stCapWin.width)
			      align_w = xcStatus.stCapWin.width; 
		   }
		   else
		   {
		        align_x = (data->gopc_capture_x + data->alignfactor - 1 ) & ~(data->alignfactor - 1);
		   }

		   enInputSourceType = xcStatus.enInputSourceType;	  
		   if ((IsSrcTypeVga(enInputSourceType)
		   		|| IsSrcTypeHDMI(enInputSourceType)
		   		|| IsSrcTypeDVI(enInputSourceType)) 
		   		&& (xcStatus.bMemYUVFmt == FALSE) )
		   {
			   if(dfb_config->mst_enable_dip == false)		   	
			       MApi_GOP_DWIN_EnableR2YCSC(TRUE);
			   else
			       MApi_XC_DIP_EnableR2Y(TRUE,data->eWindow);
		   } 
		   else
		   {
			   if(dfb_config->mst_enable_dip == false)			   	
			       MApi_GOP_DWIN_EnableR2YCSC(FALSE);
			   else
			       MApi_XC_DIP_EnableR2Y(FALSE,data->eWindow);
		   }

		   if (xcStatus.bInterlace && data->gopc_capture_src != IMG_DWIN_SRC_IP_NOSCALE)
		   {
			   //printf("dwin ip interlace = %d \n", xcStatus.bInterlace);
			   align_h >>= 1;
			   align_y >>=1;
		   }
		   if((align_x+align_w >xcStatus.stCapWin.width )||(align_y+align_h >xcStatus.stCapWin.height ))
			   {
				   printf("capture size is bigger than source size \n");
				   printf("capture size is bigger than source size %d, %d, %d, %d\n", align_x, align_y, align_w, align_h);
				   printf("capture size is bigger than source size %d, %d\n", xcStatus.stCapWin.width , xcStatus.stCapWin.height);	
				   return false;
			   }
		   
		   
	   }
	   
       if (align_w < 1 || align_h < 1)
           return false;
           
       if(dfb_config->mst_enable_dip == true) // When dip enable, check if patch for the hw limitation (4k2k video can not capture correctly) of the monaco chip.  
       {
           if( (data->gopc_capture_src == IMG_DWIN_SRC_FRAME) || (data->gopc_capture_src == IMG_DWIN_SRC_FRAME_WITHOSD) || (data->gopc_capture_src == IMG_DWIN_SRC_OP) )
           {
               MS_PNL_DST_DispInfo dstDispInfo;
               MS_U32 width  = 0;
               MS_U32 height = 0;
               MS_U16 Freq = 0; 
               MApi_PNL_GetDstInfo(&dstDispInfo, sizeof(MS_PNL_DST_DispInfo));
               width  = dstDispInfo.DEHEND - dstDispInfo.DEHST + 1;
               height = dstDispInfo.DEVEND - dstDispInfo.DEVST + 1;
               Freq = MApi_XC_GetOutputVFreqX100();
		       //printf("\33[0;36m   %s:%d   width = %d,height = %d,Freq = %d \33[m \n",__FUNCTION__,__LINE__,width,height,Freq);
               if( ( width ==  3840 ) && ( height ==  2160 ) && ( Freq > 3000) )
               {            
                   align_x /= 2;
                   align_w /= 2;
                   auto_h_scaling_down = 1;
			       //printf("\33[0;36m   %s:%d   align_x = %d,align_w = %d \33[m \n",__FUNCTION__,__LINE__,align_x,align_w); 
               }
           }
       }
       data->gopc_capture_x = align_x;
       data->gopc_capture_w = align_w;
       
       if(dfb_config->mst_enable_dip == false)		  
       {
           stProperty.u16x         = align_x;
           stProperty.u16y		   = align_y;
           stProperty.u16w		   = align_w;
           stProperty.u16h		   = align_h;
           stProperty.u16fbw	   = (data->gopc_capture_pitch / bytes_per_pixel);
           stProperty.u32fbaddr0   = data->gopc_capture_addr; //system memory does not need to consider MIU Offset?
           //stProperty.u32fbaddr1	 = data->gopc_capture_addr + (stProperty.u16fbw*(data->gopc_capture_h-1)+data->gopc_capture_w)*bytes_per_pixel; //Whole Buffer used
           stProperty.u32fbaddr1   = data->gopc_capture_addr + stProperty.u16fbw*align_h*bytes_per_pixel; //agate required

           if(GOP_API_SUCCESS != MApi_GOP_DWIN_SetWinProperty(&stProperty))
               return false;

       }
       else
       {
           XC_SETWIN_INFO stXC_SetWin_Info;
           memset(&stXC_SetWin_Info, 0, sizeof(XC_SETWIN_INFO));
        
		   if(auto_h_scaling_down == 0)	
           {
               stXC_SetWin_Info.stCapWin.x = align_x; 
               stXC_SetWin_Info.stCapWin.y = align_y;
               stXC_SetWin_Info.stCapWin.width = align_w; 
               stXC_SetWin_Info.stCapWin.height = align_h; 

               stXC_SetWin_Info.bPreHCusScaling = TRUE;
               stXC_SetWin_Info.u16PreHCusScalingSrc = align_w; 
               stXC_SetWin_Info.u16PreHCusScalingDst = align_w; 

               stXC_SetWin_Info.bPreVCusScaling = TRUE;                
               stXC_SetWin_Info.u16PreVCusScalingSrc = align_h; 
               stXC_SetWin_Info.u16PreVCusScalingDst = align_h;
               stXC_SetWin_Info.bInterlace     = FALSE;
           }
           else  //Do patch for the hw limitation of the monaco chip
           {
               stXC_SetWin_Info.stCapWin.x = (align_x*2); 
               stXC_SetWin_Info.stCapWin.y = align_y;
               stXC_SetWin_Info.stCapWin.width = (align_w*2); 
               stXC_SetWin_Info.stCapWin.height = align_h; 

               stXC_SetWin_Info.bPreHCusScaling = TRUE;
               stXC_SetWin_Info.u16PreHCusScalingSrc = (align_w*2); 
               stXC_SetWin_Info.u16PreHCusScalingDst = (align_w*2); 

               stXC_SetWin_Info.bPreVCusScaling = TRUE;                
               stXC_SetWin_Info.u16PreVCusScalingSrc = align_h; 
               stXC_SetWin_Info.u16PreVCusScalingDst = align_h;
               stXC_SetWin_Info.bInterlace     = FALSE;
           }
           MApi_XC_DIP_SetWindow(&stXC_SetWin_Info, sizeof(XC_SETWIN_INFO), data->eWindow);

           data->stDIPWinProperty.u8BufCnt = 1;
           data->stDIPWinProperty.u16Width = align_w; 
           data->stDIPWinProperty.u16Pitch = data->gopc_capture_pitch;
           data->stDIPWinProperty.u16Height = align_h;
           data->stDIPWinProperty.u32BufStart = data->gopc_capture_addr;
           data->stDIPWinProperty.u32BufEnd = data->gopc_capture_addr + data->gopc_capture_pitch*align_h;
           if(E_APIXC_RET_OK != MApi_XC_DIP_SetDIPWinProperty(&data->stDIPWinProperty, data->eWindow))
               return false;
       }
       return true;

}
static bool
gopcInit(IDirectFBImageProvider_GOPC_data *data)
{
    if(dfb_config->mst_enable_dip == false)	
    {
        if(GOP_API_SUCCESS != MApi_GOP_DWIN_Init())
            return false;

        if(GOP_API_SUCCESS != MApi_GOP_SetClkForCapture())
            return false;

        if(GOP_API_SUCCESS != MApi_GOP_DWIN_SelectSourceScanType(data->gopc_capture_scan_type))
            return false;

        if(GOP_API_SUCCESS != MApi_GOP_DWIN_SetDataFmt(data->gopc_capture_format))
            return false;

        switch(data->gopc_capture_src){
        case IMG_DWIN_SRC_FRAME:
            MApi_XC_OP2VOPDESel(E_OP2VOPDE_WHOLEFRAME);
            if(GOP_API_SUCCESS != MApi_GOP_DWIN_SetSourceSel(DWIN_SRC_OP))
                return false;
            break;
        case IMG_DWIN_SRC_OP:
            MApi_XC_OP2VOPDESel(E_OP2VOPDE_MAINWINDOW);
            if(GOP_API_SUCCESS != MApi_GOP_DWIN_SetSourceSel(DWIN_SRC_OP))
                return false;
            break;
        case IMG_DWIN_SRC_MVOP:
            if(GOP_API_SUCCESS != MApi_GOP_DWIN_SetSourceSel(DWIN_SRC_MVOP))
                return false;
            break;
    	case IMG_DWIN_SRC_IP:
    	case IMG_DWIN_SRC_IP_NOSCALE:    
    		if(GOP_API_SUCCESS != MApi_GOP_DWIN_SetSourceSel(DWIN_SRC_IP))
    				return false;
    		break;
        case IMG_DWIN_SRC_FRAME_WITHOSD:
            MApi_XC_OP2VOPDESel(E_OP2VOPDE_WHOLEFRAME_WITHOSD);
            if(GOP_API_SUCCESS != MApi_GOP_DWIN_SetSourceSel(DWIN_SRC_OP))
                return false;
            break;
        default:
            printf("!!!!!!!!!! Invalid capture source!\n");
            return false;
        }

        if(GOP_API_SUCCESS != MApi_GOP_DWIN_SetAlphaValue(data->gopc_capture_alphavalue))
            return false;

        if(GOP_API_SUCCESS != MApi_GOP_DWIN_EnableR2YCSC(data->gopc_csc_enable?TRUE:FALSE))
            return false;
    }
    else
    {
        E_APIXC_ReturnValue ret;
        
        ret = MApi_XC_DIP_InitByDIP(data->eWindow);
        if(E_APIXC_RET_OK != ret)
                return false;

        if(data->gopc_capture_scan_type == DWIN_SCAN_MODE_PROGRESSIVE)
            ret = MApi_XC_DIP_SetSourceScanType(DIP_SCAN_MODE_PROGRESSIVE,data->eWindow);
        else
            ret = MApi_XC_DIP_SetSourceScanType(DIP_SCAN_MODE_extern,data->eWindow);
        if(E_APIXC_RET_OK != ret)
                return false;


        if(data->gopc_capture_format == DWIN_DATA_FMT_UV8Y8)
        {
            ret = MApi_XC_DIP_SetOutputDataFmt(DIP_DATA_FMT_YUV422,data->eWindow);
            MApi_XC_DIP_SwapUV(true, data->eWindow);
        }
        else if(data->gopc_capture_format == DWIN_DATA_FMT_ARGB8888)
            ret = MApi_XC_DIP_SetOutputDataFmt(DIP_DATA_FMT_ARGB8888,data->eWindow);
        else if(data->gopc_capture_format == DWIN_DATA_FMT_RGB565)
            ret = MApi_XC_DIP_SetOutputDataFmt(DIP_DATA_FMT_RGB565,data->eWindow);
        else 
            ret = E_APIXC_RET_FAIL;
        if(E_APIXC_RET_OK != ret)
                return false;

        switch(data->gopc_capture_src){
        case IMG_DWIN_SRC_FRAME:
            MApi_XC_DIP_SetOutputCapture(TRUE, E_XC_DIP_VOP2,data->eWindow);
            data->stDIPWinProperty.enSource = SCALER_DIP_SOURCE_TYPE_OP_CAPTURE;
            break;
        case IMG_DWIN_SRC_OP:
            MApi_XC_OP2VOPDESel(E_OP2VOPDE_MAINWINDOW);
            data->stDIPWinProperty.enSource = SCALER_DIP_SOURCE_TYPE_OP_CAPTURE;
            break;
        case IMG_DWIN_SRC_IP:
        case IMG_DWIN_SRC_IP_NOSCALE:    
            data->stDIPWinProperty.enSource = SCALER_DIP_SOURCE_TYPE_MAIN;
            break;
        case IMG_DWIN_SRC_FRAME_WITHOSD:
            MApi_XC_DIP_SetOutputCapture(TRUE, E_XC_DIP_OP2,data->eWindow);
            data->stDIPWinProperty.enSource = SCALER_DIP_SOURCE_TYPE_OP_CAPTURE;
            break;
        default:
            printf("!!!!!!!!!! Invalid capture source!\n");
            return false;
        }

        ret = MApi_XC_DIP_SetAlpha(data->gopc_capture_alphavalue, data->eWindow);
        if(E_APIXC_RET_OK != ret)
            return false;

        ret = MApi_XC_DIP_EnableR2Y((data->gopc_csc_enable?TRUE:FALSE),data->eWindow);   
        if(E_APIXC_RET_OK != ret)
            return false;
    }
    return true;
}


static bool
gopcOpen(IDirectFBImageProvider_GOPC_data *data)
{
    return true;
}

static bool
gopcClose(IDirectFBImageProvider_GOPC_data *data)
{
    return true;
}

static bool
gopcOneFrameDone(IDirectFBImageProvider_GOPC_data *data)
{
    if(dfb_config->mst_enable_dip == false)	
    {
        MApi_GOP_DWIN_CaptureOneFrame();
    }
    else
    {
        MApi_XC_DIP_Ena(TRUE,data->eWindow);
        MApi_XC_DIP_CapOneFrame(data->eWindow);
        MApi_XC_DIP_Ena(FALSE,data->eWindow);
    }
    return true;
}

/*****************************************************************************
** Interface
*****************************************************************************/

static void
IDirectFBImageProvider_GOPC_Destruct( IDirectFBImageProvider *thiz )
{
     IDirectFBImageProvider_GOPC_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_GOPC_AddRef( IDirectFBImageProvider *thiz )
{
     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_GOPC )

     data->ref++;

     return DFB_OK;
}

static DirectResult
IDirectFBImageProvider_GOPC_Release( IDirectFBImageProvider *thiz )
{
     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_GOPC )

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

     return DFB_OK;
}

static DFBResult
IDirectFBImageProvider_GOPC_GetSurfaceDescription( IDirectFBImageProvider *thiz,
                                                  DFBSurfaceDescription  *desc )
{
     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_GOPC )

     if (!desc)
          return DFB_INVARG;

     if (!data->source)
          return DFB_FAILURE;

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

     return DFB_OK;
}

static DFBResult
IDirectFBImageProvider_GOPC_GetImageDescription( IDirectFBImageProvider *thiz,
                                                 DFBImageDescription   *desc )
{
     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_GOPC )

     desc->caps = DICAPS_NONE;

     return DFB_OK;
}


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

     DIRECT_INTERFACE_GET_DATA( IDirectFBImageProvider_GOPC )
     CoreDFB            *core;
     CoreDFBShared  *shared;
     
     core = data->core;
     shared = core->shared;
     fusion_skirmish_prevail(&shared->lock_hw_gop_Decoder);	 

     if (!destination)
     {
          fusion_skirmish_dismiss(&shared->lock_hw_gop_Decoder);
          return DFB_INVARG;
     }

     dst_data = destination->priv;
     if (!dst_data || !dst_data->surface)
     {
          fusion_skirmish_dismiss(&shared->lock_hw_gop_Decoder);
          return DFB_DESTROYED;
     }

     if (dest_rect) {
          if (dest_rect->w < 1 || dest_rect->h < 1)
          {
               fusion_skirmish_dismiss(&shared->lock_hw_gop_Decoder);
               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 == gopcInit(data))
    {
        fusion_skirmish_dismiss(&shared->lock_hw_gop_Decoder);
        return DFB_FAILURE;
    }

     /* build the clip rectangle */
     if (!dfb_rectangle_intersect( &rect, &dst_data->area.current ))
     {
          fusion_skirmish_dismiss(&shared->lock_hw_gop_Decoder);
          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:
     if (false == gopcUpdateDWinProperty(data))
     {
        dfb_state_set_destination( &data->state, NULL );
        data->destination = NULL;
        destination->Release( destination );
        fusion_skirmish_dismiss(&shared->lock_hw_gop_Decoder);
        return DFB_FAILURE;
     }
     
     gopcOpen(data);
	 
     DFB_GLOBAL_LOCK(DFB_LOCK_FOR_EXEC);
     while(1)
     {
        if(gopcOneFrameDone(data))
        {
            break;
        }
        else
        {

        }
     }
     {
        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;
        }

        if(data->gopc_capture_src == IMG_DWIN_SRC_IP_NOSCALE)
        {    
            rect.x = data->ori_capture_x - data->gopc_capture_x;
            rect.y = 0;
            rect.w = data->ori_capture_w;
            rect.h = data->ori_capture_h;   
        }
        else
        {
            rect.x = 0;  
            rect.y = 0;                  
            rect.w = data->gopc_capture_w;
            rect.h = data->gopc_capture_h;
        }

        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_GLOBAL_UNLOCK(DFB_LOCK_FOR_EXEC);
     gopcClose(data);
    dfb_state_set_destination( &data->state, NULL );
    data->destination = NULL;
    destination->Release( destination );
     fusion_skirmish_dismiss(&shared->lock_hw_gop_Decoder);
     return DFB_OK;
}

static DFBResult
IDirectFBImageProvider_GOPC_SetRenderCallback( IDirectFBImageProvider *thiz,
                                              DIRenderCallback        callback,
                                              void                   *context )
{
     DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_GOPC)

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

     return DFB_OK;
}

static DFBResult
IDirectFBImageProvider_GOPC_SetHWParameter(IDirectFBImageProvider *thiz,
                                                                void    *phw_decoder_setting)
{
    DFBGOPCSetting_t *pstGOPC_decoder_setting = (DFBGOPCSetting_t *)phw_decoder_setting;

    DIRECT_INTERFACE_GET_DATA (IDirectFBImageProvider_GOPC)



    if(pstGOPC_decoder_setting->bFlag&DFBGOPC_X)
    {
        data->gopc_capture_x = pstGOPC_decoder_setting->gopc_capture_x;
    }

    if(pstGOPC_decoder_setting->bFlag&DFBGOPC_Y)
    {
        data->gopc_capture_y = pstGOPC_decoder_setting->gopc_capture_y;
    }

    if(pstGOPC_decoder_setting->bFlag&DFBGOPC_WIDTH)
    {
        data->gopc_capture_w = pstGOPC_decoder_setting->gopc_capture_w;
        //data->gopc_capture_w  = data->gopc_capture_w& ~(data->alignfactor - 1);
    }

    if(pstGOPC_decoder_setting->bFlag&DFBGOPC_HEIGHT)
    {
        data->gopc_capture_h = pstGOPC_decoder_setting->gopc_capture_h;
    }

    //printf("\npstGOPC_decoder_setting->gopc_capture_w:%u\n",pstGOPC_decoder_setting->gopc_capture_w);
    //printf("\npstGOPC_decoder_setting->gopc_capture_h:%u\n",pstGOPC_decoder_setting->gopc_capture_h);


   return DFB_OK;
}

/*
Wrap the IDirectFBImageProvider_GOPC_xxx to _IDirectFBImageProvider_GOPC_xxx for safe call
*/
 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;
}

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

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

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

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


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

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

static DFBResult
_IDirectFBImageProvider_GOPC_SetHWParameter(IDirectFBImageProvider *thiz,
                                                                void    *phw_decoder_setting)
{

    DFBResult ret = DFB_OK;
    DFB_GLOBAL_LOCK(DFB_LOCK_FOR_EXEC);
    ret = IDirectFBImageProvider_GOPC_SetHWParameter(thiz,phw_decoder_setting);
    DFB_GLOBAL_UNLOCK(DFB_LOCK_FOR_EXEC);
    return ret;
}



/* exported symbols */
static DFBResult
Probe( IDirectFBImageProvider_ProbeContext *ctx )
{
    if (ctx->filename) {
          if (strstr( ctx->filename, ".gopc" ) ||
              strstr( ctx->filename, ".GOPC" ))
          {
               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;
     DFBResult ret;
     unsigned long cpu_phys = 0;
     
     MS_PNL_DST_DispInfo dstDispInfo;
     MApi_PNL_GetDstInfo(&dstDispInfo, sizeof(MS_PNL_DST_DispInfo)); 

     DIRECT_ALLOCATE_INTERFACE_DATA( thiz, IDirectFBImageProvider_GOPC )

     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->gopc_capture_src = DWIN_SRC_OP;
     data->gopc_capture_scan_type = DWIN_SCAN_MODE_PROGRESSIVE;
     data->gopc_capture_format = DWIN_DATA_FMT_UV8Y8;
     data->gopc_capture_x = 0;
     data->gopc_capture_y = 0;
     data->gopc_capture_w = 640;
     data->gopc_capture_h = 480;
     data->gopc_capture_alphavalue = 0x0f;
     data->gopc_csc_enable = 0;
     data->gopc_capture_addr = NULL;
     data->alignfactor = 8;
     data->ori_capture_x = 0; 
     data->ori_capture_y = 0;               
     data->ori_capture_w = 640;
     data->ori_capture_h = 480; 
     data->eWindow = dfb_config->mst_dip_select;
     
     if(parseFile(data, buffer_data->filename) == false)
     {
          D_DEBUG( "DirectFB/GOPC: Loading gopc file failed.\n");
          DIRECT_DEALLOCATE_INTERFACE( thiz );
          return DFB_FAILURE;
     }
	 
	if(data->gopc_capture_src == IMG_DWIN_SRC_IP || data->gopc_capture_src == IMG_DWIN_SRC_IP_NOSCALE)
	     data->gopc_capture_format = DWIN_DATA_FMT_UV8Y8;

	if((data->gopc_capture_format == DWIN_DATA_FMT_RGB565 )||
	   (data->gopc_capture_format == DWIN_DATA_FMT_ARGB8888 ))
	{
		data->gopc_csc_enable = 0;
	}
	else if((data->gopc_capture_format == DWIN_DATA_FMT_UV7Y8 )||
	   		(data->gopc_capture_format == DWIN_DATA_FMT_UV8Y8 )) 
	{
		if(!dstDispInfo.bYUVOutput)
            data->gopc_csc_enable = 1; //For TV, OP is RGB
        else
            data->gopc_csc_enable = 0; //For BOX, OP maybe YUV
	}
	
     //Create Capture Surface:
     dfb_gfxcard_get_device_info( &device_info );

     switch(data->gopc_capture_format)
     {
        case DWIN_DATA_FMT_UV7Y8:
            capture_fmt = DSPF_YVYU; //@Fixup: need check later;
            data->alignfactor = (u16)((device_info.limits.surface_byteoffset_alignment/2)/2);
            break;
        case DWIN_DATA_FMT_UV8Y8:
            capture_fmt = DSPF_YVYU;
            data->alignfactor = (u16)((device_info.limits.surface_byteoffset_alignment/2)/2);
            break;
        case DWIN_DATA_FMT_ARGB8888:
            capture_fmt = DSPF_ARGB;
            data->alignfactor = (u16)((device_info.limits.surface_byteoffset_alignment/2)/4);
            break;
        case DWIN_DATA_FMT_RGB565:
        default:
            capture_fmt = DSPF_RGB16;
            data->alignfactor = (u16)((device_info.limits.surface_byteoffset_alignment/2)   /2);
            break;
     }

     //Alignment check for GOP Write, if alignfactor:data->gopc_capture_w == 0, we don't have to enlarge additional 8 pixel
     //data->gopc_capture_w = data->gopc_capture_w +(alignfactor-( (data->gopc_capture_w % alignfactor == 0)? alignfactor:data->gopc_capture_w % alignfactor));
     //if(data->gopc_capture_w < alignfactor)
        //data->gopc_capture_w = alignfactor;

     //data->gopc_capture_w  = data->gopc_capture_w& ~(data->alignfactor - 1);

     if(data->gopc_capture_addr)
     {
             CoreSurfaceConfig config;
             CoreSurfaceTypeFlags type = CSTF_NONE;
             DFBSurfacePixelFormat format =  capture_fmt;
             int min_pitch = 0;
             printf("\nthe data->vec_capture_addr is %x\n",data->gopc_capture_addr);
             int width = data->gopc_capture_w;
             int height = data->gopc_capture_h;
             min_pitch = DFB_BYTES_PER_LINE(format, width);
             config.flags  = CSCONF_SIZE | CSCONF_FORMAT | CSCONF_CAPS;
             config.size.w = width;
             config.size.h = height;
             config.format = format;
             config.preallocated[0].addr  = (void *)_mstarCPUPhyAddr(data->gopc_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.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->gopc_capture_w,
                              data->gopc_capture_h,
                              capture_fmt, DSCAPS_VIDEOONLY, CSTF_INTERNAL, 0, NULL,
                              &(data->source));
     }

     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);
     cpu_phys = ret_lock.phys;
     data->gopc_capture_addr = _mstarGFXAddr(cpu_phys,dfb_config->mst_miu1_cpu_offset,dfb_config->mst_miu1_hal_offset);
     data->gopc_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_GOPC_AddRef;
     thiz->Release = _IDirectFBImageProvider_GOPC_Release;
     thiz->RenderTo = _IDirectFBImageProvider_GOPC_RenderTo;
     thiz->SetRenderCallback = _IDirectFBImageProvider_GOPC_SetRenderCallback;
     thiz->GetImageDescription = _IDirectFBImageProvider_GOPC_GetImageDescription;
     thiz->GetSurfaceDescription = _IDirectFBImageProvider_GOPC_GetSurfaceDescription;
     thiz->SetHWDecoderParameter =_IDirectFBImageProvider_GOPC_SetHWParameter;
     return DFB_OK;
}
