?? coder.c
字號:
*(int *)(cr_now + 6) = *(int *)(cr_prev + 6); *(int *)(cr_now + 7) = *(int *)(cr_prev + 7); cr_now += cpels; cr_prev += cpels;#endif } return;}/********************************************************************** * * Name: InterpolateImage * Description: Interpolates a complete image for easier half * pel prediction * * Input: pointer to image structure * Returns: pointer to interpolated image * Side effects: allocates memory to interpolated image * * Date: 950207 Author: Karl.Lillevold@nta.no * 960207 Author: Roalt aalmoes ***********************************************************************///插入半象素整個圖像,新圖像為ipol_image
//得到的新圖像大小為 width*2 height*2void InterpolateImage(unsigned int *image, unsigned int *ipol_image, int width, int height){ /* If anyone has better ideas to optimize this code, be my guest! note: assembly or some advanced bitshifts routine might do the trick...*/ register unsigned int *ii, *oo, *ii_new, *ii_new_line2, *oo_prev, *oo_prev_line2; register int i,j; register unsigned int pix1,pix2,pix3,pix4; ii = ipol_image; oo = image; oo_prev = image; oo_prev_line2 = image + width; ii_new = ipol_image; ii_new_line2 = ipol_image + (width<<1); /* main image */ for (j = 0; j < height-1; j++) { /* get Pix1 and Pix3, because they are not known the first time */ pix1 = *oo_prev; pix3 = *oo_prev_line2; for (i = 0; i < width-1; i++) { /* Pix1 Pix2 Pix3 Pix4 */ // pix1 (pix1+pix2)/2 pix2
// (pix1+pix3)/2 (pix1+pix2+pix3+pix4)/4 (pix2+pix4)/2
// /* Pix2 and Pix4 are used here for first time */ pix2 = *(oo_prev + 1); pix4 = *(oo_prev_line2 + 1); *(ii_new) = pix1; /* X. ..*/ *(ii_new + 1) = (pix1 + pix2 + 1)>>1; /* *X .. */ *ii_new_line2 = (pix1 + pix3 + 1)>>1; /* *. X. */ *(ii_new_line2 + 1) = (pix1 + pix2 + pix3 + pix4 + 2)>>2; oo_prev++; oo_prev_line2++; ii_new += 2; ii_new_line2 += 2; pix1 = pix2; pix3 = pix4; /* Pix1 Pix2=Pix1' Pix2' */ /* Pix3 Pix4=Pix3' Pix4' */ } /* 最后一列*/ *(ii_new++) = pix1; *(ii_new++) = pix3; /* Last column -On the Edge - */ *(ii_new_line2++) = (pix1 + pix3 + 1 ) >>1; *(ii_new_line2++) = (pix1 + pix3 + 1 ) >>1; ii_new += (width<<1); /* ii_new now on old position ii_new_line2,so one interpolated screen line must be added*/ ii_new_line2 += (width<<1); /* In fact, ii_new_line here has same value as ii_new */ oo_prev += 1; /* Remember, loop is done one time less! */ oo_prev_line2 += 1; } /* 最后一行 */ pix1 = *oo_prev; for (i = 0; i < width-1; i++) { pix2 = *(oo_prev + 1); *ii_new = *ii_new_line2 = pix1; *(ii_new + 1) = *(ii_new_line2 + 1) = (pix1 + pix2 + 1)>>1; ii_new += 2; ii_new_line2 += 2; oo_prev += 1; pix1 = pix2; /* Pix1 Pix2=Pix1' Pix2' */ } /* 右下角*/ *(ii_new) = pix1; *(ii_new + 1) = pix1; *(ii_new_line2) = pix1; *(ii_new_line2+1) = pix1; return;}/********************************************************************** * * Name: FullMotionEstimatePicture * Description: Finds integer and half pel motion estimation * * Input: current image, previous image, interpolated * reconstructed previous image, seek_dist, * motion vector array * Returns: * Side effects: allocates memory for MV structure * * Date: 960418 Author: Roatlt * ***********************************************************************/// 找到整象素和半象素的運動估計// curr現在圖像,prev重建后圖像,prev_ipol插入半象素后的,seek_dist 搜索窗,MV 放置mv結果,advanced_method ,EncodeThisBlock編碼
void FullMotionEstimatePicture(unsigned int *curr, unsigned int *prev, unsigned int *prev_ipol, int seek_dist, MotionVector *MV_ptr, int advanced_method, int *EncodeThisBlock){ int i,j; MotionVector *current_MV; for(j = 0; j < mbr; j++) { for(i = 0; i < mbc; i++) { current_MV = MV_ptr + j*mbc + i; if(advanced_method && !*(EncodeThisBlock + j*mbc + i) ) // encoderthisblock 檢測宏塊hasmove,為0時,表示重建的宏塊和當前宏塊近似,不需編碼,為skip
{ current_MV->x = current_MV->y = current_MV->x_half = current_MV->y_half = 0; // 整象素和半象素全部為0時,為SKIP current_MV->Mode = MODE_SKIP; }
else
{ /* EncodeThisBlock */
//估計宏塊運動矢量,到current_mv(x,y值和誤差值) ??????????????????????? FullMotionEstimation(curr, prev_ipol, seek_dist, current_MV, i*MB_SIZE, j*MB_SIZE);
// 選擇編碼模式,宏塊的方差較小時,用intra current_MV->Mode = ChooseMode(curr,i*MB_SIZE,j*MB_SIZE,current_MV->min_error);
if(current_MV->Mode == MODE_INTRA) ZeroVec(current_MV); } } }}//編碼一幀P幀void CodeInterH263(CParam *params, Bits *bits){ MotionVector *MV; MotionVector ZERO = {0,0,0,0,0}; MB_Structure *recon_data_P; MB_Structure *diff; int *qcoeff_P; unsigned int *new_recon=NULL; unsigned int *prev_recon; int Mode; int CBP, CBPB=0; int newgob; int i,j; search_p_frames = params->search_method; MV = malloc(sizeof(MotionVector)*mbc*mbr);
// 新重建圖像 new_recon = malloc(sizeof_frame);
//上幀重建圖像 prev_recon = params->recon; /* buffer control vars */ ZeroBits(bits); /* Interpolate luminance from reconstr. picture */ // 插入半象素圖像,得到params->interpolated_lum (寬,長都為原來2倍) InterpolateImage(prev_recon,params->interpolated_lum,pels,lines);
//找到運動矢量,放入MV序列,params->advanced_method=1 ,定義宏塊的類型.如果當前和重建的宏塊相同,則為skip. intra誤差小時,定義為intra. FullMotionEstimatePicture( params->data,prev_recon, params->interpolated_lum, params->half_pixel_searchwindow,MV,params->advanced_method, params->EncodeThisBlock); /* Calculate MV for each MB */ /* ENCODE TO H.263 STREAM */ //開始編碼 for ( j = 0; j < mbr; j++) { newgob = 0; if (j == 0)
{ pic->QUANT = params->Q_inter; pic->picture_coding_type = PCT_INTER; bits->header += CountBitsPicture(pic); // 估計P幀的文件頭bit數, 50 } else if (pic->use_gobsync && j%pic->use_gobsync == 0) // 0
{ bits->header += CountBitsSlice(j,params->Q_inter); /* insert gob sync */ // 估計片的bit數 newgob = 1; //新的片 } for ( i = 0; i < mbc; i++) { /* This means: For every macroblock (i,j) do ... */ /* We have 4 different situations: 1) !EncodeThisBlock: this means that the macroblock in not encoded 2) EncodeThisBlock: This means that the MB is encoded by using the predicted motion vector. 3) EncodeThisBlock: However, the approx of the motion vector was so bad, that INTRA coding is more appropiate here ... 4) EncodeThisBlock: The approx is so good that the coefficients are all zero (after quant.) and are not send. */ /* This means: For every macroblock (i,j) do ... */ pic->DQUANT = 0; Mode = MV[j*mbc + i].Mode; /* Determine position of MB */ pic->MB = i + j * mbc;
//宏塊SKIP,不需編碼 if(Mode == MODE_SKIP)
{ /* SITUATION 1 */ Mode = MODE_INTRA; /* This might be done "better" in the future*/ MV[j*mbc + i].Mode = Mode; ZeroVec(&(MV[j*mbc + i])); CBP = CBPB = 0;
/* COD值為1,skip */ CountBitsMB(Mode,1,CBP,CBPB,pic,bits); ReconCopyImage(i,j,new_recon,prev_recon); }
else //需對宏塊編碼
{
//幀間0 if (Mode == MODE_INTER)
{ /* SITUATION 2 */ /* Predict P-MB *///返回根據mv位置得到的插入圖像和現在圖像的差值,放入mb結構的diff diff = Predict_P(params->data,prev_recon,params->interpolated_lum,i*MB_SIZE,j*MB_SIZE,MV); }
else //幀內
{ /* SITUATION 3 */ /* Create MB_Structure diff that contains coefficients that must be sent to the other end */ diff = (MB_Structure *)malloc(sizeof(MB_Structure));
//從原數據params->data中復制宏塊數據到diff[16][16]中 FillLumBlock(i*MB_SIZE, j*MB_SIZE, params->data, diff);
/* Copy curr->lum to diff for macroblock (i,j) */ FillChromBlock(i*MB_SIZE, j*MB_SIZE, params->data, diff); /* Equiv. for curr->Cb and curr->Cr */ } /* P or INTRA Macroblock */ /* diff -> DCT -> QUANTIZED -> qcoeff_P */
//編碼差值系數,放入量化后的系數qcoeff_P qcoeff_P = MB_EncodeAndFindCBP(diff, params->Q_inter, Mode,&CBP); /* CBP = FindCBP(qcoeff_P, Mode, 64); -> Not required anymore */
/* 解碼宏塊 */ if (CBP == 0 && (Mode == MODE_INTER) )
{ /* SITUATION 4 */ ZeroMBlock(diff); }
else
{ /* qcoeff_P -> Dequantized -> IDCT -> diff */
//宏塊解碼,從量化系數qcoeff_P返回到diff MB_Decode(qcoeff_P, diff, params->Q_inter, Mode); } //重建p宏塊,返回重建宏塊結構 ?????????????? recon_data_P = MB_Recon_P(prev_recon, params->interpolated_lum,diff, i*MB_SIZE,j*MB_SIZE,MV); Clip(recon_data_P); free(diff);
/* 比特流編碼 */ if((CBP==0) && (EqualVec(&(MV[j*mbc+i]),&ZERO)) &&(Mode == MODE_INTER) )
{ /* Skipped MB : both CBP and CBPB are zero, 16x16 vector is zero, PB delta vector is zero and Mode = MODE_INTER */ /* SKIP */ CountBitsMB(Mode,1,CBP,CBPB,pic,bits); }
else //非skip
{ /* Normal MB */ /* VLC */ CountBitsMB(Mode,0,CBP,CBPB,pic,bits); if (Mode == MODE_INTER) //inter
{ bits->no_inter++;
//對mv系數編碼,i,j宏塊 CountBitsVectors(MV, bits, i, j, Mode, newgob, pic); //bits->vec 中記錄編碼了的bit位數 }
else
{ /* MODE_INTRA */ bits->no_intra++; } /* Only encode coefficient if they are nonzero or Mode is INTRA*/
// 對qcoeff編碼(16*16宏塊),寫入bit流,并將寫入bit數加入到 bits->Y,和 bits->U中 if (CBP || Mode == MODE_INTRA) //幀內 CountBitsCoeff(qcoeff_P, Mode, CBP, bits, 64); } /* End skip/not skip macroblock encoding */ ReconImage(i,j,recon_data_P,new_recon); free(recon_data_P); free(qcoeff_P); } /* End advanced */ } /* End for i */ } /* End for j */ pic->QP_mean = params->Q_inter; free(prev_recon); params->recon = new_recon; AddBitsPicture(bits); free(MV); return;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -