Main Page | Class List | File List | Class Members | File Members

vid_pred.c

Go to the documentation of this file.
00001 /************************************************************************
00002  *
00003  *  vid_pred.c, part of tmn (TMN encoder)
00004  *  Copyright (C) 1995, 1996  Telenor R&D, Norway
00005  *        Karl Olav Lillevold <Karl.Lillevold@nta.no>
00006  *  
00007  *  Contacts: 
00008  *  Karl Olav Lillevold               <Karl.Lillevold@nta.no>, or
00009  *  Robert Danielsen                  <Robert.Danielsen@nta.no>
00010  *
00011  *  Telenor Research and Development  http://www.nta.no/brukere/DVC/
00012  *  P.O.Box 83                        tel.:   +47 63 84 84 00
00013  *  N-2007 Kjeller, Norway            fax.:   +47 63 81 00 76
00014  *  
00015  ************************************************************************/
00016 
00017 /*
00018  * Disclaimer of Warranty
00019  *
00020  * These software programs are available to the user without any
00021  * license fee or royalty on an "as is" basis.  Telenor Research and
00022  * Development disclaims any and all warranties, whether express,
00023  * implied, or statuary, including any implied warranties or
00024  * merchantability or of fitness for a particular purpose.  In no
00025  * event shall the copyright-holder be liable for any incidental,
00026  * punitive, or consequential damages of any kind whatsoever arising
00027  * from the use of these programs.
00028  *
00029  * This disclaimer of warranty extends to the user of these programs
00030  * and user's customers, employees, agents, transferees, successors,
00031  * and assigns.
00032  *
00033  * Telenor Research and Development does not represent or warrant that
00034  * the programs furnished hereunder are free of infringement of any
00035  * third-party patents.
00036  *
00037  * Commercial implementations of H.263, including shareware, are
00038  * subject to royalty fees to patent holders.  Many of these patents
00039  * are general enough such that they are unavoidable regardless of
00040  * implementation design.
00041  * */
00042 
00043 
00044 #include"vid_sim.h"
00045 #include"video_codec.h"
00046 
00047 extern video_codec *VidSt;
00048 
00049 static int roundtab[] = {0,0,0,1,1,1,1,1,1,1,1,1,1,1,2,2};
00050 
00051 /**********************************************************************
00052  *
00053  *      Name:        Predict_P
00054  *      Description:    Predicts P macroblock in advanced or normal
00055  *                      mode
00056  *      
00057  *      Input:        pointers to current and previous frames
00058  *        and previous interpolated image,
00059  *                      position and motion vector array
00060  *      Returns:        pointer to MB_Structure of data to be coded
00061  *      Side effects:   allocates memory to MB_Structure
00062  *
00063  *      Date: 9501        Author: Karl.Lillevold@nta.no
00064  *
00065  ***********************************************************************/
00066 
00067 MB_Structure *Predict_P(PictImage *curr_image, PictImage *prev_image,
00068         unsigned char *prev_ipol, int x, int y, 
00069         MotionVector *MV[6][MBR+1][MBC+2], int PB)
00070 {
00071   int m,n;
00072   int curr[16][16];
00073   int pred[16][16];
00074   MotionVector *fr0,*fr1,*fr2,*fr3,*fr4;
00075   int sum, dx, dy;
00076   int xmb, ymb;
00077 
00078   MB_Structure *pred_error = (MB_Structure *)malloc(sizeof(MB_Structure));
00079     
00080   xmb = x/MB_SIZE+1;
00081   ymb = y/MB_SIZE+1;
00082 
00083   fr0 = MV[0][ymb][xmb];
00084   fr1 = MV[1][ymb][xmb];
00085   fr2 = MV[2][ymb][xmb];
00086   fr3 = MV[3][ymb][xmb];
00087   fr4 = MV[4][ymb][xmb];
00088 
00089   /* Find MB in current image */
00090   FindMB(x, y, curr_image->lum, curr);
00091 
00092   /* Find prediction based on half pel MV */
00093   if ((VidSt->advanced)) {
00094     FindPredOBMC(x, y, MV, prev_ipol, &pred[0][0], 0, PB);
00095     FindPredOBMC(x, y, MV, prev_ipol, &pred[0][8], 1, PB);
00096     FindPredOBMC(x, y, MV, prev_ipol, &pred[8][0], 2, PB);
00097     FindPredOBMC(x, y, MV, prev_ipol, &pred[8][8], 3, PB);
00098   }
00099 
00100   else 
00101     FindPred(x, y, fr0, prev_ipol, &pred[0][0], 16, 0);
00102 
00103   /* Do the actual prediction */
00104   if (fr0->Mode == MODE_INTER || fr0->Mode == MODE_INTER_Q) {
00105     for (n = 0; n < MB_SIZE; n++)
00106       for (m = 0; m < MB_SIZE; m++) 
00107         pred_error->lum[n][m] = (int)(curr[n][m] - pred[n][m]);
00108 
00109     dx = 2*fr0->x + fr0->x_half;
00110     dy = 2*fr0->y + fr0->y_half;
00111     dx = ( dx % 4 == 0 ? dx >> 1 : (dx>>1)|1 );
00112     dy = ( dy % 4 == 0 ? dy >> 1 : (dy>>1)|1 );
00113 
00114     DoPredChrom_P(x, y, dx, dy, curr_image, prev_image, pred_error);
00115   }
00116 
00117   else if (fr0->Mode == MODE_INTER4V) {
00118     for (n = 0; n < MB_SIZE; n++)
00119       for (m = 0; m < MB_SIZE; m++) 
00120         pred_error->lum[n][m] = (int)(curr[n][m] - pred[n][m]);
00121 
00122     sum = 2*fr1->x + fr1->x_half + 2*fr2->x + fr2->x_half +
00123       2*fr3->x + fr3->x_half + 2*fr4->x + fr4->x_half ; 
00124     dx = sign(sum)*(roundtab[abs(sum)%16] + (abs(sum)/16)*2);
00125 
00126     sum = 2*fr1->y + fr1->y_half + 2*fr2->y + fr2->y_half +
00127       2*fr3->y + fr3->y_half + 2*fr4->y + fr4->y_half;
00128     dy = sign(sum)*(roundtab[abs(sum)%16] + (abs(sum)/16)*2);
00129 
00130     DoPredChrom_P(x, y, dx, dy, curr_image, prev_image, pred_error);
00131   }
00132 
00133   else
00134     fprintf(stderr,"Illegal Mode in Predict_P (vid_pred.c)\n");
00135 
00136 
00137   return pred_error;
00138 }
00139 
00140 
00141 /***********************************************************************
00142  *
00143  *      Name:        Predict_B
00144  *      Description:    Predicts the B macroblock in PB-frame prediction
00145  *      
00146  *      Input:          pointers to current frame, previous recon. frame,
00147  *                      pos. in image, MV-data, reconstructed macroblock
00148  *                      from image ahead
00149  *      Returns:        pointer to differential MB data after prediction
00150  *      Side effects:   allocates memory to MB_structure
00151  *
00152  *      Date: 950113        Author: Karl.Lillevold@nta.no
00153  *
00154  ***********************************************************************/
00155 
00156 MB_Structure *Predict_B(PictImage *curr_image, PictImage *prev_image,
00157         unsigned char *prev_ipol,int x, int y,
00158         MotionVector *MV[5][MBR+1][MBC+2],
00159         MB_Structure *recon_P, int TRD,int TRB)
00160 {
00161   int i,j,k;
00162   int dx, dy, sad, sad_min=INT_MAX, curr[16][16], bdx=0, bdy=0;
00163   MB_Structure *p_err = (MB_Structure *)malloc(sizeof(MB_Structure));
00164   MB_Structure *pred = (MB_Structure *)malloc(sizeof(MB_Structure));
00165   MotionVector *f[5];
00166   int xvec, yvec, mvx, mvy;
00167 
00168   for (k = 0; k <= 4; k++)
00169     f[k] = MV[k][y/MB_SIZE+1][x/MB_SIZE+1];
00170 
00171   /* Find MB in current image */
00172   FindMB(x, y, curr_image->lum, curr);
00173 
00174   if (f[0]->Mode == MODE_INTER4V) {  /* Mode INTER4V */
00175     /* Find forward prediction */
00176 
00177     /* Luma */
00178     for (j = -DEF_PBDELTA_WIN; j <= DEF_PBDELTA_WIN; j++) {
00179       for (i = -DEF_PBDELTA_WIN; i <= DEF_PBDELTA_WIN; i++) {
00180 
00181         FindForwLumPredPB(prev_ipol, x, y, f[1], &pred->lum[0][0], 
00182           TRD, TRB, i, j, 8, 0);
00183         FindForwLumPredPB(prev_ipol, x, y, f[2], &pred->lum[0][8], 
00184           TRD, TRB, i, j, 8, 1);
00185         FindForwLumPredPB(prev_ipol, x, y, f[3], &pred->lum[8][0], 
00186           TRD, TRB, i, j, 8, 2);
00187         FindForwLumPredPB(prev_ipol, x, y, f[4], &pred->lum[8][8], 
00188           TRD, TRB, i, j, 8, 3);
00189 
00190         sad = SAD_MB_integer(&curr[0][0],&pred->lum[0][0], 16,INT_MAX);
00191         if (i == 0 && j == 0)
00192           sad -= PREF_PBDELTA_NULL_VEC;
00193         if (sad < sad_min) {
00194           sad_min = sad;
00195           bdx = i;
00196           bdy = j;
00197         }
00198       }
00199     }
00200 
00201     FindForwLumPredPB(prev_ipol,x,y,f[1],&pred->lum[0][0],TRD,TRB,bdx,bdy,8,0);
00202     FindForwLumPredPB(prev_ipol,x,y,f[2],&pred->lum[0][8],TRD,TRB,bdx,bdy,8,1);
00203     FindForwLumPredPB(prev_ipol,x,y,f[3],&pred->lum[8][0],TRD,TRB,bdx,bdy,8,2);
00204     FindForwLumPredPB(prev_ipol,x,y,f[4],&pred->lum[8][8],TRD,TRB,bdx,bdy,8,3);
00205 
00206     /* chroma vectors are sum of B luma vectors divided and rounded */
00207     xvec = yvec = 0;
00208     for (k = 1; k <= 4; k++) {
00209       xvec += TRB*(2*f[k]->x + f[k]->x_half)/TRD + bdx;
00210       yvec += TRB*(2*f[k]->y + f[k]->y_half)/TRD + bdy;
00211     }
00212 
00213     /* round values according to TABLE 16/H.263 */
00214     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
00215     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
00216 
00217     FindChromBlock_P(x, y, dx, dy, prev_image, pred);
00218 
00219     /* Find bidirectional prediction */
00220     FindBiDirLumPredPB(&recon_P->lum[0][0], f[1], &pred->lum[0][0], 
00221                TRD, TRB, bdx, bdy, 0, 0);
00222     FindBiDirLumPredPB(&recon_P->lum[0][8], f[2], &pred->lum[0][8], 
00223                TRD, TRB, bdx, bdy, 1, 0);
00224     FindBiDirLumPredPB(&recon_P->lum[8][0], f[3], &pred->lum[8][0], 
00225                TRD, TRB, bdx, bdy, 0, 1);
00226     FindBiDirLumPredPB(&recon_P->lum[8][8], f[4], &pred->lum[8][8], 
00227                TRD, TRB, bdx, bdy, 1, 1);
00228 
00229     /* chroma vectors are sum of B luma vectors divided and rounded */
00230     xvec = yvec = 0;
00231     for (k = 1; k <= 4; k++) {
00232       mvx = 2*f[k]->x + f[k]->x_half;
00233       mvy = 2*f[k]->y + f[k]->y_half;
00234       xvec += bdx == 0 ? (TRB-TRD) *  mvx / TRD : TRB * mvx / TRD + bdx - mvx;
00235       yvec += bdy == 0 ? (TRB-TRD) *  mvy / TRD : TRB * mvy / TRD + bdy - mvy;
00236     }
00237 
00238     /* round values according to TABLE 16/H.263 */
00239     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
00240     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
00241 
00242     FindBiDirChrPredPB(recon_P, dx, dy, pred); 
00243   }
00244 
00245   else {  /* Mode INTER or INTER_Q */
00246     /* Find forward prediction */
00247 
00248     for (j = -DEF_PBDELTA_WIN; j <= DEF_PBDELTA_WIN; j++) {
00249       for (i = -DEF_PBDELTA_WIN; i <= DEF_PBDELTA_WIN; i++) {
00250 
00251         dx = i; dy = j;
00252         /* To keep things simple I turn off PB delta vectors at the edges */
00253         if (!(VidSt->mv_outside_frame)) {
00254           if (x == 0) dx = 0;
00255           if (x == (VidSt->pels) - MB_SIZE) dx = 0;
00256           if (y == 0) dy = 0;
00257           if (y == (VidSt->lines) - MB_SIZE) dy = 0;
00258         }
00259 
00260         if (f[0]->Mode == MODE_INTRA || f[0]->Mode == MODE_INTRA_Q) {
00261           dx = dy = 0;
00262         }
00263 
00264         if (f[0]->x == 0 && f[0]->y == 0 && 
00265             f[0]->x_half == 0 && f[0]->y_half == 0) {
00266           dx = dy = 0;
00267         }
00268 
00269         FindForwLumPredPB(prev_ipol, x, y, f[0], &pred->lum[0][0], 
00270           TRD, TRB, dx, dy, 16, 0);
00271 
00272         sad = SAD_MB_integer(&curr[0][0],&pred->lum[0][0], 16, INT_MAX);
00273         if (i == 0 && j == 0)
00274           sad -= PREF_PBDELTA_NULL_VEC;
00275         if (sad < sad_min) {
00276           sad_min = sad;
00277           bdx = dx;
00278           bdy = dy;
00279         }
00280       }
00281     }
00282     FindForwLumPredPB(prev_ipol,x,y,f[0],&pred->lum[0][0],TRD,TRB,
00283               bdx,bdy,16,0);
00284 
00285     xvec = 4 * (TRB*(2*f[0]->x + f[0]->x_half) / TRD + bdx);
00286     yvec = 4 * (TRB*(2*f[0]->y + f[0]->y_half) / TRD + bdy);
00287     /* round values according to TABLE 16/H.263 */
00288     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
00289     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
00290 
00291     FindChromBlock_P(x, y, dx, dy, prev_image, pred);
00292 
00293     /* Find bidirectional prediction */
00294     FindBiDirLumPredPB(&recon_P->lum[0][0], f[0], &pred->lum[0][0], 
00295                TRD, TRB, bdx, bdy, 0, 0);
00296     FindBiDirLumPredPB(&recon_P->lum[0][8], f[0], &pred->lum[0][8], 
00297                TRD, TRB, bdx, bdy, 1, 0);
00298     FindBiDirLumPredPB(&recon_P->lum[8][0], f[0], &pred->lum[8][0], 
00299                TRD, TRB, bdx, bdy, 0, 1);
00300     FindBiDirLumPredPB(&recon_P->lum[8][8], f[0], &pred->lum[8][8], 
00301                TRD, TRB, bdx, bdy, 1, 1);
00302 
00303     /* chroma vectors */
00304     mvx = 2*f[0]->x + f[0]->x_half;
00305     xvec = bdx == 0 ? (TRB-TRD) * mvx / TRD : TRB * mvx / TRD + bdx - mvx;
00306     xvec *= 4;
00307 
00308     mvy = 2*f[0]->y + f[0]->y_half;
00309     yvec = bdy == 0 ? (TRB-TRD) * mvy / TRD : TRB * mvy / TRD + bdy - mvy;
00310     yvec *= 4;
00311       
00312     /* round values according to TABLE 16/H.263 */
00313     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
00314     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
00315 
00316     FindBiDirChrPredPB(recon_P, dx, dy, pred); 
00317   }
00318 
00319   /* store PB-deltas */
00320   MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->x = bdx; /* is in half pel format */
00321   MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->y = bdy;
00322   MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->x_half = 0;
00323   MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->y_half = 0;
00324 
00325 
00326   /* Do the actual prediction */
00327   for (j = 0; j < MB_SIZE; j++) 
00328     for (i = 0; i < MB_SIZE; i++) 
00329       p_err->lum[j][i] = 
00330         *(curr_image->lum+x+i + (y+j)*(VidSt->pels)) - pred->lum[j][i];
00331 
00332   y >>= 1;
00333   x >>= 1;
00334   for (j = 0; j < MB_SIZE>>1; j++) 
00335     for (i = 0; i < MB_SIZE>>1; i++) {
00336       p_err->Cr[j][i] = *(curr_image->Cr+x+i + (y+j)*(VidSt->cpels)) - pred->Cr[j][i];
00337       p_err->Cb[j][i] = *(curr_image->Cb+x+i + (y+j)*(VidSt->cpels)) - pred->Cb[j][i];
00338     }
00339 
00340   free(pred);
00341   return p_err;
00342 }
00343 
00344 /***********************************************************************
00345  *
00346  *      Name:        MB_Recon_B
00347  *      Description:    Reconstructs the B macroblock in PB-frame 
00348  *                      prediction
00349  *      
00350  *      Input:          pointers previous recon. frame, pred. diff.,
00351  *                      pos. in image, MV-data, reconstructed macroblock
00352  *                      from image ahead
00353  *      Returns:        pointer to reconstructed MB data 
00354  *      Side effects:   allocates memory to MB_structure
00355  *
00356  *      Date: 950114        Author: Karl.Lillevold@nta.no
00357  *
00358  ***********************************************************************/
00359 
00360 MB_Structure *MB_Recon_B(PictImage *prev_image, MB_Structure *diff,
00361          unsigned char *prev_ipol,int x, int y,
00362          MotionVector *MV[5][MBR+1][MBC+2],
00363          MB_Structure *recon_P,int TRD, int TRB)
00364 {
00365   int i,j,k;
00366   int dx, dy, bdx, bdy, mvx, mvy, xvec, yvec;
00367   MB_Structure *recon_B = (MB_Structure *)malloc(sizeof(MB_Structure));
00368   MB_Structure *pred = (MB_Structure *)malloc(sizeof(MB_Structure));
00369   MotionVector *f[5];
00370 
00371   for (k = 0; k <= 4; k++)
00372     f[k] = MV[k][y/MB_SIZE+1][x/MB_SIZE+1];
00373 
00374   bdx = MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->x;
00375   bdy = MV[5][y/MB_SIZE+1][x/MB_SIZE+1]->y;
00376 
00377   if (f[0]->Mode == MODE_INTER4V) {  /* Mode INTER4V */
00378     /* Find forward prediction */
00379 
00380     /* Luma */
00381     FindForwLumPredPB(prev_ipol,x,y,f[1],&pred->lum[0][0],TRD,TRB,bdx,bdy,8,0);
00382     FindForwLumPredPB(prev_ipol,x,y,f[2],&pred->lum[0][8],TRD,TRB,bdx,bdy,8,1);
00383     FindForwLumPredPB(prev_ipol,x,y,f[3],&pred->lum[8][0],TRD,TRB,bdx,bdy,8,2);
00384     FindForwLumPredPB(prev_ipol,x,y,f[4],&pred->lum[8][8],TRD,TRB,bdx,bdy,8,3);
00385 
00386     /* chroma vectors are sum of B luma vectors divided and rounded */
00387     xvec = yvec = 0;
00388     for (k = 1; k <= 4; k++) {
00389       xvec += TRB*(2*f[k]->x + f[k]->x_half)/TRD + bdx;
00390       yvec += TRB*(2*f[k]->y + f[k]->y_half)/TRD + bdy;
00391     }
00392 
00393     /* round values according to TABLE 16/H.263 */
00394     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
00395     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
00396 
00397     FindChromBlock_P(x, y, dx, dy, prev_image, pred);
00398 
00399     /* Find bidirectional prediction */
00400     FindBiDirLumPredPB(&recon_P->lum[0][0], f[1], &pred->lum[0][0], 
00401                TRD, TRB, bdx, bdy, 0, 0);
00402     FindBiDirLumPredPB(&recon_P->lum[0][8], f[2], &pred->lum[0][8], 
00403                TRD, TRB, bdx, bdy, 1, 0);
00404     FindBiDirLumPredPB(&recon_P->lum[8][0], f[3], &pred->lum[8][0], 
00405                TRD, TRB, bdx, bdy, 0, 1);
00406     FindBiDirLumPredPB(&recon_P->lum[8][8], f[4], &pred->lum[8][8], 
00407                TRD, TRB, bdx, bdy, 1, 1);
00408 
00409     /* chroma vectors are sum of B luma vectors divided and rounded */
00410     xvec = yvec = 0;
00411     for (k = 1; k <= 4; k++) {
00412       mvx = 2*f[k]->x + f[k]->x_half;
00413       mvy = 2*f[k]->y + f[k]->y_half;
00414       xvec += bdx == 0 ? (TRB-TRD) *  mvx / TRD : TRB * mvx / TRD + bdx - mvx;
00415       yvec += bdy == 0 ? (TRB-TRD) *  mvy / TRD : TRB * mvy / TRD + bdy - mvy;
00416     }
00417 
00418     /* round values according to TABLE 16/H.263 */
00419     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
00420     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
00421 
00422     FindBiDirChrPredPB(recon_P, dx, dy, pred); 
00423 
00424   }
00425   else {  /* Mode INTER or INTER_Q */
00426     /* Find forward prediction */
00427     
00428     FindForwLumPredPB(prev_ipol,x,y,f[0],&pred->lum[0][0],TRD,TRB,
00429               bdx,bdy,16,0);
00430 
00431     xvec = 4 * (TRB*(2*f[0]->x + f[0]->x_half) / TRD + bdx);
00432     yvec = 4 * (TRB*(2*f[0]->y + f[0]->y_half) / TRD + bdy);
00433     /* round values according to TABLE 16/H.263 */
00434     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
00435     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
00436 
00437     FindChromBlock_P(x, y, dx, dy, prev_image, pred);
00438 
00439     /* Find bidirectional prediction */
00440     FindBiDirLumPredPB(&recon_P->lum[0][0], f[0], &pred->lum[0][0], 
00441                TRD, TRB, bdx, bdy, 0, 0);
00442     FindBiDirLumPredPB(&recon_P->lum[0][8], f[0], &pred->lum[0][8], 
00443                TRD, TRB, bdx, bdy, 1, 0);
00444     FindBiDirLumPredPB(&recon_P->lum[8][0], f[0], &pred->lum[8][0], 
00445                TRD, TRB, bdx, bdy, 0, 1);
00446     FindBiDirLumPredPB(&recon_P->lum[8][8], f[0], &pred->lum[8][8], 
00447                TRD, TRB, bdx, bdy, 1, 1);
00448 
00449     /* chroma vectors */
00450     mvx = 2*f[0]->x + f[0]->x_half;
00451     xvec = bdx == 0 ? (TRB-TRD) * mvx / TRD : TRB * mvx / TRD + bdx - mvx;
00452     xvec *= 4;
00453 
00454     mvy = 2*f[0]->y + f[0]->y_half;
00455     yvec = bdy == 0 ? (TRB-TRD) * mvy / TRD : TRB * mvy / TRD + bdy - mvy;
00456     yvec *= 4;
00457       
00458     /* round values according to TABLE 16/H.263 */
00459     dx = sign(xvec)*(roundtab[abs(xvec)%16] + (abs(xvec)/16)*2);
00460     dy = sign(yvec)*(roundtab[abs(yvec)%16] + (abs(yvec)/16)*2);
00461 
00462     FindBiDirChrPredPB(recon_P, dx, dy, pred); 
00463 
00464   }
00465 
00466   /* Reconstruction */
00467   for (j = 0; j < MB_SIZE; j++) 
00468     for (i = 0; i < MB_SIZE; i++) 
00469       recon_B->lum[j][i] = pred->lum[j][i] + diff->lum[j][i];
00470         
00471   for (j = 0; j < MB_SIZE>>1; j++) 
00472     for (i = 0; i < MB_SIZE>>1; i++) {
00473       recon_B->Cr[j][i] = pred->Cr[j][i] + diff->Cr[j][i];
00474       recon_B->Cb[j][i] = pred->Cb[j][i] + diff->Cb[j][i];
00475     }
00476   
00477   free(pred);
00478   return recon_B;
00479 }
00480 
00481 /**********************************************************************
00482  *
00483  *      Name:          FindForwLumPredPB
00484  *      Description:   Finds the forward luma  prediction in PB-frame 
00485  *                     pred.
00486  *      
00487  *      Input:         pointer to prev. recon. frame, current positon,
00488  *                     MV structure and pred. structure to fill
00489  *
00490  *      Date: 950114        Author: Karl.Lillevold@nta.no
00491  *
00492  ***********************************************************************/
00493 
00494 void FindForwLumPredPB(unsigned char *prev_ipol, int x_curr, int y_curr, 
00495                MotionVector *fr, int *pred, int TRD, int TRB, 
00496                int bdx, int bdy, int bs, int comp)
00497 {
00498   int i,j;
00499   int xvec,yvec,lx;
00500 
00501   lx = ((VidSt->mv_outside_frame) ? (VidSt->pels) + ((VidSt->long_vectors)?64:32) : (VidSt->pels));
00502 
00503   /* Luma */
00504   xvec = (TRB)*(2*fr->x + fr->x_half)/TRD + bdx;
00505   yvec = (TRB)*(2*fr->y + fr->y_half)/TRD + bdy;
00506 
00507   x_curr += ((comp&1)<<3);
00508   y_curr += ((comp&2)<<2);
00509 
00510   for (j = 0; j < bs; j++) {
00511     for (i = 0; i < bs; i++) {
00512       *(pred+i+j*16) = *(prev_ipol + (i+x_curr)*2 + xvec +
00513          ((j+y_curr)*2 + yvec)*lx*2);
00514     }
00515   }
00516 
00517   return;
00518 }
00519 
00520 
00521 /**********************************************************************
00522  *
00523  *      Name:          FindBiDirLumPredPB
00524  *      Description:   Finds the bi-dir. luma prediction in PB-frame 
00525  *                     prediction
00526  *      
00527  *      Input:         pointer to future recon. data, current positon,
00528  *                     MV structure and pred. structure to fill
00529  *
00530  *      Date: 950115        Author: Karl.Lillevold@nta.no
00531  *
00532  ***********************************************************************/
00533 
00534 void FindBiDirLumPredPB(int *recon_P, MotionVector *fr, int *pred, int TRD, 
00535         int TRB, int bdx, int bdy, int nh, int nv)
00536 {
00537   int xstart,xstop,ystart,ystop;
00538   int xvec,yvec, mvx, mvy;
00539 
00540   mvx = 2*fr->x + fr->x_half;
00541   mvy = 2*fr->y + fr->y_half;
00542 
00543   xvec = (bdx == 0 ? (TRB-TRD) *  mvx / TRD : TRB * mvx / TRD + bdx - mvx);
00544   yvec = (bdy == 0 ? (TRB-TRD) *  mvy / TRD : TRB * mvy / TRD + bdy - mvy);
00545 
00546   /* Luma */
00547 
00548   FindBiDirLimits(xvec,&xstart,&xstop,nh);
00549   FindBiDirLimits(yvec,&ystart,&ystop,nv);
00550 
00551   BiDirPredBlock(xstart,xstop,ystart,ystop,xvec,yvec, recon_P,pred,16);
00552 
00553   return;
00554 }
00555 
00556 /**********************************************************************
00557  *
00558  *      Name:          FindBiDirChrPredPB
00559  *      Description:   Finds the bi-dir. chroma prediction in PB-frame 
00560  *                     prediction
00561  *      
00562  *      Input:         pointer to future recon. data, current positon,
00563  *                     MV structure and pred. structure to fill
00564  *
00565  *      Date: 950115        Author: Karl.Lillevold@nta.no
00566  *
00567  ***********************************************************************/
00568 
00569 void FindBiDirChrPredPB(MB_Structure *recon_P, int dx, int dy, 
00570         MB_Structure *pred)
00571 {
00572   int xstart,xstop,ystart,ystop;
00573 
00574   FindBiDirChromaLimits(dx,&xstart,&xstop);
00575   FindBiDirChromaLimits(dy,&ystart,&ystop);
00576 
00577   BiDirPredBlock(xstart,xstop,ystart,ystop,dx,dy,
00578          &recon_P->Cb[0][0], &pred->Cb[0][0],8);
00579   BiDirPredBlock(xstart,xstop,ystart,ystop,dx,dy,
00580          &recon_P->Cr[0][0], &pred->Cr[0][0],8);
00581 
00582   return;
00583 }
00584 
00585 void FindBiDirLimits(int vec, int *start, int *stop, int nhv)
00586 {
00587 
00588   /* limits taken from C loop in section G5 in H.263 */
00589   *start = mmax(0,(-vec+1)/2 - nhv*8);
00590   *stop = mmin(7,15-(vec+1)/2 - nhv*8);
00591 
00592   return;
00593 
00594 }
00595   
00596 void FindBiDirChromaLimits(int vec, int *start, int *stop)
00597 {
00598 
00599   /* limits taken from C loop in section G5 in H.263 */
00600   *start = mmax(0,(-vec+1)/2);
00601   *stop = mmin(7,7-(vec+1)/2);
00602 
00603   return;
00604 }
00605 
00606 
00607 void BiDirPredBlock(int xstart, int xstop, int ystart, int ystop,
00608             int xvec, int yvec, int *recon, int *pred, int bl)
00609 {
00610   int i,j,pel;
00611   int xint, yint;
00612   int xh, yh;
00613 
00614   xint = xvec>>1;
00615   xh = xvec - 2*xint;
00616   yint = yvec>>1;
00617   yh = yvec - 2*yint;
00618 
00619   if (!xh && !yh) {
00620     for (j = ystart; j <= ystop; j++) {
00621       for (i = xstart; i <= xstop; i++) {
00622         pel = *(recon +(j+yint)*bl + i+xint);
00623         *(pred + j*bl + i) = (mmin(255,mmax(0,pel)) + *(pred + j*bl + i))>>1;
00624       }
00625     }
00626   }
00627   else if (!xh && yh) {
00628     for (j = ystart; j <= ystop; j++) {
00629       for (i = xstart; i <= xstop; i++) {
00630         pel = (*(recon +(j+yint)*bl + i+xint)       + 
00631                *(recon +(j+yint+yh)*bl + i+xint) + 1)>>1;
00632         *(pred + j*bl + i) = (pel + *(pred + j*bl + i))>>1;
00633       }
00634     }
00635   }
00636   else if (xh && !yh) {
00637     for (j = ystart; j <= ystop; j++) {
00638       for (i = xstart; i <= xstop; i++) {
00639         pel = (*(recon +(j+yint)*bl + i+xint)       + 
00640                *(recon +(j+yint)*bl + i+xint+xh) + 1)>>1;
00641         *(pred + j*bl + i) = (pel + *(pred + j*bl + i))>>1;
00642       }
00643     }
00644   }
00645   else { /* xh && yh */
00646     for (j = ystart; j <= ystop; j++) {
00647       for (i = xstart; i <= xstop; i++) {
00648         pel = (*(recon +(j+yint)*bl + i+xint)       + 
00649                *(recon +(j+yint+yh)*bl + i+xint) + 
00650                *(recon +(j+yint)*bl + i+xint+xh) + 
00651                *(recon +(j+yint+yh)*bl + i+xint+xh)+2)>>2;
00652         *(pred + j*bl + i) = (pel + *(pred + j*bl + i))>>1;
00653       }
00654     }
00655   }
00656   return;
00657 }
00658 
00659 /**********************************************************************
00660  *
00661  *      Name:        DoPredChrom_P
00662  *      Description:    Does the chrominance prediction for P-frames
00663  *      
00664  *      Input:        motionvectors for each field,
00665  *        current position in image,
00666  *        pointers to current and previos image,
00667  *        pointer to pred_error array,
00668  *        (int) field: 1 if field coding
00669  *        
00670  *      Side effects:   fills chrom-array in pred_error structure
00671  *
00672  *      Date: 930211    Author: Karl.Lillevold@nta.no
00673  *
00674  ***********************************************************************/
00675 
00676 void DoPredChrom_P(int x_curr, int y_curr, int dx, int dy,
00677            PictImage *curr, PictImage *prev, 
00678            MB_Structure *pred_error)
00679 {
00680   int m,n;
00681 
00682   int x, y, ofx, ofy, pel, lx;
00683   int xint, yint;
00684   int xh, yh;
00685 
00686   lx = ((VidSt->mv_outside_frame) ? (VidSt->pels)/2 + ((VidSt->long_vectors)?32:16) : (VidSt->pels)/2);
00687 
00688   x = x_curr>>1;
00689   y = y_curr>>1;
00690 
00691   xint = dx>>1;
00692   xh = dx & 1;
00693   yint = dy>>1;
00694   yh = dy & 1;
00695 
00696   if (!xh && !yh) {
00697     for (n = 0; n < 8; n++) {
00698       for (m = 0; m < 8; m++) {
00699 
00700         ofx = x + xint + m;
00701         ofy = y + yint + n;
00702         pel=*(prev->Cr+ofx    + (ofy   )*lx);
00703         pred_error->Cr[n][m] = (int)(*(curr->Cr + x+m + (y+n)*(VidSt->cpels)) - pel);
00704 
00705         pel=*(prev->Cb+ofx    + (ofy   )*lx);
00706         pred_error->Cb[n][m] = (int)(*(curr->Cb + x+m + (y+n)*(VidSt->cpels)) - pel);
00707       }
00708     }
00709   }
00710   else if (!xh && yh) {
00711     for (n = 0; n < 8; n++) {
00712       for (m = 0; m < 8; m++) {
00713 
00714         ofx = x + xint + m;
00715         ofy = y + yint + n;
00716         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
00717              *(prev->Cr+ofx    + (ofy+yh)*lx) + 1)>>1;
00718 
00719         pred_error->Cr[n][m] = 
00720           (int)(*(curr->Cr + x+m + (y+n)*(VidSt->cpels)) - pel);
00721 
00722         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
00723              *(prev->Cb+ofx    + (ofy+yh)*lx) + 1)>>1;
00724 
00725         pred_error->Cb[n][m] = 
00726           (int)(*(curr->Cb + x+m + (y+n)*(VidSt->cpels)) - pel);
00727       
00728       }
00729     }
00730   }
00731   else if (xh && !yh) {
00732     for (n = 0; n < 8; n++) {
00733       for (m = 0; m < 8; m++) {
00734 
00735         ofx = x + xint + m;
00736         ofy = y + yint + n;
00737         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
00738              *(prev->Cr+ofx+xh + (ofy   )*lx) + 1)>>1;
00739 
00740         pred_error->Cr[n][m] = 
00741           (int)(*(curr->Cr + x+m + (y+n)*(VidSt->cpels)) - pel);
00742 
00743         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
00744              *(prev->Cb+ofx+xh + (ofy   )*lx) + 1)>>1;
00745 
00746         pred_error->Cb[n][m] = 
00747           (int)(*(curr->Cb + x+m + (y+n)*(VidSt->cpels)) - pel);
00748       
00749       }
00750     }
00751   }
00752   else { /* xh && yh */
00753     for (n = 0; n < 8; n++) {
00754       for (m = 0; m < 8; m++) {
00755         ofx = x + xint + m;
00756         ofy = y + yint + n;
00757         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
00758              *(prev->Cr+ofx+xh + (ofy   )*lx)+
00759              *(prev->Cr+ofx    + (ofy+yh)*lx)+
00760              *(prev->Cr+ofx+xh + (ofy+yh)*lx)+
00761              2)>>2;
00762 
00763         pred_error->Cr[n][m] = 
00764           (int)(*(curr->Cr + x+m + (y+n)*(VidSt->cpels)) - pel);
00765 
00766         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
00767              *(prev->Cb+ofx+xh + (ofy   )*lx)+
00768              *(prev->Cb+ofx    + (ofy+yh)*lx)+
00769              *(prev->Cb+ofx+xh + (ofy+yh)*lx)+
00770              2)>>2;
00771 
00772         pred_error->Cb[n][m] = 
00773           (int)(*(curr->Cb + x+m + (y+n)*(VidSt->cpels)) - pel);
00774       
00775       }
00776     }
00777   }
00778   return;
00779 }
00780 
00781 /**********************************************************************
00782  *
00783  *      Name:        FindHalfPel
00784  *      Description:    Find the optimal half pel prediction
00785  *      
00786  *      Input:        position, vector, array with current data
00787  *        pointer to previous interpolated luminance,
00788  *
00789  *      Returns:
00790  *
00791  *      Date: 930126        Author: Karl.Lillevold@nta.no
00792  *            950208    Mod: Karl.Lillevold@nta.no
00793  *
00794  ***********************************************************************/
00795 
00796 
00797 void FindHalfPel(int x, int y, MotionVector *fr, unsigned char *prev, 
00798          int *curr, int bs, int comp)
00799 {
00800   int i, m, n;
00801   int half_pel;
00802   int start_x, start_y, stop_x, stop_y, new_x, new_y, lx;
00803   int min_pos;
00804   int AE, AE_min;
00805   Point search[9];
00806 
00807   start_x = -1;
00808   stop_x = 1;
00809   start_y = -1;
00810   stop_y = 1;
00811 
00812   new_x = x + fr->x;
00813   new_y = y + fr->y;
00814 
00815   new_x += ((comp&1)<<3);
00816   new_y += ((comp&2)<<2);
00817 
00818   lx = ((VidSt->mv_outside_frame) ? (VidSt->pels) + ((VidSt->long_vectors)?64:32) : (VidSt->pels));
00819 
00820   /* Make sure that no addressing is outside the frame */
00821   if (!(VidSt->mv_outside_frame)) {
00822     if ((new_x) <= 0) 
00823       start_x = 0;
00824     if ((new_y) <= 0) 
00825       start_y = 0;
00826     if ((new_x) >= ((VidSt->pels)-bs)) 
00827       stop_x = 0;
00828     if ((new_y) >= ((VidSt->lines)-bs)) 
00829       stop_y = 0;
00830   }
00831 
00832   search[0].x = 0;        search[0].y = 0;
00833   search[1].x = start_x;        search[1].y = start_y; /*   1 2 3   */
00834   search[2].x = 0;        search[2].y = start_y; /*   4 0 5   */
00835   search[3].x = stop_x;        search[3].y = start_y; /*   6 7 8   */
00836   search[4].x = start_x;        search[4].y = 0;
00837   search[5].x = stop_x;        search[5].y = 0;
00838   search[6].x = start_x;        search[6].y = stop_y;
00839   search[7].x = 0;        search[7].y = stop_y;
00840   search[8].x = stop_x;        search[8].y = stop_y;
00841 
00842   AE_min = INT_MAX;
00843   min_pos = 0;
00844   for (i = 0; i < 9; i++) {
00845     AE = 0;
00846     for (n = 0; n < bs; n++) {
00847       for (m = 0; m < bs; m++) {
00848         /* Find absolute error */
00849         half_pel = *(prev + 2*new_x + 2*m + search[i].x +
00850              (2*new_y + 2*n + search[i].y)*lx*2);
00851         AE += abs(half_pel - *(curr + m + n*16));
00852       }
00853     }
00854     /*
00855      * if (i == 0 && fr->x == 0 && fr->y == 0 && bs == 16) 
00856      * AE -= PREF_NULL_VEC;
00857      */
00858     if (AE < AE_min) {
00859       AE_min = AE;
00860       min_pos = i;
00861     }
00862   }
00863 
00864   /* Store optimal values */
00865   fr->min_error = AE_min;
00866   fr->x_half = search[min_pos].x;
00867   fr->y_half = search[min_pos].y;
00868         
00869   return;
00870 }
00871 
00872 /**********************************************************************
00873  *
00874  *      Name:        FindPred
00875  *      Description:    Find the prediction block
00876  *      
00877  *      Input:        position, vector, array for prediction
00878  *        pointer to previous interpolated luminance,
00879  *
00880  *      Side effects:   fills array with prediction
00881  *
00882  *      Date: 930126        Author: Karl.Lillevold@nta.no
00883  *            950208    Mod: Karl.Lillevold@nta.no
00884  *
00885  ***********************************************************************/
00886 
00887 
00888 void FindPred(int x, int y, MotionVector *fr, unsigned char *prev, 
00889               int *pred, int bs, int comp)
00890 {
00891   int m, n;
00892   int new_x, new_y;
00893   int lx;
00894 
00895   lx = ((VidSt->mv_outside_frame) ? (VidSt->pels) + ((VidSt->long_vectors)?64:32) : (VidSt->pels));
00896 
00897   new_x = x + fr->x;
00898   new_y = y + fr->y;
00899 
00900   new_x += ((comp&1)<<3);
00901   new_y += ((comp&2)<<2);
00902 
00903 
00904   /* Fill pred. data */
00905   for (n = 0; n < bs; n++) {
00906     for (m = 0; m < bs; m++) {
00907       /* Find interpolated pixel-value */
00908       *(pred + m + n*16) = *(prev + (new_x + m)*2 + fr->x_half +
00909              ((new_y + n)*2 + fr->y_half)*lx*2);
00910     }   
00911   }
00912   return;
00913 }
00914 
00915 /**********************************************************************
00916  *
00917  *      Name:        FindPredOBMC
00918  *      Description:    Find the OBMC prediction block
00919  *      
00920  *      Input:        position, vector, array for prediction
00921  *        pointer to previous interpolated luminance,
00922  *
00923  *      Returns:
00924  *      Side effects:   fills array with prediction
00925  *
00926  *      Date: 950209        Author: Karl.Lillevold@nta.no
00927  *
00928  ***********************************************************************/
00929 
00930 
00931 void FindPredOBMC(int x, int y, MotionVector *MV[6][MBR+1][MBC+2], 
00932           unsigned char *prev, int *pred, int comp, int PB)
00933 {
00934   int m, n;
00935   int pc,pt,pb,pr,pl;
00936   int nxc,nxt,nxb,nxr,nxl;
00937   int nyc,nyt,nyb,nyr,nyl;
00938   int xit,xib,xir,xil;
00939   int yit,yib,yir,yil;
00940   int vect,vecb,vecr,vecl;
00941   int c8,t8,l8,r8;
00942   int ti8,li8,ri8;
00943   int xmb, ymb, lx;
00944   MotionVector *fc,*ft,*fb,*fr,*fl;
00945 
00946   int Mc[8][8] = {
00947     {4,5,5,5,5,5,5,4},
00948     {5,5,5,5,5,5,5,5},
00949     {5,5,6,6,6,6,5,5},
00950     {5,5,6,6,6,6,5,5},
00951     {5,5,6,6,6,6,5,5},
00952     {5,5,6,6,6,6,5,5},
00953     {5,5,5,5,5,5,5,5},
00954     {4,5,5,5,5,5,5,4},
00955   };
00956   int Mt[8][8] = {
00957     {2,2,2,2,2,2,2,2},
00958     {1,1,2,2,2,2,1,1},
00959     {1,1,1,1,1,1,1,1},
00960     {1,1,1,1,1,1,1,1},
00961     {0,0,0,0,0,0,0,0},
00962     {0,0,0,0,0,0,0,0},
00963     {0,0,0,0,0,0,0,0},
00964     {0,0,0,0,0,0,0,0},
00965   };
00966   int Mb[8][8] = {
00967     {0,0,0,0,0,0,0,0},
00968     {0,0,0,0,0,0,0,0},
00969     {0,0,0,0,0,0,0,0},
00970     {0,0,0,0,0,0,0,0},
00971     {1,1,1,1,1,1,1,1},
00972     {1,1,1,1,1,1,1,1},
00973     {1,1,2,2,2,2,1,1},
00974     {2,2,2,2,2,2,2,2},
00975   };
00976   int Mr[8][8] = {
00977     {0,0,0,0,1,1,1,2},
00978     {0,0,0,0,1,1,2,2},
00979     {0,0,0,0,1,1,2,2},
00980     {0,0,0,0,1,1,2,2},
00981     {0,0,0,0,1,1,2,2},
00982     {0,0,0,0,1,1,2,2},
00983     {0,0,0,0,1,1,2,2},
00984     {0,0,0,0,1,1,1,2},
00985   };
00986   int Ml[8][8] = {
00987     {2,1,1,1,0,0,0,0},
00988     {2,2,1,1,0,0,0,0},
00989     {2,2,1,1,0,0,0,0},
00990     {2,2,1,1,0,0,0,0},
00991     {2,2,1,1,0,0,0,0},
00992     {2,2,1,1,0,0,0,0},
00993     {2,2,1,1,0,0,0,0},
00994     {2,1,1,1,0,0,0,0},
00995   };
00996 
00997   xmb = x/MB_SIZE+1;
00998   ymb = y/MB_SIZE+1;
00999 
01000   lx = ((VidSt->mv_outside_frame) ? (VidSt->pels) + ((VidSt->long_vectors)?64:32) : (VidSt->pels));
01001 
01002   c8  = (MV[0][ymb][xmb]->Mode == MODE_INTER4V ? 1 : 0);
01003 
01004   t8  = (MV[0][ymb-1][xmb]->Mode == MODE_INTER4V ? 1 : 0);
01005   ti8 = (MV[0][ymb-1][xmb]->Mode == MODE_INTRA ? 1 : 0);
01006   ti8 = (MV[0][ymb-1][xmb]->Mode == MODE_INTRA_Q ? 1 : ti8);
01007 
01008   l8  = (MV[0][ymb][xmb-1]->Mode == MODE_INTER4V ? 1 : 0);
01009   li8 = (MV[0][ymb][xmb-1]->Mode == MODE_INTRA ? 1 : 0);
01010   li8 = (MV[0][ymb][xmb-1]->Mode == MODE_INTRA_Q ? 1 : li8);
01011   
01012   r8  = (MV[0][ymb][xmb+1]->Mode == MODE_INTER4V ? 1 : 0);
01013   ri8 = (MV[0][ymb][xmb+1]->Mode == MODE_INTRA ? 1 : 0);
01014   ri8 = (MV[0][ymb][xmb+1]->Mode == MODE_INTRA_Q ? 1 : ri8);
01015 
01016   if (PB) {
01017     ti8 = li8 = ri8 = 0;
01018   }
01019 
01020   switch (comp+1) {
01021 
01022   case 1:
01023     vect = (ti8 ? (c8 ? 1 : 0) : (t8 ? 3 : 0)); 
01024     yit  = (ti8 ? ymb : ymb - 1); 
01025     xit = xmb;
01026 
01027     vecb = (c8 ? 3 : 0) ; yib = ymb; xib = xmb;
01028 
01029     vecl = (li8 ? (c8 ? 1 : 0) : (l8 ? 2 : 0)); 
01030     yil = ymb; 
01031     xil = (li8 ? xmb : xmb-1);
01032 
01033     vecr = (c8 ? 2 : 0) ; yir = ymb; xir = xmb;
01034 
01035     /* edge handling */
01036     if (ymb == 1) {
01037       yit = ymb;
01038       vect = (c8 ? 1 : 0);
01039     }
01040     if (xmb == 1) {
01041       xil = xmb;
01042       vecl = (c8 ? 1 : 0);
01043     }
01044     break;
01045   
01046   case 2:
01047     vect = (ti8 ? (c8 ? 2 : 0) : (t8 ? 4 : 0)); 
01048     yit = (ti8 ? ymb : ymb-1); 
01049     xit = xmb;
01050 
01051     vecb = (c8 ? 4 : 0) ; yib = ymb; xib = xmb;
01052     vecl = (c8 ? 1 : 0) ; yil = ymb; xil = xmb;
01053 
01054     vecr = (ri8 ? (c8 ? 2 : 0) : (r8 ? 1 : 0)); 
01055     yir = ymb; 
01056     xir = (ri8 ? xmb : xmb+1);
01057 
01058     /* edge handling */
01059     if (ymb == 1) {
01060       yit = ymb;
01061       vect = (c8 ? 2 : 0);
01062     }
01063     if (xmb == (VidSt->pels)/16) {
01064       xir = xmb;
01065       vecr = (c8 ? 2 : 0);
01066     }
01067     break;
01068 
01069   case 3:
01070     vect = (c8 ? 1 : 0) ; yit = ymb  ; xit = xmb;
01071     vecb = (c8 ? 3 : 0) ; yib = ymb  ; xib = xmb;
01072       
01073     vecl = (li8 ? (c8 ? 3 : 0) : (l8 ? 4 : 0)); 
01074     yil = ymb;  
01075     xil = (li8 ? xmb : xmb-1);
01076     
01077     vecr = (c8 ? 4 : 0) ; yir = ymb  ; xir = xmb;
01078 
01079     /* edge handling */
01080     if (xmb == 1) {
01081       xil = xmb;
01082       vecl = (c8 ? 3 : 0);
01083     }
01084     break;
01085 
01086   case 4:
01087     vect = (c8 ? 2 : 0) ; yit = ymb  ; xit = xmb;
01088     vecb = (c8 ? 4 : 0) ; yib = ymb  ; xib = xmb;
01089     vecl = (c8 ? 3 : 0) ; yil = ymb  ; xil = xmb;
01090 
01091     vecr = (ri8 ? (c8 ? 4 : 0) : (r8 ? 3 : 0)); 
01092     yir = ymb; 
01093     xir = (ri8 ? xmb : xmb+1);
01094 
01095     /* edge handling */
01096     if (xmb == (VidSt->pels)/16) {
01097       xir = xmb;
01098       vecr = (c8 ? 4 : 0);
01099     }
01100     break;
01101 
01102   default:
01103     fprintf(stderr,"Illegal block number in FindPredOBMC (vid_pred.c)\n");
01104     exit(-1);
01105     break;
01106   }
01107 
01108   fc = MV[c8 ? comp + 1: 0][ymb][xmb];
01109 
01110   ft = MV[vect][yit][xit];
01111   fb = MV[vecb][yib][xib];
01112   fr = MV[vecr][yir][xir];
01113   fl = MV[vecl][yil][xil];
01114 
01115   nxc = 2*x + ((comp&1)<<4); nyc = 2*y + ((comp&2)<<3);
01116   nxt = nxb = nxr = nxl = nxc;
01117   nyt = nyb = nyr = nyl = nyc;
01118 
01119   nxc += 2*fc->x + fc->x_half; nyc += 2*fc->y + fc->y_half;
01120   nxt += 2*ft->x + ft->x_half; nyt += 2*ft->y + ft->y_half;
01121   nxb += 2*fb->x + fb->x_half; nyb += 2*fb->y + fb->y_half;
01122   nxr += 2*fr->x + fr->x_half; nyr += 2*fr->y + fr->y_half;
01123   nxl += 2*fl->x + fl->x_half; nyl += 2*fl->y + fl->y_half;
01124 
01125   /* Fill pred. data */
01126   for (n = 0; n < 8; n++) {
01127     for (m = 0; m < 8; m++) {
01128 
01129       /* Find interpolated pixel-value */
01130       pc = *(prev + nxc + 2*m + (nyc + 2*n)*lx*2) * Mc[n][m];
01131       pt = *(prev + nxt + 2*m + (nyt + 2*n)*lx*2) * Mt[n][m];
01132       pb = *(prev + nxb + 2*m + (nyb + 2*n)*lx*2) * Mb[n][m];
01133       pr = *(prev + nxr + 2*m + (nyr + 2*n)*lx*2) * Mr[n][m];
01134       pl = *(prev + nxl + 2*m + (nyl + 2*n)*lx*2) * Ml[n][m];
01135 
01136       /*$pc = *(prev + nxc + 2*m + (nyc + 2*n)*lx*2) * 8;
01137       pt = *(prev + nxt + 2*m + (nyt + 2*n)*lx*2) * 0;;
01138       pb = *(prev + nxb + 2*m + (nyb + 2*n)*lx*2) * 0;
01139       pr = *(prev + nxr + 2*m + (nyr + 2*n)*lx*2) * 0;
01140       pl = *(prev + nxl + 2*m + (nyl + 2*n)*lx*2) * 0;$*/
01141 
01142       *(pred + m + n*16) = (pc+pt+pb+pr+pl+4)>>3;
01143     }   
01144   }
01145   return;
01146 }
01147 
01148 
01149 /**********************************************************************
01150  *
01151  *      Name:        ReconMacroblock_P
01152  *      Description:    Reconstructs MB after quantization for P_images
01153  *      
01154  *      Input:        pointers to current and previous image,
01155  *        current slice and mb, and which mode
01156  *        of prediction has been used
01157  *      Returns:
01158  *      Side effects:
01159  *
01160  *      Date: 930122    Author: Karl.Lillevold@nta.no
01161  *
01162  ***********************************************************************/
01163 
01164 MB_Structure *MB_Recon_P(PictImage *prev_image, unsigned char *prev_ipol,
01165          MB_Structure *diff, int x_curr, int y_curr, 
01166          MotionVector *MV[6][MBR+1][MBC+2], int PB)
01167 {
01168   MB_Structure *recon_data = (MB_Structure *)malloc(sizeof(MB_Structure));
01169   MotionVector *fr0,*fr1,*fr2,*fr3,*fr4;
01170   int pred[16][16];
01171   int dx, dy, sum;
01172   int i,j;
01173 
01174   fr0 = MV[0][y_curr/MB_SIZE+1][x_curr/MB_SIZE+1];
01175 
01176   if ((VidSt->advanced)) {
01177     if (fr0->Mode == MODE_INTER || fr0->Mode == MODE_INTER_Q) {
01178       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[0][0], 0, PB);
01179       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[0][8], 1, PB);
01180       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[8][0], 2, PB);
01181       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[8][8], 3, PB);
01182       for (j = 0; j < MB_SIZE; j++) 
01183         for (i = 0; i < MB_SIZE; i++) 
01184           diff->lum[j][i] += pred[j][i];
01185 
01186       dx = 2*fr0->x + fr0->x_half;
01187       dy = 2*fr0->y + fr0->y_half;
01188       dx = ( dx % 4 == 0 ? dx >> 1 : (dx>>1)|1 );
01189       dy = ( dy % 4 == 0 ? dy >> 1 : (dy>>1)|1 );
01190       ReconChromBlock_P(x_curr, y_curr, dx, dy, prev_image, diff);
01191     }
01192     else if (fr0->Mode == MODE_INTER4V) { /* Inter 8x8 */
01193       
01194       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[0][0], 0, PB);
01195       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[0][8], 1, PB);
01196       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[8][0], 2, PB);
01197       FindPredOBMC(x_curr, y_curr, MV, prev_ipol, &pred[8][8], 3, PB);
01198       for (j = 0; j < MB_SIZE; j++) 
01199         for (i = 0; i < MB_SIZE; i++) 
01200           diff->lum[j][i] += pred[j][i];
01201 
01202       fr1 = MV[1][y_curr/MB_SIZE+1][x_curr/MB_SIZE+1];
01203       fr2 = MV[2][y_curr/MB_SIZE+1][x_curr/MB_SIZE+1];
01204       fr3 = MV[3][y_curr/MB_SIZE+1][x_curr/MB_SIZE+1];
01205       fr4 = MV[4][y_curr/MB_SIZE+1][x_curr/MB_SIZE+1];
01206 
01207       sum = 2*fr1->x + fr1->x_half + 2*fr2->x + fr2->x_half +
01208         2*fr3->x + fr3->x_half + 2*fr4->x + fr4->x_half ; 
01209       dx = sign(sum)*(roundtab[abs(sum)%16] + (abs(sum)/16)*2);
01210 
01211       sum = 2*fr1->y + fr1->y_half + 2*fr2->y + fr2->y_half +
01212         2*fr3->y + fr3->y_half + 2*fr4->y + fr4->y_half;
01213       dy = sign(sum)*(roundtab[abs(sum)%16] + (abs(sum)/16)*2);
01214 
01215       ReconChromBlock_P(x_curr, y_curr, dx, dy, prev_image, diff);
01216     }
01217   }
01218   else {
01219     if (fr0->Mode == MODE_INTER || fr0->Mode == MODE_INTER_Q) {
01220       /* Inter 16x16 */
01221       ReconLumBlock_P(x_curr,y_curr,fr0,prev_ipol,&diff->lum[0][0],16,0);
01222 
01223       dx = 2*fr0->x + fr0->x_half;
01224       dy = 2*fr0->y + fr0->y_half;
01225       dx = ( dx % 4 == 0 ? dx >> 1 : (dx>>1)|1 );
01226       dy = ( dy % 4 == 0 ? dy >> 1 : (dy>>1)|1 );
01227       ReconChromBlock_P(x_curr, y_curr, dx, dy, prev_image, diff);
01228     }
01229   }
01230 
01231   memcpy(recon_data, diff, sizeof(MB_Structure));
01232 
01233   return recon_data;
01234 }
01235 
01236 /**********************************************************************
01237  *
01238  *      Name:        ReconLumBlock_P
01239  *      Description:    Reconstructs one block of luminance data
01240  *      
01241  *      Input:        position, vector-data, previous image, data-block
01242  *      Returns:
01243  *      Side effects:   reconstructs data-block
01244  *
01245  *      Date: 950210    Author: Karl.Lillevold@nta.no
01246  *
01247  ***********************************************************************/
01248 
01249 void ReconLumBlock_P(int x, int y, MotionVector *fr, 
01250              unsigned char *prev, int *data, int bs, int comp)
01251 {
01252   int m, n;
01253   int x1, y1, lx;
01254 
01255   lx = ((VidSt->mv_outside_frame) ? (VidSt->pels) + ((VidSt->long_vectors)?64:32) : (VidSt->pels));
01256 
01257   x1 = 2*(x + fr->x) + fr->x_half;
01258   y1 = 2*(y + fr->y) + fr->y_half;
01259   
01260   x1 += ((comp&1)<<4);
01261   y1 += ((comp&2)<<3);
01262 
01263   for (n = 0; n < bs; n++) {
01264     for (m = 0; m < bs; m++) {
01265       *(data+m+n*16) += (int)(*(prev+x1+2*m + (y1+2*n)*2*lx));
01266     }
01267   }
01268 
01269   return;
01270 }
01271 
01272 /**********************************************************************
01273  *
01274  *      Name:        ReconChromBlock_P
01275  *      Description:        Reconstructs chrominance of one block in P frame
01276  *      
01277  *      Input:        position, vector-data, previous image, data-block
01278  *      Returns:        
01279  *      Side effects:   reconstructs data-block
01280  *
01281  *      Date: 930203    Author: Karl.Lillevold@nta.no
01282  *
01283  ***********************************************************************/
01284 
01285 void ReconChromBlock_P(int x_curr, int y_curr, int dx, int dy,
01286                PictImage *prev, MB_Structure *data)
01287 
01288 {
01289   int m,n;
01290 
01291   int x, y, ofx, ofy, pel,lx;
01292   int xint, yint;
01293   int xh, yh;
01294 
01295   lx = ((VidSt->mv_outside_frame) ? (VidSt->pels)/2 + ((VidSt->long_vectors)?32:16) : (VidSt->pels)/2);
01296 
01297   x = x_curr>>1;
01298   y = y_curr>>1;
01299 
01300   xint = dx>>1;
01301   xh = dx & 1;
01302   yint = dy>>1;
01303   yh = dy & 1;
01304     
01305   if (!xh && !yh) {
01306     for (n = 0; n < 8; n++) {
01307       for (m = 0; m < 8; m++) {
01308 
01309         ofx = x + xint + m;
01310         ofy = y + yint + n;
01311         pel=*(prev->Cr+ofx    + (ofy   )*lx);
01312         data->Cr[n][m] += pel;
01313 
01314         pel=*(prev->Cb+ofx    + (ofy   )*lx);
01315         data->Cb[n][m] += pel;
01316       }
01317     }
01318   }
01319   else if (!xh && yh) {
01320     for (n = 0; n < 8; n++) {
01321       for (m = 0; m < 8; m++) {
01322 
01323         ofx = x + xint + m;
01324         ofy = y + yint + n;
01325         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
01326              *(prev->Cr+ofx    + (ofy+yh)*lx) + 1)>>1;
01327 
01328         data->Cr[n][m] += pel;
01329 
01330         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
01331              *(prev->Cb+ofx    + (ofy+yh)*lx) + 1)>>1;
01332 
01333         data->Cb[n][m] += pel;
01334       
01335       }
01336     }
01337   }
01338   else if (xh && !yh) {
01339     for (n = 0; n < 8; n++) {
01340       for (m = 0; m < 8; m++) {
01341 
01342         ofx = x + xint + m;
01343         ofy = y + yint + n;
01344         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
01345              *(prev->Cr+ofx+xh + (ofy   )*lx) + 1)>>1;
01346 
01347         data->Cr[n][m] += pel;
01348 
01349         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
01350              *(prev->Cb+ofx+xh + (ofy   )*lx) + 1)>>1;
01351 
01352         data->Cb[n][m] += pel;
01353       
01354       }
01355     }
01356   }
01357   else { /* xh && yh */
01358     for (n = 0; n < 8; n++) {
01359       for (m = 0; m < 8; m++) {
01360         ofx = x + xint + m;
01361         ofy = y + yint + n;
01362         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
01363              *(prev->Cr+ofx+xh + (ofy   )*lx)+
01364              *(prev->Cr+ofx    + (ofy+yh)*lx)+
01365              *(prev->Cr+ofx+xh + (ofy+yh)*lx)+
01366              2)>>2;
01367 
01368         data->Cr[n][m] += pel;
01369 
01370         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
01371              *(prev->Cb+ofx+xh + (ofy   )*lx)+
01372              *(prev->Cb+ofx    + (ofy+yh)*lx)+
01373              *(prev->Cb+ofx+xh + (ofy+yh)*lx)+
01374              2)>>2;
01375 
01376         data->Cb[n][m] += pel;
01377       
01378       }
01379     }
01380   }
01381   return;
01382 }
01383 
01384 /**********************************************************************
01385  *
01386  *      Name:        FindChromBlock_P
01387  *      Description:        Finds chrominance of one block in P frame
01388  *      
01389  *      Input:        position, vector-data, previous image, data-block
01390  *
01391  *      Date: 950222    Author: Karl.Lillevold@nta.no
01392  *
01393  ***********************************************************************/
01394 
01395 void FindChromBlock_P(int x_curr, int y_curr, int dx, int dy,
01396               PictImage *prev, MB_Structure *data)
01397 
01398 {
01399   int m,n;
01400 
01401   int x, y, ofx, ofy, pel,lx;
01402   int xint, yint;
01403   int xh, yh;
01404 
01405   lx = ((VidSt->mv_outside_frame) ? (VidSt->pels)/2 + ((VidSt->long_vectors)?32:16) : (VidSt->pels)/2);
01406 
01407   x = x_curr>>1;
01408   y = y_curr>>1;
01409 
01410   xint = dx>>1;
01411   xh = dx & 1;
01412   yint = dy>>1;
01413   yh = dy & 1;
01414     
01415   if (!xh && !yh) {
01416     for (n = 0; n < 8; n++) {
01417       for (m = 0; m < 8; m++) {
01418 
01419         ofx = x + xint + m;
01420         ofy = y + yint + n;
01421         pel=*(prev->Cr+ofx    + (ofy   )*lx);
01422         data->Cr[n][m] = pel;
01423 
01424         pel=*(prev->Cb+ofx    + (ofy   )*lx);
01425         data->Cb[n][m] = pel;
01426       }
01427     }
01428   }
01429   else if (!xh && yh) {
01430     for (n = 0; n < 8; n++) {
01431       for (m = 0; m < 8; m++) {
01432 
01433         ofx = x + xint + m;
01434         ofy = y + yint + n;
01435         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
01436              *(prev->Cr+ofx    + (ofy+yh)*lx) + 1)>>1;
01437 
01438         data->Cr[n][m] = pel;
01439 
01440         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
01441              *(prev->Cb+ofx    + (ofy+yh)*lx) + 1)>>1;
01442 
01443         data->Cb[n][m] = pel;
01444       
01445       }
01446     }
01447   }
01448   else if (xh && !yh) {
01449     for (n = 0; n < 8; n++) {
01450       for (m = 0; m < 8; m++) {
01451 
01452         ofx = x + xint + m;
01453         ofy = y + yint + n;
01454         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
01455              *(prev->Cr+ofx+xh + (ofy   )*lx) + 1)>>1;
01456 
01457         data->Cr[n][m] = pel;
01458 
01459         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
01460              *(prev->Cb+ofx+xh + (ofy   )*lx) + 1)>>1;
01461 
01462         data->Cb[n][m] = pel;
01463       
01464       }
01465     }
01466   }
01467   else { /* xh && yh */
01468     for (n = 0; n < 8; n++) {
01469       for (m = 0; m < 8; m++) {
01470         ofx = x + xint + m;
01471         ofy = y + yint + n;
01472         pel=(*(prev->Cr+ofx    + (ofy   )*lx)+
01473              *(prev->Cr+ofx+xh + (ofy   )*lx)+
01474              *(prev->Cr+ofx    + (ofy+yh)*lx)+
01475              *(prev->Cr+ofx+xh + (ofy+yh)*lx)+
01476              2)>>2;
01477 
01478         data->Cr[n][m] = pel;
01479 
01480         pel=(*(prev->Cb+ofx    + (ofy   )*lx)+
01481              *(prev->Cb+ofx+xh + (ofy   )*lx)+
01482              *(prev->Cb+ofx    + (ofy+yh)*lx)+
01483              *(prev->Cb+ofx+xh + (ofy+yh)*lx)+
01484              2)>>2;
01485 
01486         data->Cb[n][m] = pel;
01487       
01488       }
01489     }
01490   }
01491   return;
01492 }
01493 
01494 
01495 
01496 /**********************************************************************
01497  *
01498  *      Name:        ChooseMode
01499  *      Description:    chooses coding mode
01500  *      
01501  *      Input:          pointer to original fram, min_error from 
01502  *                      integer pel search, DQUANT
01503  *      Returns:        1 for Inter, 0 for Intra
01504  *
01505  *      Date: 941130    Author: Karl.Lillevold@nta.no
01506  *
01507  ***********************************************************************/
01508 
01509 int ChooseMode(unsigned char *curr, int x_pos, int y_pos, int min_SAD)
01510 {
01511   int i,j;
01512   int MB_mean = 0, A = 0;
01513   int y_off;
01514 
01515   for (j = 0; j < MB_SIZE; j++) {
01516     y_off = (y_pos + j) * (VidSt->pels);
01517     for (i = 0; i < MB_SIZE; i++) {
01518       MB_mean += *(curr + x_pos + i + y_off);
01519     }
01520   }
01521   MB_mean /= (MB_SIZE*MB_SIZE);
01522   for (j = 0; j < MB_SIZE; j++) {
01523     y_off = (y_pos + j) * (VidSt->pels);
01524     for (i = 0; i < MB_SIZE; i++) {
01525       A += abs( *(curr + x_pos + i + y_off) - MB_mean );
01526     }
01527   }
01528 
01529   if (A < (min_SAD - 500)) 
01530     return MODE_INTRA;
01531   else
01532     return MODE_INTER;
01533 }
01534 
01535 int ModifyMode(int Mode, int dquant)
01536 {
01537 
01538   if (Mode == MODE_INTRA) {
01539     if(dquant!=0)
01540       return MODE_INTRA_Q;
01541     else
01542       return MODE_INTRA;
01543   }
01544   else{ 
01545     if(dquant!=0)
01546       return MODE_INTER_Q;
01547     else
01548       return Mode;
01549   }
01550 }

Generated on Sun Jul 16 16:27:45 2006 by  doxygen 1.3.9.1