📄 macroblock.c
字号:
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; } // Do nothing more if copy and inter mode if (img->mb_mode != COPY_MB || currMB->intraOrInter != INTER_MB || (img->type == B_IMG && input->symbol_mode == CABAC) || (img->type == B_IMG && input->symbol_mode == UVLC && currMB->cbp != 0)) { // Bits for intra prediction modes if (img->imod == INTRA_MB_OLD) { for (i=0; i < MB_BLOCK_SIZE/2; i++) { currSE->value1 = currMB->intra_pred_modes[2*i]; currSE->value2 = currMB->intra_pred_modes[2*i+1]; if (input->symbol_mode == UVLC) currSE->mapping = intrapred_linfo; else currSE->writing = writeIntraPredMode2Buffer_CABAC; currSE->type = SE_INTRAPREDMODE; // choose the appropriate data partition if (img->type != B_IMG) {#if TRACE snprintf(currSE->tracestring, TRACESTRING_SIZE, "Intra mode = %3d",IPRED_ORDER[currSE->value1][currSE->value2]);#endif dataPart = &(currSlice->partArr[partMap[SE_INTRAPREDMODE]]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -