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

图形图像处理

开发平台:

Visual C++

  1. #include"stdafx.h"
  2. #include"Global.h"
  3. /**********************************************************************
  4.  *
  5.  * Name:        Predict_P
  6.  * Description:    Predicts P macroblock in advanced or normal
  7.  *                      mode
  8.  *
  9.  * Input:        pointers to current and previous frames
  10.  *        and previous interpolated image,
  11.  *                      position and motion vector array
  12.  * Returns: pointer to MB_Structure of data to be coded
  13.  * Side effects: allocates memory to MB_Structure
  14.  *
  15.  *
  16.  ***********************************************************************/
  17. MB_Structure *Predict_P(PictImage *curr_image, PictImage *prev_image,
  18.         unsigned char *prev_ipol, int x, int y, 
  19.         MotionVector *MV[6][MBR+1][MBC+2], int PB)
  20. {
  21.   int m,n;
  22.   int curr[16][16];
  23.   int pred[16][16];
  24.   MotionVector *fr0,*fr1,*fr2,*fr3,*fr4;
  25.   int sum, dx, dy;
  26.   int xmb, ymb;
  27.   MB_Structure *pred_error = (MB_Structure *)malloc(sizeof(MB_Structure));
  28.     
  29.   xmb = x/MB_SIZE+1;
  30.   ymb = y/MB_SIZE+1;
  31.   fr0 = MV[0][ymb][xmb];
  32.   fr1 = MV[1][ymb][xmb];
  33.   fr2 = MV[2][ymb][xmb];
  34.   fr3 = MV[3][ymb][xmb];
  35.   fr4 = MV[4][ymb][xmb];
  36.   /* 装入当前宏块到curr */
  37.   FindMB(x, y, curr_image->lum, curr);
  38.   /* 基于半象素MV预测当前块 */
  39.   if (advanced) {
  40.     FindPredOBMC(x, y, MV, prev_ipol, &pred[0][0], 0, PB);
  41.     FindPredOBMC(x, y, MV, prev_ipol, &pred[0][8], 1, PB);
  42.     FindPredOBMC(x, y, MV, prev_ipol, &pred[8][0], 2, PB);
  43.     FindPredOBMC(x, y, MV, prev_ipol, &pred[8][8], 3, PB);
  44.   }
  45.   else 
  46.     FindPred(x, y, fr0, prev_ipol, &pred[0][0], 16, 0);
  47.   /* 进行预测 */
  48.   if (fr0->Mode == MODE_INTER || fr0->Mode == MODE_INTER_Q) {
  49.     for (n = 0; n < MB_SIZE; n++)
  50.       for (m = 0; m < MB_SIZE; m++) 
  51.         pred_error->lum[n][m] = (int)(curr[n][m] - pred[n][m]);
  52.     dx = 2*fr0->x + fr0->x_half;
  53.     dy = 2*fr0->y + fr0->y_half;
  54.     dx = ( dx % 4 == 0 ? dx >> 1 : (dx>>1)|1 );
  55.     dy = ( dy % 4 == 0 ? dy >> 1 : (dy>>1)|1 );
  56.     DoPredChrom_P(x, y, dx, dy, curr_image, prev_image, pred_error);
  57.   }
  58.   else if (fr0->Mode == MODE_INTER4V) {
  59.     for (n = 0; n < MB_SIZE; n++)
  60.       for (m = 0; m < MB_SIZE; m++) 
  61.         pred_error->lum[n][m] = (int)(curr[n][m] - pred[n][m]);
  62.     sum = 2*fr1->x + fr1->x_half + 2*fr2->x + fr2->x_half +
  63.       2*fr3->x + fr3->x_half + 2*fr4->x + fr4->x_half ; 
  64.     dx = sign(sum)*(roundtab[abs(sum)%16] + (abs(sum)/16)*2);
  65.     sum = 2*fr1->y + fr1->y_half + 2*fr2->y + fr2->y_half +
  66.       2*fr3->y + fr3->y_half + 2*fr4->y + fr4->y_half;
  67.     dy = sign(sum)*(roundtab[abs(sum)%16] + (abs(sum)/16)*2);
  68.     DoPredChrom_P(x, y, dx, dy, curr_image, prev_image, pred_error);
  69.   }
  70.   else
  71.     fprintf(stderr,"Illegal Mode in Predict_P (pred.c)n");
  72.   return pred_error;
  73. }
  74. /***********************************************************************
  75.  *
  76.  * Name:        Predict_B
  77.  * Description:    Predicts the B macroblock in PB-frame prediction
  78.  *
  79.  * Input:         pointers to current frame, previous recon. frame,
  80.  *                      pos. in image, MV-data, reconstructed macroblock
  81.  *                      from image ahead
  82.  * Returns:        pointer to differential MB data after prediction
  83.  * Side effects:   allocates memory to MB_structure
  84.  *
  85.  *
  86.  ***********************************************************************/
  87. MB_Structure *Predict_B(PictImage *curr_image, PictImage *prev_image,
  88.         unsigned char *prev_ipol,int x, int y,
  89.         MotionVector *MV[5][MBR+1][MBC+2],
  90.         MB_Structure *recon_P, int TRD,int TRB)
  91. {
  92.   int i,j,k;
  93.   int dx, dy, sad, sad_min=INT_MAX, curr[16][16], bdx=0, bdy=0;
  94.   MB_Structure *p_err = (MB_Structure *)malloc(sizeof(MB_Structure));
  95.   MB_Structure *pred = (MB_Structure *)malloc(sizeof(MB_Structure));
  96.   MotionVector *f[5];
  97.   int xvec, yvec, mvx, mvy;
  98.   for (k = 0; k <= 4; k++)
  99.     f[k] = MV[k][y/MB_SIZE+1][x/MB_SIZE+1];
  100.   /* Find MB in current image */
  101.   FindMB(x, y, curr_image->lum, curr);
  102.   if (f[0]->Mode == MODE_INTER4V) {  /* Mode INTER4V */
  103.     /* Find forward prediction */
  104.     /* Luma */
  105.     for (j = -DEF_PBDELTA_WIN; j <= DEF_PBDELTA_WIN; j++) {
  106.       for (i = -DEF_PBDELTA_WIN; i <= DEF_PBDELTA_WIN; i++) {
  107.         FindForwLumPredPB(prev_ipol, x, y, f[1], &pred->lum[0][0], 
  108.           TRD, TRB, i, j, 8, 0);
  109.         FindForwLumPredPB(prev_ipol, x, y, f[2], &pred->lum[0][8], 
  110.           TRD, TRB, i, j, 8, 1);
  111.         FindForwLumPredPB(prev_ipol, x, y, f[3], &pred->lum[8][0], 
  112.           TRD, TRB, i, j, 8, 2);
  113.         FindForwLumPredPB(prev_ipol, x, y, f[4], &pred->lum[8][8], 
  114.           TRD, TRB, i, j, 8, 3);
  115.         sad = SAD_MB_integer(&curr[0][0],&pred->lum[0][0], 16,INT_MAX);
  116.         if (i == 0 && j == 0)
  117.           sad -= PREF_PBDELTA_NULL_VEC;
  118.         if (sad < sad_min) {
  119.           sad_min = sad;
  120.           bdx = i;
  121.           bdy = j;
  122.         }
  123.       }
  124.     }
  125.     FindForwLumPredPB(prev_ipol,x,y,f[1],&pred->lum[0][0],TRD,TRB,bdx,bdy,8,0);
  126.     FindForwLumPredPB(prev_ipol,x,y,f[2],&pred->lum[0][8],TRD,TRB,bdx,bdy,8,1);
  127.     FindForwLumPredPB(prev_ipol,x,y,f[3],&pred->lum[8][0],TRD,TRB,bdx,bdy,8,2);
  128.     FindForwLumPredPB(prev_ipol,x,y,f[4],&pred->lum[8][8],TRD,TRB,bdx,bdy,8,3);
  129.     /* chroma vectors are sum of B luma vectors divided and rounded */
  130.     xvec = yvec = 0;
  131.     for (k = 1; k <= 4; k++) {
  132.       xvec += TRB*(2*f[k]->x + f[k]->x_half)/TRD + bdx;
  133.       yvec += TRB*(2*f[k]->y + f[k]->y_half)/TRD + bdy;
  134.     }
  135.     /* round values according to TABLE 16/H.263 */
  136.     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
  137.     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
  138.     FindChromBlock_P(x, y, dx, dy, prev_image, pred);
  139.     /* Find bidirectional prediction */
  140.     FindBiDirLumPredPB(&recon_P->lum[0][0], f[1], &pred->lum[0][0], 
  141.                TRD, TRB, bdx, bdy, 0, 0);
  142.     FindBiDirLumPredPB(&recon_P->lum[0][8], f[2], &pred->lum[0][8], 
  143.                TRD, TRB, bdx, bdy, 1, 0);
  144.     FindBiDirLumPredPB(&recon_P->lum[8][0], f[3], &pred->lum[8][0], 
  145.                TRD, TRB, bdx, bdy, 0, 1);
  146.     FindBiDirLumPredPB(&recon_P->lum[8][8], f[4], &pred->lum[8][8], 
  147.                TRD, TRB, bdx, bdy, 1, 1);
  148.     /* chroma vectors are sum of B luma vectors divided and rounded */
  149.     xvec = yvec = 0;
  150.     for (k = 1; k <= 4; k++) {
  151.       mvx = 2*f[k]->x + f[k]->x_half;
  152.       mvy = 2*f[k]->y + f[k]->y_half;
  153.       xvec += bdx == 0 ? (TRB-TRD) *  mvx / TRD : TRB * mvx / TRD + bdx - mvx;
  154.       yvec += bdy == 0 ? (TRB-TRD) *  mvy / TRD : TRB * mvy / TRD + bdy - mvy;
  155.     }
  156.     /* round values according to TABLE 16/H.263 */
  157.     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
  158.     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
  159.     FindBiDirChrPredPB(recon_P, dx, dy, pred); 
  160.   }
  161.   else {  /* Mode INTER or INTER_Q */
  162.     /* Find forward prediction */
  163.     for (j = -DEF_PBDELTA_WIN; j <= DEF_PBDELTA_WIN; j++) {
  164.       for (i = -DEF_PBDELTA_WIN; i <= DEF_PBDELTA_WIN; i++) {
  165.         dx = i; dy = j;
  166.         /* To keep things simple I turn off PB delta vectors at the edges */
  167.         if (!mv_outside_frame) {
  168.           if (x == 0) dx = 0;
  169.           if (x == pels - MB_SIZE) dx = 0;
  170.           if (y == 0) dy = 0;
  171.           if (y == lines - MB_SIZE) dy = 0;
  172.         }
  173.         if (f[0]->Mode == MODE_INTRA || f[0]->Mode == MODE_INTRA_Q) {
  174.           dx = dy = 0;
  175.         }
  176.         if (f[0]->x == 0 && f[0]->y == 0 && 
  177.             f[0]->x_half == 0 && f[0]->y_half == 0) {
  178.           dx = dy = 0;
  179.         }
  180.         FindForwLumPredPB(prev_ipol, x, y, f[0], &pred->lum[0][0], 
  181.           TRD, TRB, dx, dy, 16, 0);
  182.         sad = SAD_MB_integer(&curr[0][0],&pred->lum[0][0], 16, INT_MAX);
  183.         if (i == 0 && j == 0)
  184.           sad -= PREF_PBDELTA_NULL_VEC;
  185.         if (sad < sad_min) {
  186.           sad_min = sad;
  187.           bdx = dx;
  188.           bdy = dy;
  189.         }
  190.       }
  191.     }
  192.     FindForwLumPredPB(prev_ipol,x,y,f[0],&pred->lum[0][0],TRD,TRB,
  193.               bdx,bdy,16,0);
  194.     xvec = 4 * (TRB*(2*f[0]->x + f[0]->x_half) / TRD + bdx);
  195.     yvec = 4 * (TRB*(2*f[0]->y + f[0]->y_half) / TRD + bdy);
  196.     /* round values according to TABLE 16/H.263 */
  197.     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
  198.     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
  199.     FindChromBlock_P(x, y, dx, dy, prev_image, pred);
  200.     /* Find bidirectional prediction */
  201.     FindBiDirLumPredPB(&recon_P->lum[0][0], f[0], &pred->lum[0][0], 
  202.                TRD, TRB, bdx, bdy, 0, 0);
  203.     FindBiDirLumPredPB(&recon_P->lum[0][8], f[0], &pred->lum[0][8], 
  204.                TRD, TRB, bdx, bdy, 1, 0);
  205.     FindBiDirLumPredPB(&recon_P->lum[8][0], f[0], &pred->lum[8][0], 
  206.                TRD, TRB, bdx, bdy, 0, 1);
  207.     FindBiDirLumPredPB(&recon_P->lum[8][8], f[0], &pred->lum[8][8], 
  208.                TRD, TRB, bdx, bdy, 1, 1);
  209.     /* chroma vectors */
  210.     mvx = 2*f[0]->x + f[0]->x_half;
  211.     xvec = bdx == 0 ? (TRB-TRD) * mvx / TRD : TRB * mvx / TRD + bdx - mvx;
  212.     xvec *= 4;
  213.     mvy = 2*f[0]->y + f[0]->y_half;
  214.     yvec = bdy == 0 ? (TRB-TRD) * mvy / TRD : TRB * mvy / TRD + bdy - mvy;
  215.     yvec *= 4;
  216.       
  217.     /* round values according to TABLE 16/H.263 */
  218.     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
  219.     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
  220.     FindBiDirChrPredPB(recon_P, dx, dy, pred); 
  221.   }
  222.   /* store PB-deltas */
  223.   MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->x = bdx; /* is in half pel format */
  224.   MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->y = bdy;
  225.   MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->x_half = 0;
  226.   MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->y_half = 0;
  227.   /* Do the actual prediction */
  228.   for (j = 0; j < MB_SIZE; j++) 
  229.     for (i = 0; i < MB_SIZE; i++) 
  230.       p_err->lum[j][i] = 
  231.         *(curr_image->lum+x+i + (y+j)*pels) - pred->lum[j][i];
  232.   y >>= 1;
  233.   x >>= 1;
  234.   for (j = 0; j < (MB_SIZE>>1); j++)
  235.     for (i = 0; i < (MB_SIZE>>1); i++) {
  236.       p_err->Cr[j][i] = *(curr_image->Cr+x+i + (y+j)*cpels) - pred->Cr[j][i];
  237.       p_err->Cb[j][i] = *(curr_image->Cb+x+i + (y+j)*cpels) - pred->Cb[j][i];
  238.     }
  239.   free(pred);
  240.   return p_err;
  241. }
  242. /***********************************************************************
  243.  *
  244.  * Name:        MB_Recon_B
  245.  * Description:    Reconstructs the B macroblock in PB-frame
  246.  *                      prediction
  247.  *
  248.  * Input:         pointers previous recon. frame, pred. diff.,
  249.  *                      pos. in image, MV-data, reconstructed macroblock
  250.  *                      from image ahead
  251.  * Returns:        pointer to reconstructed MB data 
  252.  * Side effects:   allocates memory to MB_structure
  253.  *
  254.  *
  255.  ***********************************************************************/
  256. MB_Structure* MB_Recon_B(PictImage* prev_image, 
  257. MB_Structure *diff, 
  258.           unsigned char *prev_ipol, 
  259.                int x, int y,    
  260.           MotionVector *MV[5][MBR+1][MBC+2], 
  261.           MB_Structure *recon_P, 
  262.                int TRD, int TRB)
  263. {
  264.   int i,j,k;
  265.   int dx, dy, bdx, bdy, mvx, mvy, xvec, yvec;
  266.   MB_Structure *recon_B = (MB_Structure *)malloc(sizeof(MB_Structure));
  267.   MB_Structure *pred = (MB_Structure *)malloc(sizeof(MB_Structure));
  268.   MotionVector *f[5];
  269.   for (k = 0; k <= 4; k++)
  270.     f[k] = MV[k][y/MB_SIZE+1][x/MB_SIZE+1];
  271.   bdx = MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->x;
  272.   bdy = MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->y;
  273.   if (f[0]->Mode == MODE_INTER4V) {  /* Mode INTER4V */
  274.     /* Find forward prediction */
  275.     /* Luma */
  276.     FindForwLumPredPB(prev_ipol,x,y,f[1],&pred->lum[0][0],TRD,TRB,bdx,bdy,8,0);
  277.     FindForwLumPredPB(prev_ipol,x,y,f[2],&pred->lum[0][8],TRD,TRB,bdx,bdy,8,1);
  278.     FindForwLumPredPB(prev_ipol,x,y,f[3],&pred->lum[8][0],TRD,TRB,bdx,bdy,8,2);
  279.     FindForwLumPredPB(prev_ipol,x,y,f[4],&pred->lum[8][8],TRD,TRB,bdx,bdy,8,3);
  280.     /* chroma vectors are sum of B luma vectors divided and rounded */
  281.     xvec = yvec = 0;
  282.     for (k = 1; k <= 4; k++) {
  283.       xvec += TRB*(2*f[k]->x + f[k]->x_half)/TRD + bdx;
  284.       yvec += TRB*(2*f[k]->y + f[k]->y_half)/TRD + bdy;
  285.     }
  286.     /* round values according to TABLE 16/H.263 */
  287.     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
  288.     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
  289.     FindChromBlock_P(x, y, dx, dy, prev_image, pred);
  290.     /* Find bidirectional prediction */
  291.     FindBiDirLumPredPB(&recon_P->lum[0][0], f[1], &pred->lum[0][0], 
  292.                TRD, TRB, bdx, bdy, 0, 0);
  293.     FindBiDirLumPredPB(&recon_P->lum[0][8], f[2], &pred->lum[0][8], 
  294.                TRD, TRB, bdx, bdy, 1, 0);
  295.     FindBiDirLumPredPB(&recon_P->lum[8][0], f[3], &pred->lum[8][0], 
  296.                TRD, TRB, bdx, bdy, 0, 1);
  297.     FindBiDirLumPredPB(&recon_P->lum[8][8], f[4], &pred->lum[8][8], 
  298.                TRD, TRB, bdx, bdy, 1, 1);
  299.     /* chroma vectors are sum of B luma vectors divided and rounded */
  300.     xvec = yvec = 0;
  301.     for (k = 1; k <= 4; k++) {
  302.       mvx = 2*f[k]->x + f[k]->x_half;
  303.       mvy = 2*f[k]->y + f[k]->y_half;
  304.       xvec += bdx == 0 ? (TRB-TRD) *  mvx / TRD : TRB * mvx / TRD + bdx - mvx;
  305.       yvec += bdy == 0 ? (TRB-TRD) *  mvy / TRD : TRB * mvy / TRD + bdy - mvy;
  306.     }
  307.     /* round values according to TABLE 16/H.263 */
  308.     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
  309.     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
  310.     FindBiDirChrPredPB(recon_P, dx, dy, pred); 
  311.   }
  312.   else {  /* Mode INTER or INTER_Q */
  313.     /* Find forward prediction */
  314.     
  315.     FindForwLumPredPB(prev_ipol,x,y,f[0],&pred->lum[0][0],TRD,TRB,
  316.               bdx,bdy,16,0);
  317.     xvec = 4 * (TRB*(2*f[0]->x + f[0]->x_half) / TRD + bdx);
  318.     yvec = 4 * (TRB*(2*f[0]->y + f[0]->y_half) / TRD + bdy);
  319.     /* round values according to TABLE 16/H.263 */
  320.     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
  321.     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
  322.     FindChromBlock_P(x, y, dx, dy, prev_image, pred);
  323.     /* Find bidirectional prediction */
  324.     FindBiDirLumPredPB(&recon_P->lum[0][0], f[0], &pred->lum[0][0], 
  325.                TRD, TRB, bdx, bdy, 0, 0);
  326.     FindBiDirLumPredPB(&recon_P->lum[0][8], f[0], &pred->lum[0][8], 
  327.                TRD, TRB, bdx, bdy, 1, 0);
  328.     FindBiDirLumPredPB(&recon_P->lum[8][0], f[0], &pred->lum[8][0], 
  329.                TRD, TRB, bdx, bdy, 0, 1);
  330.     FindBiDirLumPredPB(&recon_P->lum[8][8], f[0], &pred->lum[8][8], 
  331.                TRD, TRB, bdx, bdy, 1, 1);
  332.     /* chroma vectors */
  333.     mvx = 2*f[0]->x + f[0]->x_half;
  334.     xvec = bdx == 0 ? (TRB-TRD) * mvx / TRD : TRB * mvx / TRD + bdx - mvx;
  335.     xvec *= 4;
  336.     mvy = 2*f[0]->y + f[0]->y_half;
  337.     yvec = bdy == 0 ? (TRB-TRD) * mvy / TRD : TRB * mvy / TRD + bdy - mvy;
  338.     yvec *= 4;
  339.       
  340.     /* round values according to TABLE 16/H.263 */
  341.     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
  342.     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
  343.     FindBiDirChrPredPB(recon_P, dx, dy, pred); 
  344.   }
  345.   /* Reconstruction */
  346.   for (j = 0; j < MB_SIZE; j++) 
  347.     for (i = 0; i < MB_SIZE; i++) 
  348.       recon_B->lum[j][i] = pred->lum[j][i] + diff->lum[j][i];
  349.         
  350.   for (j = 0; j < (MB_SIZE>>1); j++)
  351.     for (i = 0; i < (MB_SIZE>>1); i++) {
  352.       recon_B->Cr[j][i] = pred->Cr[j][i] + diff->Cr[j][i];
  353.       recon_B->Cb[j][i] = pred->Cb[j][i] + diff->Cb[j][i];
  354.     }
  355.   
  356.   free(pred);
  357.   return recon_B;
  358. }
  359. /**********************************************************************
  360.  *
  361.  * Name:        FindForwLumPredPB
  362.  * Description:   Finds the forward luma  prediction in PB-frame 
  363.  *                     pred.
  364.  *
  365.  * Input:        pointer to prev. recon. frame, current positon,
  366.  *                     MV structure and pred. structure to fill
  367.  *
  368.  *
  369.  ***********************************************************************/
  370. void FindForwLumPredPB(unsigned char *prev_ipol, int x_curr, int y_curr, 
  371.                MotionVector *fr, int *pred, int TRD, int TRB, 
  372.                int bdx, int bdy, int bs, int comp)
  373. {
  374.   int i,j;
  375.   int xvec,yvec,lx;
  376.   lx = (mv_outside_frame ? pels + (long_vectors?64:32) : pels);
  377.   /* Luma */
  378.   xvec = (TRB)*(2*fr->x + fr->x_half)/TRD + bdx;
  379.   yvec = (TRB)*(2*fr->y + fr->y_half)/TRD + bdy;
  380.   x_curr += ((comp&1)<<3);
  381.   y_curr += ((comp&2)<<2);
  382.   for (j = 0; j < bs; j++) {
  383.     for (i = 0; i < bs; i++) {
  384.       *(pred+i+j*16) = *(prev_ipol + (i+x_curr)*2 + xvec +
  385.          ((j+y_curr)*2 + yvec)*lx*2);
  386.     }
  387.   }
  388.   return;
  389. }
  390. /**********************************************************************
  391.  *
  392.  * Name:        FindBiDirLumPredPB
  393.  * Description:   Finds the bi-dir. luma prediction in PB-frame 
  394.  *                     prediction
  395.  *
  396.  * Input:        pointer to future recon. data, current positon,
  397.  *                     MV structure and pred. structure to fill
  398.  *
  399.  *
  400.  ***********************************************************************/
  401. void FindBiDirLumPredPB(int *recon_P, MotionVector *fr, int *pred, int TRD, 
  402.         int TRB, int bdx, int bdy, int nh, int nv)
  403. {
  404.   int xstart,xstop,ystart,ystop;
  405.   int xvec,yvec, mvx, mvy;
  406.   mvx = 2*fr->x + fr->x_half;
  407.   mvy = 2*fr->y + fr->y_half;
  408.   xvec = (bdx == 0 ? (TRB-TRD) *  mvx / TRD : TRB * mvx / TRD + bdx - mvx);
  409.   yvec = (bdy == 0 ? (TRB-TRD) *  mvy / TRD : TRB * mvy / TRD + bdy - mvy);
  410.   /* Luma */
  411.   FindBiDirLimits(xvec,&xstart,&xstop,nh);
  412.   FindBiDirLimits(yvec,&ystart,&ystop,nv);
  413.   BiDirPredBlock(xstart,xstop,ystart,ystop,xvec,yvec, recon_P,pred,16);
  414.   return;
  415. }
  416. /**********************************************************************
  417.  *
  418.  * Name:        FindBiDirChrPredPB
  419.  * Description:   Finds the bi-dir. chroma prediction in PB-frame 
  420.  *                     prediction
  421.  *
  422.  * Input:        pointer to future recon. data, current positon,
  423.  *                     MV structure and pred. structure to fill
  424.  *
  425.  *
  426.  ***********************************************************************/
  427. void FindBiDirChrPredPB(MB_Structure *recon_P, int dx, int dy, 
  428.         MB_Structure *pred)
  429. {
  430.   int xstart,xstop,ystart,ystop;
  431.   FindBiDirChromaLimits(dx,&xstart,&xstop);
  432.   FindBiDirChromaLimits(dy,&ystart,&ystop);
  433.   BiDirPredBlock(xstart,xstop,ystart,ystop,dx,dy,
  434.          &recon_P->Cb[0][0], &pred->Cb[0][0],8);
  435.   BiDirPredBlock(xstart,xstop,ystart,ystop,dx,dy,
  436.          &recon_P->Cr[0][0], &pred->Cr[0][0],8);
  437.   return;
  438. }
  439. void FindBiDirLimits(int vec, int *start, int *stop, int nhv)
  440. {
  441.   /* limits taken from C loop in section G5 in H.263 */
  442.   *start = mmax(0,(-vec+1)/2 - nhv*8);
  443.   *stop = mmin(7,15-(vec+1)/2 - nhv*8);
  444.   return;
  445. }
  446.   
  447. void FindBiDirChromaLimits(int vec, int *start, int *stop)
  448. {
  449.   /* limits taken from C loop in section G5 in H.263 */
  450.   *start = mmax(0,(-vec+1)/2);
  451.   *stop = mmin(7,7-(vec+1)/2);
  452.   return;
  453. }
  454. void BiDirPredBlock(int xstart, int xstop, int ystart, int ystop,
  455.             int xvec, int yvec, int *recon, int *pred, int bl)
  456. {
  457.   int i,j,pel;
  458.   int xint, yint;
  459.   int xh, yh;
  460.   xint = xvec>>1;
  461.   xh = xvec - 2*xint;
  462.   yint = yvec>>1;
  463.   yh = yvec - 2*yint;
  464.   if (!xh && !yh) {
  465.     for (j = ystart; j <= ystop; j++) {
  466.       for (i = xstart; i <= xstop; i++) {
  467.         pel = *(recon +(j+yint)*bl + i+xint);
  468.         *(pred + j*bl + i) = (mmin(255,mmax(0,pel)) + *(pred + j*bl + i))>>1;
  469.       }
  470.     }
  471.   }
  472.   else if (!xh && yh) {
  473.     for (j = ystart; j <= ystop; j++) {
  474.       for (i = xstart; i <= xstop; i++) {
  475.         pel = (*(recon +(j+yint)*bl + i+xint)       + 
  476.                *(recon +(j+yint+yh)*bl + i+xint) + 1)>>1;
  477.         *(pred + j*bl + i) = (pel + *(pred + j*bl + i))>>1;
  478.       }
  479.     }
  480.   }
  481.   else if (xh && !yh) {
  482.     for (j = ystart; j <= ystop; j++) {
  483.       for (i = xstart; i <= xstop; i++) {
  484.         pel = (*(recon +(j+yint)*bl + i+xint)       + 
  485.                *(recon +(j+yint)*bl + i+xint+xh) + 1)>>1;
  486.         *(pred + j*bl + i) = (pel + *(pred + j*bl + i))>>1;
  487.       }
  488.     }
  489.   }
  490.   else { /* xh && yh */
  491.     for (j = ystart; j <= ystop; j++) {
  492.       for (i = xstart; i <= xstop; i++) {
  493.         pel = (*(recon +(j+yint)*bl + i+xint)       + 
  494.                *(recon +(j+yint+yh)*bl + i+xint) + 
  495.                *(recon +(j+yint)*bl + i+xint+xh) + 
  496.                *(recon +(j+yint+yh)*bl + i+xint+xh)+2)>>2;
  497.         *(pred + j*bl + i) = (pel + *(pred + j*bl + i))>>1;
  498.       }
  499.     }
  500.   }
  501.   return;
  502. }
  503. /**********************************************************************
  504.  *
  505.  * Name:        DoPredChrom_P
  506.  * Description: Does the chrominance prediction for P-frames
  507.  *
  508.  * Input:        motionvectors for each field,
  509.  *        current position in image,
  510.  *        pointers to current and previos image,
  511.  *        pointer to pred_error array,
  512.  *        (int) field: 1 if field coding
  513.  *        
  514.  * Side effects: fills chrom-array in pred_error structure
  515.  *
  516.  *
  517.  ***********************************************************************/
  518. void DoPredChrom_P(int x_curr, int y_curr, int dx, int dy,
  519.            PictImage *curr, PictImage *prev, 
  520.            MB_Structure *pred_error)
  521. {
  522.   int m,n;
  523.   int x, y, ofx, ofy, pel, lx;
  524.   int xint, yint;
  525.   int xh, yh;
  526.   lx = (mv_outside_frame ? pels/2 + (long_vectors?32:16) : pels/2);
  527.   x = x_curr>>1;
  528.   y = y_curr>>1;
  529.   xint = dx>>1;
  530.   xh = dx & 1;
  531.   yint = dy>>1;
  532.   yh = dy & 1;
  533.   if (!xh && !yh) {
  534.     for (n = 0; n < 8; n++) {
  535.       for (m = 0; m < 8; m++) {
  536.         ofx = x + xint + m;
  537.         ofy = y + yint + n;
  538.         pel=*(prev->Cr+ofx    + (ofy   )*lx);
  539.         pred_error->Cr[n][m] = (int)(*(curr->Cr + x+m + (y+n)*cpels) - pel);
  540.         pel=*(prev->Cb+ofx    + (ofy   )*lx);
  541.         pred_error->Cb[n][m] = (int)(*(curr->Cb + x+m + (y+n)*cpels) - pel);
  542.       }
  543.     }
  544.   }
  545.   else if (!xh && yh) {
  546.     for (n = 0; n < 8; n++) {
  547.       for (m = 0; m < 8; m++) {
  548.         ofx = x + xint + m;
  549.         ofy = y + yint + n;
  550.         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
  551.              *(prev->Cr+ofx    + (ofy+yh)*lx) + 1)>>1;
  552.         pred_error->Cr[n][m] = 
  553.           (int)(*(curr->Cr + x+m + (y+n)*cpels) - pel);
  554.         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
  555.              *(prev->Cb+ofx    + (ofy+yh)*lx) + 1)>>1;
  556.         pred_error->Cb[n][m] = 
  557.           (int)(*(curr->Cb + x+m + (y+n)*cpels) - pel);
  558.       
  559.       }
  560.     }
  561.   }
  562.   else if (xh && !yh) {
  563.     for (n = 0; n < 8; n++) {
  564.       for (m = 0; m < 8; m++) {
  565.         ofx = x + xint + m;
  566.         ofy = y + yint + n;
  567.         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
  568.              *(prev->Cr+ofx+xh + (ofy   )*lx) + 1)>>1;
  569.         pred_error->Cr[n][m] = 
  570.           (int)(*(curr->Cr + x+m + (y+n)*cpels) - pel);
  571.         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
  572.              *(prev->Cb+ofx+xh + (ofy   )*lx) + 1)>>1;
  573.         pred_error->Cb[n][m] = 
  574.           (int)(*(curr->Cb + x+m + (y+n)*cpels) - pel);
  575.       
  576.       }
  577.     }
  578.   }
  579.   else { /* xh && yh */
  580.     for (n = 0; n < 8; n++) {
  581.       for (m = 0; m < 8; m++) {
  582.         ofx = x + xint + m;
  583.         ofy = y + yint + n;
  584.         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
  585.              *(prev->Cr+ofx+xh + (ofy   )*lx)+
  586.              *(prev->Cr+ofx    + (ofy+yh)*lx)+
  587.              *(prev->Cr+ofx+xh + (ofy+yh)*lx)+
  588.              2)>>2;
  589.         pred_error->Cr[n][m] = 
  590.           (int)(*(curr->Cr + x+m + (y+n)*cpels) - pel);
  591.         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
  592.              *(prev->Cb+ofx+xh + (ofy   )*lx)+
  593.              *(prev->Cb+ofx    + (ofy+yh)*lx)+
  594.              *(prev->Cb+ofx+xh + (ofy+yh)*lx)+
  595.              2)>>2;
  596.         pred_error->Cb[n][m] = 
  597.           (int)(*(curr->Cb + x+m + (y+n)*cpels) - pel);
  598.       
  599.       }
  600.     }
  601.   }
  602.   return;
  603. }
  604. /**********************************************************************
  605.  *
  606.  * Name:        FindHalfPel
  607.  * Description: Find the optimal half pel prediction
  608.  *
  609.  * Input:        position, vector, array with current data
  610.  *        pointer to previous interpolated luminance,
  611.  *
  612.  * Returns:
  613.  *
  614.  *            950208    Mod: Karl.Lillevold@nta.no
  615.  *
  616.  ***********************************************************************/
  617. void FindHalfPel(int x, int y, MotionVector *fr, unsigned char *prev, 
  618.          int *curr, int bs, int comp)
  619. {
  620.   int i, m, n;
  621.   int half_pel;
  622.   int start_x, start_y, stop_x, stop_y, new_x, new_y, lx;
  623.   int min_pos;
  624.   int AE, AE_min;
  625.   CPoint search[9];
  626.   start_x = -1;
  627.   stop_x = 1;
  628.   start_y = -1;
  629.   stop_y = 1;
  630.   new_x = x + fr->x;
  631.   new_y = y + fr->y;
  632.   new_x += ((comp&1)<<3);
  633.   new_y += ((comp&2)<<2);
  634.   lx = (mv_outside_frame ? pels + (long_vectors?64:32) : pels);
  635.   if (!mv_outside_frame) {
  636.     if ((new_x) <= 0) 
  637.       start_x = 0;
  638.     if ((new_y) <= 0) 
  639.       start_y = 0;
  640.     if ((new_x) >= (pels-bs)) 
  641.       stop_x = 0;
  642.     if ((new_y) >= (lines-bs)) 
  643.       stop_y = 0;
  644.   }
  645.   search[0].x = 0;             search[0].y = 0;
  646.   search[1].x = start_x;       search[1].y = start_y; /*   1 2 3   */
  647.   search[2].x = 0;             search[2].y = start_y; /*   4 0 5   */
  648.   search[3].x = stop_x;        search[3].y = start_y; /*   6 7 8   */
  649.   search[4].x = start_x;       search[4].y = 0;
  650.   search[5].x = stop_x;        search[5].y = 0;
  651.   search[6].x = start_x;       search[6].y = stop_y;
  652.   search[7].x = 0;             search[7].y = stop_y;
  653.   search[8].x = stop_x;        search[8].y = stop_y;
  654.   AE_min = INT_MAX;
  655.   min_pos = 0;
  656.   for (i = 0; i < 9; i++) {
  657.     AE = 0;
  658.     for (n = 0; n < bs; n++) {
  659.       for (m = 0; m < bs; m++) {
  660.         /* 计算绝对误差 */
  661.         half_pel = *(prev + 2*new_x + 2*m + search[i].x +
  662.              (2*new_y + 2*n + search[i].y)*lx*2);
  663.         AE += abs(half_pel - *(curr + m + n*16));
  664.       }
  665.     }
  666.     if (AE < AE_min) {
  667.       AE_min = AE;
  668.       min_pos = i;
  669.     }
  670.   }
  671.   /* 存储最优值 */
  672.   fr->min_error = AE_min;
  673.   fr->x_half = search[min_pos].x;
  674.   fr->y_half = search[min_pos].y;
  675.         
  676.   return;
  677. }
  678. /**********************************************************************
  679.  *
  680.  * Name:        FindPred
  681.  * Description: Find the prediction block
  682.  *
  683.  * Input:        position, vector, array for prediction
  684.  *        pointer to previous interpolated luminance,
  685.  *
  686.  * Side effects: fills array with prediction
  687.  *
  688.  *            950208    Mod: Karl.Lillevold@nta.no
  689.  *
  690.  ***********************************************************************/
  691. void FindPred(int x, int y, MotionVector *fr, unsigned char *prev, 
  692.               int *pred, int bs, int comp)
  693. {
  694.   int m, n;
  695.   int new_x, new_y;
  696.   int lx;
  697.   lx = (mv_outside_frame ? pels + (long_vectors?64:32) : pels);
  698.   new_x = x + fr->x;
  699.   new_y = y + fr->y;
  700.   new_x += ((comp&1)<<3);
  701.   new_y += ((comp&2)<<2);
  702.   /* 填充预测数据 */
  703.   for (n = 0; n < bs; n++) {
  704.     for (m = 0; m < bs; m++) {
  705.       *(pred + m + n*16) = *(prev + (new_x + m)*2 + fr->x_half +
  706.              ((new_y + n)*2 + fr->y_half)*lx*2);
  707.     }
  708.   }
  709.   return;
  710. }
  711. /**********************************************************************
  712.  *
  713.  * Name:        FindPredOBMC
  714.  * Description: Find the OBMC prediction block
  715.  *
  716.  * Input:        position, vector, array for prediction
  717.  *        pointer to previous interpolated luminance,
  718.  *
  719.  * Returns:
  720.  * Side effects: fills array with prediction
  721.  *
  722.  *
  723.  ***********************************************************************/
  724. void FindPredOBMC(int x, int y, MotionVector *MV[6][MBR+1][MBC+2], 
  725.           unsigned char *prev, int *pred, int comp, int PB)
  726. {
  727.   int m, n;
  728.   int pc,pt,pb,pr,pl;
  729.   int nxc,nxt,nxb,nxr,nxl;
  730.   int nyc,nyt,nyb,nyr,nyl;
  731.   int xit,xib,xir,xil;
  732.   int yit,yib,yir,yil;
  733.   int vect,vecb,vecr,vecl;
  734.   int c8,t8,l8,r8;
  735.   int ti8,li8,ri8;
  736.   int xmb, ymb, lx;
  737.   MotionVector *fc,*ft,*fb,*fr,*fl;
  738.   int Mc[8][8] = {
  739.     {4,5,5,5,5,5,5,4},
  740.     {5,5,5,5,5,5,5,5},
  741.     {5,5,6,6,6,6,5,5},
  742.     {5,5,6,6,6,6,5,5},
  743.     {5,5,6,6,6,6,5,5},
  744.     {5,5,6,6,6,6,5,5},
  745.     {5,5,5,5,5,5,5,5},
  746.     {4,5,5,5,5,5,5,4},
  747.   };
  748.   int Mt[8][8] = {
  749.     {2,2,2,2,2,2,2,2},
  750.     {1,1,2,2,2,2,1,1},
  751.     {1,1,1,1,1,1,1,1},
  752.     {1,1,1,1,1,1,1,1},
  753.     {0,0,0,0,0,0,0,0},
  754.     {0,0,0,0,0,0,0,0},
  755.     {0,0,0,0,0,0,0,0},
  756.     {0,0,0,0,0,0,0,0},
  757.   };
  758.   int Mb[8][8] = {
  759.     {0,0,0,0,0,0,0,0},
  760.     {0,0,0,0,0,0,0,0},
  761.     {0,0,0,0,0,0,0,0},
  762.     {0,0,0,0,0,0,0,0},
  763.     {1,1,1,1,1,1,1,1},
  764.     {1,1,1,1,1,1,1,1},
  765.     {1,1,2,2,2,2,1,1},
  766.     {2,2,2,2,2,2,2,2},
  767.   };
  768.   int Mr[8][8] = {
  769.     {0,0,0,0,1,1,1,2},
  770.     {0,0,0,0,1,1,2,2},
  771.     {0,0,0,0,1,1,2,2},
  772.     {0,0,0,0,1,1,2,2},
  773.     {0,0,0,0,1,1,2,2},
  774.     {0,0,0,0,1,1,2,2},
  775.     {0,0,0,0,1,1,2,2},
  776.     {0,0,0,0,1,1,1,2},
  777.   };
  778.   int Ml[8][8] = {
  779.     {2,1,1,1,0,0,0,0},
  780.     {2,2,1,1,0,0,0,0},
  781.     {2,2,1,1,0,0,0,0},
  782.     {2,2,1,1,0,0,0,0},
  783.     {2,2,1,1,0,0,0,0},
  784.     {2,2,1,1,0,0,0,0},
  785.     {2,2,1,1,0,0,0,0},
  786.     {2,1,1,1,0,0,0,0},
  787.   };
  788.   xmb = x/MB_SIZE+1;
  789.   ymb = y/MB_SIZE+1;
  790.   lx = (mv_outside_frame ? pels + (long_vectors?64:32) : pels);
  791.   c8  = (MV[0][ymb][xmb]->Mode == MODE_INTER4V ? 1 : 0);
  792.   t8  = (MV[0][ymb-1][xmb]->Mode == MODE_INTER4V ? 1 : 0);
  793.   ti8 = (MV[0][ymb-1][xmb]->Mode == MODE_INTRA ? 1 : 0);
  794.   ti8 = (MV[0][ymb-1][xmb]->Mode == MODE_INTRA_Q ? 1 : ti8);
  795.   l8  = (MV[0][ymb][xmb-1]->Mode == MODE_INTER4V ? 1 : 0);
  796.   li8 = (MV[0][ymb][xmb-1]->Mode == MODE_INTRA ? 1 : 0);
  797.   li8 = (MV[0][ymb][xmb-1]->Mode == MODE_INTRA_Q ? 1 : li8);
  798.   
  799.   r8  = (MV[0][ymb][xmb+1]->Mode == MODE_INTER4V ? 1 : 0);
  800.   ri8 = (MV[0][ymb][xmb+1]->Mode == MODE_INTRA ? 1 : 0);
  801.   ri8 = (MV[0][ymb][xmb+1]->Mode == MODE_INTRA_Q ? 1 : ri8);
  802.   if (PB) {
  803.     ti8 = li8 = ri8 = 0;
  804.   }
  805.   switch (comp+1) {
  806.   case 1:
  807.     vect = (ti8 ? (c8 ? 1 : 0) : (t8 ? 3 : 0)); 
  808.     yit  = (ti8 ? ymb : ymb - 1); 
  809.     xit = xmb;
  810.     vecb = (c8 ? 3 : 0) ; yib = ymb; xib = xmb;
  811.     vecl = (li8 ? (c8 ? 1 : 0) : (l8 ? 2 : 0)); 
  812.     yil = ymb; 
  813.     xil = (li8 ? xmb : xmb-1);
  814.     vecr = (c8 ? 2 : 0) ; yir = ymb; xir = xmb;
  815.     /* edge handling */
  816.     if (ymb == 1) {
  817.       yit = ymb;
  818.       vect = (c8 ? 1 : 0);
  819.     }
  820.     if (xmb == 1) {
  821.       xil = xmb;
  822.       vecl = (c8 ? 1 : 0);
  823.     }
  824.     break;
  825.   
  826.   case 2:
  827.     vect = (ti8 ? (c8 ? 2 : 0) : (t8 ? 4 : 0)); 
  828.     yit = (ti8 ? ymb : ymb-1); 
  829.     xit = xmb;
  830.     vecb = (c8 ? 4 : 0) ; yib = ymb; xib = xmb;
  831.     vecl = (c8 ? 1 : 0) ; yil = ymb; xil = xmb;
  832.     vecr = (ri8 ? (c8 ? 2 : 0) : (r8 ? 1 : 0)); 
  833.     yir = ymb; 
  834.     xir = (ri8 ? xmb : xmb+1);
  835.     /* edge handling */
  836.     if (ymb == 1) {
  837.       yit = ymb;
  838.       vect = (c8 ? 2 : 0);
  839.     }
  840.     if (xmb == pels/16) {
  841.       xir = xmb;
  842.       vecr = (c8 ? 2 : 0);
  843.     }
  844.     break;
  845.   case 3:
  846.     vect = (c8 ? 1 : 0) ; yit = ymb  ; xit = xmb;
  847.     vecb = (c8 ? 3 : 0) ; yib = ymb  ; xib = xmb;
  848.       
  849.     vecl = (li8 ? (c8 ? 3 : 0) : (l8 ? 4 : 0)); 
  850.     yil = ymb;  
  851.     xil = (li8 ? xmb : xmb-1);
  852.     
  853.     vecr = (c8 ? 4 : 0) ; yir = ymb  ; xir = xmb;
  854.     /* edge handling */
  855.     if (xmb == 1) {
  856.       xil = xmb;
  857.       vecl = (c8 ? 3 : 0);
  858.     }
  859.     break;
  860.   case 4:
  861.     vect = (c8 ? 2 : 0) ; yit = ymb  ; xit = xmb;
  862.     vecb = (c8 ? 4 : 0) ; yib = ymb  ; xib = xmb;
  863.     vecl = (c8 ? 3 : 0) ; yil = ymb  ; xil = xmb;
  864.     vecr = (ri8 ? (c8 ? 4 : 0) : (r8 ? 3 : 0)); 
  865.     yir = ymb; 
  866.     xir = (ri8 ? xmb : xmb+1);
  867.     /* edge handling */
  868.     if (xmb == pels/16) {
  869.       xir = xmb;
  870.       vecr = (c8 ? 4 : 0);
  871.     }
  872.     break;
  873.   default:
  874.     fprintf(stderr,"Illegal block number in FindPredOBMC (pred.c)n");
  875.     exit(-1);
  876.     break;
  877.   }
  878.   fc = MV[c8 ? comp + 1: 0][ymb][xmb];
  879.   ft = MV[vect][yit][xit];
  880.   fb = MV[vecb][yib][xib];
  881.   fr = MV[vecr][yir][xir];
  882.   fl = MV[vecl][yil][xil];
  883.   nxc = 2*x + ((comp&1)<<4); nyc = 2*y + ((comp&2)<<3);
  884.   nxt = nxb = nxr = nxl = nxc;
  885.   nyt = nyb = nyr = nyl = nyc;
  886.   nxc += 2*fc->x + fc->x_half; nyc += 2*fc->y + fc->y_half;
  887.   nxt += 2*ft->x + ft->x_half; nyt += 2*ft->y + ft->y_half;
  888.   nxb += 2*fb->x + fb->x_half; nyb += 2*fb->y + fb->y_half;
  889.   nxr += 2*fr->x + fr->x_half; nyr += 2*fr->y + fr->y_half;
  890.   nxl += 2*fl->x + fl->x_half; nyl += 2*fl->y + fl->y_half;
  891.   /* Fill pred. data */
  892.   for (n = 0; n < 8; n++) {
  893.     for (m = 0; m < 8; m++) {
  894.       /* Find interpolated pixel-value */
  895.       pc = *(prev + nxc + 2*m + (nyc + 2*n)*lx*2) * Mc[n][m];
  896.       pt = *(prev + nxt + 2*m + (nyt + 2*n)*lx*2) * Mt[n][m];
  897.       pb = *(prev + nxb + 2*m + (nyb + 2*n)*lx*2) * Mb[n][m];
  898.       pr = *(prev + nxr + 2*m + (nyr + 2*n)*lx*2) * Mr[n][m];
  899.       pl = *(prev + nxl + 2*m + (nyl + 2*n)*lx*2) * Ml[n][m];
  900.       /*$pc = *(prev + nxc + 2*m + (nyc + 2*n)*lx*2) * 8;
  901.       pt = *(prev + nxt + 2*m + (nyt + 2*n)*lx*2) * 0;;
  902.       pb = *(prev + nxb + 2*m + (nyb + 2*n)*lx*2) * 0;
  903.       pr = *(prev + nxr + 2*m + (nyr + 2*n)*lx*2) * 0;
  904.       pl = *(prev + nxl + 2*m + (nyl + 2*n)*lx*2) * 0;$*/
  905.       *(pred + m + n*16) = (pc+pt+pb+pr+pl+4)>>3;
  906.     }
  907.   }
  908.   return;
  909. }
  910. /**********************************************************************
  911.  *
  912.  * Name:        ReconMacroblock_P
  913.  * Description: Reconstructs MB after quantization for P_images
  914.  *
  915.  * Input:        pointers to current and previous image,
  916.  *        current slice and mb, and which mode
  917.  *        of prediction has been used
  918.  * Returns:
  919.  * Side effects:
  920.  *
  921.  *
  922.  ***********************************************************************/
  923. MB_Structure *MB_Recon_P(PictImage *prev_image, unsigned char *prev_ipol,
  924.          MB_Structure *diff, int x_curr, int y_curr, 
  925.          MotionVector *MV[6][MBR+1][MBC+2], int PB)
  926. {
  927.   MB_Structure *recon_data = (MB_Structure *)malloc(sizeof(MB_Structure));
  928.   MotionVector *fr0,*fr1,*fr2,*fr3,*fr4;
  929.   int pred[16][16];
  930.   int dx, dy, sum;
  931.   int i,j;
  932.   fr0 = MV[0][y_curr/MB_SIZE+1][x_curr/MB_SIZE+1];
  933.   if (advanced) {
  934.     if (fr0->Mode == MODE_INTER || fr0->Mode == MODE_INTER_Q) {
  935.       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[0][0], 0, PB);
  936.       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[0][8], 1, PB);
  937.       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[8][0], 2, PB);
  938.       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[8][8], 3, PB);
  939.       for (j = 0; j < MB_SIZE; j++) 
  940.         for (i = 0; i < MB_SIZE; i++) 
  941.           diff->lum[j][i] += pred[j][i];
  942.       dx = 2*fr0->x + fr0->x_half;
  943.       dy = 2*fr0->y + fr0->y_half;
  944.       dx = ( dx % 4 == 0 ? dx >> 1 : (dx>>1)|1 );
  945.       dy = ( dy % 4 == 0 ? dy >> 1 : (dy>>1)|1 );
  946.       ReconChromBlock_P(x_curr, y_curr, dx, dy, prev_image, diff);
  947.     }
  948.     else if (fr0->Mode == MODE_INTER4V) { /* Inter 8x8 */
  949.       
  950.       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[0][0], 0, PB);
  951.       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[0][8], 1, PB);
  952.       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[8][0], 2, PB);
  953.       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[8][8], 3, PB);
  954.       for (j = 0; j < MB_SIZE; j++) 
  955.         for (i = 0; i < MB_SIZE; i++) 
  956.           diff->lum[j][i] += pred[j][i];
  957.       fr1 = MV[1][y_curr/MB_SIZE+1][x_curr/MB_SIZE+1];
  958.       fr2 = MV[2][y_curr/MB_SIZE+1][x_curr/MB_SIZE+1];
  959.       fr3 = MV[3][y_curr/MB_SIZE+1][x_curr/MB_SIZE+1];
  960.       fr4 = MV[4][y_curr/MB_SIZE+1][x_curr/MB_SIZE+1];
  961.       sum = 2*fr1->x + fr1->x_half + 2*fr2->x + fr2->x_half +
  962.         2*fr3->x + fr3->x_half + 2*fr4->x + fr4->x_half ; 
  963.       dx = sign(sum)*(roundtab[abs(sum)%16] + (abs(sum)/16)*2);
  964.       sum = 2*fr1->y + fr1->y_half + 2*fr2->y + fr2->y_half +
  965.         2*fr3->y + fr3->y_half + 2*fr4->y + fr4->y_half;
  966.       dy = sign(sum)*(roundtab[abs(sum)%16] + (abs(sum)/16)*2);
  967.       ReconChromBlock_P(x_curr, y_curr, dx, dy, prev_image, diff);
  968.     }
  969.   }
  970.   else {
  971.     if (fr0->Mode == MODE_INTER || fr0->Mode == MODE_INTER_Q) {
  972.       /* Inter 16x16 */
  973.       ReconLumBlock_P(x_curr,y_curr,fr0,prev_ipol,&diff->lum[0][0],16,0);
  974.       dx = 2*fr0->x + fr0->x_half;
  975.       dy = 2*fr0->y + fr0->y_half;
  976.       dx = ( dx % 4 == 0 ? dx >> 1 : (dx>>1)|1 );
  977.       dy = ( dy % 4 == 0 ? dy >> 1 : (dy>>1)|1 );
  978.       ReconChromBlock_P(x_curr, y_curr, dx, dy, prev_image, diff);
  979.     }
  980.   }
  981.   memcpy(recon_data, diff, sizeof(MB_Structure));
  982.   return recon_data;
  983. }
  984. /**********************************************************************
  985.  *
  986.  * Name:        ReconLumBlock_P
  987.  * Description: Reconstructs one block of luminance data
  988.  *
  989.  * Input:        position, vector-data, previous image, data-block
  990.  * Returns:
  991.  * Side effects: reconstructs data-block
  992.  *
  993.  *
  994.  ***********************************************************************/
  995. void ReconLumBlock_P(int x, int y, MotionVector *fr, 
  996.              unsigned char *prev, int *data, int bs, int comp)
  997. {
  998.   int m, n;
  999.   int x1, y1, lx;
  1000.   lx = (mv_outside_frame ? pels + (long_vectors?64:32) : pels);
  1001.   x1 = 2*(x + fr->x) + fr->x_half;
  1002.   y1 = 2*(y + fr->y) + fr->y_half;
  1003.   
  1004.   x1 += ((comp&1)<<4);
  1005.   y1 += ((comp&2)<<3);
  1006.   for (n = 0; n < bs; n++) {
  1007.     for (m = 0; m < bs; m++) {
  1008.       *(data+m+n*16) += (int)(*(prev+x1+2*m + (y1+2*n)*2*lx));
  1009.     }
  1010.   }
  1011.   return;
  1012. }
  1013. /**********************************************************************
  1014.  *
  1015.  * Name:        ReconChromBlock_P
  1016.  * Description:        Reconstructs chrominance of one block in P frame
  1017.  *
  1018.  * Input:        position, vector-data, previous image, data-block
  1019.  * Returns:        
  1020.  * Side effects: reconstructs data-block
  1021.  *
  1022.  *
  1023.  ***********************************************************************/
  1024. void ReconChromBlock_P(int x_curr, int y_curr, int dx, int dy,
  1025.                PictImage *prev, MB_Structure *data)
  1026. {
  1027.   int m,n;
  1028.   int x, y, ofx, ofy, pel,lx;
  1029.   int xint, yint;
  1030.   int xh, yh;
  1031.   lx = (mv_outside_frame ? pels/2 + (long_vectors?32:16) : pels/2);
  1032.   x = x_curr>>1;
  1033.   y = y_curr>>1;
  1034.   xint = dx>>1;
  1035.   xh = dx & 1;
  1036.   yint = dy>>1;
  1037.   yh = dy & 1;
  1038.     
  1039.   if (!xh && !yh) {
  1040.     for (n = 0; n < 8; n++) {
  1041.       for (m = 0; m < 8; m++) {
  1042.         ofx = x + xint + m;
  1043.         ofy = y + yint + n;
  1044.         pel=*(prev->Cr+ofx    + (ofy   )*lx);
  1045.         data->Cr[n][m] += pel;
  1046.         pel=*(prev->Cb+ofx    + (ofy   )*lx);
  1047.         data->Cb[n][m] += pel;
  1048.       }
  1049.     }
  1050.   }
  1051.   else if (!xh && yh) {
  1052.     for (n = 0; n < 8; n++) {
  1053.       for (m = 0; m < 8; m++) {
  1054.         ofx = x + xint + m;
  1055.         ofy = y + yint + n;
  1056.         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
  1057.              *(prev->Cr+ofx    + (ofy+yh)*lx) + 1)>>1;
  1058.         data->Cr[n][m] += pel;
  1059.         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
  1060.              *(prev->Cb+ofx    + (ofy+yh)*lx) + 1)>>1;
  1061.         data->Cb[n][m] += pel;
  1062.       
  1063.       }
  1064.     }
  1065.   }
  1066.   else if (xh && !yh) {
  1067.     for (n = 0; n < 8; n++) {
  1068.       for (m = 0; m < 8; m++) {
  1069.         ofx = x + xint + m;
  1070.         ofy = y + yint + n;
  1071.         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
  1072.              *(prev->Cr+ofx+xh + (ofy   )*lx) + 1)>>1;
  1073.         data->Cr[n][m] += pel;
  1074.         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
  1075.              *(prev->Cb+ofx+xh + (ofy   )*lx) + 1)>>1;
  1076.         data->Cb[n][m] += pel;
  1077.       
  1078.       }
  1079.     }
  1080.   }
  1081.   else { /* xh && yh */
  1082.     for (n = 0; n < 8; n++) {
  1083.       for (m = 0; m < 8; m++) {
  1084.         ofx = x + xint + m;
  1085.         ofy = y + yint + n;
  1086.         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
  1087.              *(prev->Cr+ofx+xh + (ofy   )*lx)+
  1088.              *(prev->Cr+ofx    + (ofy+yh)*lx)+
  1089.              *(prev->Cr+ofx+xh + (ofy+yh)*lx)+
  1090.              2)>>2;
  1091.         data->Cr[n][m] += pel;
  1092.         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
  1093.              *(prev->Cb+ofx+xh + (ofy   )*lx)+
  1094.              *(prev->Cb+ofx    + (ofy+yh)*lx)+
  1095.              *(prev->Cb+ofx+xh + (ofy+yh)*lx)+
  1096.              2)>>2;
  1097.         data->Cb[n][m] += pel;
  1098.       
  1099.       }
  1100.     }
  1101.   }
  1102.   return;
  1103. }
  1104. /**********************************************************************
  1105.  *
  1106.  * Name:        FindChromBlock_P
  1107.  * Description:        Finds chrominance of one block in P frame
  1108.  *
  1109.  * Input:        position, vector-data, previous image, data-block
  1110.  *
  1111.  *
  1112.  ***********************************************************************/
  1113. void FindChromBlock_P(int x_curr, int y_curr, int dx, int dy,
  1114.               PictImage *prev, MB_Structure *data)
  1115. {
  1116.   int m,n;
  1117.   int x, y, ofx, ofy, pel,lx;
  1118.   int xint, yint;
  1119.   int xh, yh;
  1120.   lx = (mv_outside_frame ? pels/2 + (long_vectors?32:16) : pels/2);
  1121.   x = x_curr>>1;
  1122.   y = y_curr>>1;
  1123.   xint = dx>>1;
  1124.   xh = dx & 1;
  1125.   yint = dy>>1;
  1126.   yh = dy & 1;
  1127.     
  1128.   if (!xh && !yh) {
  1129.     for (n = 0; n < 8; n++) {
  1130.       for (m = 0; m < 8; m++) {
  1131.         ofx = x + xint + m;
  1132.         ofy = y + yint + n;
  1133.         pel=*(prev->Cr+ofx    + (ofy   )*lx);
  1134.         data->Cr[n][m] = pel;
  1135.         pel=*(prev->Cb+ofx    + (ofy   )*lx);
  1136.         data->Cb[n][m] = pel;
  1137.       }
  1138.     }
  1139.   }
  1140.   else if (!xh && yh) {
  1141.     for (n = 0; n < 8; n++) {
  1142.       for (m = 0; m < 8; m++) {
  1143.         ofx = x + xint + m;
  1144.         ofy = y + yint + n;
  1145.         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
  1146.              *(prev->Cr+ofx    + (ofy+yh)*lx) + 1)>>1;
  1147.         data->Cr[n][m] = pel;
  1148.         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
  1149.              *(prev->Cb+ofx    + (ofy+yh)*lx) + 1)>>1;
  1150.         data->Cb[n][m] = pel;
  1151.       
  1152.       }
  1153.     }
  1154.   }
  1155.   else if (xh && !yh) {
  1156.     for (n = 0; n < 8; n++) {
  1157.       for (m = 0; m < 8; m++) {
  1158.         ofx = x + xint + m;
  1159.         ofy = y + yint + n;
  1160.         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
  1161.              *(prev->Cr+ofx+xh + (ofy   )*lx) + 1)>>1;
  1162.         data->Cr[n][m] = pel;
  1163.         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
  1164.              *(prev->Cb+ofx+xh + (ofy   )*lx) + 1)>>1;
  1165.         data->Cb[n][m] = pel;
  1166.       
  1167.       }
  1168.     }
  1169.   }
  1170.   else { /* xh && yh */
  1171.     for (n = 0; n < 8; n++) {
  1172.       for (m = 0; m < 8; m++) {
  1173.         ofx = x + xint + m;
  1174.         ofy = y + yint + n;
  1175.         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
  1176.              *(prev->Cr+ofx+xh + (ofy   )*lx)+
  1177.              *(prev->Cr+ofx    + (ofy+yh)*lx)+
  1178.              *(prev->Cr+ofx+xh + (ofy+yh)*lx)+
  1179.              2)>>2;
  1180.         data->Cr[n][m] = pel;
  1181.         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
  1182.              *(prev->Cb+ofx+xh + (ofy   )*lx)+
  1183.              *(prev->Cb+ofx    + (ofy+yh)*lx)+
  1184.              *(prev->Cb+ofx+xh + (ofy+yh)*lx)+
  1185.              2)>>2;
  1186.         data->Cb[n][m] = pel;
  1187.       
  1188.       }
  1189.     }
  1190.   }
  1191.   return;
  1192. }
  1193. /**********************************************************************
  1194.  *
  1195.  * Name:        ChooseMode
  1196.  * Description:    chooses coding mode
  1197.  *
  1198.  * Input:         pointer to original fram, min_error from 
  1199.  *                      integer pel search, DQUANT
  1200.  * Returns:        1 for Inter, 0 for Intra
  1201.  *
  1202.  *
  1203.  ***********************************************************************/
  1204. int ChooseMode(unsigned char *curr, int x_pos, int y_pos, int min_SAD)
  1205. {
  1206.   int i,j;
  1207.   int MB_mean = 0, A = 0;
  1208.   int y_off;
  1209.   for (j = 0; j < MB_SIZE; j++) {
  1210.     y_off = (y_pos + j) * pels;
  1211.     for (i = 0; i < MB_SIZE; i++) {
  1212.       MB_mean += *(curr + x_pos + i + y_off);
  1213.     }
  1214.   }
  1215.   MB_mean /= (MB_SIZE*MB_SIZE);
  1216.   for (j = 0; j < MB_SIZE; j++) {
  1217.     y_off = (y_pos + j) * pels;
  1218.     for (i = 0; i < MB_SIZE; i++) {
  1219.       A += abs( *(curr + x_pos + i + y_off) - MB_mean );
  1220.     }
  1221.   }
  1222.   if (A < (min_SAD - 500)) 
  1223.     return MODE_INTRA;
  1224.   else
  1225.     return MODE_INTER;
  1226. }
  1227. int ModifyMode(int Mode, int dquant)
  1228. {
  1229.   if (Mode == MODE_INTRA) {
  1230.     if(dquant!=0)
  1231.       return MODE_INTRA_Q;
  1232.     else
  1233.       return MODE_INTRA;
  1234.   }
  1235.   else{ 
  1236.     if(dquant!=0)
  1237.       return MODE_INTER_Q;
  1238.     else
  1239.       return Mode;
  1240.   }
  1241. }