CodeInter.cpp
上传用户:szklck
上传日期:2007-01-22
资源大小:925k
文件大小:12k
源码类别:

图形图像处理

开发平台:

Visual C++

  1. #include"stdafx.h"
  2. #include"Global.h"
  3. /**********************************************************************
  4.  *
  5.  * Name:        CodeOneInter
  6.  * Description: code one image normally or two images
  7.  *                      as a PB-frame (CodeTwoPB and CodeOnePred merged)
  8.  *
  9.  * Input:        pointer to image, prev_image, prev_recon, Q
  10.  *        
  11.  * Returns: pointer to reconstructed image
  12.  * Side effects: memory is allocated to recon image
  13.  *
  14.  ************************************************************************/
  15. void CodeOneInter(PictImage *prev,PictImage *curr,
  16.   PictImage *pr,PictImage *curr_recon,
  17.   int QP, int frameskip, Bits *bits, Pict *pic)
  18. {
  19.  ZeroBits(bits);
  20.  unsigned char *prev_ipol,*pi,*orig_lum;
  21.      PictImage *prev_recon=NULL;
  22.  MotionVector *MV[6][MBR+1][MBC+2]; 
  23.  MotionVector ZERO = {0,0,0,0,0};
  24.  int i,j,k;
  25.  int newgob,Mode;
  26.     int *qcoeff_P;
  27.  int CBP, CBPB=0;
  28.      MB_Structure *recon_data_P; 
  29.      MB_Structure *diff; 
  30.        
  31.  /* 缓冲器控制变量 */
  32.      float QP_cumulative = (float)0.0;
  33.      int abs_mb_num = 0, QuantChangePostponed = 0;
  34.      int QP_new, QP_prev, dquant, QP_xmitted=QP;
  35.      QP_new = QP_xmitted = QP_prev = QP; /* 复制旧QP */
  36.  /* 图象插值 */
  37.  if(!mv_outside_frame)
  38.  {
  39.  pi = InterpolateImage(pr->lum,pels,lines);
  40.      prev_ipol = pi;
  41.      prev_recon = pr;
  42.      orig_lum = prev->lum;
  43.  }
  44.  
  45.      /* 为每个编码块标记MV */
  46.     for (i = 1; i < (pels>>4)+1; i++) {
  47.       for (k = 0; k < 6; k++) {
  48.         MV[k][0][i] = (MotionVector *)malloc(sizeof(MotionVector));
  49.         MarkVec(MV[k][0][i]);
  50.   }
  51.       MV[0][0][i]->Mode = MODE_INTRA;
  52. }
  53.     /* 超出图象边界的MV置为0 */
  54.     for (i = 0; i < (lines>>4)+1; i++) {
  55.       for (k = 0; k < 6; k++) {
  56.         MV[k][i][0] = (MotionVector *)malloc(sizeof(MotionVector));
  57.         ZeroVec(MV[k][i][0]);
  58.         MV[k][i][(pels>>4)+1] = (MotionVector *)malloc(sizeof(MotionVector));
  59.         ZeroVec(MV[k][i][(pels>>4)+1]);
  60.   }
  61.       MV[0][i][0]->Mode = MODE_INTRA;
  62.       MV[0][i][(pels>>4)+1]->Mode = MODE_INTRA;
  63. }
  64. /* 整数和半象素运动估值 */
  65.     MotionEstimatePicture(curr->lum, prev_recon->lum, prev_ipol,
  66.                     pic->seek_dist, MV, pic->use_gobsync);
  67.     #ifndef OFFLINE_RATE_CONTROL
  68.       if (pic->bit_rate != 0) {
  69.       /* 初始化码率控制 */
  70.       QP_new = InitializeQuantizer(PCT_INTER, (float)pic->bit_rate, 
  71.                (pic->PB ? pic->target_frame_rate/2 : pic->target_frame_rate),
  72.                pic->QP_mean);
  73.       QP_xmitted = QP_prev = QP_new; 
  74.   }
  75.       else {
  76.       QP_new = QP_xmitted = QP_prev = QP; /* 复制旧 QP */
  77.   }
  78.     #else
  79.       QP_new = QP_xmitted = QP_prev = QP; /* 复制旧 QP */
  80.     #endif
  81. dquant = 0; 
  82. for ( j = 0; j < lines/MB_SIZE; j++) {
  83.     #ifndef OFFLINE_RATE_CONTROL
  84.       if (pic->bit_rate != 0) {
  85.       AddBitsPicture(bits);
  86.       /* 更新QP */      
  87.       QP_new =  UpdateQuantizer(abs_mb_num, pic->QP_mean, PCT_INTER, 
  88.            (float)pic->bit_rate, pels/MB_SIZE, lines/MB_SIZE, 
  89.            bits->total);
  90.   }
  91.     #endif
  92.       newgob = 0;
  93.       if (j == 0) {
  94.         pic->QUANT = QP;
  95.         bits->header += CountBitsPicture(pic);//计算图象层码字
  96.   }
  97.       else if (pic->use_gobsync && j%pic->use_gobsync == 0) {
  98.         bits->header += CountBitsSlice(j,QP); //输出GOB同步头
  99.         newgob = 1;
  100.   }
  101.   for ( i = 0; i < pels/MB_SIZE; i++) {
  102.      /* 更新dquant */
  103.          dquant = QP_new - QP_prev;
  104.          if (dquant != 0 && i != 0 && MV[0][j+1][i+1]->Mode == MODE_INTER4V) {
  105.            dquant = 0;
  106.            QP_xmitted = QP_prev;
  107.            QuantChangePostponed = 1;
  108.  }
  109.          else {
  110.            QP_xmitted = QP_new;
  111.            QuantChangePostponed = 0;
  112.  }
  113.  if (dquant > 2)  { dquant =  2; QP_xmitted = QP_prev + dquant;}
  114.          if (dquant < -2) { dquant = -2; QP_xmitted = QP_prev + dquant;}
  115.          pic->DQUANT = dquant;
  116.          /* 当dquant != 0,修改宏块类型 (例如 MODE_INTER -> MODE_INTER_Q) */
  117.          Mode = ModifyMode(MV[0][j+1][i+1]->Mode,pic->DQUANT);
  118.          MV[0][j+1][i+1]->Mode = Mode;
  119.  pic->MB = i + j * (pels/MB_SIZE);
  120.          if (Mode == MODE_INTER || Mode == MODE_INTER_Q || Mode==MODE_INTER4V) {
  121.          /* 预测P-宏块 */
  122.            diff = Predict_P(curr,prev_recon,prev_ipol,
  123.            i*MB_SIZE,j*MB_SIZE,MV,pic->PB);
  124.  }
  125.          else {
  126.            diff = (MB_Structure *)malloc(sizeof(MB_Structure));
  127.            FillLumBlock(i*MB_SIZE, j*MB_SIZE, curr, diff);//写亮度图像  curr:图像数据 diff:宏块树组
  128.            FillChromBlock(i*MB_SIZE, j*MB_SIZE, curr, diff);//写色度图像
  129.  }
  130.          /* P或INTRA宏块 */
  131.          qcoeff_P = MB_Encode(diff, QP_xmitted, Mode); //对宏块数据(P块为残差数据)进行DCT变换量化
  132.          CBP = FindCBP(qcoeff_P, Mode, 64); 
  133.          if (CBP == 0 && (Mode == MODE_INTER || Mode == MODE_INTER_Q)) 
  134.            ZeroMBlock(diff); //宏块数据设为0
  135.          else
  136.            MB_Decode(qcoeff_P, diff, QP_xmitted, Mode);//反变换
  137.          recon_data_P = MB_Recon_P(prev_recon, prev_ipol,diff,i*MB_SIZE,j*MB_SIZE,MV,pic->PB);//重建P图象
  138.          Clip(recon_data_P); //使 0<=recon_data_P<=255 
  139.          free(diff);
  140.         
  141.          if(pic->PB==0)
  142.          ZeroVec(MV[5][j+1][i+1]); //PB帧矢量差置为0
  143.  if ((CBP==0) && (CBPB==0) && 
  144.  (EqualVec(MV[0][j+1][i+1],&ZERO)) && 
  145.              (EqualVec(MV[5][j+1][i+1],&ZERO)) &&
  146.              (Mode == MODE_INTER || Mode == MODE_INTER_Q)) {
  147.           /* 当 CBP 和 CBPB 为0, 16x16 运动矢量为0,PB矢量差为0,
  148.  并且编码模式为MODE_INTER或MODE_INTER_Q,跳过该宏块编码*/
  149.          if (!syntax_arith_coding)
  150.              CountBitsMB(Mode,1,CBP,CBPB,pic,bits);//输出宏块层信息
  151.  }
  152.          else {      /* 正常编码宏块 */
  153.           if (!syntax_arith_coding) { /* VLC */
  154.              CountBitsMB(Mode,0,CBP,CBPB,pic,bits);
  155.             if (Mode == MODE_INTER  || Mode == MODE_INTER_Q) {
  156.              bits->no_inter++;
  157.              CountBitsVectors(MV, bits, i, j, Mode, newgob, pic);//输出运动矢量数据
  158.             }
  159.             else if (Mode == MODE_INTER4V) {
  160.              bits->no_inter4v++;
  161.              CountBitsVectors(MV, bits, i, j, Mode, newgob, pic);
  162.             }
  163.             else {
  164.              /* MODE_INTRA 或 MODE_INTRA_Q */
  165.              bits->no_intra++;
  166.              if (pic->PB)
  167.                CountBitsVectors(MV, bits, i, j, Mode, newgob, pic);
  168.             }
  169.             if (CBP || Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
  170.               CountBitsCoeff(qcoeff_P, Mode, CBP, bits, 64);//输出系数
  171.   } // end VLC 
  172.          
  173.          QP_prev = QP_xmitted;
  174.  }//end Normal MB
  175.          abs_mb_num++;
  176.          QP_cumulative += QP_xmitted;     
  177.      
  178.          ReconImage(i,j,recon_data_P,curr_recon);//重建图象
  179.          free(recon_data_P);
  180.          free(qcoeff_P);
  181.   }//end for i
  182. }//end for j
  183.   pic->QP_mean = QP_cumulative/(float)abs_mb_num;
  184.   /* 释放内存 */
  185.   free(pi);
  186.   for (j = 0; j < (lines>>4)+1; j++)
  187.     for (i = 0; i < (pels>>4)+2; i++) 
  188.       for (k = 0; k < 6; k++)
  189.         free(MV[k][j][i]);
  190.   return;
  191. }
  192. void ZeroVec(MotionVector *MV)
  193. {
  194.   MV->x = 0;
  195.   MV->y = 0;
  196.   MV->x_half = 0;
  197.   MV->y_half = 0;
  198.   return;
  199. }
  200. void MarkVec(MotionVector *MV)
  201. {
  202.   MV->x = NO_VEC;
  203.   MV->y = NO_VEC;
  204.   MV->x_half = 0;
  205.   MV->y_half = 0;
  206.   return;
  207. }
  208. void CopyVec(MotionVector *MV2, MotionVector *MV1)
  209. {
  210.   MV2->x = MV1->x;
  211.   MV2->x_half = MV1->x_half;
  212.   MV2->y = MV1->y;
  213.   MV2->y_half = MV1->y_half;
  214.   return;
  215. }
  216. int EqualVec(MotionVector *MV2, MotionVector *MV1)
  217. {
  218.   if (MV1->x != MV2->x)
  219.     return 0;
  220.   if (MV1->y != MV2->y)
  221.     return 0;
  222.   if (MV1->x_half != MV2->x_half)
  223.     return 0;
  224.   if (MV1->y_half != MV2->y_half)
  225.     return 0;
  226.   return 1;
  227. }
  228. unsigned char *InterpolateImage(unsigned char *image, int width, int height)
  229. {
  230.   unsigned char *ipol_image, *ii, *oo;
  231.   int i,j;
  232.   ipol_image = (unsigned char *)malloc(sizeof(char)*width*height*4);
  233.   ii = ipol_image;
  234.   oo = image;
  235.   /* main image */
  236.   for (j = 0; j < height-1; j++) {
  237.     for (i = 0; i  < width-1; i++) {
  238.       *(ii + (i<<1)) = *(oo + i);
  239.       *(ii + (i<<1)+1) = (unsigned char)((*(oo + i) + *(oo + i + 1) + 1)>>1); 
  240.       *(ii + (i<<1)+(width<<1)) = (unsigned char)((*(oo + i) + *(oo + i + width) + 1)>>1); 
  241.       *(ii + (i<<1)+1+(width<<1)) = (unsigned char)((*(oo+i) + *(oo+i+1) +
  242.          *(oo+i+width) + *(oo+i+1+width) + 2)>>2);  
  243.     }
  244.     /* last pels on each line */
  245.     *(ii+ (width<<1) - 2) = *(oo + width - 1);
  246.     *(ii+ (width<<1) - 1) = *(oo + width - 1);
  247.     *(ii+ (width<<1)+ (width<<1)-2) = (unsigned char)((*(oo+width-1)+*(oo+width+width-1)+1)>>1); 
  248.     *(ii+ (width<<1)+ (width<<1)-1) = (unsigned char)((*(oo+width-1)+*(oo+width+width-1)+1)>>1); 
  249.     ii += (width<<2);
  250.     oo += width;
  251.   }
  252.   /* last lines */
  253.   for (i = 0; i < width-1; i++) {
  254.     *(ii+ (i<<1)) = *(oo + i);    
  255.     *(ii+ (i<<1)+1) = (unsigned char)((*(oo + i) + *(oo + i + 1) + 1)>>1);
  256.     *(ii+ (width<<1)+ (i<<1)) = *(oo + i);    
  257.     *(ii+ (width<<1)+ (i<<1)+1) = (unsigned char)((*(oo + i) + *(oo + i + 1) + 1)>>1);
  258.           
  259.   }
  260.   /* bottom right corner pels */
  261.   *(ii + (width<<1) - 2) = *(oo + width -1);
  262.   *(ii + (width<<1) - 1) = *(oo + width -1);
  263.   *(ii + (width<<2) - 2) = *(oo + width -1);
  264.   *(ii + (width<<2) - 1) = *(oo + width -1);
  265.   return ipol_image;
  266. }
  267. void MotionEstimatePicture(unsigned char *curr, unsigned char *prev, 
  268.            unsigned char *prev_ipol, int seek_dist, 
  269.            MotionVector *MV[6][MBR+1][MBC+2], int gobsync)
  270. {
  271.   int i,j,k;
  272.   int pmv0,pmv1,xoff,yoff;
  273.   int curr_mb[16][16];
  274.   int sad8 = INT_MAX, sad16, sad0;
  275.   int newgob;
  276.   MotionVector *f0,*f1,*f2,*f3,*f4;
  277.   /* 运动估计并存储结果MV */
  278.   for ( j = 0; j < lines/MB_SIZE; j++) {
  279.     newgob = 0;
  280.     if (gobsync && j%gobsync == 0) {
  281.       newgob = 1;
  282.     }
  283.     for ( i = 0; i < pels/MB_SIZE; i++) {
  284.       for (k = 0; k < 6; k++)
  285.         MV[k][j+1][i+1] = (MotionVector *)malloc(sizeof(MotionVector));
  286.       /* 整象素搜索 */
  287.       f0 = MV[0][j+1][i+1];
  288.       f1 = MV[1][j+1][i+1];
  289.       f2 = MV[2][j+1][i+1];
  290.       f3 = MV[3][j+1][i+1];
  291.       f4 = MV[4][j+1][i+1];
  292.       FindPMV(MV,i+1,j+1,&pmv0,&pmv1,0,newgob,0);
  293.       if (long_vectors) {
  294.         xoff = pmv0/2; /* 总是能被2整除 */
  295.         yoff = pmv1/2;
  296.       }
  297.       else {
  298.         xoff = yoff = 0;
  299.       }
  300.       
  301.       MotionEstimation(curr, prev, i*MB_SIZE, j*MB_SIZE, 
  302.                xoff, yoff, seek_dist, MV, &sad0);
  303.       sad16 = f0->min_error;
  304.       if (advanced)
  305.         sad8 = f1->min_error + f2->min_error + f3->min_error + f4->min_error;
  306.       f0->Mode = ChooseMode(curr,i*MB_SIZE,j*MB_SIZE, mmin(sad8,sad16));
  307.       /* 半象素精度搜索 */
  308.       if (f0->Mode != MODE_INTRA) {
  309.         FindMB(i*MB_SIZE,j*MB_SIZE ,curr, curr_mb);//当前宏块放入curr_mb
  310.         FindHalfPel(i*MB_SIZE,j*MB_SIZE,f0, prev_ipol, &curr_mb[0][0],16,0);
  311.         sad16 = f0->min_error;
  312.         if (advanced) {
  313.           FindHalfPel(i*MB_SIZE,j*MB_SIZE,f1, prev_ipol, &curr_mb[0][0],8,0);
  314.           FindHalfPel(i*MB_SIZE,j*MB_SIZE,f2, prev_ipol, &curr_mb[0][8],8,1);
  315.           FindHalfPel(i*MB_SIZE,j*MB_SIZE,f3, prev_ipol, &curr_mb[8][0],8,2);
  316.           FindHalfPel(i*MB_SIZE,j*MB_SIZE,f4, prev_ipol, &curr_mb[8][8],8,3);
  317.           sad8 = f1->min_error +f2->min_error +f3->min_error +f4->min_error;
  318.           sad8 += PREF_16_VEC;
  319.           
  320.           /* 选择0运动矢量, 基于8x8或16x16的运动矢量  */
  321.           if (sad0 < sad8 && sad0 < sad16) {
  322.             f0->x = f0->y = 0;
  323.             f0->x_half = f0->y_half = 0;
  324.           }
  325.           else {
  326.             if (sad8 < sad16) 
  327.               f0->Mode = MODE_INTER4V;
  328.           }
  329.         }
  330.         else {
  331.           /* 选择0运动矢量或基于16x16的运动矢量 */
  332.           if (sad0 < sad16) {
  333.             f0->x = f0->y = 0;
  334.             f0->x_half = f0->y_half = 0;
  335.           }
  336.         }
  337.       }
  338.       else 
  339.         for (k = 0; k < 5; k++)
  340.           ZeroVec(MV[k][j+1][i+1]);
  341.     }
  342.   }
  343.   return;
  344. }
  345.            
  346. void ZeroMBlock(MB_Structure *data)
  347. {
  348.   int n;
  349.   register int m;
  350.   for (n = 0; n < MB_SIZE; n++)
  351.     for (m = 0; m < MB_SIZE; m++)
  352.       data->lum[n][m] = 0;
  353.   for (n = 0; n < (MB_SIZE>>1); n++)
  354.     for (m = 0; m < (MB_SIZE>>1); m++) {
  355.       data->Cr[n][m] = 0;
  356.       data->Cb[n][m] = 0;
  357.     }
  358.   return;
  359. }