📄 macroblock.c
字号:
for (i=0;i<4;i++)
{
i2 = ii4+i*4;
img->mpr[i+block_x][j+block_y]=UMVPelY_14 (mref[img->multframe_no], j2, i2);
}
}
}
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];
}
}
if (img->types!=SP_IMG)
nonzero=dct_luma(block_x,block_y,&coeff_cost);
else nonzero=dct_luma_sp(block_x,block_y,&coeff_cost);
if (nonzero)
{
currMB->cbp_blk |= 1 << cbp_blk_mask ; // one bit for every 4x4 block
currMB->cbp |= cbp_mask; // one bit for the 4x4 blocks of an 8x8 block
}
}
}
/*
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 ) ;
currMB->cbp_blk &= ~(51 << (mb_y + (mb_x>>2) )) ;
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 (img->types==SP_IMG)
for (i=mb_x; i < mb_x+BLOCK_SIZE*2; i+=BLOCK_SIZE)
for (j=mb_y; j < mb_y+BLOCK_SIZE*2; j+=BLOCK_SIZE)
copyblock_sp(i,j);
}
}
}
if (sum_cnt_nonz <= 5 )
{
currMB->cbp &= 0xfffff0 ;
currMB->cbp_blk &= 0xff0000 ;
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];
}
}
if (img->types==SP_IMG)
for (i=0; i < MB_BLOCK_SIZE; i+=BLOCK_SIZE)
for (j=0; j < MB_BLOCK_SIZE; j+=BLOCK_SIZE)
copyblock_sp(i,j);
}
}
/*!
************************************************************************
* \brief
* 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];
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));
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];
}
}
}
if (img->types!=SP_IMG || (img->imod == INTRA_MB_OLD || img->imod == INTRA_MB_NEW) )
*cr_cbp=dct_chroma(uv,*cr_cbp);
else *cr_cbp=dct_chroma_sp(uv,*cr_cbp);
}
currMB->cbp += *cr_cbp*16;
}
/*!
************************************************************************
* \brief
* 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;
}
}
}
}
/*!
************************************************************************
* \brief
* 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
if (input->rdopt)
{
RD_Mode_Decision ();
}
else
{
Macroblock *currMB = &img->mb_data[img->current_mb_nr];
tot_intra_sad = MakeIntraPrediction(&intra_pred_mode_2); // Intra Prediction
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); // P-frames MV-search
}
}
else // B-frame
currMB->ref_frame = motion_search_Bframe(tot_intra_sad); // B-frames MV-search
if (img->type == B_IMG) // B-frame
{
LumaResidualCoding_B(img); // Residual coding of Luma (B-modes only)
ChromaCoding_B(&cr_cbp); // Coding of Chrominance
SetRefFrameInfo_B(); // Set ref-frame info for mv-prediction of future MBs
}
else // I- or P-frame
{
if (currMB->intraOrInter == INTER_MB)
LumaResidualCoding_P(); // Residual coding of Luma (only for inter modes)
// Coding of Luma in intra mode is done implicitly in MakeIntraPredicition
ChromaCoding_P(&cr_cbp); // Coding of Chrominance
// Set reference frame information for motion vector prediction of future MBs
SetRefFrameInfo_P();
// Check if a MB is skipped (no coeffs. only 0-vectors and prediction from the most recent frame)
if( (currMB->ref_frame == 0) && (currMB->intraOrInter == INTER_MB)
&& (tmp_mv[0][img->block_y][img->block_x+4]== 0) && (img->mb_mode == M16x16_MB)
&& (tmp_mv[1][img->block_y][img->block_x+4]== 0) && (currMB->cbp == 0) )
img->mb_mode=COPY_MB;
}
currMB->qp = img->qp; // this should (or has to be) done somewere else. where?
DeblockMb(img, imgY, imgUV) ; // Deblock this MB ( pixels to the right and above are affected)
if (img->imod==INTRA_MB_NEW) // Set 16x16 intra mode and make "intra CBP"
{
img->mb_mode += intra_pred_mode_2 + 4*cr_cbp + 12*img->kac;
currMB->cbp += 15*img->kac; //GB
}
if ((((img->type == INTER_IMG)||(img->types==SP_IMG)) && ((img->imod==INTRA_MB_NEW) || (img->imod==INTRA_MB_OLD)))
|| (img->type == B_IMG && (img->imod==B_Backward || img->imod==B_Direct || img->imod==INTRA_MB_NEW || img->imod==INTRA_MB_OLD)))// gb b-frames too
currMB->ref_frame = 0;
}
}
/*!
************************************************************************
* \brief
* Passes the chosen syntax elements to the NAL
************************************************************************
*/
void write_one_macroblock()
{
int i;
int mb_nr = img->current_mb_nr;
SyntaxElement *currSE = img->MB_SyntaxElements;
Macroblock *currMB = &img->mb_data[mb_nr];
int *bitCount = currMB->bitcounter;
Slice *currSlice = img->currentSlice;
DataPartition *dataPart;
int *partMap = assignSE2partition[input->partition_mode];
// Store imod for further use
currMB->mb_imode = img->imod;
// Store mb_mode for further use
currMB->mb_type = (currSE->value1 = img->mb_mode);
// choose the appropriate data partition
if (img->type == B_IMG)
dataPart = &(currSlice->partArr[partMap[SE_BFRAME]]);
else
dataPart = &(currSlice->partArr[partMap[SE_MBTYPE]]);
// Bits for mode
if(img->type == INTRA_IMG || img->types == SP_IMG || input->symbol_mode == CABAC)
{
if (input->symbol_mode == UVLC)
currSE->mapping = n_linfo2;
else
currSE->writing = writeMB_typeInfo2Buffer_CABAC;
currSE->type = SE_MBTYPE;
#if TRACE
if (img->type == B_IMG)
snprintf(currSE->tracestring, TRACESTRING_SIZE, "B_MB mode(%2d,%2d) = %3d",img->mb_x, img->mb_y, img->mb_mode);
else
snprintf(currSE->tracestring, TRACESTRING_SIZE, "MB mode(%2d,%2d) = %3d",img->mb_x, img->mb_y,img->mb_mode);
#endif
dataPart->writeSyntaxElement( currSE, dataPart);
bitCount[BITS_MB_MODE]+=currSE->len;
currSE++;
currMB->currSEnr++;
}
else
{
if (img->mb_mode != COPY_MB || currMB->intraOrInter != INTER_MB || (img->type == B_IMG && currMB->cbp != 0))
{
// Macroblock is coded, put out run and mbmode
currSE->value1 = img->cod_counter;
currSE->mapping = n_linfo2;
currSE->type = SE_MBTYPE;
#if TRACE
snprintf(currSE->tracestring, TRACESTRING_SIZE, "MB runlength = %3d",img->cod_counter);
#endif
dataPart->writeSyntaxElement( currSE, dataPart);
bitCount[BITS_MB_MODE]+=currSE->len;
currSE++;
currMB->currSEnr++;
// Reset cod counter
img->cod_counter = 0;
// Put out mb mode
currSE->value1 = img->mb_mode;
if(img->type != B_IMG)
currSE->value1--;
currSE->mapping = n_linfo2;
currSE->type = SE_MBTYPE;
#if TRACE
if (img->type == B_IMG)
snprintf(currSE->tracestring, TRACESTRING_SIZE, "B_MB mode(%2d,%2d) = %3d",img->mb_x, img->mb_y, img->mb_mode);
else
snprintf(currSE->tracestring, TRACESTRING_SIZE, "MB mode(%2d,%2d) = %3d",img->mb_x, img->mb_y,img->mb_mode);
#endif
dataPart->writeSyntaxElement( currSE, dataPart);
bitCount[BITS_MB_MODE]+=currSE->len;
currSE++;
currMB->currSEnr++;
}
else
{
// Macroblock is skipped, increase cod_counter
img->cod_counter++;
if(img->current_mb_nr == img->total_number_mb)
{
// Put out run
currSE->value1 = img->cod_counter;
currSE->mapping = n_linfo2;
currSE->type = SE_MBTYPE;
#if TRACE
snprintf(currSE->tracestring, TRACESTRING_SIZE, "MB runlength = %3d",img->cod_counter);
#endif
dataPart->writeSyntaxElement( currSE, dataPart);
bitCount[BITS_MB_MODE]+=currSE->len;
currSE++;
currMB->currSEnr++;
// Reset cod counter
img->cod_counter = 0;
}
}
}
if(input->UseConstrainedIntraPred)
{
if (img->type==INTER_IMG && img->types != SP_IMG)
if(currMB->intraOrInter == INTER_MB)
img->intra_mb[img->current_mb_nr] = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -