📄 vlx_test.c
字号:
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 + -