00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 #include "all.h"
00091 #include "mtypes.h"
00092 #include "frames.h"
00093 #include "search.h"
00094 #include "fsize.h"
00095 
00096 
00097 
00098 
00099 
00100 
00101 static int      bsearchAlg;
00102 
00103 
00104 
00105 
00106 
00107 
00108 static int32    FindBestMatch _ANSI_ARGS_((LumBlock block, LumBlock currentBlock, MpegFrame *prev,
00109                       int by, int bx, int *motionY, int *motionX, int32 bestSoFar, int searchRange));
00110 static int BMotionSearchSimple _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev,
00111                         MpegFrame *next, int by, int bx, int *fmy, int *fmx,
00112                         int *bmy, int *bmx, int oldMode));
00113 static int BMotionSearchCross2 _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev,
00114                         MpegFrame *next, int by, int bx, int *fmy, int *fmx,
00115                         int *bmy, int *bmx, int oldMode));
00116 static int BMotionSearchExhaust _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev,
00117                         MpegFrame *next, int by, int bx, int *fmy, int *fmx,
00118                         int *bmy, int *bmx, int oldMode));
00119 static void BMotionSearchNoInterp _ANSI_ARGS_((LumBlock currentBlock, MpegFrame *prev,
00120                                   MpegFrame *next, int by, int bx,
00121                                   int *fmy, int *fmx, int32 *forwardErr,
00122                                   int *bmy, int *bmx, int32 *backErr,
00123                                                boolean backNeeded));
00124 static int32    FindBestMatchExhaust _ANSI_ARGS_((LumBlock block, LumBlock currentBlock, MpegFrame *prev,
00125                       int by, int bx, int *motionY, int *motionX,
00126                       int32 bestSoFar, int searchRange));
00127 static int32    FindBestMatchTwoLevel _ANSI_ARGS_((LumBlock block, LumBlock currentBlock, MpegFrame *prev,
00128                       int by, int bx, int *motionY, int *motionX,
00129                       int32 bestSoFar, int searchRange));
00130 static int32    FindBestMatchLogarithmic _ANSI_ARGS_((LumBlock block, LumBlock currentBlock, MpegFrame *prev,
00131                       int by, int bx, int *motionY, int *motionX,
00132                       int32 bestSoFar, int searchRange));
00133 static int32    FindBestMatchSubSample _ANSI_ARGS_((LumBlock block, LumBlock currentBlock, MpegFrame *prev,
00134                       int by, int bx, int *motionY, int *motionX,
00135                       int32 bestSoFar, int searchRange));
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 void
00159 SetBSearchAlg(alg)
00160     char *alg;
00161 {
00162     if ( strcmp(alg, "SIMPLE") == 0 ) {
00163         bsearchAlg = BSEARCH_SIMPLE;
00164     } else if ( strcmp(alg, "CROSS2") == 0 ) {
00165         bsearchAlg = BSEARCH_CROSS2;
00166     } else if ( strcmp(alg, "EXHAUSTIVE") == 0 ) {
00167         bsearchAlg = BSEARCH_EXHAUSTIVE;
00168     } else {
00169         fprintf(stderr, "ERROR:  Illegal bsearch alg:  %s\n", alg);
00170         exit(1);
00171     }
00172 }
00173 
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 
00183 
00184 
00185 
00186 char *
00187 BSearchName()
00188 {
00189     switch(bsearchAlg) {
00190         case BSEARCH_SIMPLE:
00191             return "SIMPLE";
00192         case BSEARCH_CROSS2:
00193             return "CROSS2";
00194         case BSEARCH_EXHAUSTIVE:
00195             return "EXHAUSTIVE";
00196         default:
00197             exit(1);
00198             break;
00199     }
00200 }
00201 
00202 
00203 
00204 
00205 
00206 
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 
00236 
00237 int
00238 BMotionSearch(currentBlock, prev, next, by, bx, fmy, fmx, bmy, bmx, oldMode)
00239     LumBlock currentBlock;
00240     MpegFrame *prev;
00241     MpegFrame *next;
00242     int by;
00243     int bx;
00244     int *fmy;
00245     int *fmx;
00246     int *bmy;
00247     int *bmx;
00248     int oldMode;
00249 {
00250   
00251   if (prev == (MpegFrame *) NULL) {
00252     PMotionSearch(currentBlock, next, by, bx, bmy, bmx);
00253     return MOTION_BACKWARD;
00254   }
00255   
00256   
00257   
00258     switch(bsearchAlg) {
00259         case BSEARCH_SIMPLE:
00260             return BMotionSearchSimple(currentBlock, prev, next, by, bx, fmy,
00261                                        fmx, bmy, bmx, oldMode);
00262             break;
00263         case BSEARCH_CROSS2:
00264             return BMotionSearchCross2(currentBlock, prev, next, by, bx, fmy,
00265                                        fmx, bmy, bmx, oldMode);
00266             break;
00267         case BSEARCH_EXHAUSTIVE:
00268             return BMotionSearchExhaust(currentBlock, prev, next, by, bx, fmy,
00269                                        fmx, bmy, bmx, oldMode);
00270             break;
00271         default:
00272             fprintf(stderr, "Illegal B-frame motion search algorithm:  %d\n",
00273                     bsearchAlg);
00274             exit(1);
00275     }
00276 }
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 static int
00293 BMotionSearchSimple(currentBlock, prev, next, by, bx, fmy, fmx, bmy, bmx,
00294                     oldMode)
00295     LumBlock currentBlock;
00296     MpegFrame *prev;
00297     MpegFrame *next;
00298     int by;
00299     int bx;
00300     int *fmy;
00301     int *fmx;
00302     int *bmy;
00303     int *bmx;
00304     int oldMode;
00305 {
00306     int32       forwardErr, backErr, interpErr;
00307     LumBlock    interpBlock;
00308     int32       bestSoFar;
00309 
00310                             
00311     BMotionSearchNoInterp(currentBlock, prev, next, by, bx, fmy, fmx,
00312                           &forwardErr, bmy, bmx, &backErr, TRUE);
00313                           
00314                             
00315 
00316     ComputeBMotionLumBlock(prev, next, by, bx, MOTION_INTERPOLATE,
00317                            *fmy, *fmx, *bmy, *bmx, interpBlock);
00318     bestSoFar = min(backErr, forwardErr);
00319     interpErr = LumBlockMAD(currentBlock, interpBlock, bestSoFar);
00320 
00321                             
00322 
00323     if ( interpErr <= forwardErr ) {
00324         if ( interpErr <= backErr ) {
00325             return MOTION_INTERPOLATE;
00326         }
00327         else
00328             return MOTION_BACKWARD;
00329     } else if ( forwardErr <= backErr ) {
00330         return MOTION_FORWARD;
00331     } else {
00332         return MOTION_BACKWARD;
00333     }
00334 }
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 static int
00351 BMotionSearchCross2(currentBlock, prev, next, by, bx, fmy, fmx, bmy, bmx,
00352                     oldMode)
00353     LumBlock currentBlock;
00354     MpegFrame *prev;
00355     MpegFrame *next;
00356     int by;
00357     int bx;
00358     int *fmy;
00359     int *fmx;
00360     int *bmy;
00361     int *bmx;
00362     int oldMode;
00363 {
00364     LumBlock    forwardBlock, backBlock;
00365     int32       forwardErr, backErr, interpErr;
00366     int         newfmy, newfmx, newbmy, newbmx;
00367     int32       interpErr2;
00368     int32       bestErr;
00369 
00370                             
00371 
00372     BMotionSearchNoInterp(currentBlock, prev, next, by, bx, fmy, fmx,
00373                           &forwardErr, bmy, bmx, &backErr, TRUE);
00374 
00375     bestErr = min(forwardErr, backErr);
00376 
00377                             
00378     ComputeBMotionLumBlock(prev, next, by, bx, MOTION_FORWARD,
00379                            *fmy, *fmx, 0, 0, forwardBlock);
00380     ComputeBMotionLumBlock(prev, next, by, bx, MOTION_BACKWARD,
00381                            0, 0, *bmy, *bmx, backBlock);
00382 
00383         
00384     newbmy = *bmy;      newbmx = *bmx;
00385     newfmy = *fmy;      newfmx = *fmx;
00386 
00387     interpErr = FindBestMatch(forwardBlock, currentBlock, next, by, bx,
00388                               &newbmy, &newbmx, bestErr, searchRangeB);
00389     bestErr = min(bestErr, interpErr);
00390     interpErr2 = FindBestMatch(backBlock, currentBlock, prev, by, bx,
00391                                &newfmy, &newfmx, bestErr, searchRangeB);
00392 
00393                             
00394 
00395     if ( interpErr <= interpErr2 ) {
00396         newfmy = *fmy;
00397         newfmx = *fmx;
00398     }
00399     else
00400     {
00401         newbmy = *bmy;
00402         newbmx = *bmx;
00403         interpErr = interpErr2;
00404     }
00405 
00406     if ( interpErr <= forwardErr ) {
00407         if ( interpErr <= backErr ) {
00408             *fmy = newfmy;
00409             *fmx = newfmx;
00410             *bmy = newbmy;
00411             *bmx = newbmx;
00412 
00413             return MOTION_INTERPOLATE;
00414         }
00415         else
00416             return MOTION_BACKWARD;
00417     } else if ( forwardErr <= backErr ) {
00418         return MOTION_FORWARD;
00419     } else {
00420         return MOTION_BACKWARD;
00421     }
00422 }
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 
00438 static int
00439 BMotionSearchExhaust(currentBlock, prev, next, by, bx, fmy, fmx, bmy, bmx,
00440                     oldMode)
00441     LumBlock currentBlock;
00442     MpegFrame *prev;
00443     MpegFrame *next;
00444     int by;
00445     int bx;
00446     int *fmy;
00447     int *fmx;
00448     int *bmy;
00449     int *bmx;
00450     int oldMode;
00451 {
00452     register int mx, my;
00453     int32 diff, bestDiff;
00454     int     stepSize;
00455     LumBlock    forwardBlock;
00456     int32       forwardErr, backErr;
00457     int         newbmy, newbmx;
00458     int     leftMY, leftMX;
00459     int     rightMY, rightMX;
00460     boolean result;
00461 
00462                             
00463 
00464     BMotionSearchNoInterp(currentBlock, prev, next, by, bx, fmy, fmx,
00465                           &forwardErr, bmy, bmx, &backErr, FALSE);
00466 
00467     if ( forwardErr <= backErr ) {
00468         bestDiff = forwardErr;
00469         result = MOTION_FORWARD;
00470     }
00471     else
00472     {
00473         bestDiff = backErr;
00474         result = MOTION_BACKWARD;
00475     }
00476 
00477                             
00478 
00479     stepSize = (pixelFullSearch ? 2 : 1);
00480 
00481     COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX);
00482 
00483     if ( searchRangeB < rightMY ) {
00484         rightMY = searchRangeB;
00485     }
00486     if ( searchRangeB < rightMX ) {
00487         rightMX = searchRangeB;
00488     }
00489 
00490     for ( my = -searchRangeB; my < rightMY; my += stepSize ) {
00491         if ( my < leftMY ) {
00492             continue;
00493         }
00494 
00495         for ( mx = -searchRangeB; mx < rightMX; mx += stepSize ) {
00496             if ( mx < leftMX ) {
00497                 continue;
00498             }
00499 
00500             ComputeBMotionLumBlock(prev, next, by, bx, MOTION_FORWARD,
00501                            my, mx, 0, 0, forwardBlock);
00502 
00503             newbmy = my;        newbmx = mx;
00504 
00505             diff = FindBestMatch(forwardBlock, currentBlock, next, by, bx,
00506                                  &newbmy, &newbmx, bestDiff, searchRangeB);
00507 
00508             if ( diff < bestDiff ) {
00509                 *fmy = my;
00510                 *fmx = mx;
00511                 *bmy = newbmy;
00512                 *bmx = newbmx;
00513                 bestDiff = diff;
00514                 result = MOTION_INTERPOLATE;
00515             }
00516         }
00517     }
00518 
00519     return result;
00520 }
00521 
00522 
00523 
00524 
00525 
00526 
00527 
00528 
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 static int32
00539 FindBestMatch(block, currentBlock, prev, by, bx, motionY, motionX, bestSoFar, searchRange)
00540     LumBlock block;
00541     LumBlock currentBlock;
00542     MpegFrame *prev;
00543     int by;
00544     int bx;
00545     int *motionY;
00546     int *motionX;
00547     int32 bestSoFar;
00548     int searchRange;
00549 {
00550     int32       result;
00551 
00552     switch(psearchAlg) {
00553         case PSEARCH_SUBSAMPLE:
00554             result = FindBestMatchSubSample(block, currentBlock, prev, by, bx,
00555                                             motionY, motionX, bestSoFar, searchRange);
00556             break;
00557         case PSEARCH_EXHAUSTIVE:
00558             result = FindBestMatchExhaust(block, currentBlock, prev, by, bx,
00559                                           motionY, motionX, bestSoFar, searchRange);
00560             break;
00561         case PSEARCH_LOGARITHMIC:
00562             result = FindBestMatchLogarithmic(block, currentBlock, prev, by, bx,
00563                                               motionY, motionX, bestSoFar, searchRange);
00564             break;
00565         case PSEARCH_TWOLEVEL:
00566             result = FindBestMatchTwoLevel(block, currentBlock, prev, by, bx,
00567                                            motionY, motionX, bestSoFar, searchRange);
00568             break;
00569         default:
00570             fprintf(stderr, "ERROR:  Illegal P-search alg %d\n", psearchAlg);
00571             exit(1);
00572     }
00573 
00574     return result;
00575 }
00576 
00577 
00578 
00579 
00580 
00581 
00582 
00583 
00584 
00585 
00586 
00587 
00588 static int32
00589 FindBestMatchExhaust(block, currentBlock, prev, by, bx, motionY, motionX,
00590                      bestSoFar, searchRange)
00591     LumBlock block;
00592     LumBlock currentBlock;
00593     MpegFrame *prev;
00594     int by;
00595     int bx;
00596     int *motionY;
00597     int *motionX;
00598     int32 bestSoFar;
00599     int searchRange;
00600 {
00601     register int mx, my;
00602     int32 diff, bestDiff;
00603     int     stepSize;
00604     int     leftMY, leftMX;
00605     int     rightMY, rightMX;
00606     int     distance;
00607     int     tempRightMY, tempRightMX;
00608     boolean changed = FALSE;
00609 
00610     stepSize = (pixelFullSearch ? 2 : 1);
00611 
00612     COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX);
00613 
00614     
00615     if ( VALID_MOTION(*motionY, *motionX) ) {
00616         bestDiff = LumAddMotionError(currentBlock, block, prev, by, bx,
00617                                      *motionY, *motionX, bestSoFar);
00618 
00619         if ( bestSoFar < bestDiff ) {
00620             bestDiff = bestSoFar;
00621         }
00622     }
00623     else
00624     {
00625         *motionY = 0;
00626         *motionX = 0;
00627 
00628         bestDiff = bestSoFar;
00629     }
00630 
00631 
00632 
00633 
00634         
00635     for ( distance = stepSize; distance <= searchRange; distance += stepSize ) {
00636         tempRightMY = rightMY;
00637         if ( distance < tempRightMY ) {
00638             tempRightMY = distance;
00639         }
00640         tempRightMX = rightMX;
00641         if ( distance < tempRightMX ) {
00642             tempRightMX = distance;
00643         }
00644 
00645         
00646         for ( my = -distance; my < tempRightMY;
00647               my += max(tempRightMY+distance-stepSize, stepSize) ) {
00648             if ( my < leftMY ) {
00649                 continue;
00650             }
00651 
00652             for ( mx = -distance; mx < tempRightMX; mx += stepSize ) {
00653                 if ( mx < leftMX ) {
00654                     continue;
00655                 }
00656 
00657                 diff = LumAddMotionError(currentBlock, block, prev, by, bx,
00658                                      my, mx, bestDiff);
00659 
00660                 if ( diff < bestDiff ) {
00661                     *motionY = my;
00662                     *motionX = mx;
00663                     bestDiff = diff;
00664                 }
00665             }
00666         }
00667 
00668         
00669         for ( mx = -distance; mx < tempRightMX; mx += max(tempRightMX+distance-stepSize, stepSize) ) {
00670             if ( mx < leftMX ) {
00671                 continue;
00672             }
00673 
00674             for ( my = -distance+stepSize; my < tempRightMY-stepSize; my += stepSize ) {
00675                 if ( my < leftMY ) {
00676                     continue;
00677                 }
00678 
00679                 diff = LumAddMotionError(currentBlock, block, prev, by, bx,
00680                                      my, mx, bestDiff);
00681 
00682                 if ( diff < bestDiff ) {
00683                     *motionY = my;
00684                     *motionX = mx;
00685                     bestDiff = diff;
00686                     changed = TRUE;
00687                 }
00688             }
00689         }
00690     }
00691 
00692     if ( ! changed ) {
00693         bestDiff++;
00694     }
00695 
00696     return bestDiff;
00697 }
00698 
00699 
00700 
00701 
00702 
00703 
00704 
00705 
00706 
00707 
00708 
00709 
00710 
00711 static int32
00712 FindBestMatchTwoLevel(block, currentBlock, prev, by, bx, motionY, motionX,
00713                       bestSoFar, searchRange)
00714     LumBlock block;
00715     LumBlock currentBlock;
00716     MpegFrame *prev;
00717     int by;
00718     int bx;
00719     int *motionY;
00720     int *motionX;
00721     int32 bestSoFar;
00722     int searchRange;
00723 {
00724     register int mx, my;
00725     int32 diff, bestDiff;
00726     int     leftMY, leftMX;
00727     int     rightMY, rightMX;
00728     int     distance;
00729     int     tempRightMY, tempRightMX;
00730     boolean changed = FALSE;
00731     int     yOffset, xOffset;
00732 
00733     
00734 
00735     COMPUTE_MOTION_BOUNDARY(by,bx,2,leftMY,leftMX,rightMY,rightMX);
00736 
00737     rightMY--;
00738     rightMX--;
00739 
00740     
00741     if ( *motionY > 0 ) {
00742         if ( ((*motionY) % 2) == 1 ) {
00743             (*motionY)--;
00744         }
00745     } else if ( ((-(*motionY)) % 2) == 1 ) {
00746         (*motionY)++;
00747     }
00748 
00749     if ( *motionX > 0 ) {
00750         if ( ((*motionX) % 2) == 1 ) {
00751             (*motionX)--;
00752         }
00753     } else if ( ((-(*motionX)) % 2) == 1 ) {
00754         (*motionX)++;
00755     }
00756 
00757     
00758     if ( VALID_MOTION(*motionY, *motionX) ) {
00759         bestDiff = LumAddMotionError(currentBlock, block, prev, by, bx,
00760                                      *motionY, *motionX, bestSoFar);
00761 
00762         if ( bestSoFar < bestDiff ) {
00763             bestDiff = bestSoFar;
00764         }
00765     }
00766     else
00767     {
00768         *motionY = 0;
00769         *motionX = 0;
00770 
00771         bestDiff = bestSoFar;
00772     }
00773 
00774     rightMY++;
00775     rightMX++;
00776 
00777 
00778 
00779 
00780         
00781     for ( distance = 2; distance <= searchRange; distance += 2 ) {
00782         tempRightMY = rightMY;
00783         if ( distance < tempRightMY ) {
00784             tempRightMY = distance;
00785         }
00786         tempRightMX = rightMX;
00787         if ( distance < tempRightMX ) {
00788             tempRightMX = distance;
00789         }
00790 
00791         
00792         for ( my = -distance; my < tempRightMY;
00793               my += max(tempRightMY+distance-2, 2) ) {
00794             if ( my < leftMY ) {
00795                 continue;
00796             }
00797 
00798             for ( mx = -distance; mx < tempRightMX; mx += 2 ) {
00799                 if ( mx < leftMX ) {
00800                     continue;
00801                 }
00802 
00803                 diff = LumAddMotionError(currentBlock, block, prev, by, bx,
00804                                      my, mx, bestDiff);
00805 
00806                 if ( diff < bestDiff ) {
00807                     *motionY = my;
00808                     *motionX = mx;
00809                     bestDiff = diff;
00810                 }
00811             }
00812         }
00813 
00814         
00815         for ( mx = -distance; mx < tempRightMX; mx += max(tempRightMX+distance-2, 2) ) {
00816             if ( mx < leftMX ) {
00817                 continue;
00818             }
00819 
00820             for ( my = -distance+2; my < tempRightMY-2; my += 2 ) {
00821                 if ( my < leftMY ) {
00822                     continue;
00823                 }
00824 
00825                 diff = LumAddMotionError(currentBlock, block, prev, by, bx,
00826                                      my, mx, bestDiff);
00827 
00828                 if ( diff < bestDiff ) {
00829                     *motionY = my;
00830                     *motionX = mx;
00831                     bestDiff = diff;
00832                     changed = TRUE;
00833                 }
00834             }
00835         }
00836     }
00837 
00838     
00839     my = *motionY;
00840     mx = *motionX;
00841 
00842     rightMY--;
00843     rightMX--;
00844 
00845     for ( yOffset = -1; yOffset <= 1; yOffset++ ) {
00846         for ( xOffset = -1; xOffset <= 1; xOffset++ ) {
00847             if ( (yOffset == 0) && (xOffset == 0) )
00848                 continue;
00849 
00850             if ( VALID_MOTION(my+yOffset, mx+xOffset) &&
00851                  ((diff = LumAddMotionError(currentBlock, block, prev, by, bx,
00852                          my+yOffset, mx+xOffset, bestDiff)) < bestDiff) ) {
00853                 *motionY = my+yOffset;
00854                 *motionX = mx+xOffset;
00855                 bestDiff = diff;
00856                 changed = TRUE;
00857             }
00858         }
00859     }
00860 
00861     if ( ! changed ) {
00862         bestDiff++;
00863     }
00864 
00865     return bestDiff;
00866 }
00867 
00868 
00869 
00870 
00871 
00872 
00873 
00874 
00875 
00876 
00877 
00878 
00879 static int32
00880 FindBestMatchLogarithmic(block, currentBlock, prev, by, bx, motionY, motionX,
00881                      bestSoFar, searchRange)
00882     LumBlock block;
00883     LumBlock currentBlock;
00884     MpegFrame *prev;
00885     int by;
00886     int bx;
00887     int *motionY;
00888     int *motionX;
00889     int32 bestSoFar;
00890     int searchRange;
00891 {
00892     register int mx, my;
00893     int32 diff, bestDiff;
00894     int     stepSize;
00895     int     leftMY, leftMX;
00896     int     rightMY, rightMX;
00897     int     tempRightMY, tempRightMX;
00898     int     spacing;
00899     int     centerX, centerY;
00900     int     newCenterX, newCenterY;
00901 
00902     stepSize = (pixelFullSearch ? 2 : 1);
00903 
00904     COMPUTE_MOTION_BOUNDARY(by,bx,stepSize,leftMY,leftMX,rightMY,rightMX);
00905 
00906     bestDiff = 0x7fffffff;
00907 
00908     
00909     if ( stepSize == 2 ) {      
00910         spacing = (searchRange+1)/2;
00911         if ( (spacing % 2) != 0 ) {
00912             spacing++;
00913         }
00914     }
00915     else
00916         spacing = (searchRange+1)/2;
00917     centerX = 0;
00918     centerY = 0;
00919 
00920     while ( spacing >= stepSize ) {
00921         newCenterY = centerY;
00922         newCenterX = centerX;
00923 
00924         tempRightMY = rightMY;
00925         if ( centerY+spacing+1 < tempRightMY ) {
00926             tempRightMY = centerY+spacing+1;
00927         }
00928         tempRightMX = rightMX;
00929         if ( centerX+spacing+1 < tempRightMX ) {
00930             tempRightMX = centerX+spacing+1;
00931         }
00932 
00933         for ( my = centerY-spacing; my < tempRightMY; my += spacing ) {
00934             if ( my < leftMY ) {
00935                 continue;
00936             }
00937 
00938             for ( mx = centerX-spacing; mx < tempRightMX; mx += spacing ) {
00939                 if ( mx < leftMX ) {
00940                     continue;
00941                 }
00942 
00943                 diff = LumAddMotionError(currentBlock, block, prev, by, bx,
00944                                      my, mx, bestDiff);
00945 
00946                 if ( diff < bestDiff ) {
00947                     newCenterY = my;
00948                     newCenterX = mx;
00949 
00950                     bestDiff = diff;
00951                 }
00952             }
00953         }
00954 
00955         centerY = newCenterY;
00956         centerX = newCenterX;
00957 
00958         if ( stepSize == 2 ) {  
00959             if ( spacing == 2 ) {
00960                 spacing = 0;
00961             }
00962             else
00963             {
00964                 spacing = (spacing+1)/2;
00965                 if ( (spacing % 2) != 0 ) {
00966                     spacing++;
00967                 }
00968             }
00969         }
00970         else
00971         {
00972             if ( spacing == 1 ) {
00973                 spacing = 0;
00974             }
00975             else
00976                 spacing = (spacing+1)/2;
00977         }
00978     }
00979 
00980     
00981     if ( (*motionY >= leftMY) && (*motionY < rightMY) &&
00982          (*motionX >= leftMX) && (*motionX < rightMX) ) {
00983         diff = LumAddMotionError(currentBlock, block, prev, by, bx, *motionY, *motionX, bestDiff);
00984     } else {
00985         diff = 0x7fffffff;
00986     }
00987 
00988     if ( bestDiff < diff ) {
00989         *motionY = centerY;
00990         *motionX = centerX;
00991     }
00992     else
00993         bestDiff = diff;
00994 
00995     return bestDiff;
00996 }
00997 
00998 
00999 
01000 
01001 
01002 
01003 
01004 
01005 
01006 
01007 
01008 
01009 
01010 static int32
01011 FindBestMatchSubSample(block, currentBlock, prev, by, bx, motionY, motionX,
01012                      bestSoFar, searchRange)
01013     LumBlock block;
01014     LumBlock currentBlock;
01015     MpegFrame *prev;
01016     int by;
01017     int bx;
01018     int *motionY;
01019     int *motionX;
01020     int32 bestSoFar;
01021     int searchRange;
01022 {
01023     
01024 
01025     return FindBestMatchExhaust(block, currentBlock, prev,
01026                                 by, bx, motionY, motionX, bestSoFar, searchRange);
01027 }
01028 
01029 
01030 
01031 
01032 
01033 
01034 
01035 
01036 
01037 
01038 
01039 
01040 
01041 
01042 
01043 
01044 static void
01045 BMotionSearchNoInterp(currentBlock, prev, next, by, bx, fmy, fmx, forwardErr,
01046                       bmy, bmx, backErr, backNeeded)
01047     LumBlock currentBlock;
01048     MpegFrame *prev;
01049     MpegFrame *next;
01050     int by;
01051     int bx;
01052     int *fmy;
01053     int *fmx;
01054     int32 *forwardErr;
01055     int *bmy;
01056     int *bmx;
01057     int32 *backErr;
01058     boolean backNeeded;
01059 {
01060     
01061     switch(psearchAlg) {
01062         case PSEARCH_SUBSAMPLE:
01063             *forwardErr = PSubSampleSearch(currentBlock, prev, by, bx, 
01064                                            fmy, fmx, searchRangeB);
01065             *backErr = PSubSampleSearch(currentBlock, next, by, bx, 
01066                                         bmy, bmx, searchRangeB);
01067             break;
01068         case PSEARCH_EXHAUSTIVE:
01069             *forwardErr = PLocalSearch(currentBlock, prev, by, bx, fmy, fmx, 
01070                                        0x7fffffff, searchRangeB);
01071             if ( backNeeded ) {
01072                 *backErr = PLocalSearch(currentBlock, next, by, bx, bmy, bmx, 
01073                                         0x7fffffff, searchRangeB);
01074             } else {
01075                 *backErr = PLocalSearch(currentBlock, next, by, bx, bmy, bmx, 
01076                                         *forwardErr, searchRangeB);
01077             }
01078             break;
01079         case PSEARCH_LOGARITHMIC:
01080             *forwardErr = PLogarithmicSearch(currentBlock, prev, by, bx, 
01081                                              fmy, fmx, searchRangeB);
01082             *backErr = PLogarithmicSearch(currentBlock, next, by, bx, 
01083                                           bmy, bmx, searchRangeB);
01084             break;
01085         case PSEARCH_TWOLEVEL:
01086             *forwardErr = PTwoLevelSearch(currentBlock, prev, by, bx, fmy, fmx, 
01087                                           0x7fffffff, searchRangeB);
01088             if ( backNeeded ) {
01089                 *backErr = PTwoLevelSearch(currentBlock, next, by, bx, bmy, bmx, 
01090                                            0x7fffffff, searchRangeB);
01091             } else {
01092                 *backErr = PTwoLevelSearch(currentBlock, next, by, bx, bmy, bmx, 
01093                                            *forwardErr, searchRangeB);
01094             }
01095             break;
01096         default:
01097             fprintf(stderr, "ERROR:  Illegal PSEARCH ALG:  %d\n", psearchAlg);
01098             exit(1);    
01099             break;
01100     }
01101 }
01102 
01103 
01104 
01105 
01106 
01107 
01108 
01109 
01110 
01111 
01112 
01113 
01114 
01115 
01116 #ifdef UNUSED_PROCEDURES
01117 
01118 
01119 
01120 
01121 
01122 
01123 
01124 
01125 
01126 
01127 
01128 
01129 boolean
01130 ValidBMotion(by, bx, mode, fmy, fmx, bmy, bmx)
01131     int by;
01132     int bx;
01133     int mode;
01134     int fmy;
01135     int fmx;
01136     int bmy;
01137     int bmx;
01138 {
01139     if ( mode != MOTION_BACKWARD ) {
01140         
01141         if ( (by*DCTSIZE+(fmy-1)/2 < 0) || ((by+2)*DCTSIZE+(fmy+1)/2-1 >= Fsize_y) ) {
01142             return FALSE;
01143         }
01144         if ( (bx*DCTSIZE+(fmx-1)/2 < 0) || ((bx+2)*DCTSIZE+(fmx+1)/2-1 >= Fsize_x) ) {
01145             return FALSE;
01146         }
01147     }
01148 
01149     if ( mode != MOTION_FORWARD ) {
01150         
01151         if ( (by*DCTSIZE+(bmy-1)/2 < 0) || ((by+2)*DCTSIZE+(bmy+1)/2-1 >= Fsize_y) ) {
01152             return FALSE;
01153         }
01154         if ( (bx*DCTSIZE+(bmx-1)/2 < 0) || ((bx+2)*DCTSIZE+(bmx+1)/2-1 >= Fsize_x) ) {
01155             return FALSE;
01156         }
01157     }
01158 
01159     return TRUE;
01160 }
01161 
01162 
01163 #endif