⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codeinter.cpp

📁 h263 encoder
💻 CPP
字号:
#include"stdafx.h"
#include"Global.h"
/**********************************************************************
 *
 *	Name:        CodeOneInter
 *	Description:	code one image normally or two images
 *                      as a PB-frame (CodeTwoPB and CodeOnePred merged)
 *	
 *	Input:        pointer to image, prev_image, prev_recon, Q
 *        
 *	Returns:	pointer to reconstructed image
 *	Side effects:	memory is allocated to recon image
 *
 ************************************************************************/
void CodeOneInter(PictImage *prev,PictImage *curr,
				  PictImage *pr,PictImage *curr_recon,
				  int QP, int frameskip, Bits *bits, Pict *pic)
{
	 ZeroBits(bits);
	 unsigned char *prev_ipol,*pi,*orig_lum;
     PictImage *prev_recon=NULL;
	 MotionVector *MV[6][MBR+1][MBC+2]; 
	 MotionVector ZERO = {0,0,0,0,0};
	 int i,j,k;
	 int newgob,Mode;
  	 int *qcoeff_P;
	 int CBP, CBPB=0;
     MB_Structure *recon_data_P; 
     MB_Structure *diff; 
       
	 /* 缓冲器控制变量 */
     float QP_cumulative = (float)0.0;
     int abs_mb_num = 0, QuantChangePostponed = 0;
     int QP_new, QP_prev, dquant, QP_xmitted=QP;
     QP_new = QP_xmitted = QP_prev = QP; /* 复制旧QP */

	 /* 图象插值 */
	 if(!mv_outside_frame)
	 {
	 pi = InterpolateImage(pr->lum,pels,lines);
     prev_ipol = pi;
     prev_recon = pr;
     orig_lum = prev->lum;
	 }
	 
     /* 为每个编码块标记MV */
    for (i = 1; i < (pels>>4)+1; i++) {
      for (k = 0; k < 6; k++) {
        MV[k][0][i] = (MotionVector *)malloc(sizeof(MotionVector));
        MarkVec(MV[k][0][i]);
	  }
      MV[0][0][i]->Mode = MODE_INTRA;
	}
    /* 超出图象边界的MV置为0 */
    for (i = 0; i < (lines>>4)+1; i++) {
      for (k = 0; k < 6; k++) {
        MV[k][i][0] = (MotionVector *)malloc(sizeof(MotionVector));
        ZeroVec(MV[k][i][0]);
        MV[k][i][(pels>>4)+1] = (MotionVector *)malloc(sizeof(MotionVector));
        ZeroVec(MV[k][i][(pels>>4)+1]);
	  }
      MV[0][i][0]->Mode = MODE_INTRA;
      MV[0][i][(pels>>4)+1]->Mode = MODE_INTRA;
	}

	/* 整数和半象素运动估值 */
    MotionEstimatePicture(curr->lum, prev_recon->lum, prev_ipol,
	                    pic->seek_dist, MV, pic->use_gobsync);


    #ifndef OFFLINE_RATE_CONTROL
      if (pic->bit_rate != 0) {
      /* 初始化码率控制 */
      QP_new = InitializeQuantizer(PCT_INTER, (float)pic->bit_rate, 
               (pic->PB ? pic->target_frame_rate/2 : pic->target_frame_rate),
               pic->QP_mean);
      QP_xmitted = QP_prev = QP_new; 
	  }
      else {
      QP_new = QP_xmitted = QP_prev = QP; /* 复制旧 QP */
	  }
    #else
      QP_new = QP_xmitted = QP_prev = QP; /* 复制旧 QP */
    #endif

	dquant = 0; 
	for ( j = 0; j < lines/MB_SIZE; j++) {

    #ifndef OFFLINE_RATE_CONTROL
      if (pic->bit_rate != 0) {

      AddBitsPicture(bits);
      /* 更新QP */      
      QP_new =  UpdateQuantizer(abs_mb_num, pic->QP_mean, PCT_INTER, 
           (float)pic->bit_rate, pels/MB_SIZE, lines/MB_SIZE, 
           bits->total);
	  }
    #endif

      newgob = 0;
      if (j == 0) {
        pic->QUANT = QP;
        bits->header += CountBitsPicture(pic);//计算图象层码字
	  }
      else if (pic->use_gobsync && j%pic->use_gobsync == 0) {
        bits->header += CountBitsSlice(j,QP); //输出GOB同步头
        newgob = 1;
	  }
	  for ( i = 0; i < pels/MB_SIZE; i++) {
	     /* 更新dquant */
         dquant = QP_new - QP_prev;
         if (dquant != 0 && i != 0 && MV[0][j+1][i+1]->Mode == MODE_INTER4V) {
           dquant = 0;
           QP_xmitted = QP_prev;
           QuantChangePostponed = 1;
		 }
         else {
           QP_xmitted = QP_new;
           QuantChangePostponed = 0;
		 }
		 if (dquant > 2)  { dquant =  2; QP_xmitted = QP_prev + dquant;}
         if (dquant < -2) { dquant = -2; QP_xmitted = QP_prev + dquant;}

         pic->DQUANT = dquant;
	
         /* 当dquant != 0,修改宏块类型 (例如 MODE_INTER -> MODE_INTER_Q) */
         Mode = ModifyMode(MV[0][j+1][i+1]->Mode,pic->DQUANT);
         MV[0][j+1][i+1]->Mode = Mode;

		 pic->MB = i + j * (pels/MB_SIZE);

         if (Mode == MODE_INTER || Mode == MODE_INTER_Q || Mode==MODE_INTER4V) {
         /* 预测P-宏块 */
           diff = Predict_P(curr,prev_recon,prev_ipol,
           i*MB_SIZE,j*MB_SIZE,MV,pic->PB);
		 }
         else {
           diff = (MB_Structure *)malloc(sizeof(MB_Structure));
           FillLumBlock(i*MB_SIZE, j*MB_SIZE, curr, diff);//写亮度图像  curr:图像数据 diff:宏块树组
           FillChromBlock(i*MB_SIZE, j*MB_SIZE, curr, diff);//写色度图像
		 }

         /* P或INTRA宏块 */
         qcoeff_P = MB_Encode(diff, QP_xmitted, Mode); //对宏块数据(P块为残差数据)进行DCT变换量化
         CBP = FindCBP(qcoeff_P, Mode, 64); 
         if (CBP == 0 && (Mode == MODE_INTER || Mode == MODE_INTER_Q)) 
           ZeroMBlock(diff); //宏块数据设为0
         else
           MB_Decode(qcoeff_P, diff, QP_xmitted, Mode);//反变换
         recon_data_P = MB_Recon_P(prev_recon, prev_ipol,diff,i*MB_SIZE,j*MB_SIZE,MV,pic->PB);//重建P图象
         Clip(recon_data_P); //使 0<=recon_data_P<=255 
         free(diff);
        
         if(pic->PB==0)
         ZeroVec(MV[5][j+1][i+1]); //PB帧矢量差置为0

		 if ((CBP==0) && (CBPB==0) && 
			 (EqualVec(MV[0][j+1][i+1],&ZERO)) && 
             (EqualVec(MV[5][j+1][i+1],&ZERO)) &&
             (Mode == MODE_INTER || Mode == MODE_INTER_Q)) {
          /* 当 CBP 和 CBPB 为0, 16x16 运动矢量为0,PB矢量差为0,
			 并且编码模式为MODE_INTER或MODE_INTER_Q,跳过该宏块编码*/
         if (!syntax_arith_coding)
             CountBitsMB(Mode,1,CBP,CBPB,pic,bits);//输出宏块层信息
		 }
         else {      /* 正常编码宏块 */
          if (!syntax_arith_coding) { /* VLC */
             CountBitsMB(Mode,0,CBP,CBPB,pic,bits);
            if (Mode == MODE_INTER  || Mode == MODE_INTER_Q) {
             bits->no_inter++;
             CountBitsVectors(MV, bits, i, j, Mode, newgob, pic);//输出运动矢量数据
            }
            else if (Mode == MODE_INTER4V) {
             bits->no_inter4v++;
             CountBitsVectors(MV, bits, i, j, Mode, newgob, pic);
            }
            else {
             /* MODE_INTRA 或 MODE_INTRA_Q */
             bits->no_intra++;
             if (pic->PB)
               CountBitsVectors(MV, bits, i, j, Mode, newgob, pic);
            }
            if (CBP || Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
              CountBitsCoeff(qcoeff_P, Mode, CBP, bits, 64);//输出系数
		  } // end VLC 
         
         QP_prev = QP_xmitted;
		 }//end Normal MB

         abs_mb_num++;
         QP_cumulative += QP_xmitted;     
     
         ReconImage(i,j,recon_data_P,curr_recon);//重建图象
         free(recon_data_P);
         free(qcoeff_P);
	  }//end for i
	}//end for j

  pic->QP_mean = QP_cumulative/(float)abs_mb_num;
  /* 释放内存 */
  free(pi);
  for (j = 0; j < (lines>>4)+1; j++)
    for (i = 0; i < (pels>>4)+2; i++) 
      for (k = 0; k < 6; k++)
        free(MV[k][j][i]);
  return;

}

void ZeroVec(MotionVector *MV)
{
  MV->x = 0;
  MV->y = 0;
  MV->x_half = 0;
  MV->y_half = 0;
  return;
}
void MarkVec(MotionVector *MV)
{
  MV->x = NO_VEC;
  MV->y = NO_VEC;
  MV->x_half = 0;
  MV->y_half = 0;
  return;
}

void CopyVec(MotionVector *MV2, MotionVector *MV1)
{
  MV2->x = MV1->x;
  MV2->x_half = MV1->x_half;
  MV2->y = MV1->y;
  MV2->y_half = MV1->y_half;
  return;
}

int EqualVec(MotionVector *MV2, MotionVector *MV1)
{
  if (MV1->x != MV2->x)
    return 0;
  if (MV1->y != MV2->y)
    return 0;
  if (MV1->x_half != MV2->x_half)
    return 0;
  if (MV1->y_half != MV2->y_half)
    return 0;
  return 1;
}

unsigned char *InterpolateImage(unsigned char *image, int width, int height)
{
  unsigned char *ipol_image, *ii, *oo;
  int i,j;

  ipol_image = (unsigned char *)malloc(sizeof(char)*width*height*4);
  ii = ipol_image;
  oo = image;

  /* main image */
  for (j = 0; j < height-1; j++) {
    for (i = 0; i  < width-1; i++) {
      *(ii + (i<<1)) = *(oo + i);
      *(ii + (i<<1)+1) = (unsigned char)((*(oo + i) + *(oo + i + 1) + 1)>>1); 
      *(ii + (i<<1)+(width<<1)) = (unsigned char)((*(oo + i) + *(oo + i + width) + 1)>>1); 
      *(ii + (i<<1)+1+(width<<1)) = (unsigned char)((*(oo+i) + *(oo+i+1) +
         *(oo+i+width) + *(oo+i+1+width) + 2)>>2);									 
    }
    /* last pels on each line */
    *(ii+ (width<<1) - 2) = *(oo + width - 1);
    *(ii+ (width<<1) - 1) = *(oo + width - 1);
    *(ii+ (width<<1)+ (width<<1)-2) = (unsigned char)((*(oo+width-1)+*(oo+width+width-1)+1)>>1); 
    *(ii+ (width<<1)+ (width<<1)-1) = (unsigned char)((*(oo+width-1)+*(oo+width+width-1)+1)>>1); 
    ii += (width<<2);
    oo += width;
  }

  /* last lines */
  for (i = 0; i < width-1; i++) {
    *(ii+ (i<<1)) = *(oo + i);    
    *(ii+ (i<<1)+1) = (unsigned char)((*(oo + i) + *(oo + i + 1) + 1)>>1);
    *(ii+ (width<<1)+ (i<<1)) = *(oo + i);    
    *(ii+ (width<<1)+ (i<<1)+1) = (unsigned char)((*(oo + i) + *(oo + i + 1) + 1)>>1);
          
  }

  /* bottom right corner pels */
  *(ii + (width<<1) - 2) = *(oo + width -1);
  *(ii + (width<<1) - 1) = *(oo + width -1);
  *(ii + (width<<2) - 2) = *(oo + width -1);
  *(ii + (width<<2) - 1) = *(oo + width -1);

  return ipol_image;
}

void MotionEstimatePicture(unsigned char *curr, unsigned char *prev, 
           unsigned char *prev_ipol, int seek_dist, 
           MotionVector *MV[6][MBR+1][MBC+2], int gobsync)
{
  int i,j,k;
  int pmv0,pmv1,xoff,yoff;
  int curr_mb[16][16];
  int sad8 = INT_MAX, sad16, sad0;
  int newgob;
  MotionVector *f0,*f1,*f2,*f3,*f4;

  /* 运动估计并存储结果MV */
  for ( j = 0; j < lines/MB_SIZE; j++) {

    newgob = 0;
    if (gobsync && j%gobsync == 0) {
      newgob = 1;
    }

    for ( i = 0; i < pels/MB_SIZE; i++) {
      for (k = 0; k < 6; k++)
        MV[k][j+1][i+1] = (MotionVector *)malloc(sizeof(MotionVector));

      /* 整象素搜索 */
      f0 = MV[0][j+1][i+1];
      f1 = MV[1][j+1][i+1];
      f2 = MV[2][j+1][i+1];
      f3 = MV[3][j+1][i+1];
      f4 = MV[4][j+1][i+1];

      FindPMV(MV,i+1,j+1,&pmv0,&pmv1,0,newgob,0);

      if (long_vectors) {
        xoff = pmv0/2; /* 总是能被2整除 */
        yoff = pmv1/2;
      }
      else {
        xoff = yoff = 0;
      }
      
      MotionEstimation(curr, prev, i*MB_SIZE, j*MB_SIZE, 
               xoff, yoff, seek_dist, MV, &sad0);

      sad16 = f0->min_error;
      if (advanced)
        sad8 = f1->min_error + f2->min_error + f3->min_error + f4->min_error;

      f0->Mode = ChooseMode(curr,i*MB_SIZE,j*MB_SIZE, mmin(sad8,sad16));

      /* 半象素精度搜索 */
      if (f0->Mode != MODE_INTRA) {
        FindMB(i*MB_SIZE,j*MB_SIZE ,curr, curr_mb);//当前宏块放入curr_mb
        FindHalfPel(i*MB_SIZE,j*MB_SIZE,f0, prev_ipol, &curr_mb[0][0],16,0);
        sad16 = f0->min_error;

        if (advanced) {
          FindHalfPel(i*MB_SIZE,j*MB_SIZE,f1, prev_ipol, &curr_mb[0][0],8,0);
          FindHalfPel(i*MB_SIZE,j*MB_SIZE,f2, prev_ipol, &curr_mb[0][8],8,1);
          FindHalfPel(i*MB_SIZE,j*MB_SIZE,f3, prev_ipol, &curr_mb[8][0],8,2);
          FindHalfPel(i*MB_SIZE,j*MB_SIZE,f4, prev_ipol, &curr_mb[8][8],8,3);

          sad8 = f1->min_error +f2->min_error +f3->min_error +f4->min_error;
          sad8 += PREF_16_VEC;
          
          /* 选择0运动矢量, 基于8x8或16x16的运动矢量  */
          if (sad0 < sad8 && sad0 < sad16) {
            f0->x = f0->y = 0;
            f0->x_half = f0->y_half = 0;
          }
          else {
            if (sad8 < sad16) 
              f0->Mode = MODE_INTER4V;
          }
        }
        else {
          /* 选择0运动矢量或基于16x16的运动矢量 */
          if (sad0 < sad16) {
            f0->x = f0->y = 0;
            f0->x_half = f0->y_half = 0;
          }
        }

      }
      else 
        for (k = 0; k < 5; k++)
          ZeroVec(MV[k][j+1][i+1]);
    }
  }

  return;
}
           
void ZeroMBlock(MB_Structure *data)
{
  int n;
  register int m;

  for (n = 0; n < MB_SIZE; n++)
    for (m = 0; m < MB_SIZE; m++)
      data->lum[n][m] = 0;
  for (n = 0; n < (MB_SIZE>>1); n++)
    for (m = 0; m < (MB_SIZE>>1); m++) {
      data->Cr[n][m] = 0;
      data->Cb[n][m] = 0;
    }
  return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -