⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vlx_test.c

📁 支持三星原产的S3C24A0开发板
💻 C
📖 第 1 页 / 共 2 页
字号:

typedef struct tag_DC_ARRAY
{
    S16 y1;
    S16 y2;
    S16 y3;
    S16 y4;
    S16 cb;
    S16 cr;
}DC_ARRAY;


// Y1 Y2     B C
// Y3 Y4     A X
// Cb 
// Cr

#define CONV_DCTQ12_NUM(n)	( (((n) & 0x800)?-1:1)*((n)&0x7ff) )
    //DCTQ number [11:0]  11:sign  [10:0]:num    
    //a negative number in DCTQ is not 2's complement.
#define CONV_NUM_DCTQ12(n)	( ((n)<0)? (((n)*-1)&0x7ff|0x800):((n)&0x7ff) )
#define RDIV(m,n)		(((m)+(n)/2)/(n))

#define GET_QDC_Y1(pDctqCoeff,xmbn,mx,my) \
	*((U16 *)(pDctqCoeff->yStartAddr+ (mx)*16*2 + (my*16)*(xmbn)*16*2))
#define GET_QDC_Y2(pDctqCoeff,xmbn,mx,my) \
	*((U16 *)(pDctqCoeff->yStartAddr+ (mx)*16*2 + (my*16)*(xmbn)*16*2 + 8*2))
#define GET_QDC_Y3(pDctqCoeff,xmbn,mx,my) \
	*((U16 *)(pDctqCoeff->yStartAddr+ (mx)*16*2 + (my*16+8)*(xmbn)*16*2))
#define GET_QDC_Y4(pDctqCoeff,xmbn,mx,my) \
	*((U16 *)(pDctqCoeff->yStartAddr+ (mx)*16*2 + (my*16+8)*(xmbn)*16*2 + 8*2))
#define GET_QDC_CB(pDctqCoeff,xmbn,mx,my) \
	*((U16 *)(pDctqCoeff->cbStartAddr+ (mx)*8*2 + (my*8)*(xmbn)*8*2))
#define GET_QDC_CR(pDctqCoeff,xmbn,mx,my) \
	*((U16 *)(pDctqCoeff->crStartAddr+ (mx)*8*2 + (my*8)*(xmbn)*8*2))

#define PUT_QDC_Y1(pDctqCoeff,xmbn,mx,my,qdc) \
	*((U16 *)(pDctqCoeff->yStartAddr+ (mx)*16*2 + (my*16)*(xmbn)*16*2))=(qdc)
#define PUT_QDC_Y2(pDctqCoeff,xmbn,mx,my,qdc) \
	*((U16 *)(pDctqCoeff->yStartAddr+ (mx)*16*2 + (my*16)*(xmbn)*16*2 + 8*2))=(qdc)
#define PUT_QDC_Y3(pDctqCoeff,xmbn,mx,my,qdc) \
	*((U16 *)(pDctqCoeff->yStartAddr+ (mx)*16*2 + (my*16+8)*(xmbn)*16*2))=(qdc)
#define PUT_QDC_Y4(pDctqCoeff,xmbn,mx,my,qdc) \
	*((U16 *)(pDctqCoeff->yStartAddr+ (mx)*16*2 + (my*16+8)*(xmbn)*16*2 + 8*2))=(qdc)
#define PUT_QDC_CB(pDctqCoeff,xmbn,mx,my,qdc) \
	*((U16 *)(pDctqCoeff->cbStartAddr+ (mx)*8*2 + (my*8)*(xmbn)*8*2))=(qdc)
#define PUT_QDC_CR(pDctqCoeff,xmbn,mx,my,qdc) \
	*((U16 *)(pDctqCoeff->crStartAddr+ (mx)*8*2 + (my*8)*(xmbn)*8*2))=(qdc)

#define VLD_CBP_Y1_SKIP		(1<<0)
#define VLD_CBP_Y2_SKIP		(1<<1)
#define VLD_CBP_Y3_SKIP		(1<<2)
#define VLD_CBP_Y4_SKIP		(1<<3)
#define VLD_CBP_CB_SKIP		(1<<4)
#define VLD_CBP_CR_SKIP		(1<<5)






static DC_ARRAY dcArray[FIMV_IMAGE_WIDTH/16][FIMV_IMAGE_HEIGHT/16];

//VLC do dc-prediction for intra-macroblock. But, VLD doesn't do dc-prediction compensation.
//So, S/W should compensate the VLD output for IDCTQ to use the VLD output.
//dcArray is for saving the dc values for each sub-blocks

//- In order to call DecodeDcPrediction(), the macro-block should be intra.
//- RestoreDcPredictedMblk should be called with sequential mx,my parameter,
//  such as (0,0),(0,1),(0,2),...

//
void RestoreDcPredictedMblk(PIMAGE420 pDctqCoeff,U32 mx,U32 my,U32 qpStep,U32 cbpValue)
{
    int i;
    int diffQdcA,diffQdcC,dcx;
    int lay1,ay1,ay2,ly1,ly3,lacb,acb,lcb,lacr,acr,lcr,y1,y2,y3; //dc values
    int predQdc,qdc;
    int dcScaler1,dcScaler2;
    int xmbn=pDctqCoeff->imageWidth/16;

    dcScaler1=CalDcScaler(qpStep,1);
    dcScaler2=CalDcScaler(qpStep,2);


    if(mx==0 && my==0)
    {
	//    B C     LAY1 AY1 AY2   LACB ACB	 LACR ACR  
	//    A X     LY1  Y1  Y2    LCB  CB	 LCR  CR
	//	      LY3  Y3  Y4
	lay1=1024;
	ay1=1024;
	ay2=1024;
	ly1=1024;
	ly3=1024;
	lacb=1024;
	acb=1024;
	lcb=1024;
	lacr=1024;
	acr=1024;
	lcr=1024;
    }
    else if(mx==0)
    {
	lay1=1024;
	ay1=dcArray[mx][my-1].y3;
	ay2=dcArray[mx][my-1].y4;
	ly1=1024;
	ly3=1024;
	lacb=1024;
	acb=dcArray[mx][my-1].cb;
	lcb=1024;
	lacr=1024;
	acr=dcArray[mx][my-1].cr;
	lcr=1024;
    }
    else if(my==0)
    {
    //	  B C	  LAY1 AY1 AY2	 LACB ACB    LACR ACR  
    //	  A X	  LY1  Y1  Y2	 LCB  CB     LCR  CR
    //		  LY3  Y3  Y4    
    	lay1=1024;
	ay1=1024;
	ay2=1024;
	ly1=dcArray[mx-1][my].y2;
	ly3=dcArray[mx-1][my].y4;
	lacb=1024;
	acb=1024;
	lcb=dcArray[mx-1][my].cb;
	lacr=1024;
	acr=1024;
	lcr=dcArray[mx-1][my].cr;
    }
    else
    {
	lay1=dcArray[mx-1][my-1].y4;
	ay1=dcArray[mx][my-1].y3;
	ay2=dcArray[mx][my-1].y4;
	ly1=dcArray[mx-1][my].y2;
	ly3=dcArray[mx-1][my].y4;
	lacb=dcArray[mx-1][my-1].cb;
	acb=dcArray[mx][my-1].cb;
	lcb=dcArray[mx-1][my].cb;
	lacr=dcArray[mx-1][my-1].cr;
	acr=dcArray[mx][my-1].cr;
	lcr=dcArray[mx-1][my].cr;
    }


    //	  B C	  LAY1 AY1 AY2	 LACB ACB    LACR ACR  
    //	  A X	  LY1  Y1  Y2	 LCB  CB     LCR  CR
    //		  LY3  Y3  Y4	

    //y1
    diffQdcA=abs(ly1-lay1);
    diffQdcC=abs(ay1-lay1);
    dcx= (diffQdcC>diffQdcA) ? ay1:ly1;
    predQdc=CONV_DCTQ12_NUM(GET_QDC_Y1(pDctqCoeff,xmbn,mx,my));
    qdc=predQdc+RDIV(dcx,dcScaler1);
    PUT_QDC_Y1(pDctqCoeff,xmbn,mx,my,CONV_NUM_DCTQ12(qdc));		
    dcArray[mx][my].y1=y1=qdc*dcScaler1;
    
    //y2
	diffQdcA=abs(y1-ay1);
	diffQdcC=abs(ay2-ay1);
	dcx= (diffQdcC>diffQdcA) ? ay2:y1;
	predQdc=CONV_DCTQ12_NUM(GET_QDC_Y2(pDctqCoeff,xmbn,mx,my));
	qdc=predQdc+RDIV(dcx,dcScaler1);
	PUT_QDC_Y2(pDctqCoeff,xmbn,mx,my,CONV_NUM_DCTQ12(qdc));	    
	dcArray[mx][my].y2=y2=qdc*dcScaler1;
    
    //y3
	diffQdcA=abs(ly3-ly1);
	diffQdcC=abs(y1-ly1);
	dcx= (diffQdcC>diffQdcA) ? y1:ly3;
	predQdc=CONV_DCTQ12_NUM(GET_QDC_Y3(pDctqCoeff,xmbn,mx,my));
	qdc=predQdc+RDIV(dcx,dcScaler1);
	PUT_QDC_Y3(pDctqCoeff,xmbn,mx,my,CONV_NUM_DCTQ12(qdc));	    
	dcArray[mx][my].y3=y3=qdc*dcScaler1;
    
    //y4
	diffQdcA=abs(y3-y1);
	diffQdcC=abs(y2-y1);
	dcx= (diffQdcC>diffQdcA) ? y2:y3;
	predQdc=CONV_DCTQ12_NUM(GET_QDC_Y4(pDctqCoeff,xmbn,mx,my));
	qdc=predQdc+RDIV(dcx,dcScaler1);
	PUT_QDC_Y4(pDctqCoeff,xmbn,mx,my,CONV_NUM_DCTQ12(qdc));
	dcArray[mx][my].y4=qdc*dcScaler1;


    //	  B C	  LAY1 AY1 AY2	 LACB ACB    LACR ACR  
    //	  A X	  LY1  Y1  Y2	 LCB  CB     LCR  CR
    //		  LY3  Y3  Y4	
    
    //cb
	diffQdcA=abs(lcb-lacb);
	diffQdcC=abs(acb-lacb);
	dcx= (diffQdcC>diffQdcA) ? acb:lcb;
	predQdc=CONV_DCTQ12_NUM(GET_QDC_CB(pDctqCoeff,xmbn,mx,my));
	qdc=predQdc+RDIV(dcx,dcScaler2);
	PUT_QDC_CB(pDctqCoeff,xmbn,mx,my,CONV_NUM_DCTQ12(qdc)); 	    
	dcArray[mx][my].cb=qdc*dcScaler2;

    
    //cr
	diffQdcA=abs(lcr-lacr);
	diffQdcC=abs(acr-lacr);
	dcx= (diffQdcC>diffQdcA) ? acr:lcr;
	predQdc=CONV_DCTQ12_NUM(GET_QDC_CR(pDctqCoeff,xmbn,mx,my));
	qdc=predQdc+RDIV(dcx,dcScaler2);
	PUT_QDC_CR(pDctqCoeff,xmbn,mx,my,CONV_NUM_DCTQ12(qdc));	    
	dcArray[mx][my].cr=qdc*dcScaler2;
}    




void InitDcArray(void)
{
    int mx,my;
    
    printf("dcArray is initialized for compensation of intra-mblock dc prediction.\n");    
    
    for(my=0;my<FIMV_IMAGE_HEIGHT/16;my++)
	for(mx=0;mx<FIMV_IMAGE_WIDTH/16;mx++)
	{
	    dcArray[mx][my].y1=1024;
	    dcArray[mx][my].y2=1024;
	    dcArray[mx][my].y3=1024;
	    dcArray[mx][my].y4=1024;
	    dcArray[mx][my].cb=1024;
	    dcArray[mx][my].cr=1024;
	}
	
}







void WaitForVldDone(void)
{
    while(rVLX_OUT1&VLX_BUSY);
}
/********************************************************
 VlcConfig4Dctq - VLC engine configuration processing a frame with DCTQ
 
 Description:	
 - none
*/
void VlcConfig4Dctq(U32 imgXsize,U32 vlcDataAddr,U32 opUnit,U32 mode)
{
    vlxDone=0;

    //VLC needs soft-reset before starting a new operation.
    rVLC_CON1=VLX_SOFT_RESET;
    rVLC_CON1=0;    
    
    rVLC_CON1=VLC_DCTQ_ZIGZAG_SCAN|VLC_FROM_DCTQ|(imgXsize<<0);
    rVLC_CON2=0x0;	
    rVLC_CON3=vlcDataAddr;
    //rVLC_CON3 = 0x12000000;
    rVLC_CON4=0x0;

    rVLD_CON1=0x0;   //??

    rVLX_COMMON1= VLX_ON|VLX_ENCODE_MODE|VLX_INT_ENABLE|VLX_USE_MARKER_BIT|
    	  	  (opUnit<<9)|
    	  	  (0<<6);  //intra_dc_vlc_thr=0 => use intra DC VLC for entire VOP
}





/********************************************************
 VlcEngine - VLC engine processing a frame. 
 
 Description:	
 - none 
*/
void VlcEngine(PIMAGE420 pDctqCoeff,PQINFO pQInfo,U32 vlcDataAddr,U32 mode)
{
    U32 opUnit;

    rVLC_CON1=VLX_SOFT_RESET;  //VLX soft-reset should be done only at frame start.
    rVLC_CON1=0;    

    vlxDone=0;

    opUnit=(pDctqCoeff->imageWidth/16)*(pDctqCoeff->imageHeight/16);

    rVLX_FRAMESTARTY=pDctqCoeff->yStartAddr;
    rVLX_FRAMESTARTCB=pDctqCoeff->cbStartAddr;
    rVLX_FRAMESTARTCR=pDctqCoeff->crStartAddr;
        
    rVLC_CON1=VLC_DCTQ_ZIGZAG_SCAN |(pDctqCoeff->imageWidth<<0);
    rVLC_CON2=(U32)pQInfo;
    rVLC_CON3=vlcDataAddr;
    rVLC_CON4=0x0;
    
    rVLD_CON1=0x0;
    
    rVLX_COMMON1= VLX_ON|VLX_ENCODE_MODE|VLX_INT_ENABLE|VLX_USE_MARKER_BIT|
		  VLX_FRAME_START|VLX_START|(opUnit<<9);
    rVLX_COMMON1= VLX_ON|VLX_ENCODE_MODE|VLX_INT_ENABLE|VLX_USE_MARKER_BIT|
    	  	  ~VLX_FRAME_START|~VLX_START|(opUnit<<9);
}




/********************************************************
 VlcConfig4DctqGob - VLC engine configuration processing a GOB with DCTQ
 
 Description:	
 - modes: VLX_FRAME_START_MODE
*/
void VlcConfig4DctqGob(U32 imgXsize,U32 vlcDataAddr,U32 opUnit,U32 mode)
{
    vlxDone=0;

    if(mode&VLX_FRAME_START_MODE)	
    {
	//VLC needs soft-reset before starting a new operation.
	rVLC_CON1=VLX_SOFT_RESET;
	rVLC_CON1=0;    

	rVLC_CON1=VLC_DCTQ_ZIGZAG_SCAN|VLC_FROM_DCTQ|(imgXsize<<0);
	rVLC_CON2=0x0;	
	rVLC_CON3=vlcDataAddr;
	rVLC_CON4=0x0;

	rVLD_CON1=0x0;

	rVLX_COMMON1= VLX_ON|VLX_ENCODE_MODE|VLX_INT_ENABLE|VLX_USE_MARKER_BIT|
		      (opUnit<<9)|
	  	      (0<<6);  //intra_dc_vlc_thr=0 => use intra DC VLC for entire VOP
    }
}






/********************************************************
 VldEngine - VLD engine processing a m-block.
 
 Description:	
 - firstBitStuff: Bit31 30 29 28 ... 03 02 01 00
                      x  x  x  x  
      firstBitStuff-> 0  1  2  3     28 29 30 31
 
*/
void VldEngine(PIMAGE420 pDctqCoeff,U32 vlcDataAddr,U32 firstBitStuff,
	       U32 cbpValue,U32 qpStep,U32 mode)
{
    vlxDone=0;

    if(mode&VLX_FRAME_START_MODE)
    {
	rVLC_CON1=(1<<14);//VLX_SOFT_RESET;
	rVLC_CON1=0; 
    }

    //VLD destination
    rVLX_FRAMESTARTY=pDctqCoeff->yStartAddr;   
    rVLX_FRAMESTARTCB=pDctqCoeff->cbStartAddr;
    rVLX_FRAMESTARTCR=pDctqCoeff->crStartAddr;
	
    rVLC_CON1=VLC_DCTQ_ZIGZAG_SCAN |(pDctqCoeff->imageWidth<<0);
    rVLC_CON2=0x0;
    rVLC_CON3=0x0;
    rVLC_CON4=0x0;

    rVLD_CON2=vlcDataAddr;
    

    //At first, the only single transfer is supported.
    rVLD_CON1= (BURST_INCR8<<NBIT_VLD_BURST)|(0x1<<NBIT_VLD_CNT)|  //the BUSRT type and count will be optimized by experiment.
	       (firstBitStuff<<NBIT_VLD_BITSTUFF)|
	       ((mode&VLD_INTRA_MODE)?VLD_INTRA : VLD_INTER)|
	       VLD_USE_INTERNAL_ADDR|
	       (cbpValue<<NBIT_VLD_CBP_VALUE)|
	       (qpStep<<NBIT_VLD_QP_VALUE)|
	       VLD_MAKE_IMG;
        
    rVLX_COMMON1= VLX_ON|VLX_DECODE_MODE|VLX_INT_ENABLE|VLX_USE_MARKER_BIT|
    	          ((mode&VLX_FRAME_START_MODE) ? VLX_FRAME_START:0)|
    	          VLX_START|(1<<9);
    rVLX_COMMON1= VLX_ON|VLX_DECODE_MODE|VLX_INT_ENABLE|VLX_USE_MARKER_BIT|
		  ~VLX_FRAME_START|~VLX_START|(1<<9);
}

void __irq VlxIsr(void)
{
	printf("4= %08x\n",rVLX_OUT1);

    rSUBSRCPND |= BIT_SUB_VLX;
    ClearPending(BIT_VLX_SPI1);	
	printf("5= %08x\n",rVLX_OUT1);

    vlxDone=1;
    //printf("{v}");
}



void VlxInitIsr(void)
{
    pISR_VLX_SPI1=(U32)VlxIsr;
    rINTSUBMSK &= ~BIT_SUB_VLX;
    rINTMSK&=~BIT_VLX_SPI1;
}


/********************************************************
 VlcEngineGob - VLC engine processing a GOB. 
 
 Description:	
 - available mode:VLX_FRAME_START_MODE
*/
void VlcEngineGob(PIMAGE420 pDctqCoeff,PQINFO pQInfo,U32 vlcDataAddr,U32 opUnit,U32 mode)
{
    vlxDone=0;

    if(mode&VLX_FRAME_START_MODE)
    {
	rVLC_CON1=VLX_SOFT_RESET;  //VLX soft-reset should be done only at frame start.
	rVLC_CON1=0;    

    	rVLX_FRAMESTARTY=pDctqCoeff->yStartAddr;
    	rVLX_FRAMESTARTCB=pDctqCoeff->cbStartAddr;
    	rVLX_FRAMESTARTCR=pDctqCoeff->crStartAddr;
	
    	rVLC_CON1=VLC_DCTQ_ZIGZAG_SCAN |(pDctqCoeff->imageWidth<<0);
    	rVLC_CON2=(U32)pQInfo;
    	rVLC_CON3=vlcDataAddr;
    	rVLC_CON4=0x0;
    
    	rVLD_CON1=0x0;
    }
    rVLX_COMMON1= VLX_ON|VLX_ENCODE_MODE|VLX_INT_ENABLE|VLX_USE_MARKER_BIT|
		  ((mode& VLX_FRAME_START_MODE)? VLX_FRAME_START : 0)|
		  VLX_START|(opUnit<<9);
    rVLX_COMMON1= VLX_ON|VLX_ENCODE_MODE|VLX_INT_ENABLE|VLX_USE_MARKER_BIT|
		  (opUnit<<9);
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -