[svn] / branches / dev-api-4 / xvidcore / src / motion / motion_est.c Repository:
ViewVC logotype

Diff of /branches/dev-api-4/xvidcore/src/motion/motion_est.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 348, Sun Jul 28 17:10:39 2002 UTC revision 677, Tue Nov 26 23:44:11 2002 UTC
# Line 1  Line 1 
1  /**************************************************************************  /*****************************************************************************
2   *   *
3   *      XVID MPEG-4 VIDEO CODEC   *      XVID MPEG-4 VIDEO CODEC
4   *      motion estimation   *  - Motion Estimation module -
5   *   *
6   *      This program is an implementation of a part of one or more MPEG-4   *  Copyright(C) 2002 Christoph Lampert <gruel@web.de>
7   *      Video tools as specified in ISO/IEC 14496-2 standard.  Those intending   *               2002 Michael Militzer <michael@xvid.org>
  *      to use this software module in hardware or software products are  
  *      advised that its use may infringe existing patents or copyrights, and  
  *      any such use would be at such party's own risk.  The original  
  *      developer of this software module and his/her company, and subsequent  
  *      editors and their companies, will have no liability for use of this  
  *      software or modifications or derivatives thereof.  
8   *   *
9   *      This program is free software; you can redistribute it and/or modify   *  This file is part of XviD, a free MPEG-4 video encoder/decoder
10   *      it under the terms of the GNU General Public License as published by   *
11     *  XviD is free software; you can redistribute it and/or modify it
12     *  under the terms of the GNU General Public License as published by
13   *      the Free Software Foundation; either version 2 of the License, or   *      the Free Software Foundation; either version 2 of the License, or
14   *      (at your option) any later version.   *      (at your option) any later version.
15   *   *
# Line 24  Line 20 
20   *   *
21   *      You should have received a copy of the GNU General Public License   *      You should have received a copy of the GNU General Public License
22   *      along with this program; if not, write to the Free Software   *      along with this program; if not, write to the Free Software
23   *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
24   *   *
25   *************************************************************************/   *  Under section 8 of the GNU General Public License, the copyright
26     *  holders of XVID explicitly forbid distribution in the following
27  /**************************************************************************   *  countries:
28     *
29     *    - Japan
30     *    - United States of America
31   *   *
32   *  Modifications:   *  Linking XviD statically or dynamically with other modules is making a
33     *  combined work based on XviD.  Thus, the terms and conditions of the
34     *  GNU General Public License cover the whole combination.
35   *   *
36   *      01.05.2002      updated MotionEstimationBVOP   *  As a special exception, the copyright holders of XviD give you
37   *      25.04.2002 partial prevMB conversion   *  permission to link XviD with independent modules that communicate with
38   *  22.04.2002 remove some compile warning by chenm001 <chenm001@163.com>   *  XviD solely through the VFW1.1 and DShow interfaces, regardless of the
39   *  14.04.2002 added MotionEstimationBVOP()   *  license terms of these independent modules, and to copy and distribute
40   *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between   *  the resulting combined work under terms of your choice, provided that
41   *             EPZS and EPZS^2   *  every copy of the combined work is accompanied by a complete copy of
42   *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop   *  the source code of XviD (the version of XviD used to produce the
43   *             PMVFast_Refine to support multiple searches with different start points   *  combined work), being distributed under the terms of the GNU General
44   *  07.01.2002 uv-block-based interpolation   *  Public License plus this exception.  An independent module is a module
45   *  06.01.2002 INTER/INTRA-decision is now done before any SEARCH8 (speedup)   *  which is not derived from or based on XviD.
  *             changed INTER_BIAS to 150 (as suggested by suxen_drol)  
  *             removed halfpel refinement step in PMVfastSearch8 + quality=5  
  *             added new quality mode = 6 which performs halfpel refinement  
  *             filesize difference between quality 5 and 6 is smaller than 1%  
  *             (Isibaar)  
  *  31.12.2001 PMVfastSearch16 and PMVfastSearch8 (gruel)  
  *  30.12.2001 get_range/MotionSearchX simplified; blue/green bug fix  
  *  22.12.2001 commented best_point==99 check  
  *  19.12.2001 modified get_range (purple bug fix)  
  *  15.12.2001 moved pmv displacement from mbprediction  
  *  02.12.2001 motion estimation/compensation split (Isibaar)  
  *  16.11.2001 rewrote/tweaked search algorithms; pross@cs.rmit.edu.au  
  *  10.11.2001 support for sad16/sad8 functions  
  *  28.08.2001 reactivated MODE_INTER4V for EXT_MODE  
  *  24.08.2001 removed MODE_INTER4V_Q, disabled MODE_INTER4V for EXT_MODE  
  *  22.08.2001 added MODE_INTER4V_Q  
  *  20.08.2001 added pragma to get rid of internal compiler error with VC6  
  *             idea by Cyril. Thanks.  
46   *   *
47   *  Michael Militzer <isibaar@videocoding.de>   *  Note that people who make modified versions of XviD are not obligated
48     *  to grant this special exception for their modified versions; it is
49     *  their choice whether to do so.  The GNU General Public License gives
50     *  permission to release a modified version without this exception; this
51     *  exception also makes it possible to release a modified version which
52     *  carries forward this exception.
53   *   *
54   **************************************************************************/   * $Id: motion_est.c,v 1.54 2002-11-26 23:44:10 edgomez Exp $
55     *
56     *************************************************************************/
57    
58  #include <assert.h>  #include <assert.h>
59  #include <stdio.h>  #include <stdio.h>
# Line 99  Line 89 
89    
90    
91    
92  // mv.length table  /* mv.length table */
93  static const uint32_t mvtab[33] = {  static const uint32_t mvtab[33] = {
94          1, 2, 3, 4, 6, 7, 7, 7,          1, 2, 3, 4, 6, 7, 7, 7,
95          9, 9, 9, 10, 10, 10, 10, 10,          9, 9, 9, 10, 10, 10, 10, 10,
# Line 174  Line 164 
164          static const VECTOR zeroMV = { 0, 0 };          static const VECTOR zeroMV = { 0, 0 };
165          VECTOR predMV;          VECTOR predMV;
166    
167          int32_t x, y;          uint32_t x, y;
168          int32_t iIntra = 0;          uint32_t iIntra = 0;
169          VECTOR pmv;          VECTOR pmv;
170    
171          if (sadInit)          if (sadInit)
# Line 389  Line 379 
379      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \      {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } \
380  }  }
381    
382    #if 0
383  /* too slow and not fully functional at the moment */  /* too slow and not fully functional at the moment */
 /*  
384  int32_t ZeroSearch16(  int32_t ZeroSearch16(
385                                          const uint8_t * const pRef,                                          const uint8_t * const pRef,
386                                          const uint8_t * const pRefH,                                          const uint8_t * const pRefH,
# Line 429  Line 419 
419          return iSAD;          return iSAD;
420    
421  }  }
422  */  #endif /* 0 */
423    
424  int32_t  int32_t
425  Diamond16_MainSearch(const uint8_t * const pRef,  Diamond16_MainSearch(const uint8_t * const pRef,
# Line 723  Line 713 
713                                                  const uint8_t * const cur,                                                  const uint8_t * const cur,
714                                                  const int x,                                                  const int x,
715                                                  const int y,                                                  const int y,
716                                             int start_x,                                                  const int start_xi,
717                                             int start_y,                                                  const int start_yi,
718                                             int iMinSAD,                                             int iMinSAD,
719                                             VECTOR * const currMV,                                             VECTOR * const currMV,
720                                             const int center_x,                                             const int center_x,
# Line 741  Line 731 
731  {  {
732    
733          int32_t iSAD;          int32_t iSAD;
734            int start_x = start_xi, start_y = start_yi;
735    
736  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
737    
# Line 754  Line 745 
745    
746                  do {                  do {
747                          iDirection = 0;                          iDirection = 0;
748                          if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)                          if (bDirection & 1)     /*we only want to check left if we came from the right (our last motion was to the left, up-left or down-left) */
749                                  CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);                                  CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
750    
751                          if (bDirection & 2)                          if (bDirection & 2)
# Line 768  Line 759 
759    
760                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
761    
762                          if (iDirection)         //checking if anything found                          if (iDirection)         /*checking if anything found */
763                          {                          {
764                                  bDirection = iDirection;                                  bDirection = iDirection;
765                                  iDirection = 0;                                  iDirection = 0;
766                                  start_x = currMV->x;                                  start_x = currMV->x;
767                                  start_y = currMV->y;                                  start_y = currMV->y;
768                                  if (bDirection & 3)     //our candidate is left or right                                  if (bDirection & 3)     /*our candidate is left or right */
769                                  {                                  {
770                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
771                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);                                          CHECK_MV16_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
772                                  } else                  // what remains here is up or down                                  } else                  /* what remains here is up or down */
773                                  {                                  {
774                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);                                          CHECK_MV16_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
775                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
# Line 789  Line 780 
780                                          start_x = currMV->x;                                          start_x = currMV->x;
781                                          start_y = currMV->y;                                          start_y = currMV->y;
782                                  }                                  }
783                          } else                          //about to quit, eh? not so fast....                          } else                          /*about to quit, eh? not so fast.... */
784                          {                          {
785                                  switch (bDirection) {                                  switch (bDirection) {
786                                  case 2:                                  case 2:
# Line 849  Line 840 
840                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
841                                                                                           start_y + iDiamondSize, 1 + 8);                                                                                           start_y + iDiamondSize, 1 + 8);
842                                          break;                                          break;
843                                  default:                //1+2+4+8 == we didn't find anything at all                                  default:                /*1+2+4+8 == we didn't find anything at all */
844                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
845                                                                                           start_y - iDiamondSize, 1 + 4);                                                                                           start_y - iDiamondSize, 1 + 4);
846                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,                                          CHECK_MV16_CANDIDATE_DIR(start_x - iDiamondSize,
# Line 861  Line 852 
852                                          break;                                          break;
853                                  }                                  }
854                                  if (!iDirection)                                  if (!iDirection)
855                                          break;          //ok, the end. really                                          break;          /*ok, the end. really */
856                                  else {                                  else {
857                                          bDirection = iDirection;                                          bDirection = iDirection;
858                                          start_x = currMV->x;                                          start_x = currMV->x;
# Line 869  Line 860 
860                                  }                                  }
861                          }                          }
862                  }                  }
863                  while (1);                              //forever                  while (1);                              /*forever */
         }  
         return iMinSAD;  
 }  
   
 #define CHECK_MV16_F_INTERPOL(X,Y) { \  
   if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \  
     && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \  
   { \  
     iSAD = sad16bi( cur, \  
                         get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \  
                         get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \  
                         iEdgedWidth); \  
     iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\  
     iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); } } \  
 }  
   
 #define CHECK_MV16_F_INTERPOL_FOUND(X,Y) { \  
   if ( ((X) <= f_max_dx) && ((X) >= f_min_dx) \  
     && ((Y) <= f_max_dy) && ((Y) >= f_min_dy) ) \  
   { \  
     iSAD = sad16bi( cur, \  
                         get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \  
                         get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, b_currMV->x, b_currMV->y, iEdgedWidth),   \  
                         iEdgedWidth); \  
     iSAD += calc_delta_16((X) - f_center_x, (Y) - f_center_y, (uint8_t)f_iFcode, iQuant);\  
     iSAD += calc_delta_16(b_currMV->x - b_center_x, b_currMV->y - b_center_y, (uint8_t)b_iFcode, iQuant);\  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; f_currMV->x=(X); f_currMV->y=(Y); iFound=0;} } \  
 }  
   
 #define CHECK_MV16_B_INTERPOL(X,Y) { \  
   if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \  
     && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \  
   { \  
     iSAD = sad16bi( cur, \  
                         get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \  
                         get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \  
                         iEdgedWidth); \  
     iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\  
     iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); } } \  
 }  
   
 #define CHECK_MV16_B_INTERPOL_FOUND(X,Y) { \  
   if ( ((X) <= b_max_dx) && ((X) >= b_min_dx) \  
     && ((Y) <= b_max_dy) && ((Y) >= b_min_dy) ) \  
   { \  
     iSAD = sad16bi( cur, \  
                         get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, x, y, 16, f_currMV->x, f_currMV->y, iEdgedWidth),   \  
                         get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, x, y, 16, X, Y, iEdgedWidth),       \  
                         iEdgedWidth); \  
     iSAD += calc_delta_16(f_currMV->x - f_center_x, f_currMV->y - f_center_y, (uint8_t)f_iFcode, iQuant);\  
     iSAD += calc_delta_16((X) - b_center_x, (Y) - b_center_y, (uint8_t)b_iFcode, iQuant);\  
     if (iSAD < iMinSAD) \  
     {  iMinSAD=iSAD; b_currMV->x=(X); b_currMV->y=(Y); iFound=0;} } \  
864  }  }
865    
 int32_t  
 Diamond16_InterpolMainSearch(  
                                         const uint8_t * const f_pRef,  
                                          const uint8_t * const f_pRefH,  
                                          const uint8_t * const f_pRefV,  
                                          const uint8_t * const f_pRefHV,  
   
                                          const uint8_t * const cur,  
   
                                         const uint8_t * const b_pRef,  
                                          const uint8_t * const b_pRefH,  
                                          const uint8_t * const b_pRefV,  
                                          const uint8_t * const b_pRefHV,  
   
                                          const int x,  
                                          const int y,  
   
                                    const int f_start_x,  
                                    const int f_start_y,  
                                    const int b_start_x,  
                                    const int b_start_y,  
   
                                    int iMinSAD,  
                                    VECTOR * const f_currMV,  
                                    VECTOR * const b_currMV,  
   
                                    const int f_center_x,  
                                    const int f_center_y,  
                                    const int b_center_x,  
                                    const int b_center_y,  
   
                                     const int32_t f_min_dx,  
                                         const int32_t f_max_dx,  
                                         const int32_t f_min_dy,  
                                         const int32_t f_max_dy,  
   
                                     const int32_t b_min_dx,  
                                         const int32_t b_max_dx,  
                                         const int32_t b_min_dy,  
                                         const int32_t b_max_dy,  
   
                                         const int32_t iEdgedWidth,  
                                         const int32_t iDiamondSize,  
   
                                         const int32_t f_iFcode,  
                                         const int32_t b_iFcode,  
   
                                         const int32_t iQuant,  
                                         int iFound)  
 {  
 /* Do a diamond search around given starting point, return SAD of best */  
   
         int32_t iSAD;  
   
         VECTOR f_backupMV;  
         VECTOR b_backupMV;  
   
         f_currMV->x = f_start_x;  
         f_currMV->y = f_start_y;  
         b_currMV->x = b_start_x;  
         b_currMV->y = b_start_y;  
   
         do  
         {  
                 iFound = 1;  
   
                 f_backupMV = *f_currMV;  
   
                 CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x - iDiamondSize, f_backupMV.y);  
                 CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x + iDiamondSize, f_backupMV.y);  
                 CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y - iDiamondSize);  
                 CHECK_MV16_F_INTERPOL_FOUND(f_backupMV.x, f_backupMV.y + iDiamondSize);  
   
                 b_backupMV = *b_currMV;  
   
                 CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x - iDiamondSize, b_backupMV.y);  
                 CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x + iDiamondSize, b_backupMV.y);  
                 CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y - iDiamondSize);  
                 CHECK_MV16_B_INTERPOL_FOUND(b_backupMV.x, b_backupMV.y + iDiamondSize);  
   
         } while (!iFound);  
   
866          return iMinSAD;          return iMinSAD;
867  }  }
868    
 /* Sorry, these MACROS really got too large... I'll turn them into function soon! */  
   
 #define CHECK_MV16_DIRECT_FOUND(X,Y) \  
         if ( (X)>=(-32) && (X)<=(31) && ((Y)>=-32) && ((Y)<=31) ) \  
         { int k;\  
         VECTOR mvs,b_mvs;       \  
         iSAD = 0;\  
         for (k = 0; k < 4; k++) {       \  
                                         mvs.x = (int32_t) ((TRB * directmv[k].x) / TRD + (X));          \  
                     b_mvs.x = (int32_t) (((X) == 0)                                                     \  
                                                                                 ? ((TRB - TRD) * directmv[k].x) / TRD   \  
                                             : mvs.x - directmv[k].x);                           \  
                                                                                                                                                                 \  
                     mvs.y = (int32_t) ((TRB * directmv[k].y) / TRD + (Y));              \  
                         b_mvs.y = (int32_t) (((Y) == 0)                                                         \  
                                                                                 ? ((TRB - TRD) * directmv[k].y) / TRD   \  
                                             : mvs.y - directmv[k].y);                           \  
                                                                                                                                                                 \  
   if ( (mvs.x <= max_dx) && (mvs.x >= min_dx) \  
     && (mvs.y <= max_dy) && (mvs.y >= min_dy)  \  
         && (b_mvs.x <= max_dx) && (b_mvs.x >= min_dx)  \  
     && (b_mvs.y <= max_dy) && (b_mvs.y >= min_dy) ) { \  
             iSAD += sad8bi( cur + 8*(k&1) + 8*(k>>1)*iEdgedWidth,                                                                                                       \  
                         get_ref(f_pRef, f_pRefH, f_pRefV, f_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \  
                                         mvs.x, mvs.y, iEdgedWidth),                                                             \  
                         get_ref(b_pRef, b_pRefH, b_pRefV, b_pRefHV, 2*x+(k&1), 2*y+(k>>1), 8, \  
                                         b_mvs.x, b_mvs.y, iEdgedWidth),                                                         \  
                         iEdgedWidth); \  
                 }       \  
         else    \  
                 iSAD = 65535;   \  
         } \  
         iSAD += calc_delta_16((X),(Y), 1, iQuant);\  
         if (iSAD < iMinSAD) \  
             {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iFound=0; } \  
 }  
   
   
   
 int32_t  
 Diamond16_DirectMainSearch(  
                                         const uint8_t * const f_pRef,  
                                         const uint8_t * const f_pRefH,  
                                         const uint8_t * const f_pRefV,  
                                         const uint8_t * const f_pRefHV,  
   
                                         const uint8_t * const cur,  
   
                                         const uint8_t * const b_pRef,  
                                         const uint8_t * const b_pRefH,  
                                         const uint8_t * const b_pRefV,  
                                         const uint8_t * const b_pRefHV,  
   
                                         const int x,  
                                         const int y,  
   
                                         const int TRB,  
                                         const int TRD,  
   
                                     const int start_x,  
                                     const int start_y,  
   
                                     int iMinSAD,  
                                     VECTOR * const currMV,  
                                         const VECTOR * const directmv,  
   
                                     const int32_t min_dx,  
                                         const int32_t max_dx,  
                                         const int32_t min_dy,  
                                         const int32_t max_dy,  
   
                                         const int32_t iEdgedWidth,  
                                         const int32_t iDiamondSize,  
   
                                         const int32_t iQuant,  
                                         int iFound)  
 {  
 /* Do a diamond search around given starting point, return SAD of best */  
   
         int32_t iSAD;  
   
         VECTOR backupMV;  
   
         currMV->x = start_x;  
         currMV->y = start_y;  
   
 /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */  
   
         do  
         {  
                 iFound = 1;  
   
                 backupMV = *currMV;  
   
                 CHECK_MV16_DIRECT_FOUND(backupMV.x - iDiamondSize, backupMV.y);  
                 CHECK_MV16_DIRECT_FOUND(backupMV.x + iDiamondSize, backupMV.y);  
                 CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y - iDiamondSize);  
                 CHECK_MV16_DIRECT_FOUND(backupMV.x, backupMV.y + iDiamondSize);  
   
         } while (!iFound);  
   
         return iMinSAD;  
 }  
   
   
869  int32_t  int32_t
870  AdvDiamond8_MainSearch(const uint8_t * const pRef,  AdvDiamond8_MainSearch(const uint8_t * const pRef,
871                                             const uint8_t * const pRefH,                                             const uint8_t * const pRefH,
# Line 1128  Line 874 
874                                             const uint8_t * const cur,                                             const uint8_t * const cur,
875                                             const int x,                                             const int x,
876                                             const int y,                                             const int y,
877                                             int start_x,                                             const int start_xi,
878                                             int start_y,                                             const int start_yi,
879                                             int iMinSAD,                                             int iMinSAD,
880                                             VECTOR * const currMV,                                             VECTOR * const currMV,
881                                             const int center_x,                                             const int center_x,
# Line 1146  Line 892 
892  {  {
893    
894          int32_t iSAD;          int32_t iSAD;
895            int start_x = start_xi, start_y = start_yi;
896    
897  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */  /* directions: 1 - left (x-1); 2 - right (x+1), 4 - up (y-1); 8 - down (y+1) */
898    
# Line 1159  Line 906 
906    
907                  do {                  do {
908                          iDirection = 0;                          iDirection = 0;
909                          if (bDirection & 1)     //we only want to check left if we came from the right (our last motion was to the left, up-left or down-left)                          if (bDirection & 1)     /*we only want to check left if we came from the right (our last motion was to the left, up-left or down-left) */
910                                  CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);                                  CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
911    
912                          if (bDirection & 2)                          if (bDirection & 2)
# Line 1173  Line 920 
920    
921                          /* now we're doing diagonal checks near our candidate */                          /* now we're doing diagonal checks near our candidate */
922    
923                          if (iDirection)         //checking if anything found                          if (iDirection)         /*checking if anything found */
924                          {                          {
925                                  bDirection = iDirection;                                  bDirection = iDirection;
926                                  iDirection = 0;                                  iDirection = 0;
927                                  start_x = currMV->x;                                  start_x = currMV->x;
928                                  start_y = currMV->y;                                  start_y = currMV->y;
929                                  if (bDirection & 3)     //our candidate is left or right                                  if (bDirection & 3)     /*our candidate is left or right */
930                                  {                                  {
931                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y + iDiamondSize, 8);
932                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);                                          CHECK_MV8_CANDIDATE_DIR(start_x, start_y - iDiamondSize, 4);
933                                  } else                  // what remains here is up or down                                  } else                  /* what remains here is up or down */
934                                  {                                  {
935                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);                                          CHECK_MV8_CANDIDATE_DIR(start_x + iDiamondSize, start_y, 2);
936                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize, start_y, 1);
# Line 1194  Line 941 
941                                          start_x = currMV->x;                                          start_x = currMV->x;
942                                          start_y = currMV->y;                                          start_y = currMV->y;
943                                  }                                  }
944                          } else                          //about to quit, eh? not so fast....                          } else                          /*about to quit, eh? not so fast.... */
945                          {                          {
946                                  switch (bDirection) {                                  switch (bDirection) {
947                                  case 2:                                  case 2:
# Line 1253  Line 1000 
1000                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1001                                                                                          start_y + iDiamondSize, 1 + 8);                                                                                          start_y + iDiamondSize, 1 + 8);
1002                                          break;                                          break;
1003                                  default:                //1+2+4+8 == we didn't find anything at all                                  default:                /*1+2+4+8 == we didn't find anything at all */
1004                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
1005                                                                                          start_y - iDiamondSize, 1 + 4);                                                                                          start_y - iDiamondSize, 1 + 4);
1006                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,                                          CHECK_MV8_CANDIDATE_DIR(start_x - iDiamondSize,
# Line 1265  Line 1012 
1012                                          break;                                          break;
1013                                  }                                  }
1014                                  if (!(iDirection))                                  if (!(iDirection))
1015                                          break;          //ok, the end. really                                          break;          /*ok, the end. really */
1016                                  else {                                  else {
1017                                          bDirection = iDirection;                                          bDirection = iDirection;
1018                                          start_x = currMV->x;                                          start_x = currMV->x;
# Line 1273  Line 1020 
1020                                  }                                  }
1021                          }                          }
1022                  }                  }
1023                  while (1);                              //forever                  while (1);                              /*forever */
1024          }          }
1025          return iMinSAD;          return iMinSAD;
1026  }  }
# Line 1425  Line 1172 
1172          }          }
1173    
1174          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
         //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);  
1175          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
1176    
1177          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
# Line 1483  Line 1229 
1229          if ((iMinSAD < 256) ||          if ((iMinSAD < 256) ||
1230                  ((MVequal(*currMV, prevMB->mvs[0])) &&                  ((MVequal(*currMV, prevMB->mvs[0])) &&
1231                   ((int32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
1232                  if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode                  if (iMinSAD < (int)(2 * iQuant))        /* high chances for SKIP-mode */
1233                  {                  {
1234                          if (!MVzero(*currMV)) {                          if (!MVzero(*currMV)) {
1235                                  iMinSAD += MV16_00_BIAS;                                  iMinSAD += MV16_00_BIAS;
1236                                  CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures                                  CHECK_MV16_ZERO;        /* (0,0) saves space for letterboxed pictures */
1237                                  iMinSAD -= MV16_00_BIAS;                                  iMinSAD -= MV16_00_BIAS;
1238                          }                          }
1239                  }                  }
# Line 1512  Line 1258 
1258  */  */
1259    
1260          if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))          if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))
1261                  iDiamondSize = 1;               // halfpel!                  iDiamondSize = 1;               /* halfpel! */
1262          else          else
1263                  iDiamondSize = 2;               // halfpel!                  iDiamondSize = 2;               /* halfpel! */
1264    
1265          if (!(MotionFlags & PMV_HALFPELDIAMOND16))          if (!(MotionFlags & PMV_HALFPELDIAMOND16))
1266                  iDiamondSize *= 2;                  iDiamondSize *= 2;
# Line 1526  Line 1272 
1272     If MV is (0,0) subtract offset.     If MV is (0,0) subtract offset.
1273  */  */
1274    
1275  // (0,0) is always possible  /* (0,0) is always possible */
1276    
1277          if (!MVzero(pmv[0]))          if (!MVzero(pmv[0]))
1278                  CHECK_MV16_ZERO;                  CHECK_MV16_ZERO;
1279    
1280  // previous frame MV is always possible  /* previous frame MV is always possible */
1281    
1282          if (!MVzero(prevMB->mvs[0]))          if (!MVzero(prevMB->mvs[0]))
1283                  if (!MVequal(prevMB->mvs[0], pmv[0]))                  if (!MVequal(prevMB->mvs[0], pmv[0]))
1284                          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);                          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
1285    
1286  // left neighbour, if allowed  /* left neighbour, if allowed */
1287    
1288          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
1289                  if (!MVequal(pmv[1], prevMB->mvs[0]))                  if (!MVequal(pmv[1], prevMB->mvs[0]))
# Line 1549  Line 1295 
1295    
1296                                  CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);                                  CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
1297                          }                          }
1298  // top neighbour, if allowed  /* top neighbour, if allowed */
1299          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
1300                  if (!MVequal(pmv[2], prevMB->mvs[0]))                  if (!MVequal(pmv[2], prevMB->mvs[0]))
1301                          if (!MVequal(pmv[2], pmv[0]))                          if (!MVequal(pmv[2], pmv[0]))
# Line 1560  Line 1306 
1306                                          }                                          }
1307                                          CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);                                          CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
1308    
1309  // top right neighbour, if allowed  /* top right neighbour, if allowed */
1310                                          if (!MVzero(pmv[3]))                                          if (!MVzero(pmv[3]))
1311                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))                                                  if (!MVequal(pmv[3], prevMB->mvs[0]))
1312                                                          if (!MVequal(pmv[3], pmv[0]))                                                          if (!MVequal(pmv[3], pmv[0]))
# Line 1663  Line 1409 
1409  */  */
1410    
1411    PMVfast16_Terminate_with_Refine:    PMVfast16_Terminate_with_Refine:
1412          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)  /* perform final half-pel step  */
1413                  iMinSAD =                  iMinSAD =
1414                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
1415                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
# Line 1688  Line 1434 
1434                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1435                                          const int x,                                          const int x,
1436                                          const int y,                                          const int y,
1437                                          int32_t start_x,                                          const int32_t start_x,
1438                                          int32_t start_y,                                          const int32_t start_y,
1439                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1440                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1441                                     const int center_x,                                     const int center_x,
# Line 1724  Line 1470 
1470          if (iDirection) {          if (iDirection) {
1471                  while (!iFound) {                  while (!iFound) {
1472                          iFound = 1;                          iFound = 1;
1473                          backupMV = *currMV;     // since iDirection!=0, this is well defined!                          backupMV = *currMV;     /* since iDirection!=0, this is well defined! */
1474                          iDirectionBackup = iDirection;                          iDirectionBackup = iDirection;
1475    
1476                          if (iDirectionBackup != 2)                          if (iDirectionBackup != 2)
# Line 1758  Line 1504 
1504                                          const uint8_t * const cur,                                          const uint8_t * const cur,
1505                                          const int x,                                          const int x,
1506                                          const int y,                                          const int y,
1507                                          int32_t start_x,                                     const int32_t start_x,
1508                                          int32_t start_y,                                     const int32_t start_y,
1509                                          int32_t iMinSAD,                                          int32_t iMinSAD,
1510                                          VECTOR * const currMV,                                          VECTOR * const currMV,
1511                                     const int center_x,                                     const int center_x,
# Line 2013  Line 1759 
1759          VECTOR backupMV;          VECTOR backupMV;
1760          VECTOR startMV;          VECTOR startMV;
1761    
1762  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  /*  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount; */
1763          const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;          const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
1764    
1765           int32_t threshA, threshB;           int32_t threshA, threshB;
# Line 2040  Line 1786 
1786          }          }
1787    
1788          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
         //bPredEq = get_pmvdata(pMBs, (x >> 1), (y >> 1), iWcount, iSubBlock, pmv, psad);  
1789          bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, (x >> 1), (y >> 1), iSubBlock, pmv, psad);
1790    
1791          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
# Line 2068  Line 1813 
1813  */  */
1814    
1815    
1816  // Prepare for main loop  /* Prepare for main loop  */
1817    
1818    if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
1819        MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
# Line 2112  Line 1857 
1857  */  */
1858    
1859          if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))          if ((!MVzero(pmv[0])) || (threshB < 1536 / 4) || (bPredEq))
1860                  iDiamondSize = 1;               // 1 halfpel!                  iDiamondSize = 1;               /* 1 halfpel! */
1861          else          else
1862                  iDiamondSize = 2;               // 2 halfpel = 1 full pixel!                  iDiamondSize = 2;               /* 2 halfpel = 1 full pixel! */
1863    
1864          if (!(MotionFlags & PMV_HALFPELDIAMOND8))          if (!(MotionFlags & PMV_HALFPELDIAMOND8))
1865                  iDiamondSize *= 2;                  iDiamondSize *= 2;
# Line 2127  Line 1872 
1872     If MV is (0,0) subtract offset.     If MV is (0,0) subtract offset.
1873  */  */
1874    
1875  // the median prediction might be even better than mv16  /* the median prediction might be even better than mv16 */
1876    
1877          if (!MVequal(pmv[0], startMV))          if (!MVequal(pmv[0], startMV))
1878                  CHECK_MV8_CANDIDATE(center_x, center_y);                  CHECK_MV8_CANDIDATE(center_x, center_y);
1879    
1880  // (0,0) if needed  /* (0,0) if needed */
1881          if (!MVzero(pmv[0]))          if (!MVzero(pmv[0]))
1882                  if (!MVzero(startMV))                  if (!MVzero(startMV))
1883                          CHECK_MV8_ZERO;                          CHECK_MV8_ZERO;
1884    
1885  // previous frame MV if needed  /* previous frame MV if needed */
1886          if (!MVzero(prevMB->mvs[iSubBlock]))          if (!MVzero(prevMB->mvs[iSubBlock]))
1887                  if (!MVequal(prevMB->mvs[iSubBlock], startMV))                  if (!MVequal(prevMB->mvs[iSubBlock], startMV))
1888                          if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))                          if (!MVequal(prevMB->mvs[iSubBlock], pmv[0]))
# Line 2153  Line 1898 
1898                          goto PMVfast8_Terminate_with_Refine;                          goto PMVfast8_Terminate_with_Refine;
1899          }          }
1900    
1901  // left neighbour, if allowed and needed  /* left neighbour, if allowed and needed */
1902          if (!MVzero(pmv[1]))          if (!MVzero(pmv[1]))
1903                  if (!MVequal(pmv[1], startMV))                  if (!MVequal(pmv[1], startMV))
1904                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))                          if (!MVequal(pmv[1], prevMB->mvs[iSubBlock]))
# Line 2164  Line 1909 
1909                                          }                                          }
1910                                          CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);                                          CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
1911                                  }                                  }
1912  // top neighbour, if allowed and needed  /* top neighbour, if allowed and needed */
1913          if (!MVzero(pmv[2]))          if (!MVzero(pmv[2]))
1914                  if (!MVequal(pmv[2], startMV))                  if (!MVequal(pmv[2], startMV))
1915                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))                          if (!MVequal(pmv[2], prevMB->mvs[iSubBlock]))
# Line 2176  Line 1921 
1921                                                  }                                                  }
1922                                                  CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);                                                  CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
1923    
1924  // top right neighbour, if allowed and needed  /* top right neighbour, if allowed and needed */
1925                                                  if (!MVzero(pmv[3]))                                                  if (!MVzero(pmv[3]))
1926                                                          if (!MVequal(pmv[3], startMV))                                                          if (!MVequal(pmv[3], startMV))
1927                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))                                                                  if (!MVequal(pmv[3], prevMB->mvs[iSubBlock]))
# Line 2271  Line 2016 
2016  */  */
2017    
2018    PMVfast8_Terminate_with_Refine:    PMVfast8_Terminate_with_Refine:
2019          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   /* perform final half-pel step  */
2020                  iMinSAD =                  iMinSAD =
2021                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2022                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
# Line 2328  Line 2073 
2073    
2074          static MACROBLOCK *oldMBs = NULL;          static MACROBLOCK *oldMBs = NULL;
2075    
2076  //  const MACROBLOCK * const pMB = pMBs + x + y * iWcount;  /*  const MACROBLOCK * const pMB = pMBs + x + y * iWcount; */
2077          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;          const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;
2078          MACROBLOCK *oldMB = NULL;          MACROBLOCK *oldMB = NULL;
2079    
# Line 2340  Line 2085 
2085    
2086          if (oldMBs == NULL) {          if (oldMBs == NULL) {
2087                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));                  oldMBs = (MACROBLOCK *) calloc(iWcount * iHcount, sizeof(MACROBLOCK));
2088  //      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK));  /*      fprintf(stderr,"allocated %d bytes for oldMBs\n",iWcount*iHcount*sizeof(MACROBLOCK)); */
2089          }          }
2090          oldMB = oldMBs + x + y * iWcount;          oldMB = oldMBs + x + y * iWcount;
2091    
# Line 2355  Line 2100 
2100                  max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
2101          }          }
2102          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
         //bPredEq = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);  
2103          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x, y, 0, pmv, psad);
2104    
2105  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
# Line 2365  Line 2109 
2109          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
2110  */  */
2111    
2112  // Prepare for main loop  /* Prepare for main loop  */
2113    
2114          currMV->x = start_x;          currMV->x = start_x;
2115          currMV->y = start_y;          currMV->y = start_y;
# Line 2394  Line 2138 
2138                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,                  calc_delta_16(currMV->x - center_x, currMV->y - center_y,
2139                                            (uint8_t) iFcode, iQuant);                                            (uint8_t) iFcode, iQuant);
2140    
2141  // thresh1 is fixed to 256  /* thresh1 is fixed to 256  */
2142          if ((iMinSAD < 256) ||          if ((iMinSAD < 256) ||
2143                  ((MVequal(*currMV, prevMB->mvs[0])) &&                  ((MVequal(*currMV, prevMB->mvs[0])) &&
2144                   ((int32_t) iMinSAD < prevMB->sad16))) {                   ((int32_t) iMinSAD < prevMB->sad16))) {
# Line 2406  Line 2150 
2150    
2151  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2152    
2153  // previous frame MV  /* previous frame MV  */
2154          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);          CHECK_MV16_CANDIDATE(prevMB->mvs[0].x, prevMB->mvs[0].y);
2155    
2156  // set threshhold based on Min of Prediction and SAD of collocated block  /* set threshhold based on Min of Prediction and SAD of collocated block */
2157  // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want  /* CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want */
2158    
2159          if ((x == 0) && (y == 0)) {          if ((x == 0) && (y == 0)) {
2160                  thresh2 = 512;                  thresh2 = 512;
# Line 2420  Line 2164 
2164                  thresh2 = MIN(psad[0], iSAD) * 6 / 5 + 128;                  thresh2 = MIN(psad[0], iSAD) * 6 / 5 + 128;
2165          }          }
2166    
2167  // MV=(0,0) is often a good choice  /* MV=(0,0) is often a good choice */
2168    
2169          CHECK_MV16_ZERO;          CHECK_MV16_ZERO;
2170    
2171    
2172  // left neighbour, if allowed  /* left neighbour, if allowed */
2173          if (x != 0) {          if (x != 0) {
2174                  if (!(MotionFlags & PMV_HALFPEL16)) {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2175                          pmv[1].x = EVEN(pmv[1].x);                          pmv[1].x = EVEN(pmv[1].x);
# Line 2433  Line 2177 
2177                  }                  }
2178                  CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);                  CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);
2179          }          }
2180  // top neighbour, if allowed  /* top neighbour, if allowed */
2181          if (y != 0) {          if (y != 0) {
2182                  if (!(MotionFlags & PMV_HALFPEL16)) {                  if (!(MotionFlags & PMV_HALFPEL16)) {
2183                          pmv[2].x = EVEN(pmv[2].x);                          pmv[2].x = EVEN(pmv[2].x);
# Line 2441  Line 2185 
2185                  }                  }
2186                  CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);                  CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);
2187    
2188  // top right neighbour, if allowed  /* top right neighbour, if allowed */
2189                  if ((uint32_t) x != (iWcount - 1)) {                  if ((uint32_t) x != (iWcount - 1)) {
2190                          if (!(MotionFlags & PMV_HALFPEL16)) {                          if (!(MotionFlags & PMV_HALFPEL16)) {
2191                                  pmv[3].x = EVEN(pmv[3].x);                                  pmv[3].x = EVEN(pmv[3].x);
# Line 2466  Line 2210 
2210    
2211  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/  /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
2212    
2213          backupMV = prevMB->mvs[0];      // collocated MV          backupMV = prevMB->mvs[0];      /* collocated MV */
2214          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     // acceleration X          backupMV.x += (prevMB->mvs[0].x - oldMB->mvs[0].x);     /* acceleration X */
2215          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     // acceleration Y          backupMV.y += (prevMB->mvs[0].y - oldMB->mvs[0].y);     /* acceleration Y  */
2216    
2217          CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y);          CHECK_MV16_CANDIDATE(backupMV.x, backupMV.y);
2218    
2219  // left neighbour  /* left neighbour */
2220          if (x != 0)          if (x != 0)
2221                  CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB - 1)->mvs[0].x, (prevMB - 1)->mvs[0].y);
2222    
2223  // top neighbour  /* top neighbour  */
2224          if (y != 0)          if (y != 0)
2225                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,                  CHECK_MV16_CANDIDATE((prevMB - iWcount)->mvs[0].x,
2226                                                           (prevMB - iWcount)->mvs[0].y);                                                           (prevMB - iWcount)->mvs[0].y);
2227    
2228  // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  /* right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs  */
2229    
2230          if ((uint32_t) x != iWcount - 1)          if ((uint32_t) x != iWcount - 1)
2231                  CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);                  CHECK_MV16_CANDIDATE((prevMB + 1)->mvs[0].x, (prevMB + 1)->mvs[0].y);
2232    
2233  // bottom neighbour, dito  /* bottom neighbour, dito */
2234          if ((uint32_t) y != iHcount - 1)          if ((uint32_t) y != iHcount - 1)
2235                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,                  CHECK_MV16_CANDIDATE((prevMB + iWcount)->mvs[0].x,
2236                                                           (prevMB + iWcount)->mvs[0].y);                                                           (prevMB + iWcount)->mvs[0].y);
# Line 2556  Line 2300 
2300  /***************        Choose best MV found     **************/  /***************        Choose best MV found     **************/
2301    
2302    EPZS16_Terminate_with_Refine:    EPZS16_Terminate_with_Refine:
2303          if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE16)  /* perform final half-pel step  */
2304                  iMinSAD =                  iMinSAD =
2305                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2306                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,                                                           iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
# Line 2617  Line 2361 
2361    
2362          const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);          const int32_t iSubBlock = ((y & 1) << 1) + (x & 1);
2363    
2364  //  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;  /*  const MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount; */
2365          const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;          const MACROBLOCK *const prevMB = prevMBs + (x >> 1) + (y >> 1) * iWcount;
2366    
2367          int32_t bPredEq;          int32_t bPredEq;
# Line 2638  Line 2382 
2382                  max_dy = EVEN(max_dy);                  max_dy = EVEN(max_dy);
2383          }          }
2384          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */          /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
         //bPredEq = get_pmvdata(pMBs, x >> 1, y >> 1, iWcount, iSubBlock, pmv[0].x, pmv[0].y, psad);  
2385          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);          bPredEq = get_pmvdata2(pMBs, iWcount, 0, x >> 1, y >> 1, iSubBlock, pmv, psad);
2386    
   
2387  /* Step 4: Calculate SAD around the Median prediction.  /* Step 4: Calculate SAD around the Median prediction.
2388          MinSAD=SAD          MinSAD=SAD
2389          If Motion Vector equal to Previous frame motion vector          If Motion Vector equal to Previous frame motion vector
# Line 2649  Line 2391 
2391          If SAD<=256 goto Step 10.          If SAD<=256 goto Step 10.
2392  */  */
2393    
2394  // Prepare for main loop  /* Prepare for main loop  */
2395    
2396    
2397          if (!(MotionFlags & PMV_HALFPEL8)) {          if (!(MotionFlags & PMV_HALFPEL8)) {
# Line 2678  Line 2420 
2420                                           (uint8_t) iFcode, iQuant);                                           (uint8_t) iFcode, iQuant);
2421    
2422    
2423  // thresh1 is fixed to 256  /* thresh1 is fixed to 256  */
2424          if (iMinSAD < 256 / 4) {          if (iMinSAD < 256 / 4) {
2425                  if (MotionFlags & PMV_QUICKSTOP8)                  if (MotionFlags & PMV_QUICKSTOP8)
2426                          goto EPZS8_Terminate_without_Refine;                          goto EPZS8_Terminate_without_Refine;
# Line 2689  Line 2431 
2431  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/  /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/
2432    
2433    
2434  // MV=(0,0) is often a good choice  /* MV=(0,0) is often a good choice */
2435          CHECK_MV8_ZERO;          CHECK_MV8_ZERO;
2436    
2437  // previous frame MV  /* previous frame MV  */
2438          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);          CHECK_MV8_CANDIDATE(prevMB->mvs[iSubBlock].x, prevMB->mvs[iSubBlock].y);
2439    
2440  // left neighbour, if allowed  /* left neighbour, if allowed */
2441          if (psad[1] != MV_MAX_ERROR) {          if (psad[1] != MV_MAX_ERROR) {
2442                  if (!(MotionFlags & PMV_HALFPEL8)) {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2443                          pmv[1].x = EVEN(pmv[1].x);                          pmv[1].x = EVEN(pmv[1].x);
# Line 2703  Line 2445 
2445                  }                  }
2446                  CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);                  CHECK_MV8_CANDIDATE(pmv[1].x, pmv[1].y);
2447          }          }
2448  // top neighbour, if allowed  /* top neighbour, if allowed */
2449          if (psad[2] != MV_MAX_ERROR) {          if (psad[2] != MV_MAX_ERROR) {
2450                  if (!(MotionFlags & PMV_HALFPEL8)) {                  if (!(MotionFlags & PMV_HALFPEL8)) {
2451                          pmv[2].x = EVEN(pmv[2].x);                          pmv[2].x = EVEN(pmv[2].x);
# Line 2711  Line 2453 
2453                  }                  }
2454                  CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);                  CHECK_MV8_CANDIDATE(pmv[2].x, pmv[2].y);
2455    
2456  // top right neighbour, if allowed  /* top right neighbour, if allowed */
2457                  if (psad[3] != MV_MAX_ERROR) {                  if (psad[3] != MV_MAX_ERROR) {
2458                          if (!(MotionFlags & PMV_HALFPEL8)) {                          if (!(MotionFlags & PMV_HALFPEL8)) {
2459                                  pmv[3].x = EVEN(pmv[3].x);                                  pmv[3].x = EVEN(pmv[3].x);
# Line 2721  Line 2463 
2463                  }                  }
2464          }          }
2465    
2466  /*  // this bias is zero anyway, at the moment!  #if     0
2467      /* this bias is zero anyway, at the moment!  */
2468    
2469          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) // && (iMinSAD <= iQuant * 96)          if ( (MVzero(*currMV)) && (!MVzero(pmv[0])) ) /* && (iMinSAD <= iQuant * 96)  */
2470                  iMinSAD -= MV8_00_BIAS;                  iMinSAD -= MV8_00_BIAS;
2471    
2472  */  #endif
2473    
2474  /* Terminate if MinSAD <= T_2  /* Terminate if MinSAD <= T_2
2475     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]     Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1]
# Line 2748  Line 2491 
2491    
2492  /* default: use best prediction as starting point for one call of EPZS_MainSearch */  /* default: use best prediction as starting point for one call of EPZS_MainSearch */
2493    
2494  // there is no EPZS^2 for inter4v at the moment  /* there is no EPZS^2 for inter4v at the moment  */
2495    
2496    if (MotionFlags & PMV_USESQUARES8)    if (MotionFlags & PMV_USESQUARES8)
2497        MainSearchPtr = Square8_MainSearch;        MainSearchPtr = Square8_MainSearch;
# Line 2804  Line 2547 
2547  /***************        Choose best MV found     **************/  /***************        Choose best MV found     **************/
2548    
2549    EPZS8_Terminate_with_Refine:    EPZS8_Terminate_with_Refine:
2550          if (MotionFlags & PMV_HALFPELREFINE8)   // perform final half-pel step          if (MotionFlags & PMV_HALFPELREFINE8)   /* perform final half-pel step  */
2551                  iMinSAD =                  iMinSAD =
2552                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,                          Halfpel8_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,
2553                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,
# Line 2816  Line 2559 
2559          currPMV->y = currMV->y - center_y;          currPMV->y = currMV->y - center_y;
2560          return iMinSAD;          return iMinSAD;
2561  }  }
   
   
   
 int32_t  
 PMVfastIntSearch16(const uint8_t * const pRef,  
                                 const uint8_t * const pRefH,  
                                 const uint8_t * const pRefV,  
                                 const uint8_t * const pRefHV,  
                                 const IMAGE * const pCur,  
                                 const int x,  
                                 const int y,  
                                 const int start_x,              /* start should be most likely vector */  
                                 const int start_y,  
                                 const int center_x,             /* center is from where length of MVs is measured */  
                                 const int center_y,  
                                 const uint32_t MotionFlags,  
                                 const uint32_t iQuant,  
                                 const uint32_t iFcode,  
                                 const MBParam * const pParam,  
                                 const MACROBLOCK * const pMBs,  
                                 const MACROBLOCK * const prevMBs,  
                                 VECTOR * const currMV,  
                                 VECTOR * const currPMV)  
 {  
         const uint32_t iWcount = pParam->mb_width;  
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
         const int32_t iEdgedWidth = pParam->edged_width;  
   
         const uint8_t *cur = pCur->y + x * 16 + y * 16 * iEdgedWidth;  
         const VECTOR zeroMV = { 0, 0 };  
   
         int32_t iDiamondSize;  
   
         int32_t min_dx;  
         int32_t max_dx;  
         int32_t min_dy;  
         int32_t max_dy;  
   
         int32_t iFound;  
   
         VECTOR newMV;  
         VECTOR backupMV;  
   
         VECTOR pmv[4];  
         int32_t psad[4];  
   
         MainSearch16FuncPtr MainSearchPtr;  
   
         const MACROBLOCK *const prevMB = prevMBs + x + y * iWcount;  
         MACROBLOCK *const pMB = pMBs + x + y * iWcount;  
   
         int32_t threshA, threshB;  
         int32_t bPredEq;  
         int32_t iMinSAD, iSAD;  
   
   
 /* Get maximum range */  
         get_range(&min_dx, &max_dx, &min_dy, &max_dy, x, y, 16, iWidth, iHeight,  
                           iFcode);  
   
 /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */  
   
         if ((x == 0) && (y == 0)) {  
                 threshA = 512;  
                 threshB = 1024;  
   
                 bPredEq = 0;  
                 psad[0] = psad[1] = psad[2] = psad[3] = 0;  
                 *currMV = pmv[0] = pmv[1] = pmv[2] = pmv[3] = zeroMV;  
   
         } else {  
                 threshA = psad[0];  
                 threshB = threshA + 256;  
                 if (threshA < 512)  
                         threshA = 512;  
                 if (threshA > 1024)  
                         threshA = 1024;  
                 if (threshB > 1792)  
                         threshB = 1792;  
   
                 bPredEq = get_ipmvdata(pMBs, iWcount, 0, x, y, 0, pmv, psad);  
                 *currMV = pmv[0];                       /* current best := prediction */  
         }  
   
         iFound = 0;  
   
 /* Step 4: Calculate SAD around the Median prediction.  
    MinSAD=SAD  
    If Motion Vector equal to Previous frame motion vector  
    and MinSAD<PrevFrmSAD goto Step 10.  
    If SAD<=256 goto Step 10.  
 */  
   
         if (currMV->x > max_dx) {  
                 currMV->x = EVEN(max_dx);  
         }  
         if (currMV->x < min_dx) {  
                 currMV->x = EVEN(min_dx);  
         }  
         if (currMV->y > max_dy) {  
                 currMV->y = EVEN(max_dy);  
         }  
         if (currMV->y < min_dy) {  
                 currMV->y = EVEN(min_dy);  
         }  
   
         iMinSAD =  
                 sad16(cur,  
                           get_iref_mv(pRef, x, y, 16, currMV,  
                                                  iEdgedWidth), iEdgedWidth, MV_MAX_ERROR);  
         iMinSAD +=  
                 calc_delta_16(currMV->x - center_x, currMV->y - center_y,  
                                           (uint8_t) iFcode, iQuant);  
   
         if ((iMinSAD < 256) ||  
                 ((MVequal(*currMV, prevMB->i_mvs[0])) &&  
                  ((int32_t) iMinSAD < prevMB->i_sad16))) {  
                 if (iMinSAD < 2 * iQuant)       // high chances for SKIP-mode  
                 {  
                         if (!MVzero(*currMV)) {  
                                 iMinSAD += MV16_00_BIAS;  
                                 CHECK_MV16_ZERO;        // (0,0) saves space for letterboxed pictures  
                                 iMinSAD -= MV16_00_BIAS;  
                         }  
                 }  
   
                 if (MotionFlags & PMV_EARLYSTOP16)  
                         goto PMVfastInt16_Terminate_with_Refine;  
         }  
   
   
 /* Step 2 (lazy eval): Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion  
    vector of the median.  
    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
 */  
   
         if ((bPredEq) && (MVequal(pmv[0], prevMB->i_mvs[0])))  
                 iFound = 2;  
   
 /* Step 3 (lazy eval): If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search.  
    Otherwise select large Diamond Search.  
 */  
   
         if ((!MVzero(pmv[0])) || (threshB < 1536) || (bPredEq))  
                 iDiamondSize = 2;               // halfpel units!  
         else  
                 iDiamondSize = 4;               // halfpel units!  
   
 /*  
    Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block.  
    Also calculate (0,0) but do not subtract offset.  
    Let MinSAD be the smallest SAD up to this point.  
    If MV is (0,0) subtract offset.  
 */  
   
 // (0,0) is often a good choice  
   
         if (!MVzero(pmv[0]))  
                 CHECK_MV16_ZERO;  
   
 // previous frame MV is always possible  
   
         if (!MVzero(prevMB->i_mvs[0]))  
                 if (!MVequal(prevMB->i_mvs[0], pmv[0]))  
                         CHECK_MV16_CANDIDATE(prevMB->i_mvs[0].x, prevMB->i_mvs[0].y);  
   
 // left neighbour, if allowed  
   
         if (!MVzero(pmv[1]))  
                 if (!MVequal(pmv[1], prevMB->i_mvs[0]))  
                         if (!MVequal(pmv[1], pmv[0]))  
                                 CHECK_MV16_CANDIDATE(pmv[1].x, pmv[1].y);  
   
 // top neighbour, if allowed  
         if (!MVzero(pmv[2]))  
                 if (!MVequal(pmv[2], prevMB->i_mvs[0]))  
                         if (!MVequal(pmv[2], pmv[0]))  
                                 if (!MVequal(pmv[2], pmv[1]))  
                                         CHECK_MV16_CANDIDATE(pmv[2].x, pmv[2].y);  
   
 // top right neighbour, if allowed  
                                         if (!MVzero(pmv[3]))  
                                                 if (!MVequal(pmv[3], prevMB->i_mvs[0]))  
                                                         if (!MVequal(pmv[3], pmv[0]))  
                                                                 if (!MVequal(pmv[3], pmv[1]))  
                                                                         if (!MVequal(pmv[3], pmv[2]))  
                                                                                 CHECK_MV16_CANDIDATE(pmv[3].x,  
                                                                                                                          pmv[3].y);  
   
         if ((MVzero(*currMV)) &&  
                 (!MVzero(pmv[0])) /* && (iMinSAD <= iQuant * 96) */ )  
                 iMinSAD -= MV16_00_BIAS;  
   
   
 /* Step 6: If MinSAD <= thresa goto Step 10.  
    If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10.  
 */  
   
         if ((iMinSAD <= threshA) ||  
                 (MVequal(*currMV, prevMB->i_mvs[0]) &&  
                  ((int32_t) iMinSAD < prevMB->i_sad16))) {  
   
                 if (MotionFlags & PMV_EARLYSTOP16)  
                         goto PMVfastInt16_Terminate_with_Refine;  
         }  
   
   
 /************ (Diamond Search)  **************/  
 /*  
    Step 7: Perform Diamond search, with either the small or large diamond.  
    If Found=2 only examine one Diamond pattern, and afterwards goto step 10  
    Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond.  
    If center then goto step 10.  
    Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center.  
    Refine by using small diamond and goto step 10.  
 */  
   
         if (MotionFlags & PMV_USESQUARES16)  
                 MainSearchPtr = Square16_MainSearch;  
         else if (MotionFlags & PMV_ADVANCEDDIAMOND16)  
                 MainSearchPtr = AdvDiamond16_MainSearch;  
         else  
                 MainSearchPtr = Diamond16_MainSearch;  
   
         backupMV = *currMV;                     /* save best prediction, actually only for EXTSEARCH */  
   
   
 /* default: use best prediction as starting point for one call of PMVfast_MainSearch */  
         iSAD =  
                 (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV->x,  
                                                   currMV->y, iMinSAD, &newMV, center_x, center_y, min_dx, max_dx,  
                                                   min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode,  
                                                   iQuant, iFound);  
   
         if (iSAD < iMinSAD) {  
                 *currMV = newMV;  
                 iMinSAD = iSAD;  
         }  
   
         if (MotionFlags & PMV_EXTSEARCH16) {  
 /* extended: search (up to) two more times: orignal prediction and (0,0) */  
   
                 if (!(MVequal(pmv[0], backupMV))) {  
                         iSAD =  
                                 (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y,  
                                                                   pmv[0].x, pmv[0].y, iMinSAD, &newMV, center_x, center_y,  
                                                                   min_dx, max_dx, min_dy, max_dy, iEdgedWidth,  
                                                                   iDiamondSize, iFcode, iQuant, iFound);  
   
                         if (iSAD < iMinSAD) {  
                                 *currMV = newMV;  
                                 iMinSAD = iSAD;  
                         }  
                 }  
   
                 if ((!(MVzero(pmv[0]))) && (!(MVzero(backupMV)))) {  
                         iSAD =  
                                 (*MainSearchPtr) (pRef, pRefH, pRefV, pRefHV, cur, x, y, 0, 0,  
                                                                   iMinSAD, &newMV, center_x, center_y, min_dx, max_dx, min_dy,  
                                                                   max_dy, iEdgedWidth, iDiamondSize, iFcode,  
                                                                   iQuant, iFound);  
   
                         if (iSAD < iMinSAD) {  
                                 *currMV = newMV;  
                                 iMinSAD = iSAD;  
                         }  
                 }  
         }  
   
 /*  
    Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.  
 */  
   
 PMVfastInt16_Terminate_with_Refine:  
   
         pMB->i_mvs[0] = pMB->i_mvs[1] = pMB->i_mvs[2] = pMB->i_mvs[3] = pMB->i_mv16 = *currMV;  
         pMB->i_sad8[0] = pMB->i_sad8[1] = pMB->i_sad8[2] = pMB->i_sad8[3] = pMB->i_sad16 = iMinSAD;  
   
         if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step  
                 iMinSAD =  
                         Halfpel16_Refine(pRef, pRefH, pRefV, pRefHV, cur, x, y, currMV,  
                                                          iMinSAD, center_x, center_y, min_dx, max_dx, min_dy, max_dy,  
                                                          iFcode, iQuant, iEdgedWidth);  
   
         pmv[0] = get_pmv2(pMBs, pParam->mb_width, 0, x, y, 0);          // get _REAL_ prediction (halfpel possible)  
   
 PMVfastInt16_Terminate_without_Refine:  
         currPMV->x = currMV->x - center_x;  
         currPMV->y = currMV->y - center_y;  
         return iMinSAD;  
 }  
   
   
   
 /* ***********************************************************  
         bvop motion estimation  
 ***************************************************************/  
   
 void  
 MotionEstimationBVOP(MBParam * const pParam,  
                                          FRAMEINFO * const frame,  
                                          const int32_t time_bp,  
                                          const int32_t time_pp,  
                                          // forward (past) reference  
                                          const MACROBLOCK * const f_mbs,  
                                          const IMAGE * const f_ref,  
                                          const IMAGE * const f_refH,  
                                          const IMAGE * const f_refV,  
                                          const IMAGE * const f_refHV,  
                                          // backward (future) reference  
                                          const MACROBLOCK * const b_mbs,  
                                          const IMAGE * const b_ref,  
                                          const IMAGE * const b_refH,  
                                          const IMAGE * const b_refV,  
                                          const IMAGE * const b_refHV)  
 {  
         const int mb_width = pParam->mb_width;  
         const int mb_height = pParam->mb_height;  
         const int edged_width = pParam->edged_width;  
   
         const int32_t iWidth = pParam->width;  
         const int32_t iHeight = pParam->height;  
   
         int i, j, k;  
   
         static const VECTOR zeroMV={0,0};  
   
         int f_sad16;    /* forward (as usual) search */  
         int b_sad16;    /* backward (only in b-frames) search */  
         int i_sad16;    /* interpolated (both direction, b-frames only) */  
         int d_sad16;    /* direct mode (assume almost linear motion) */  
   
         int best_sad;  
   
         VECTOR f_predMV, b_predMV;      /* there is no prediction for direct mode*/  
         VECTOR f_interpolMV, b_interpolMV;  
         VECTOR pmv_dontcare;  
   
         int min_dx, max_dx, min_dy, max_dy;  
         int f_min_dx, f_max_dx, f_min_dy, f_max_dy;  
         int b_min_dx, b_max_dx, b_min_dy, b_max_dy;  
   
         int f_count=0;  
         int b_count=0;  
         int i_count=0;  
         int d_count=0;  
   
         const int64_t TRB = (int32_t)time_pp - (int32_t)time_bp;  
     const int64_t TRD = (int32_t)time_pp;  
   
         // fprintf(stderr,"TRB = %lld  TRD = %lld  time_bp =%d time_pp =%d\n\n",TRB,TRD,time_bp,time_pp);  
         // note: i==horizontal, j==vertical  
         for (j = 0; j < mb_height; j++) {  
   
                 f_predMV = zeroMV;      /* prediction is reset at left boundary */  
                 b_predMV = zeroMV;  
   
                 for (i = 0; i < mb_width; i++) {  
                         MACROBLOCK *mb = &frame->mbs[i + j * mb_width];  
                         const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width];  
                         const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width];  
   
                         mb->deltamv=zeroMV;  
   
 /* special case, if collocated block is SKIPed: encoding is forward (0,0), cpb=0 without further ado */  
   
                         if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 &&  
                                 b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) {  
                                 mb->mode = MODE_NOT_CODED;  
                                 mb->b_mvs[0] = mb->mvs[0] = zeroMV;  
                                 continue;  
                         }  
   
                         if (b_mb->mode == MODE_INTER4V)  
                         {  
                                 d_sad16 = 0;  
                         /* same method of scaling as in decoder.c, so we copy from there */  
                     for (k = 0; k < 4; k++) {  
   
                                         mb->directmv[k] = b_mb->mvs[k];  
   
                                         mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);  
                     mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)  
                                                                                 ? ((TRB - TRD) * mb->directmv[k].x) / TRD  
                                             : mb->mvs[k].x - mb->directmv[k].x);  
   
                     mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);  
                         mb->b_mvs[k].y = (int32_t) ((mb->deltamv.y == 0)  
                                                                                 ? ((TRB - TRD) * mb->directmv[k].y) / TRD  
                                             : mb->mvs[k].y - mb->directmv[k].y);  
   
                                         d_sad16 +=  
                                                 sad8bi(frame->image.y + 2*(i+(k&1))*8 + 2*(j+(k>>1))*8*edged_width,  
                                                   get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
                                                                 2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->mvs[k], edged_width),  
                                                   get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
                                                                 2*(i+(k&1)), 2*(j+(k>>1)), 8, &mb->b_mvs[k], edged_width),  
                                                   edged_width);  
                                 }  
                         }  
                         else  
                         {  
                                 mb->directmv[3] = mb->directmv[2] = mb->directmv[1] =  
                                         mb->directmv[0] = b_mb->mvs[0];  
   
                                 mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);  
                     mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)  
                                                                         ? ((TRB - TRD) * mb->directmv[0].x) / TRD  
                                     : mb->mvs[0].x - mb->directmv[0].x);  
   
                     mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);  
                 mb->b_mvs[0].y = (int32_t) ((mb->directmv[0].y == 0)  
                                                                         ? ((TRB - TRD) * mb->directmv[0].y) / TRD  
                                     : mb->mvs[0].y - mb->directmv[0].y);  
   
                                 d_sad16 = sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,  
                                                   get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
                                                                 i, j, 16, &mb->mvs[0], edged_width),  
                                                   get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
                                                                 i, j, 16, &mb->b_mvs[0], edged_width),  
                                                   edged_width);  
   
             }  
                     d_sad16 += calc_delta_16(mb->deltamv.x, mb->deltamv.y, 1, frame->quant);  
   
                         // forward search  
                         f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
                                                 &frame->image, i, j,  
                                                 mb->mvs[0].x, mb->mvs[0].y,                     /* start point f_directMV */  
                                                 f_predMV.x, f_predMV.y,                         /* center is f-prediction */  
                                                 frame->motion_flags,  
                                                 frame->quant, frame->fcode, pParam,  
                                                 f_mbs, f_mbs,  
                                                 &mb->mvs[0], &pmv_dontcare);  
   
   
                         // backward search  
                         b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
                                                 &frame->image, i, j,  
                                                 mb->b_mvs[0].x, mb->b_mvs[0].y,         /* start point b_directMV */  
                                                 b_predMV.x, b_predMV.y,                         /* center is b-prediction */  
                                                 frame->motion_flags,  
                                                 frame->quant, frame->bcode, pParam,  
                                                 b_mbs, b_mbs,  
                                                 &mb->b_mvs[0], &pmv_dontcare);  
   
                         i_sad16 =  
                                 sad16bi(frame->image.y + i * 16 + j * 16 * edged_width,  
                                                   get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
                                                                 i, j, 16, &mb->mvs[0], edged_width),  
                                                   get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
                                                                 i, j, 16, &mb->b_mvs[0], edged_width),  
                                                   edged_width);  
                     i_sad16 += calc_delta_16(mb->mvs[0].x-f_predMV.x, mb->mvs[0].y-f_predMV.y,  
                                                                 frame->fcode, frame->quant);  
                     i_sad16 += calc_delta_16(mb->b_mvs[0].x-b_predMV.x, mb->b_mvs[0].y-b_predMV.y,  
                                                                 frame->bcode, frame->quant);  
   
                         get_range(&f_min_dx, &f_max_dx, &f_min_dy, &f_max_dy, i, j, 16, iWidth, iHeight,  
                           frame->fcode);  
                         get_range(&b_min_dx, &b_max_dx, &b_min_dy, &b_max_dy, i, j, 16, iWidth, iHeight,  
                           frame->bcode);  
   
 /* Interpolated MC motion vector search, this is tedious and more complicated because there are  
    two values for everything, always one for backward and one for forward ME. Still, we don't gain  
    much from this search, maybe it should simply be skipped and simply current i_sad16 value used  
    as "optimal". */  
   
                         i_sad16 = Diamond16_InterpolMainSearch(  
                                                 f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
                                                 frame->image.y + i * 16 + j * 16 * edged_width,  
                                                 b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
                                                 i, j,  
                                                 mb->mvs[0].x, mb->mvs[0].y,  
                                                 mb->b_mvs[0].x, mb->b_mvs[0].y,  
                                                 i_sad16,  
                                                 &f_interpolMV, &b_interpolMV,  
                                                 f_predMV.x, f_predMV.y, b_predMV.x, b_predMV.y,  
                                                 f_min_dx, f_max_dx, f_min_dy, f_max_dy,  
                                                 b_min_dx, b_max_dx, b_min_dy, b_max_dy,  
                                                 edged_width,  2,  
                                                 frame->fcode, frame->bcode,frame->quant,0);  
   
                         i_sad16 = Diamond16_InterpolMainSearch(  
                                                 f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
                                                 frame->image.y + i * 16 + j * 16 * edged_width,  
                                                 b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
                                                 i, j,  
                                                 f_interpolMV.x, f_interpolMV.y,  
                                                 b_interpolMV.x, b_interpolMV.y,  
                                                 i_sad16,  
                                                 &f_interpolMV, &b_interpolMV,  
                                                 f_predMV.x, f_predMV.y, b_predMV.x, b_predMV.y,  
                                                 f_min_dx, f_max_dx, f_min_dy, f_max_dy,  
                                                 b_min_dx, b_max_dx, b_min_dy, b_max_dy,  
                                                 edged_width,  1,  
                                                 frame->fcode, frame->bcode,frame->quant,0);             // equiv to halfpel refine  
   
   
 /*  DIRECT MODE DELTA VECTOR SEARCH.  
     This has to be made more effective, but at the moment I'm happy it's running at all */  
   
 /* There are two range restrictions for direct mode: deltaMV is limited to [-32,31] in halfpel units, and  
    absolute vector must not lie outside of image dimensions. Constraint one is dealt with by CHECK_MV16_DIRECT  
    and for constraint two we need distance to boundary. This is done by get_range very large fcode (hack!) */  
   
                         get_range(&min_dx, &max_dx, &min_dy, &max_dy, i, j, 16, iWidth, iHeight, 19);  
   
                         d_sad16 = Diamond16_DirectMainSearch(  
                                                 f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
                                                 frame->image.y + i*16 + j*16*edged_width,  
                                                 b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
                                                 i, j,  
                                                 TRB,TRD,  
                                                 0,0,  
                                                 d_sad16,  
                                                 &mb->deltamv,  
                                                 mb->directmv, // this has to be pre-initialized with b_mb->mvs[]  
                                         min_dx, max_dx, min_dy, max_dy,  
                                                 edged_width, 2, frame->quant, 0);  
   
                         d_sad16 = Diamond16_DirectMainSearch(  
                                                 f_ref->y, f_refH->y, f_refV->y, f_refHV->y,  
                                                 frame->image.y + i*16 + j*16*edged_width,  
                                                 b_ref->y, b_refH->y, b_refV->y, b_refHV->y,  
                                                 i, j,  
                                                 TRB,TRD,  
                                                 mb->deltamv.x, mb->deltamv.y,  
                                                 d_sad16,  
                                                 &mb->deltamv,  
                                                 mb->directmv, // this has to be pre-initialized with b_mb->mvs[]  
                                         min_dx, max_dx, min_dy, max_dy,  
                                                 edged_width, 1, frame->quant, 0);               // equiv to halfpel refine  
   
   
 //                      i_sad16 = 65535;                /* remove the comment to disable any of the MODEs */  
 //                      f_sad16 = 65535;  
 //                      b_sad16 = 65535;  
 //                      d_sad16 = 65535;  
   
                         if (f_sad16 < b_sad16) {  
                                 best_sad = f_sad16;  
                                 mb->mode = MODE_FORWARD;  
                         } else {  
                                 best_sad = b_sad16;  
                                 mb->mode = MODE_BACKWARD;  
                         }  
   
                         if (i_sad16 < best_sad) {  
                                 best_sad = i_sad16;  
                                 mb->mode = MODE_INTERPOLATE;  
                         }  
   
                         if (d_sad16 < best_sad) {  
   
                                 if (b_mb->mode == MODE_INTER4V)  
                                 {  
   
                                 /* how to calc vectors is defined in standard. mvs[] and b_mvs[] are only for motion compensation */  
                                 /* for the bitstream, the value mb->deltamv is read directly */  
   
                             for (k = 0; k < 4; k++) {  
   
                                                 mb->mvs[k].x = (int32_t) ((TRB * mb->directmv[k].x) / TRD + mb->deltamv.x);  
                             mb->b_mvs[k].x = (int32_t) ((mb->deltamv.x == 0)  
                                                                                         ? ((TRB - TRD) * mb->directmv[k].x) / TRD  
                                                     : mb->mvs[k].x - mb->directmv[k].x);  
   
                             mb->mvs[k].y = (int32_t) ((TRB * mb->directmv[k].y) / TRD + mb->deltamv.y);  
                         mb->b_mvs[k].y = (int32_t) ((mb->deltamv.y == 0)  
                                                                                         ? ((TRB - TRD) * mb->directmv[k].y) / TRD  
                                             : mb->mvs[k].y - mb->directmv[k].y);  
                                         }  
                                 }  
                                 else  
                                 {  
                                         mb->mvs[0].x = (int32_t) ((TRB * mb->directmv[0].x) / TRD + mb->deltamv.x);  
   
                     mb->b_mvs[0].x = (int32_t) ((mb->deltamv.x == 0)  
                                                                                 ? ((TRB - TRD) * mb->directmv[0].x) / TRD  
                                         : mb->mvs[0].x - mb->directmv[0].x);  
   
                             mb->mvs[0].y = (int32_t) ((TRB * mb->directmv[0].y) / TRD + mb->deltamv.y);  
   
                         mb->b_mvs[0].y = (int32_t) ((mb->deltamv.y == 0)  
                                                                                 ? ((TRB - TRD) * mb->directmv[0].y) / TRD  
                                             : mb->mvs[0].y - mb->directmv[0].y);  
   
                                         mb->mvs[3] = mb->mvs[2] = mb->mvs[1] = mb->mvs[0];  
                                         mb->b_mvs[3] = mb->b_mvs[2] = mb->b_mvs[1] = mb->b_mvs[0];  
                 }  
   
                                 best_sad = d_sad16;  
                                 mb->mode = MODE_DIRECT;  
                         }  
   
                         switch (mb->mode)  
                         {  
                                 case MODE_FORWARD:  
                                         f_count++;  
                                         f_predMV = mb->mvs[0];  
                                         break;  
                                 case MODE_BACKWARD:  
                                         b_count++;  
                                         b_predMV = mb->b_mvs[0];  
   
                                         break;  
                                 case MODE_INTERPOLATE:  
                                         i_count++;  
                                         mb->mvs[0] = f_interpolMV;  
                                         mb->b_mvs[0] = b_interpolMV;  
                                         f_predMV = mb->mvs[0];  
                                         b_predMV = mb->b_mvs[0];  
                                         break;  
                                 case MODE_DIRECT:  
                                         d_count++;  
                                         break;  
                                 default:  
                                         break;  
                         }  
   
                 }  
         }  
   
 #ifdef _DEBUG_BFRAME_STAT  
         fprintf(stderr,"B-Stat: F: %04d   B: %04d   I: %04d  D: %04d\n",  
                                 f_count,b_count,i_count,d_count);  
 #endif  
   
 }  

Legend:
Removed from v.348  
changed lines
  Added in v.677

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4