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

vid_mot_est.c File Reference

#include "vid_sim.h"
#include "video_codec.h"

Go to the source code of this file.

Functions

void MotionEstimation (unsigned char *curr, unsigned char *prev, int x_curr, int y_curr, int xoff, int yoff, int seek_dist, MotionVector *MV[6][MBR+1][MBC+2], int *SAD_0)
unsigned char * LoadArea (unsigned char *im, int x, int y, int x_size, int y_size, int lx)
int SAD_Macroblock (unsigned char *ii, unsigned char *act_block, int h_length, int Min_FRAME)
int SAD_Block (unsigned char *ii, unsigned char *act_block, int h_length, int min_sofar)
int SAD_MB_Bidir (unsigned char *ii, unsigned char *aa, unsigned char *bb, int width, int min_sofar)
int SAD_MB_integer (int *ii, int *act_block, int h_length, int min_sofar)
void FindMB (int x, int y, unsigned char *image, int MB[16][16])

Variables

video_codecVidSt


Function Documentation

void FindMB int  x,
int  y,
unsigned char *  image,
int  MB[16][16]
 

Definition at line 490 of file vid_mot_est.c.

References video_codec::pels, and VidSt.

Referenced by MotionEstimatePicture(), Predict_B(), and Predict_P().

00492 {
00493   int n;
00494   register int m;
00495 
00496   for (n = 0; n < MB_SIZE; n++)
00497     for (m = 0; m < MB_SIZE; m++)
00498       MB[n][m] = *(image + x+m + (y+n)*(VidSt->pels));
00499 }

unsigned char* LoadArea unsigned char *  im,
int  x,
int  y,
int  x_size,
int  y_size,
int  lx
 

Definition at line 330 of file vid_mot_est.c.

Referenced by MotionEstimation().

00332 {
00333   unsigned char *res = (unsigned char *)malloc(sizeof(char)*x_size*y_size);
00334   unsigned char *in;
00335   unsigned char *out;
00336   int i = x_size;
00337   int j = y_size;
00338 
00339   in = im + (y*lx) + x;
00340   out = res;
00341 
00342   while (j--) {
00343     while (i--)
00344       *out++ = *in++;
00345     i = x_size;
00346     in += lx - x_size;
00347   };
00348   return res;
00349 }

void MotionEstimation unsigned char *  curr,
unsigned char *  prev,
int  x_curr,
int  y_curr,
int  xoff,
int  yoff,
int  seek_dist,
MotionVector MV[6][MBR+1][MBC+2],
int *  SAD_0
 

Definition at line 67 of file vid_mot_est.c.

References video_codec::advanced, DEF_8X8_WIN, video_codec::lines, LoadArea(), video_codec::long_vectors, MB_SIZE, motionvector::min_error, mmax, mmin, MotionVector, video_codec::mv_outside_frame, video_codec::pels, SAD_Block(), SAD_Macroblock(), VidSt, motionvector::x, motionvector::x_half, motionvector::y, and motionvector::y_half.

00071 {
00072 
00073   int Min_FRAME[5];
00074   MotionVector MV_FRAME[5];
00075   unsigned char *act_block,*aa,*ii;
00076   unsigned char *search_area, *adv_search_area = NULL, *zero_area = NULL;
00077   int sxy,i,k,j,l;
00078   int ihigh,ilow,jhigh,jlow,h_length,v_length;
00079   int adv_ihigh,adv_ilow,adv_jhigh,adv_jlow,adv_h_length,adv_v_length;
00080   int xmax,ymax,block,sad,lx;
00081   int adv_x_curr, adv_y_curr,xvec,yvec;
00082 
00083   xmax = (VidSt->pels);
00084   ymax = (VidSt->lines);
00085   sxy = seek_dist;
00086   if (!(VidSt->long_vectors)) {
00087     /* Maximum normal search range centered around _zero-vector_ */
00088     sxy = mmin(15, sxy);  
00089   }
00090   else {
00091     /* Maximum extended search range centered around _predictor_ */
00092     sxy = mmin(15 - (2*DEF_8X8_WIN+1), sxy);
00093 
00094     /* NB! */
00095 
00096     /* It is only possible to transmit motion vectors within
00097        a 15x15 window around the motion vector predictor
00098        for any 8x8 or 16x16 block */
00099 
00100     /* The reason for the search window's reduction above with
00101        2*DEF_8X8_WIN+1 is that the 8x8 search may change the MV
00102        predictor for some of the blocks within the macroblock. When we
00103        impose the limitation above, we are sure that any 8x8 vector we
00104        might find is possible to transmit */
00105 
00106     /* We have found that with OBMC, DEF_8X8_WIN should be quite small
00107        for two reasons: (i) a good filtering effect, and (ii) not too
00108        many bits used for transferring the vectors. As can be seen
00109        above this is also useful to avoid a large limitation on the MV
00110        search range */
00111 
00112     /* It is possible to make sure the motion vectors found are legal
00113        in other less limiting ways than above, but this would be more
00114        complicated as well as time-consuming. Any good suggestions for
00115        improvement is welcome, though */
00116 
00117     xoff = mmin(16,mmax(-16,xoff));
00118     yoff = mmin(16,mmax(-16,yoff));
00119 
00120     /* There is no need to check if (xoff + x_curr) points outside
00121        the picture, since the Extended Motion Vector Range is
00122        always used together with the Unrestricted MV mode */
00123   }
00124 
00125 
00126   lx = ((VidSt->mv_outside_frame) ? (VidSt->pels) + ((VidSt->long_vectors)?64:32) : (VidSt->pels));
00127 
00128   ilow = x_curr + xoff - sxy;
00129   ihigh = x_curr + xoff + sxy;
00130 
00131   jlow = y_curr + yoff - sxy;
00132   jhigh = y_curr + yoff + sxy;
00133 
00134   if (!(VidSt->mv_outside_frame)) {
00135     if (ilow<0) ilow = 0;
00136     if (ihigh>xmax-16) ihigh = xmax-16;
00137     if (jlow<0) jlow = 0;
00138     if (jhigh>ymax-16) jhigh = ymax-16;
00139   }
00140 
00141   h_length = ihigh - ilow + 16;
00142   v_length = jhigh - jlow + 16;
00143   act_block = LoadArea(curr, x_curr, y_curr, 16, 16, (VidSt->pels));
00144   search_area = LoadArea(prev, ilow, jlow, h_length, v_length, lx);
00145 
00146   for (k = 0; k < 5; k++) {
00147     Min_FRAME[k] = INT_MAX;
00148     MV_FRAME[k].x = 0;
00149     MV_FRAME[k].y = 0;
00150     MV_FRAME[k].x_half = 0;
00151     MV_FRAME[k].y_half = 0;
00152   }
00153 
00154 
00155   /* Zero vector search*/
00156   if (x_curr-ilow         < 0        || y_curr-jlow         < 0        ||
00157       x_curr-ilow+MB_SIZE > h_length || y_curr-jlow+MB_SIZE > v_length) {
00158     /* in case the zero vector is outside the loaded area in search_area */
00159     zero_area = LoadArea(prev, x_curr, y_curr, 16, 16, lx);
00160     *SAD_0 = SAD_Macroblock(zero_area, act_block, 16, Min_FRAME[0]) -
00161        PREF_NULL_VEC;
00162     free(zero_area);
00163   }
00164   else {
00165     /* the zero vector is within search_area */
00166     ii = search_area + (x_curr-ilow) + (y_curr-jlow)*h_length;
00167     *SAD_0 = SAD_Macroblock(ii, act_block, h_length, Min_FRAME[0]) -
00168        PREF_NULL_VEC;
00169   }
00170 
00171   if (xoff == 0 && yoff == 0) {
00172     Min_FRAME[0] = *SAD_0;
00173     MV_FRAME[0].x = 0;
00174     MV_FRAME[0].y = 0;
00175   }
00176   else {
00177     ii = search_area + (x_curr+xoff-ilow) + (y_curr+yoff-jlow)*h_length;
00178     Min_FRAME[0] = SAD_Macroblock(ii, act_block, h_length, Min_FRAME[0]);
00179     MV_FRAME[0].x = xoff;
00180     MV_FRAME[0].y = yoff;
00181   }
00182   /* NB: if xoff or yoff != 0, the Extended MV Range is used. If we
00183      allow the zero vector to be chosen prior to the half pel search
00184      in this case, the half pel search might lead to a
00185      non-transmittable vector (on the wrong side of zero). If SAD_0
00186      turns out to be the best SAD, the zero-vector will be chosen
00187      after half pel search instead.  The zero-vector can be
00188      transmitted in all modes, no matter what the MV predictor is */
00189 
00190   /* Spiral search */
00191   for (l = 1; l <= sxy; l++) {
00192     i = x_curr + xoff - l;
00193     j = y_curr + yoff - l;
00194     for (k = 0; k < 8*l; k++) {
00195       if (i>=ilow && i<=ihigh && j>=jlow && j<=jhigh) {
00196 
00197         /* 16x16 integer pel MV */
00198         ii = search_area + (i-ilow) + (j-jlow)*h_length;
00199         sad = SAD_Macroblock(ii, act_block, h_length, Min_FRAME[0]);
00200         if (sad < Min_FRAME[0]) {
00201           MV_FRAME[0].x = i - x_curr;
00202           MV_FRAME[0].y = j - y_curr;
00203           Min_FRAME[0] = sad;
00204         }
00205 
00206       }
00207       if      (k<2*l) i++;
00208       else if (k<4*l) j++;
00209       else if (k<6*l) i--;
00210       else            j--;
00211     }      
00212   }
00213 
00214 
00215   if ((VidSt->advanced)) {
00216 
00217     /* Center the 8x8 search around the 16x16 vector.  This is
00218        different than in TMN5 where the 8x8 search is also a full
00219        search. The reasons for this is: (i) it is faster, and (ii) it
00220        generally gives better results because of a better OBMC
00221        filtering effect and less bits spent for vectors, and (iii) if
00222        the Extended MV Range is used, the search range around the
00223        motion vector predictor will be less limited */
00224 
00225     xvec = MV_FRAME[0].x;
00226     yvec = MV_FRAME[0].y;
00227     
00228     if (!(VidSt->long_vectors)) {
00229       if (xvec > 15 - DEF_8X8_WIN) { xvec =  15 - DEF_8X8_WIN ;}
00230       if (yvec > 15 - DEF_8X8_WIN) { yvec =  15 - DEF_8X8_WIN ;}
00231 
00232       if (xvec < -15 + DEF_8X8_WIN) { xvec =  -15 + DEF_8X8_WIN ;}
00233       if (yvec < -15 + DEF_8X8_WIN) { yvec =  -15 + DEF_8X8_WIN ;}
00234     }
00235 
00236     adv_x_curr = x_curr  + xvec;
00237     adv_y_curr = y_curr  + yvec;
00238 
00239     sxy = DEF_8X8_WIN;
00240 
00241     adv_ilow = adv_x_curr - sxy;
00242     adv_ihigh = adv_x_curr + sxy;
00243 
00244     adv_jlow = adv_y_curr - sxy;
00245     adv_jhigh = adv_y_curr + sxy;
00246 
00247     adv_h_length = adv_ihigh - adv_ilow + 16;
00248     adv_v_length = adv_jhigh - adv_jlow + 16;
00249 
00250     adv_search_area = LoadArea(prev, adv_ilow, adv_jlow, 
00251                adv_h_length, adv_v_length, lx);
00252 
00253     for (block = 0; block < 4; block++) {
00254       ii = adv_search_area + (adv_x_curr-adv_ilow) + ((block&1)<<3) + 
00255         (adv_y_curr-adv_jlow + ((block&2)<<2) )*adv_h_length;
00256       aa = act_block + ((block&1)<<3) + ((block&2)<<2)*16;
00257       Min_FRAME[block+1] = SAD_Block(ii,aa,adv_h_length,Min_FRAME[block+1]);
00258       MV_FRAME[block+1].x = MV_FRAME[0].x;
00259       MV_FRAME[block+1].y = MV_FRAME[0].y;
00260     }
00261 
00262     /* Spiral search */
00263     for (l = 1; l <= sxy; l++) {
00264       i = adv_x_curr - l;
00265       j = adv_y_curr - l;
00266       for (k = 0; k < 8*l; k++) {
00267         if (i>=adv_ilow && i<=adv_ihigh && j>=adv_jlow && j<=adv_jhigh) {
00268           
00269           /* 8x8 integer pel MVs */
00270           for (block = 0; block < 4; block++) {
00271             ii = adv_search_area + (i-adv_ilow) + ((block&1)<<3) + 
00272               (j-adv_jlow + ((block&2)<<2) )*adv_h_length;
00273             aa = act_block + ((block&1)<<3) + ((block&2)<<2)*16;
00274             sad = SAD_Block(ii, aa, adv_h_length, Min_FRAME[block+1]);
00275             if (sad < Min_FRAME[block+1]) {
00276               MV_FRAME[block+1].x = i - x_curr;
00277               MV_FRAME[block+1].y = j - y_curr;
00278               Min_FRAME[block+1] = sad;
00279             }
00280           }
00281           
00282         }
00283         if      (k<2*l) i++;
00284         else if (k<4*l) j++;
00285         else if (k<6*l) i--;
00286         else            j--;
00287       }      
00288     }
00289 
00290   }
00291 
00292   i = x_curr/MB_SIZE+1;
00293   j = y_curr/MB_SIZE+1;
00294 
00295   if (!(VidSt->advanced)) {
00296     MV[0][j][i]->x = MV_FRAME[0].x;
00297     MV[0][j][i]->y = MV_FRAME[0].y;
00298     MV[0][j][i]->min_error = Min_FRAME[0];
00299   }
00300   else {
00301     for (k = 0; k < 5; k++) {
00302       MV[k][j][i]->x = MV_FRAME[k].x;
00303       MV[k][j][i]->y = MV_FRAME[k].y;
00304       MV[k][j][i]->min_error = Min_FRAME[k];
00305     }
00306   }
00307 
00308   free(act_block);
00309   free(search_area);
00310   if ((VidSt->advanced))
00311     free(adv_search_area);
00312   return;
00313 }

int SAD_Block unsigned char *  ii,
unsigned char *  act_block,
int  h_length,
int  min_sofar
 

Definition at line 394 of file vid_mot_est.c.

Referenced by MotionEstimation().

00396 {
00397   int i;
00398   int sad = 0;
00399   unsigned char *kk;
00400 
00401   kk = act_block;
00402   i = 8;
00403   while (i--) {
00404     sad += (abs(*ii     - *kk     ) +abs(*(ii+1 ) - *(kk+1) )
00405             +abs(*(ii+2) - *(kk+2) ) +abs(*(ii+3 ) - *(kk+3) )
00406             +abs(*(ii+4) - *(kk+4) ) +abs(*(ii+5 ) - *(kk+5) )
00407             +abs(*(ii+6) - *(kk+6) ) +abs(*(ii+7 ) - *(kk+7) ));
00408 
00409     ii += h_length;
00410     kk += 16;
00411     if (sad > min_sofar)
00412       return INT_MAX;
00413   } 
00414   return sad;
00415 }

int SAD_Macroblock unsigned char *  ii,
unsigned char *  act_block,
int  h_length,
int  Min_FRAME
 

Definition at line 367 of file vid_mot_est.c.

Referenced by MotionEstimation().

00369 {
00370   int i;
00371   int sad = 0;
00372   unsigned char *kk;
00373 
00374   kk = act_block;
00375   i = 16;
00376   while (i--) {
00377     sad += (abs(*ii     - *kk     ) +abs(*(ii+1 ) - *(kk+1) )
00378             +abs(*(ii+2) - *(kk+2) ) +abs(*(ii+3 ) - *(kk+3) )
00379             +abs(*(ii+4) - *(kk+4) ) +abs(*(ii+5 ) - *(kk+5) )
00380             +abs(*(ii+6) - *(kk+6) ) +abs(*(ii+7 ) - *(kk+7) )
00381             +abs(*(ii+8) - *(kk+8) ) +abs(*(ii+9 ) - *(kk+9) )
00382             +abs(*(ii+10)- *(kk+10)) +abs(*(ii+11) - *(kk+11))
00383             +abs(*(ii+12)- *(kk+12)) +abs(*(ii+13) - *(kk+13))
00384             +abs(*(ii+14)- *(kk+14)) +abs(*(ii+15) - *(kk+15)) );
00385 
00386     ii += h_length;
00387     kk += 16;
00388     if (sad > Min_FRAME)
00389       return INT_MAX;
00390   } 
00391   return sad;
00392 }

int SAD_MB_Bidir unsigned char *  ii,
unsigned char *  aa,
unsigned char *  bb,
int  width,
int  min_sofar
 

Definition at line 417 of file vid_mot_est.c.

Referenced by NextTwoPB().

00419 {
00420   int i, sad = 0;
00421   unsigned char *ll, *kk;
00422   kk = aa;
00423   ll = bb;
00424   i = 16;
00425   while (i--) {
00426     sad += (abs(*ii     - ((*kk    + *ll    )>>1)) +
00427             abs(*(ii+1) - ((*(kk+1)+ *(ll+1))>>1)) +
00428             abs(*(ii+2) - ((*(kk+2)+ *(ll+2))>>1)) +
00429             abs(*(ii+3) - ((*(kk+3)+ *(ll+3))>>1)) +
00430             abs(*(ii+4) - ((*(kk+4)+ *(ll+4))>>1)) +
00431             abs(*(ii+5) - ((*(kk+5)+ *(ll+5))>>1)) +
00432             abs(*(ii+6) - ((*(kk+6)+ *(ll+6))>>1)) +
00433             abs(*(ii+7) - ((*(kk+7)+ *(ll+7))>>1)) +
00434             abs(*(ii+8) - ((*(kk+8)+ *(ll+8))>>1)) +
00435             abs(*(ii+9) - ((*(kk+9)+ *(ll+9))>>1)) +
00436             abs(*(ii+10) - ((*(kk+10)+ *(ll+10))>>1)) +
00437             abs(*(ii+11) - ((*(kk+11)+ *(ll+11))>>1)) +
00438             abs(*(ii+12) - ((*(kk+12)+ *(ll+12))>>1)) +
00439             abs(*(ii+13) - ((*(kk+13)+ *(ll+13))>>1)) +
00440             abs(*(ii+14) - ((*(kk+14)+ *(ll+14))>>1)) +
00441             abs(*(ii+15) - ((*(kk+15)+ *(ll+15))>>1)));
00442 
00443     ii += width;
00444     kk += width;
00445     ll += width;
00446     if (sad > min_sofar)
00447       return INT_MAX;
00448   } 
00449   return sad;
00450 }

int SAD_MB_integer int *  ii,
int *  act_block,
int  h_length,
int  min_sofar
 

Definition at line 452 of file vid_mot_est.c.

Referenced by Predict_B().

00453 {
00454   int i, sad = 0, *kk;
00455 
00456   kk = act_block;
00457   i = 16;
00458   while (i--) {
00459     sad += (abs(*ii     - *kk     ) +abs(*(ii+1 ) - *(kk+1) )
00460             +abs(*(ii+2) - *(kk+2) ) +abs(*(ii+3 ) - *(kk+3) )
00461             +abs(*(ii+4) - *(kk+4) ) +abs(*(ii+5 ) - *(kk+5) )
00462             +abs(*(ii+6) - *(kk+6) ) +abs(*(ii+7 ) - *(kk+7) )
00463             +abs(*(ii+8) - *(kk+8) ) +abs(*(ii+9 ) - *(kk+9) )
00464             +abs(*(ii+10)- *(kk+10)) +abs(*(ii+11) - *(kk+11))
00465             +abs(*(ii+12)- *(kk+12)) +abs(*(ii+13) - *(kk+13))
00466             +abs(*(ii+14)- *(kk+14)) +abs(*(ii+15) - *(kk+15)) );
00467 
00468     ii += h_length;
00469     kk += 16;
00470     if (sad > min_sofar)
00471       return INT_MAX;
00472   } 
00473   return sad;
00474 }


Variable Documentation

video_codec* VidSt
 

Definition at line 16 of file vid_wrapper.c.


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