📄 macroblock.c
字号:
{
best_intra_sad=current_intra_sad;
best_ipmode=ipmode;
for (j=0; j < BLOCK_SIZE; j++)
for (i=0; i < BLOCK_SIZE; i++)
img->mpr[i+block_x][j+block_y]=img->mprr[ipmode][j][i]; /* store the currently best intra prediction block*/
}
}
}
}
tot_intra_sad += best_intra_sad;
img->ipredmode[pic_block_x+1][pic_block_y+1]=best_ipmode;
if ((pic_block_x & 1) == 1) /* just even blocks, two and two predmodes are sent together */
{
currMB->intra_pred_modes[block_x/4+block_y]=PRED_IPRED[img->ipredmode[pic_block_x+1][pic_block_y]+1][img->ipredmode[pic_block_x][pic_block_y+1]+1][best_ipmode];
currMB->intra_pred_modes[block_x/4-1+block_y]=last_ipred;
}
last_ipred=PRED_IPRED[img->ipredmode[pic_block_x+1][pic_block_y]+1][img->ipredmode[pic_block_x][pic_block_y+1]+1][best_ipmode];
/* Make difference from prediction to be transformed*/
for (j=0; j < BLOCK_SIZE; j++)
{
for (i=0; i < BLOCK_SIZE; i++)
{
img->m7[i][j] =imgY_org[img->pix_y+block_y+j][img->pix_x+block_x+i] - img->mpr[i+block_x][j+block_y];
}
}
nonzero = dct_luma(block_x,block_y,&coeff_cost);
if (nonzero)
{
currMB->cbp |= cbp_mask;/* set coded block pattern if there are nonzero coeffs */
}
}
}
/* 16x16 intra prediction */
intrapred_luma_2(img); /* make intra pred for the new 4 modes */
tot_intra_sad2 = find_sad2(intra_pred_mode_2); /* find best SAD for new modes */
if (tot_intra_sad2<tot_intra_sad)
{
currMB->cbp = 0; /* cbp for 16x16 LUMA is signaled by the MB-mode */
tot_intra_sad = tot_intra_sad2; /* update best intra sad if necessary */
img->imod = INTRA_MB_NEW; /* one of the new modes is used */
img->mb_data[img->current_mb_nr].intraOrInter = INTRA_MB_16x16;
dct_luma2(*intra_pred_mode_2);
for (i=0;i<4;i++)
for (j=0;j<4;j++)
img->ipredmode[img->block_x+i+1][img->block_y+j+1]=0;
}
return tot_intra_sad;
}
/************************************************************************
*
* Name : LumaResidualCoding_P()
*
* Description: Performs DCT, R-D constrained quantization, run/level
* pre-coding and IDCT for the MC-compensated MB residue
* of P-frame; current cbp (for LUMA only) is affected
*
************************************************************************/
void LumaResidualCoding_P()
{
int i,j;
int block_x, block_y;
int pic_pix_y,pic_pix_x,pic_block_y,pic_block_x;
int ii4,i2,jj4,j2;
int sum_cnt_nonz;
int mb_x, mb_y;
int cbp_mask;
int coeff_cost;
int nonzero;
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
currMB->cbp=0;
sum_cnt_nonz=0;
for (mb_y=0; mb_y < MB_BLOCK_SIZE; mb_y += BLOCK_SIZE*2)
{
for (mb_x=0; mb_x < MB_BLOCK_SIZE; mb_x += BLOCK_SIZE*2)
{
cbp_mask=(1<<(mb_x/8+mb_y/4));
coeff_cost=0;
for (block_y=mb_y; block_y < mb_y+BLOCK_SIZE*2; block_y += BLOCK_SIZE)
{
pic_pix_y=img->pix_y+block_y;
pic_block_y=pic_pix_y/BLOCK_SIZE;
for (block_x=mb_x; block_x < mb_x+BLOCK_SIZE*2; block_x += BLOCK_SIZE)
{
pic_pix_x=img->pix_x+block_x;
pic_block_x=pic_pix_x/BLOCK_SIZE;
img->ipredmode[pic_block_x+1][pic_block_y+1]=0;
if(input->mv_res)
{
ii4=(img->pix_x+block_x)*8+tmp_mv[0][pic_block_y][pic_block_x+4];
jj4=(img->pix_y+block_y)*8+tmp_mv[1][pic_block_y][pic_block_x+4];
for (j=0;j<4;j++)
{
j2=j*8;
for (i=0;i<4;i++)
{
i2=i*8;
#ifdef UMV
img->mpr[i+block_x][j+block_y]=UMVPelY_18 (mref[img->multframe_no], jj4+j2, ii4+i2);
#else
img->mpr[i+block_x][j+block_y]=FastPelY_18 (mref[img->multframe_no], jj4+j2, ii4+i2);
#endif
//img->mpr[i+block_x][j+block_y]=get_eigthpix_pel(ii4+i2,jj4+j2,img->multframe_no);
}
}
}
else
{
ii4=(img->pix_x+block_x)*4+tmp_mv[0][pic_block_y][pic_block_x+4];
jj4=(img->pix_y+block_y)*4+tmp_mv[1][pic_block_y][pic_block_x+4];
for (j=0;j<4;j++)
{
#ifndef UMV
j2=j*4;
#endif
#ifdef UMV
j2 = max (0, min(img->mvert,jj4+j*4));
#endif
for (i=0;i<4;i++)
{
#ifndef UMV
i2=i*4;
img->mpr[i+block_x][j+block_y]=mref[img->multframe_no][jj4+j2][ii4+i2];
#endif
#ifdef UMV
i2 = max(0, min(img->mhor, ii4+i*4));
img->mpr[i+block_x][j+block_y]=FastPelY_14 (mref[img->multframe_no], j2, i2);
#endif
}
}
}
for (j=0; j < BLOCK_SIZE; j++)
{
for (i=0; i < BLOCK_SIZE; i++)
{
img->m7[i][j] =imgY_org[img->pix_y+block_y+j][img->pix_x+block_x+i] - img->mpr[i+block_x][j+block_y];
}
}
nonzero=dct_luma(block_x,block_y,&coeff_cost);
if (nonzero)
{
currMB->cbp |= cbp_mask;
}
}
}
/*
The purpose of the action below is to prevent that single or 'expensive' coefficients are coded.
With 4x4 transform there is larger chance that a single coefficient in a 8x8 or 16x16 block may be nonzero.
A single small (level=1) coefficient in a 8x8 block will cost: 3 or more bits for the coefficient,
4 bits for EOBs for the 4x4 blocks,possibly also more bits for CBP. Hence the total 'cost' of that single
coefficient will typically be 10-12 bits which in a RD consideration is too much to justify the distortion improvement.
The action below is to watch such 'single' coefficients and set the reconstructed block equal to the prediction according
to a given criterium. The action is taken only for inter luma blocks.
Notice that this is a pure encoder issue and hence does not have any implication on the standard.
coeff_cost is a parameter set in dct_luma() and accumulated for each 8x8 block. If level=1 for a coefficient,
coeff_cost is increased by a number depending on RUN for that coefficient.The numbers are (see also dct_luma()): 3,2,2,1,1,1,0,0,...
when RUN equals 0,1,2,3,4,5,6, etc.
If level >1 coeff_cost is increased by 9 (or any number above 3). The threshold is set to 3. This means for example:
1: If there is one coefficient with (RUN,level)=(0,1) in a 8x8 block this coefficient is discarded.
2: If there are two coefficients with (RUN,level)=(1,1) and (4,1) the coefficients are also discarded
sum_cnt_nonz is the accumulation of coeff_cost over a whole macro block. If sum_cnt_nonz is 5 or less for the whole MB,
all nonzero coefficients are discarded for the MB and the reconstructed block is set equal to the prediction.
*/
if (coeff_cost > 3)
{
sum_cnt_nonz += coeff_cost;
}
else /*discard */
{
currMB->cbp &= (63-cbp_mask);
for (i=mb_x; i < mb_x+BLOCK_SIZE*2; i++)
{
for (j=mb_y; j < mb_y+BLOCK_SIZE*2; j++)
{
imgY[img->pix_y+j][img->pix_x+i]=img->mpr[i][j];
}
}
}
}
}
if (sum_cnt_nonz <= 5 )
{
currMB->cbp &= 48; /* mask bit 4 and 5 */
for (i=0; i < MB_BLOCK_SIZE; i++)
{
for (j=0; j < MB_BLOCK_SIZE; j++)
{
imgY[img->pix_y+j][img->pix_x+i]=img->mpr[i][j];
}
}
}
}
/************************************************************************
*
* Name : ChromaCoding_P()
*
* Description: Performs DCT, quantization, run/level pre-coding and IDCT
* for the chrominance of a I- of P-frame macroblock;
* current cbp and cr_cbp are affected
*
************************************************************************/
void ChromaCoding_P(int *cr_cbp)
{
int i, j;
int uv, ii,jj,ii0,jj0,ii1,jj1,if1,jf1,if0,jf0,f1,f2,f3,f4;
int pic_block_y, pic_block_x;
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
if(input->mv_res)
{
f1=16;
f2=15;
}
else
{
f1=8;
f2=7;
}
f3=f1*f1;
f4=f3/2;
*cr_cbp=0;
for (uv=0; uv < 2; uv++)
{
if (img->imod == INTRA_MB_OLD || img->imod == INTRA_MB_NEW)
{
intrapred_chroma(img->pix_c_x,img->pix_c_y,uv);
}
else
{
for (j=0; j < MB_BLOCK_SIZE/2; j++)
{
pic_block_y=(img->pix_c_y+j)/2;
for (i=0; i < MB_BLOCK_SIZE/2; i++)
{
pic_block_x=(img->pix_c_x+i)/2;
ii=(img->pix_c_x+i)*f1+tmp_mv[0][pic_block_y][pic_block_x+4];
jj=(img->pix_c_y+j)*f1+tmp_mv[1][pic_block_y][pic_block_x+4];
#ifndef UMV
ii0=ii/f1;
jj0=jj/f1;
ii1=(ii+f2)/f1;
jj1=(jj+f2)/f1;
#endif
#ifdef UMV
ii0 = max (0, min (img->width_cr-1,ii/f1));
jj0 = max (0, min (img->height_cr-1,jj/f1));
ii1 = max (0, min (img->width_cr-1,(ii+f2)/f1));
jj1 = max (0, min (img->height_cr-1,(jj+f2)/f1));
#endif
if1=(ii & f2);
jf1=(jj & f2);
if0=f1-if1;
jf0=f1-jf1;
img->mpr[i][j]=(if0*jf0*mcef[img->multframe_no][uv][jj0][ii0]+
if1*jf0*mcef[img->multframe_no][uv][jj0][ii1]+
if0*jf1*mcef[img->multframe_no][uv][jj1][ii0]+
if1*jf1*mcef[img->multframe_no][uv][jj1][ii1]+f4)/f3;
img->m7[i][j]=imgUV_org[uv][img->pix_c_y+j][img->pix_c_x+i]-img->mpr[i][j];
}
}
}
*cr_cbp=dct_chroma(uv,*cr_cbp);
}
currMB->cbp += *cr_cbp*16;
}
/************************************************************************
*
* Name : SetRefFrameInfo_P()
*
* Description: Set reference frame information in global arrays
* depending on mode decision. Used for motion vector prediction.
*
************************************************************************/
void SetRefFrameInfo_P()
{
int i,j;
if (img->imod == INTRA_MB_OLD || img->imod == INTRA_MB_NEW)
{
/* Set the reference frame information for motion vector prediction as unavailable */
for (j = 0;j < BLOCK_MULTIPLE;j++)
{
for (i = 0;i < BLOCK_MULTIPLE;i++)
{
refFrArr[img->block_y+j][img->block_x+i] = -1;
}
}
}
else
{
/* Set the reference frame information for motion vector prediction */
for (j = 0;j < BLOCK_MULTIPLE;j++)
{
for (i = 0;i < BLOCK_MULTIPLE;i++)
{
refFrArr[img->block_y+j][img->block_x+i] = img->mb_data[img->current_mb_nr].ref_frame;
}
}
}
}
/************************************************************************
*
* Name : SetLoopfilterStrength_P()
*
* Description: Set the filter strength for a macroblock of a I- or P-frame
*
************************************************************************/
void SetLoopfilterStrength_P()
{
int i,j;
int ii,jj;
int i3,j3,mvDiffX,mvDiffY;
if (img->imod == INTRA_MB_OLD || img->imod == INTRA_MB_NEW)
{
for (i=0;i<BLOCK_MULTIPLE;i++)
{
ii=img->block_x+i;
i3=ii/2;
for (j=0;j<BLOCK_MULTIPLE;j++)
{
jj=img->block_y+j;
j3=jj/2;
loopb[ii+1][jj+1]=3;
loopb[ii ][jj+1]=max(loopb[ii ][jj+1],2);
loopb[ii+1][jj ]=max(loopb[ii+1][jj ],2);
loopb[ii+2][jj+1]=max(loopb[ii+2][jj+1],2);
loopb[ii+1][jj+2]=max(loopb[ii+1][jj+2],2);
loopc[i3+1][j3+1]=2;
loopc[i3 ][j3+1]=max(loopc[i3 ][j3+1],1);
loopc[i3+1][j3 ]=max(loopc[i3+1][j3 ],1);
loopc[i3+2][j3+1]=max(loopc[i3+2][j3+1],1);
loopc[i3+1][j3+2]=max(loopc[i3+1][j3+2],1);
}
}
}
else
{
for (i=0;i<4;i++)
{
ii=img->block_x+i;
i3=ii/2;
for (j=0;j<4;j++)
{
jj=img->block_y+j;
j3=jj/2;
mvDiffX = tmp_mv[0][jj][ii+4] - tmp_mv[0][jj][ii-1+4];
mvDiffY = tmp_mv[1][jj][ii+4] - tmp_mv[1][jj][ii-1+4];
if((mvDiffX*mvDiffX >= 16 || mvDiffY*mvDiffY >= 16) && ii > 0)
{
loopb[ii ][jj+1]=max(loopb[ii ][jj+1],1);
loopb[ii+1][jj+1]=max(loopb[ii+1][jj+1],1);
loopc[i3 ][j3+1]=max(loopc[i3 ][j3+1],1);
loopc[i3+1][j3+1]=max(loopc[i3+1][j3+1],1);
}
if(jj > 0) /*GH: bug fix to avoid tmp_mv[][-1][ii+4]*/
{
mvDiffX = tmp_mv[0][jj][ii+4] - tmp_mv[0][jj-1][ii+4];
mvDiffY = tmp_mv[1][jj][ii+4] - tmp_mv[1][jj-1][ii+4];
if(mvDiffX*mvDiffX >= 16 || mvDiffY*mvDiffY >= 16)
{
loopb[ii+1][jj ]=max(loopb[ii+1][jj ],1);
loopb[ii+1][jj+1]=max(loopb[ii+1][jj+1],1);
loopc[i3+1][j3 ]=max(loopc[i3+1][j3 ],1);
loopc[i3+1][j3+1]=max(loopc[i3+1][j3+1],1);
}
}
}
}
}
}
/************************************************************************
*
* Name : encode_one_macroblock()
*
* Description: Encode one macroblock depending on chosen picture type
*
************************************************************************/
void encode_one_macroblock()
{
int cr_cbp; /* chroma coded block pattern */
int tot_intra_sad;
int intra_pred_mode_2; /* best 16x16 intra mode */
#ifdef _RD_OPT_
if ((img->type!=B_IMG && input->rdopt) || (input->rdopt>0))
{
RD_Mode_Decision ();
}
else
{
#endif
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
/* Intra Prediction */
tot_intra_sad = MakeIntraPrediction(&intra_pred_mode_2);
if (img->type != B_IMG) /* I- or P-frame */
{
if ((img->mb_y == img->mb_y_upd && img->mb_y_upd != img->mb_y_intra) || img->type == INTRA_IMG)
{
img->mb_mode=8*img->type+img->imod; /* Intra mode: set if intra image or if intra GOB for error robustness */
}
else
{
currMB->ref_frame = motion_search(tot_intra_sad); /* Motion vector search for P-frames */
}
}
else /* B-frame */
currMB->ref_frame = motion_search_Bframe(tot_intra_sad); /* Motion vector search for B-frames */
if (img->type == B_IMG) /* B-frame */
{
/* Residual coding of Luminance (only for B-modes) */
LumaResidualCoding_B(img);
/* Coding of Chrominance */
ChromaCoding_B(&cr_cbp);
/* Set loop filter strength depending on mode decision */
SetLoopfilterStrength_B();
/* Set reference frame information for motion vector prediction of future MBs */
SetRefFrameInfo_B();
}
else /* I- or P-frame */
{
if (currMB->intraOrInter == INTER_MB)
LumaResidualCoding_P(); /* Residual coding of Luminance (only for inter modes) */
/* Coding of Luma in intra mode is done implicitly in MakeIntraPredicition */
/* Coding of Chrominance */
ChromaCoding_P(&cr_cbp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -