📄 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 + -