motion_est.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:57k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /**************************************************************************
  2.  *
  3.  *  Modifications:
  4.  *
  5.  *  02.04.2002 add EPZS(^2) as ME algorithm, use PMV_USESQUARES to choose between 
  6.  *             EPZS and EPZS^2
  7.  *  08.02.2002 split up PMVfast into three routines: PMVFast, PMVFast_MainLoop
  8.  *             PMVFast_Refine to support multiple searches with different start points
  9.  *  07.01.2002 uv-block-based interpolation
  10.  *  06.01.2002 INTER/INTRA-decision is now done before any SEARCH8 (speedup)
  11.  *             changed INTER_BIAS to 150 (as suggested by suxen_drol)
  12.  *             removed halfpel refinement step in PMVfastSearch8 + quality=5
  13.  *             added new quality mode = 6 which performs halfpel refinement
  14.  *             filesize difference between quality 5 and 6 is smaller than 1%
  15.  *             (Isibaar)
  16.  *  31.12.2001 PMVfastSearch16 and PMVfastSearch8 (gruel)
  17.  *  30.12.2001 get_range/MotionSearchX simplified; blue/green bug fix
  18.  *  22.12.2001 commented best_point==99 check
  19.  *  19.12.2001 modified get_range (purple bug fix)
  20.  *  15.12.2001 moved pmv displacement from mbprediction
  21.  *  02.12.2001 motion estimation/compensation split (Isibaar)
  22.  *  16.11.2001 rewrote/tweaked search algorithms; pross@cs.rmit.edu.au
  23.  *  10.11.2001 support for sad16/sad8 functions
  24.  *  28.08.2001 reactivated MODE_INTER4V for EXT_MODE
  25.  *  24.08.2001 removed MODE_INTER4V_Q, disabled MODE_INTER4V for EXT_MODE
  26.  *  22.08.2001 added MODE_INTER4V_Q
  27.  *  20.08.2001 added pragma to get rid of internal compiler error with VC6
  28.  *             idea by Cyril. Thanks.
  29.  *
  30.  *  Michael Militzer <isibaar@videocoding.de>
  31.  *
  32.  **************************************************************************/
  33. #include <assert.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include "../encoder.h"
  37. #include "../utils/mbfunctions.h"
  38. #include "../prediction/mbprediction.h"
  39. #include "../global.h"
  40. #include "../utils/timer.h"
  41. #include "sad.h"
  42. // very large value
  43. #define MV_MAX_ERROR (4096 * 256)
  44. // stop search if sdelta < THRESHOLD
  45. #define MV16_THRESHOLD 192
  46. #define MV8_THRESHOLD 56
  47. /* sad16(0,0) bias; mpeg4 spec suggests nb/2+1 */
  48. /* nb  = vop pixels * 2^(bpp-8) */
  49. #define MV16_00_BIAS (128+1)
  50. /* INTER bias for INTER/INTRA decision; mpeg4 spec suggests 2*nb */
  51. #define INTER_BIAS 512
  52. /* Parameters which control inter/inter4v decision */
  53. #define IMV16X16 5
  54. /* vector map (vlc delta size) smoother parameters */
  55. #define NEIGH_TEND_16X16 2
  56. #define NEIGH_TEND_8X8 2
  57. // fast ((A)/2)*2
  58. #define EVEN(A) (((A)<0?(A)+1:(A)) & ~1)
  59. #ifndef MIN
  60. #define MIN(X, Y) ((X)<(Y)?(X):(Y))
  61. #endif
  62. #ifndef MAX
  63. #define MAX(X, Y) ((X)>(Y)?(X):(Y))
  64. #endif
  65. #define ABS(X)    (((X)>0)?(X):-(X))
  66. #define SIGN(X)   (((X)>0)?1:-1)
  67. int32_t PMVfastSearch16(
  68. const uint8_t * const pRef,
  69. const uint8_t * const pRefH,
  70. const uint8_t * const pRefV,
  71. const uint8_t * const pRefHV,
  72. const IMAGE * const pCur,
  73. const int x, const int y,
  74. const uint32_t MotionFlags,
  75. const MBParam * const pParam,
  76. MACROBLOCK * const pMBs,
  77. VECTOR * const currMV,
  78. VECTOR * const currPMV);
  79. int32_t EPZSSearch16(
  80. const uint8_t * const pRef,
  81. const uint8_t * const pRefH,
  82. const uint8_t * const pRefV,
  83. const uint8_t * const pRefHV,
  84. const IMAGE * const pCur,
  85. const int x, const int y,
  86. const uint32_t MotionFlags,
  87. const MBParam * const pParam,
  88. MACROBLOCK * const pMBs,
  89. VECTOR * const currMV,
  90. VECTOR * const currPMV);
  91. int32_t PMVfastSearch8(
  92. const uint8_t * const pRef,
  93. const uint8_t * const pRefH,
  94. const uint8_t * const pRefV,
  95. const uint8_t * const pRefHV,
  96. const IMAGE * const pCur,
  97. const int x, const int y,
  98. const int start_x, int start_y,
  99. const uint32_t MotionFlags,
  100. const MBParam * const pParam,
  101. MACROBLOCK * const pMBs,
  102. VECTOR * const currMV,
  103. VECTOR * const currPMV);
  104. int32_t EPZSSearch8(
  105. const uint8_t * const pRef,
  106. const uint8_t * const pRefH,
  107. const uint8_t * const pRefV,
  108. const uint8_t * const pRefHV,
  109. const IMAGE * const pCur,
  110. const int x, const int y,
  111. const int start_x, int start_y,
  112. const uint32_t MotionFlags,
  113. const MBParam * const pParam,
  114. MACROBLOCK * const pMBs,
  115. VECTOR * const currMV,
  116. VECTOR * const currPMV);
  117. typedef int32_t (MainSearch16Func)(
  118. const uint8_t * const pRef,
  119. const uint8_t * const pRefH,
  120. const uint8_t * const pRefV,
  121. const uint8_t * const pRefHV,
  122. const uint8_t * const cur,
  123. const int x, const int y,
  124. int32_t startx, int32_t starty,
  125. int32_t iMinSAD,
  126. VECTOR * const currMV,
  127. const VECTOR * const pmv,
  128. const int32_t min_dx, const int32_t max_dx, 
  129. const int32_t min_dy, const int32_t max_dy,
  130. const int32_t iEdgedWidth, 
  131. const int32_t iDiamondSize, 
  132. const int32_t iFcode,
  133. const int32_t iQuant,
  134. int iFound);
  135. typedef MainSearch16Func* MainSearch16FuncPtr;
  136. typedef int32_t (MainSearch8Func)(
  137. const uint8_t * const pRef,
  138. const uint8_t * const pRefH,
  139. const uint8_t * const pRefV,
  140. const uint8_t * const pRefHV,
  141. const uint8_t * const cur,
  142. const int x, const int y,
  143. int32_t startx, int32_t starty,
  144. int32_t iMinSAD,
  145. VECTOR * const currMV,
  146. const VECTOR * const pmv,
  147. const int32_t min_dx, const int32_t max_dx, 
  148. const int32_t min_dy, const int32_t max_dy,
  149. const int32_t iEdgedWidth, 
  150. const int32_t iDiamondSize, 
  151. const int32_t iFcode,
  152. const int32_t iQuant,
  153. int iFound);
  154. typedef MainSearch8Func* MainSearch8FuncPtr;
  155. // mv.length table
  156. static const uint32_t mvtab[33] = {
  157.     1,  2,  3,  4,  6,  7,  7,  7,
  158.     9,  9,  9,  10, 10, 10, 10, 10,
  159.     10, 10, 10, 10, 10, 10, 10, 10,
  160.     10, 11, 11, 11, 11, 11, 11, 12, 12
  161. };
  162. static __inline uint32_t mv_bits(int32_t component, const uint32_t iFcode)
  163. {
  164.     if (component == 0)
  165. return 1;
  166.     if (component < 0)
  167. component = -component;
  168.     if (iFcode == 1)
  169.     {
  170. if (component > 32)
  171.     component = 32;
  172. return mvtab[component] + 1;
  173.     }
  174.     component += (1 << (iFcode - 1)) - 1;
  175.     component >>= (iFcode - 1);
  176.     if (component > 32)
  177. component = 32;
  178.     return mvtab[component] + 1 + iFcode - 1;
  179. }
  180. static __inline uint32_t calc_delta_16(const int32_t dx, const int32_t dy, const uint32_t iFcode)
  181. {
  182. return NEIGH_TEND_16X16 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
  183. }
  184. static __inline uint32_t calc_delta_8(const int32_t dx, const int32_t dy, const uint32_t iFcode)
  185. {
  186.     return NEIGH_TEND_8X8 * (mv_bits(dx, iFcode) + mv_bits(dy, iFcode));
  187. }
  188. /* calculate the min/max range (in halfpixels)
  189. relative to the _MACROBLOCK_ position
  190. */
  191. static void __inline get_range(
  192. int32_t * const min_dx, int32_t * const max_dx,
  193. int32_t * const min_dy, int32_t * const max_dy,
  194. const uint32_t x, const uint32_t y, 
  195. const uint32_t block_sz, // block dimension, 8 or 16
  196. const uint32_t width, const uint32_t height,
  197. const uint32_t fcode)
  198. {
  199. const int search_range = 32 << (fcode - 1);
  200. const int high = search_range - 1;
  201. const int low = -search_range;
  202. // convert full-pixel measurements to half pixel
  203. const int hp_width = 2 * width;
  204. const int hp_height = 2 * height;
  205. const int hp_edge = 2 * block_sz;
  206. const int hp_x = 2 * (x) * block_sz; // we need _right end_ of block, not x-coordinate
  207. const int hp_y = 2 * (y) * block_sz; // same for _bottom end_
  208. *max_dx = MIN(high, hp_width - hp_x);
  209. *max_dy = MIN(high, hp_height - hp_y);
  210. *min_dx = MAX(low, -(hp_edge + hp_x));
  211. *min_dy = MAX(low, -(hp_edge + hp_y));
  212. }
  213. /*
  214.  * getref: calculate reference image pointer 
  215.  * the decision to use interpolation h/v/hv or the normal image is
  216.  * based on dx & dy.
  217.  */
  218. static __inline const uint8_t * get_ref(
  219. const uint8_t * const refn,
  220. const uint8_t * const refh,
  221. const uint8_t * const refv,
  222. const uint8_t * const refhv,
  223. const uint32_t x, const uint32_t y,
  224. const uint32_t block, // block dimension, 8 or 16
  225. const int32_t dx, const int32_t dy,
  226. const uint32_t stride)
  227. {
  228. switch ( ((dx&1)<<1) + (dy&1) ) // ((dx%2)?2:0)+((dy%2)?1:0)
  229. {
  230. case 0  : return refn + (x*block+dx/2) + (y*block+dy/2)*stride;
  231. case 1  : return refv + (x*block+dx/2) + (y*block+(dy-1)/2)*stride;
  232. case 2  : return refh + (x*block+(dx-1)/2) + (y*block+dy/2)*stride;
  233. default : 
  234. case 3  : return refhv + (x*block+(dx-1)/2) + (y*block+(dy-1)/2)*stride;
  235. }
  236. }
  237. /* This is somehow a copy of get_ref, but with MV instead of X,Y */
  238. static __inline const uint8_t * get_ref_mv(
  239. const uint8_t * const refn,
  240. const uint8_t * const refh,
  241. const uint8_t * const refv,
  242. const uint8_t * const refhv,
  243. const uint32_t x, const uint32_t y,
  244. const uint32_t block, // block dimension, 8 or 16
  245. const VECTOR* mv, // measured in half-pel!
  246. const uint32_t stride)
  247. {
  248. switch ( (((mv->x)&1)<<1) + ((mv->y)&1) )
  249. {
  250. case 0  : return refn + (x*block+(mv->x)/2) + (y*block+(mv->y)/2)*stride;
  251.      case 1  : return refv + (x*block+(mv->x)/2) + (y*block+((mv->y)-1)/2)*stride;
  252. case 2  : return refh + (x*block+((mv->x)-1)/2) + (y*block+(mv->y)/2)*stride;
  253. default : 
  254. case 3  : return refhv + (x*block+((mv->x)-1)/2) + (y*block+((mv->y)-1)/2)*stride;
  255. }
  256. }
  257. #ifndef SEARCH16
  258. #define SEARCH16 PMVfastSearch16
  259. //#define SEARCH16 FullSearch16
  260. //#define SEARCH16 EPZSSearch16
  261. #endif
  262. #ifndef SEARCH8
  263. #define SEARCH8 PMVfastSearch8
  264. //#define SEARCH8 EPZSSearch8
  265. #endif
  266. bool MotionEstimation(
  267. MACROBLOCK * const pMBs,
  268. MBParam * const pParam,
  269. const IMAGE * const pRef,
  270. const IMAGE * const pRefH,
  271. const IMAGE * const pRefV,
  272. const IMAGE * const pRefHV,
  273. IMAGE * const pCurrent, 
  274. const uint32_t iLimit)
  275. {
  276. const uint32_t iWcount = pParam->mb_width;
  277. const uint32_t iHcount = pParam->mb_height;
  278.  
  279. uint32_t i, j, iIntra = 0;
  280. VECTOR mv16;
  281. VECTOR pmv16;
  282. int32_t sad8 = 0;
  283. int32_t sad16;
  284. int32_t deviation;
  285. if (sadInit)
  286. (*sadInit)();
  287. // note: i==horizontal, j==vertical
  288. for (i = 0; i < iHcount; i++)
  289. for (j = 0; j < iWcount; j++)
  290. {
  291. MACROBLOCK *pMB = &pMBs[j + i * iWcount];
  292. sad16 = SEARCH16(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, 
  293.  j, i, pParam->motion_flags,
  294.  pParam, pMBs, &mv16, &pmv16); 
  295. pMB->sad16=sad16;
  296. /* decide: MODE_INTER or MODE_INTRA 
  297.    if (dev_intra < sad_inter - 2 * nb) use_intra
  298. */
  299. deviation = dev16(pCurrent->y + j*16 + i*16*pParam->edged_width, pParam->edged_width);
  300. if (deviation < (sad16 - INTER_BIAS))
  301. {
  302. pMB->mode = MODE_INTRA;
  303. pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0;
  304. pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0;
  305. iIntra++;
  306. if(iIntra >= iLimit)
  307. return 1;
  308. continue;
  309. }
  310. if (pParam->global_flags & XVID_INTER4V)
  311. {
  312. pMB->sad8[0] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, 
  313.        2 * j, 2 * i, mv16.x, mv16.y, pParam->motion_flags, 
  314.        pParam, pMBs, &pMB->mvs[0], &pMB->pmvs[0]); 
  315. pMB->sad8[1] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, 
  316.        2 * j + 1, 2 * i, mv16.x, mv16.y, pParam->motion_flags,
  317.        pParam, pMBs, &pMB->mvs[1], &pMB->pmvs[1]); 
  318. pMB->sad8[2] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, 
  319.        2 * j, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,
  320.        pParam, pMBs, &pMB->mvs[2], &pMB->pmvs[2]); 
  321. pMB->sad8[3] = SEARCH8(pRef->y, pRefH->y, pRefV->y, pRefHV->y, pCurrent, 
  322.        2 * j + 1, 2 * i + 1, mv16.x, mv16.y, pParam->motion_flags,
  323.        pParam, pMBs, &pMB->mvs[3], &pMB->pmvs[3]); 
  324. sad8 = pMB->sad8[0] + pMB->sad8[1] + pMB->sad8[2] + pMB->sad8[3];
  325. }
  326.     
  327. /* decide: MODE_INTER or MODE_INTER4V 
  328.    mpeg4:   if (sad8 < sad16 - nb/2+1) use_inter4v
  329. */
  330. if (pMB->dquant == NO_CHANGE) {
  331. if (((pParam->global_flags & XVID_INTER4V)==0) || 
  332.     (sad16 < (sad8 + (int32_t)(IMV16X16 * pParam->quant)))) { 
  333. sad8 = sad16;
  334. pMB->mode = MODE_INTER;
  335. pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;
  336. pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;
  337. pMB->pmvs[0].x = pmv16.x;
  338. pMB->pmvs[0].y = pmv16.y;
  339. }
  340. else
  341. pMB->mode = MODE_INTER4V;
  342. }
  343. else 
  344. {
  345. sad8 = sad16;
  346. pMB->mode = MODE_INTER;
  347. pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = mv16.x;
  348. pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = mv16.y;
  349. pMB->pmvs[0].x = pmv16.x;
  350. pMB->pmvs[0].y = pmv16.y;
  351. }
  352. }
  353. return 0;
  354. }
  355. #define MVzero(A) ( ((A).x)==(0) && ((A).y)==(0) )
  356. #define MVequal(A,B) ( ((A).x)==((B).x) && ((A).y)==((B).y) )
  357. #define CHECK_MV16_ZERO {
  358.   if ( (0 <= max_dx) && (0 >= min_dx) 
  359.     && (0 <= max_dy) && (0 >= min_dy) ) 
  360.   { 
  361.     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0, 0 , iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); 
  362.     iSAD += calc_delta_16(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;
  363.     if (iSAD <= iQuant * 96)
  364.     iSAD -= MV16_00_BIAS; 
  365.     if (iSAD < iMinSAD) 
  366.     {  iMinSAD=iSAD; currMV->x=0; currMV->y=0; }  }
  367. }
  368. #define NOCHECK_MV16_CANDIDATE(X,Y) { 
  369.     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); 
  370.     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;
  371.     if (iSAD < iMinSAD) 
  372.     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } 
  373. }
  374. #define CHECK_MV16_CANDIDATE(X,Y) { 
  375.   if ( ((X) <= max_dx) && ((X) >= min_dx) 
  376.     && ((Y) <= max_dy) && ((Y) >= min_dy) ) 
  377.   { 
  378.     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); 
  379.     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;
  380.     if (iSAD < iMinSAD) 
  381.     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } 
  382. }
  383. #define CHECK_MV16_CANDIDATE_DIR(X,Y,D) { 
  384.   if ( ((X) <= max_dx) && ((X) >= min_dx) 
  385.     && ((Y) <= max_dy) && ((Y) >= min_dy) ) 
  386.   { 
  387.     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); 
  388.     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;
  389.     if (iSAD < iMinSAD) 
  390.     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } 
  391. }
  392. #define CHECK_MV16_CANDIDATE_FOUND(X,Y,D) { 
  393.   if ( ((X) <= max_dx) && ((X) >= min_dx) 
  394.     && ((Y) <= max_dy) && ((Y) >= min_dy) ) 
  395.   { 
  396.     iSAD = sad16( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, X, Y, iEdgedWidth),iEdgedWidth, iMinSAD); 
  397.     iSAD += calc_delta_16((X) - pmv[0].x, (Y) - pmv[0].y, (uint8_t)iFcode) * iQuant;
  398.     if (iSAD < iMinSAD) 
  399.     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } 
  400. }
  401. #define CHECK_MV8_ZERO {
  402.   iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, 0, 0 , iEdgedWidth), iEdgedWidth); 
  403.   iSAD += calc_delta_8(-pmv[0].x, -pmv[0].y, (uint8_t)iFcode) * iQuant;
  404.   if (iSAD < iMinSAD) 
  405.   { iMinSAD=iSAD; currMV->x=0; currMV->y=0; } 
  406. }
  407. #define NOCHECK_MV8_CANDIDATE(X,Y) 
  408.   { 
  409.     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); 
  410.     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;
  411.     if (iSAD < iMinSAD) 
  412.     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } 
  413. }
  414. #define CHECK_MV8_CANDIDATE(X,Y) { 
  415.   if ( ((X) <= max_dx) && ((X) >= min_dx) 
  416.     && ((Y) <= max_dy) && ((Y) >= min_dy) ) 
  417.   { 
  418.     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); 
  419.     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;
  420.     if (iSAD < iMinSAD) 
  421.     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); } } 
  422. }
  423. #define CHECK_MV8_CANDIDATE_DIR(X,Y,D) { 
  424.   if ( ((X) <= max_dx) && ((X) >= min_dx) 
  425.     && ((Y) <= max_dy) && ((Y) >= min_dy) ) 
  426.   { 
  427.     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); 
  428.     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;
  429.     if (iSAD < iMinSAD) 
  430.     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); } } 
  431. }
  432. #define CHECK_MV8_CANDIDATE_FOUND(X,Y,D) { 
  433.   if ( ((X) <= max_dx) && ((X) >= min_dx) 
  434.     && ((Y) <= max_dy) && ((Y) >= min_dy) ) 
  435.   { 
  436.     iSAD = sad8( cur, get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 8, (X), (Y), iEdgedWidth),iEdgedWidth); 
  437.     iSAD += calc_delta_8((X)-pmv[0].x, (Y)-pmv[0].y, (uint8_t)iFcode) * iQuant;
  438.     if (iSAD < iMinSAD) 
  439.     {  iMinSAD=iSAD; currMV->x=(X); currMV->y=(Y); iDirection=(D); iFound=0; } } 
  440. }
  441. /* too slow and not fully functional at the moment */
  442. /*
  443. int32_t ZeroSearch16(
  444. const uint8_t * const pRef,
  445. const uint8_t * const pRefH,
  446. const uint8_t * const pRefV,
  447. const uint8_t * const pRefHV,
  448. const IMAGE * const pCur,
  449. const int x, const int y,
  450. const uint32_t MotionFlags, 
  451. MBParam * const pParam,
  452. MACROBLOCK * const pMBs,
  453. VECTOR * const currMV,
  454. VECTOR * const currPMV)
  455. {
  456. const int32_t iEdgedWidth = pParam->edged_width; 
  457. const int32_t iQuant = pParam->quant;
  458. const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
  459. int32_t iSAD;
  460. int32_t pred_x,pred_y;
  461. get_pmv(pMBs, x, y, pParam->mb_width, 0, &pred_x, &pred_y);    
  462. iSAD = sad16( cur, 
  463. get_ref(pRef, pRefH, pRefV, pRefHV, x, y, 16, 0,0, iEdgedWidth),
  464. iEdgedWidth, MV_MAX_ERROR);
  465. if (iSAD <= iQuant * 96)
  466.     iSAD -= MV16_00_BIAS; 
  467. currMV->x = 0;
  468. currMV->y = 0;
  469. currPMV->x = -pred_x;
  470. currPMV->y = -pred_y;
  471. return iSAD;
  472. }
  473. */
  474. int32_t Diamond16_MainSearch(
  475. const uint8_t * const pRef,
  476. const uint8_t * const pRefH,
  477. const uint8_t * const pRefV,
  478. const uint8_t * const pRefHV,
  479. const uint8_t * const cur,
  480. const int x, const int y,
  481. int32_t startx, int32_t starty,
  482. int32_t iMinSAD,
  483. VECTOR * const currMV,
  484. const VECTOR * const pmv,
  485. const int32_t min_dx, const int32_t max_dx, 
  486. const int32_t min_dy, const int32_t max_dy,
  487. const int32_t iEdgedWidth, 
  488. const int32_t iDiamondSize, 
  489. const int32_t iFcode,
  490. const int32_t iQuant,
  491. int iFound)
  492. {
  493. /* Do a diamond search around given starting point, return SAD of best */
  494. int32_t iDirection=0;
  495. int32_t iSAD;
  496. VECTOR backupMV;
  497. backupMV.x = startx;
  498. backupMV.y = starty;
  499. /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
  500. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
  501. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
  502. CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
  503. CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
  504. if (iDirection)
  505. while (!iFound)
  506. {
  507. iFound = 1; 
  508. backupMV=*currMV;
  509. if ( iDirection != 2) 
  510. CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
  511. if ( iDirection != 1) 
  512. CHECK_MV16_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);
  513. if ( iDirection != 4) 
  514. CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);
  515. if ( iDirection != 3) 
  516. CHECK_MV16_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);
  517. }
  518. else
  519. {
  520. currMV->x = startx;
  521. currMV->y = starty;
  522. }
  523. return iMinSAD;
  524. }
  525. int32_t Square16_MainSearch(
  526. const uint8_t * const pRef,
  527. const uint8_t * const pRefH,
  528. const uint8_t * const pRefV,
  529. const uint8_t * const pRefHV,
  530. const uint8_t * const cur,
  531. const int x, const int y,
  532. int32_t startx, int32_t starty,
  533. int32_t iMinSAD,
  534. VECTOR * const currMV,
  535. const VECTOR * const pmv,
  536. const int32_t min_dx, const int32_t max_dx, 
  537. const int32_t min_dy, const int32_t max_dy,
  538. const int32_t iEdgedWidth, 
  539. const int32_t iDiamondSize, 
  540. const int32_t iFcode,
  541. const int32_t iQuant,
  542. int iFound)
  543. {
  544. /* Do a square search around given starting point, return SAD of best */
  545. int32_t iDirection=0;
  546. int32_t iSAD;
  547. VECTOR backupMV;
  548. backupMV.x = startx;
  549. backupMV.y = starty;
  550. /* It's one search with full square pattern, and new parts for all following diamonds */
  551. /*   new direction are extra, so 1-4 is normal diamond
  552.       537
  553.       1*2
  554.       648  
  555. */
  556. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
  557. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
  558. CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
  559. CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
  560. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
  561. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
  562. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
  563. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
  564. if (iDirection)
  565. while (!iFound)
  566. {
  567. iFound = 1; 
  568. backupMV=*currMV;
  569. switch (iDirection)
  570. {
  571. case 1:
  572. CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
  573. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
  574. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
  575. break;
  576. case 2:
  577. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
  578. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
  579. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
  580. break;
  581. case 3:
  582. CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
  583. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
  584. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
  585. break;
  586. case 4:
  587. CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
  588. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
  589. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
  590. break;
  591. case 5:
  592. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
  593. CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
  594. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
  595. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
  596. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
  597. break; 
  598. case 6:
  599. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
  600. CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
  601. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
  602. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
  603. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
  604. break;
  605. case 7:
  606. CHECK_MV16_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
  607. CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
  608. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
  609. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
  610. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
  611. break;
  612. case 8:
  613. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
  614. CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
  615. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
  616. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
  617. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
  618. break; 
  619. default:
  620. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
  621. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
  622. CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
  623. CHECK_MV16_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
  624. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y-iDiamondSize,5);
  625. CHECK_MV16_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y+iDiamondSize,6);
  626. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y-iDiamondSize,7);
  627. CHECK_MV16_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y+iDiamondSize,8);
  628. break;
  629. }
  630. }
  631. else
  632. {
  633. currMV->x = startx;
  634. currMV->y = starty;
  635. }
  636. return iMinSAD;
  637. }
  638. int32_t Full16_MainSearch(
  639. const uint8_t * const pRef,
  640. const uint8_t * const pRefH,
  641. const uint8_t * const pRefV,
  642. const uint8_t * const pRefHV,
  643. const uint8_t * const cur,
  644. const int x, const int y,
  645. int32_t startx, int32_t starty,
  646. int32_t iMinSAD,
  647. VECTOR * const currMV,
  648. const VECTOR * const pmv,
  649. const int32_t min_dx, const int32_t max_dx, 
  650. const int32_t min_dy, const int32_t max_dy,
  651. const int32_t iEdgedWidth, 
  652. const int32_t iDiamondSize, 
  653. const int32_t iFcode,
  654. const int32_t iQuant,
  655. int iFound)
  656. {
  657. int32_t iSAD;
  658. int32_t dx,dy;
  659. VECTOR backupMV;
  660. backupMV.x = startx;
  661. backupMV.y = starty;
  662. for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
  663. for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
  664. NOCHECK_MV16_CANDIDATE(dx,dy);
  665. return iMinSAD;
  666. }
  667. int32_t Full8_MainSearch(
  668. const uint8_t * const pRef,
  669. const uint8_t * const pRefH,
  670. const uint8_t * const pRefV,
  671. const uint8_t * const pRefHV,
  672. const uint8_t * const cur,
  673. const int x, const int y,
  674. int32_t startx, int32_t starty,
  675. int32_t iMinSAD,
  676. VECTOR * const currMV,
  677. const VECTOR * const pmv,
  678. const int32_t min_dx, const int32_t max_dx, 
  679. const int32_t min_dy, const int32_t max_dy,
  680. const int32_t iEdgedWidth, 
  681. const int32_t iDiamondSize, 
  682. const int32_t iFcode,
  683. const int32_t iQuant,
  684. int iFound)
  685. {
  686. int32_t iSAD;
  687. int32_t dx,dy;
  688. VECTOR backupMV;
  689. backupMV.x = startx;
  690. backupMV.y = starty;
  691. for (dx = min_dx; dx<=max_dx; dx+=iDiamondSize)
  692. for (dy = min_dy; dy<= max_dy; dy+=iDiamondSize)
  693. NOCHECK_MV8_CANDIDATE(dx,dy);
  694. return iMinSAD;
  695. }
  696. int32_t Halfpel16_Refine(
  697. const uint8_t * const pRef,
  698. const uint8_t * const pRefH,
  699. const uint8_t * const pRefV,
  700. const uint8_t * const pRefHV,
  701. const uint8_t * const cur,
  702. const int x, const int y,
  703. VECTOR * const currMV,
  704. int32_t iMinSAD,
  705. const VECTOR * const pmv,
  706. const int32_t min_dx, const int32_t max_dx, 
  707. const int32_t min_dy, const int32_t max_dy,
  708. const int32_t iFcode,
  709. const int32_t iQuant,
  710. const int32_t iEdgedWidth)
  711. {
  712. /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
  713. int32_t iSAD;
  714. VECTOR backupMV = *currMV;
  715. CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y-1);
  716. CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y-1);
  717. CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y-1);
  718. CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y);
  719. CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y);
  720. CHECK_MV16_CANDIDATE(backupMV.x-1,backupMV.y+1);
  721. CHECK_MV16_CANDIDATE(backupMV.x  ,backupMV.y+1);
  722. CHECK_MV16_CANDIDATE(backupMV.x+1,backupMV.y+1);
  723. return iMinSAD;
  724. }
  725. #define PMV_HALFPEL16 (PMV_HALFPELDIAMOND16|PMV_HALFPELREFINE16)
  726. int32_t PMVfastSearch16(
  727. const uint8_t * const pRef,
  728. const uint8_t * const pRefH,
  729. const uint8_t * const pRefV,
  730. const uint8_t * const pRefHV,
  731. const IMAGE * const pCur,
  732. const int x, const int y,
  733. const uint32_t MotionFlags,
  734. const MBParam * const pParam,
  735. MACROBLOCK * const pMBs,
  736. VECTOR * const currMV,
  737. VECTOR * const currPMV)
  738. {
  739.         const uint32_t iWcount = pParam->mb_width;
  740. const int32_t iFcode = pParam->fixed_code;
  741. const int32_t iQuant = pParam->quant;
  742. const int32_t iWidth = pParam->width;
  743. const int32_t iHeight = pParam->height;
  744. const int32_t iEdgedWidth = pParam->edged_width; 
  745. const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
  746. int32_t iDiamondSize;
  747. int32_t min_dx;
  748. int32_t max_dx;
  749. int32_t min_dy;
  750. int32_t max_dy;
  751. int32_t iFound;
  752. VECTOR newMV;
  753. VECTOR backupMV; /* just for PMVFAST */
  754. VECTOR pmv[4];
  755. int32_t psad[4];
  756. MACROBLOCK * const pMB = pMBs + x + y * iWcount;
  757. static int32_t threshA,threshB;
  758.      int32_t bPredEq;
  759.      int32_t iMinSAD,iSAD;
  760. /* Get maximum range */
  761. get_range(&min_dx, &max_dx, &min_dy, &max_dy,
  762.   x, y, 16, iWidth, iHeight, iFcode);
  763. /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
  764. if (!(MotionFlags & PMV_HALFPEL16 ))
  765. { min_dx = EVEN(min_dx);
  766. max_dx = EVEN(max_dx);
  767. min_dy = EVEN(min_dy);
  768. max_dy = EVEN(max_dy); 
  769. } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
  770. bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
  771. if ((x==0) && (y==0) )
  772. {
  773. threshA =  512;
  774. threshB = 1024;
  775. }
  776. else
  777. {
  778. threshA = psad[0];
  779. threshB = threshA+256;
  780. if (threshA< 512) threshA =  512;
  781.                 if (threshA>1024) threshA = 1024; 
  782.          if (threshB>1792) threshB = 1792; 
  783. }
  784. iFound=0;
  785. /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion 
  786.    vector of the median. 
  787.    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
  788. */
  789.         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[0]) ) )
  790. iFound=2;
  791. /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search. 
  792.    Otherwise select large Diamond Search. 
  793. */
  794. if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536) || (bPredEq) ) 
  795. iDiamondSize=1; // halfpel!
  796. else
  797. iDiamondSize=2; // halfpel!
  798. if (!(MotionFlags & PMV_HALFPELDIAMOND16) )
  799. iDiamondSize*=2;
  800. /* Step 4: Calculate SAD around the Median prediction. 
  801.    MinSAD=SAD 
  802.    If Motion Vector equal to Previous frame motion vector 
  803.    and MinSAD<PrevFrmSAD goto Step 10. 
  804.    If SAD<=256 goto Step 10. 
  805. */
  806. // Prepare for main loop 
  807. *currMV=pmv[0]; /* current best := prediction */
  808. if (!(MotionFlags & PMV_HALFPEL16 ))
  809. {  /* This should NOT be necessary! */
  810. currMV->x = EVEN(currMV->x);
  811. currMV->y = EVEN(currMV->y);
  812. }
  813. if (currMV->x > max_dx) 
  814. {
  815. currMV->x=max_dx;
  816. }
  817. if (currMV->x < min_dx) 
  818. {
  819. currMV->x=min_dx;
  820. }
  821. if (currMV->y > max_dy) 
  822. {
  823. currMV->y=max_dy;
  824. }
  825. if (currMV->y < min_dy) 
  826. {
  827. currMV->y=min_dy;
  828. }
  829. iMinSAD = sad16( cur, 
  830.  get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
  831.  iEdgedWidth, MV_MAX_ERROR);
  832.    iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
  833. if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )
  834. {
  835. if (MotionFlags & PMV_QUICKSTOP16) 
  836. goto PMVfast16_Terminate_without_Refine;
  837. if (MotionFlags & PMV_EARLYSTOP16)
  838. goto PMVfast16_Terminate_with_Refine;
  839. }
  840. /* 
  841.    Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block. 
  842.    Also calculate (0,0) but do not subtract offset. 
  843.    Let MinSAD be the smallest SAD up to this point. 
  844.    If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********
  845. */
  846. // (0,0) is always possible
  847. CHECK_MV16_ZERO;
  848. // previous frame MV is always possible
  849. CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
  850. // left neighbour, if allowed
  851. if (x != 0) 
  852. {
  853. if (!(MotionFlags & PMV_HALFPEL16 ))
  854. { pmv[1].x = EVEN(pmv[1].x);
  855. pmv[1].y = EVEN(pmv[1].y);
  856. }
  857. CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
  858. }
  859. // top neighbour, if allowed
  860. if (y != 0)
  861. {
  862. if (!(MotionFlags & PMV_HALFPEL16 ))
  863. { pmv[2].x = EVEN(pmv[2].x);
  864. pmv[2].y = EVEN(pmv[2].y);
  865. }
  866. CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
  867. // top right neighbour, if allowed
  868. if (x != (iWcount-1))
  869. {
  870. if (!(MotionFlags & PMV_HALFPEL16 ))
  871. { pmv[3].x = EVEN(pmv[3].x);
  872. pmv[3].y = EVEN(pmv[3].y);
  873. }
  874. CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
  875. }
  876. }
  877. /* Step 6: If MinSAD <= thresa goto Step 10. 
  878.    If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10. 
  879. */
  880. if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD < pMB->sad16) ) )
  881. {
  882. if (MotionFlags & PMV_QUICKSTOP16) 
  883. goto PMVfast16_Terminate_without_Refine;
  884. if (MotionFlags & PMV_EARLYSTOP16)
  885. goto PMVfast16_Terminate_with_Refine;
  886. }
  887. /************ (Diamond Search)  **************/
  888. /* 
  889.    Step 7: Perform Diamond search, with either the small or large diamond. 
  890.    If Found=2 only examine one Diamond pattern, and afterwards goto step 10 
  891.    Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond. 
  892.    If center then goto step 10. 
  893.    Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center. 
  894.    Refine by using small diamond and goto step 10. 
  895. */
  896. backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
  897. /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
  898. iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
  899.   x, y, 
  900.   currMV->x, currMV->y, iMinSAD, &newMV, 
  901.   pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
  902. if (iSAD < iMinSAD) 
  903. {
  904. *currMV = newMV;
  905. iMinSAD = iSAD;
  906. }
  907. if (MotionFlags & PMV_EXTSEARCH16)
  908. {
  909. /* extended: search (up to) two more times: orignal prediction and (0,0) */
  910. if (!(MVequal(pmv[0],backupMV)) )
  911. {  iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
  912.   x, y, 
  913.   pmv[0].x, pmv[0].y, iMinSAD, &newMV, 
  914.   pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
  915. if (iSAD < iMinSAD) 
  916. {
  917. *currMV = newMV;
  918. iMinSAD = iSAD;
  919. }
  920. }
  921. if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
  922. {  iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
  923.   x, y, 
  924.   0, 0, iMinSAD, &newMV, 
  925.   pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
  926. if (iSAD < iMinSAD) 
  927. {
  928. *currMV = newMV;
  929. iMinSAD = iSAD;
  930. }
  931. }
  932. }
  933. /* 
  934.    Step 10:  The motion vector is chosen according to the block corresponding to MinSAD.
  935. */
  936. PMVfast16_Terminate_with_Refine:
  937. if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step 
  938. iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
  939.   x, y,
  940.   currMV, iMinSAD, 
  941.   pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
  942. PMVfast16_Terminate_without_Refine:
  943. currPMV->x = currMV->x - pmv[0].x;
  944. currPMV->y = currMV->y - pmv[0].y;
  945. return iMinSAD;
  946. }
  947. int32_t Diamond8_MainSearch(
  948. const uint8_t * const pRef,
  949. const uint8_t * const pRefH,
  950. const uint8_t * const pRefV,
  951. const uint8_t * const pRefHV,
  952. const uint8_t * const cur,
  953. const int x, const int y,
  954. int32_t startx, int32_t starty,
  955. int32_t iMinSAD,
  956. VECTOR * const currMV,
  957. const VECTOR * const pmv,
  958. const int32_t min_dx, const int32_t max_dx, 
  959. const int32_t min_dy, const int32_t max_dy,
  960. const int32_t iEdgedWidth, 
  961. const int32_t iDiamondSize, 
  962. const int32_t iFcode,
  963. const int32_t iQuant,
  964. int iFound)
  965. {
  966. /* Do a diamond search around given starting point, return SAD of best */
  967. int32_t iDirection=0;
  968. int32_t iSAD;
  969. VECTOR backupMV;
  970. backupMV.x = startx;
  971. backupMV.y = starty;
  972. /* It's one search with full Diamond pattern, and only 3 of 4 for all following diamonds */
  973. CHECK_MV8_CANDIDATE_DIR(backupMV.x-iDiamondSize,backupMV.y,1);
  974. CHECK_MV8_CANDIDATE_DIR(backupMV.x+iDiamondSize,backupMV.y,2);
  975. CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y-iDiamondSize,3);
  976. CHECK_MV8_CANDIDATE_DIR(backupMV.x,backupMV.y+iDiamondSize,4);
  977. if (iDirection)
  978. while (!iFound)
  979. {
  980. iFound = 1; 
  981. backupMV=*currMV; // since iDirection!=0, this is well defined!
  982. if ( iDirection != 2) 
  983. CHECK_MV8_CANDIDATE_FOUND(backupMV.x-iDiamondSize,backupMV.y,1);
  984. if ( iDirection != 1) 
  985. CHECK_MV8_CANDIDATE_FOUND(backupMV.x+iDiamondSize,backupMV.y,2);
  986. if ( iDirection != 4) 
  987. CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y-iDiamondSize,3);
  988. if ( iDirection != 3) 
  989. CHECK_MV8_CANDIDATE_FOUND(backupMV.x,backupMV.y+iDiamondSize,4);
  990. }
  991. else
  992. {
  993. currMV->x = startx;
  994. currMV->y = starty;
  995. }
  996. return iMinSAD;
  997. }
  998. int32_t Halfpel8_Refine(
  999. const uint8_t * const pRef,
  1000. const uint8_t * const pRefH,
  1001. const uint8_t * const pRefV,
  1002. const uint8_t * const pRefHV,
  1003. const uint8_t * const cur,
  1004. const int x, const int y,
  1005. VECTOR * const currMV,
  1006. int32_t iMinSAD,
  1007. const VECTOR * const pmv,
  1008. const int32_t min_dx, const int32_t max_dx, 
  1009. const int32_t min_dy, const int32_t max_dy,
  1010. const int32_t iFcode,
  1011. const int32_t iQuant,
  1012. const int32_t iEdgedWidth)
  1013. {
  1014. /* Do a half-pel refinement (or rather a "smallest possible amount" refinement) */
  1015. int32_t iSAD;
  1016. VECTOR backupMV = *currMV;
  1017. CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y-1);
  1018. CHECK_MV8_CANDIDATE(backupMV.x  ,backupMV.y-1);
  1019. CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y-1);
  1020. CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y);
  1021. CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y);
  1022. CHECK_MV8_CANDIDATE(backupMV.x-1,backupMV.y+1);
  1023. CHECK_MV8_CANDIDATE(backupMV.x  ,backupMV.y+1);
  1024. CHECK_MV8_CANDIDATE(backupMV.x+1,backupMV.y+1);
  1025. return iMinSAD;
  1026. }
  1027. #define PMV_HALFPEL8 (PMV_HALFPELDIAMOND8|PMV_HALFPELREFINE8)
  1028. int32_t PMVfastSearch8(
  1029. const uint8_t * const pRef,
  1030. const uint8_t * const pRefH,
  1031. const uint8_t * const pRefV,
  1032. const uint8_t * const pRefHV,
  1033. const IMAGE * const pCur,
  1034. const int x, const int y,
  1035. const int start_x, int start_y,
  1036. const uint32_t MotionFlags,
  1037. const MBParam * const pParam,
  1038. MACROBLOCK * const pMBs,
  1039. VECTOR * const currMV,
  1040. VECTOR * const currPMV)
  1041. {
  1042.         const uint32_t iWcount = pParam->mb_width;
  1043. const int32_t iFcode = pParam->fixed_code;
  1044. const int32_t iQuant = pParam->quant;
  1045. const int32_t iWidth = pParam->width;
  1046. const int32_t iHeight = pParam->height;
  1047. const int32_t iEdgedWidth = pParam->edged_width; 
  1048. const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
  1049. int32_t iDiamondSize;
  1050. int32_t min_dx;
  1051. int32_t max_dx;
  1052. int32_t min_dy;
  1053. int32_t max_dy;
  1054. VECTOR pmv[4];
  1055. int32_t psad[4];
  1056. VECTOR newMV;
  1057. VECTOR backupMV;
  1058. MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
  1059. static int32_t threshA,threshB;
  1060.      int32_t iFound,bPredEq;
  1061.      int32_t iMinSAD,iSAD;
  1062. int32_t iSubBlock = ((y&1)<<1) + (x&1);
  1063. /* Get maximum range */
  1064. get_range(&min_dx, &max_dx, &min_dy, &max_dy,
  1065.   x, y, 8, iWidth, iHeight, iFcode);
  1066. /* we work with abs. MVs, not relative to prediction, so range is relative to 0,0 */
  1067. if (!(MotionFlags & PMV_HALFPELDIAMOND8 ))
  1068. { min_dx = EVEN(min_dx);
  1069. max_dx = EVEN(max_dx);
  1070. min_dy = EVEN(min_dy);
  1071. max_dy = EVEN(max_dy); 
  1072. } /* because we might use IF (dx>max_dx) THEN dx=max_dx; */
  1073. bPredEq  = get_pmvdata(pMBs, (x>>1), (y>>1), iWcount, iSubBlock, pmv, psad);
  1074. if ((x==0) && (y==0) )
  1075. {
  1076. threshA =  512/4;
  1077. threshB = 1024/4;
  1078. }
  1079. else
  1080. {
  1081. threshA = psad[0]/4; /* good estimate */
  1082. threshB = threshA+256/4;
  1083. if (threshA< 512/4) threshA =  512/4;
  1084.                 if (threshA>1024/4) threshA = 1024/4; 
  1085.          if (threshB>1792/4) threshB = 1792/4; 
  1086. }
  1087. iFound=0;
  1088. /* Step 2: Calculate Distance= |MedianMVX| + |MedianMVY| where MedianMV is the motion 
  1089.    vector of the median. 
  1090.    If PredEq=1 and MVpredicted = Previous Frame MV, set Found=2  
  1091. */
  1092.         if ((bPredEq) && (MVequal(pmv[0],pMB->mvs[iSubBlock]) ) )
  1093. iFound=2;
  1094. /* Step 3: If Distance>0 or thresb<1536 or PredEq=1 Select small Diamond Search. 
  1095.    Otherwise select large Diamond Search. 
  1096. */
  1097. if ( (pmv[0].x != 0) || (pmv[0].y != 0) || (threshB<1536/4) || (bPredEq) ) 
  1098. iDiamondSize=1; // 1 halfpel!
  1099. else
  1100. iDiamondSize=2; // 2 halfpel = 1 full pixel!
  1101. if (!(MotionFlags & PMV_HALFPELDIAMOND8) )
  1102. iDiamondSize*=2;
  1103. /* Step 4: Calculate SAD around the Median prediction. 
  1104.    MinSAD=SAD 
  1105.    If Motion Vector equal to Previous frame motion vector 
  1106.    and MinSAD<PrevFrmSAD goto Step 10. 
  1107.    If SAD<=256 goto Step 10. 
  1108. */
  1109. // Prepare for main loop 
  1110. currMV->x=start_x; /* start with mv16 */
  1111. currMV->y=start_y;
  1112. iMinSAD = sad8( cur, 
  1113. get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
  1114. iEdgedWidth);
  1115.    iMinSAD += calc_delta_8(currMV->x - pmv[0].x, currMV->y - pmv[0].y, (uint8_t)iFcode) * iQuant;
  1116. if ( (iMinSAD < 256/4 ) || ( (MVequal(*currMV,pMB->mvs[iSubBlock])) && (iMinSAD < pMB->sad8[iSubBlock]) ) )
  1117. {
  1118. if (MotionFlags & PMV_QUICKSTOP16) 
  1119. goto PMVfast8_Terminate_without_Refine;
  1120. if (MotionFlags & PMV_EARLYSTOP16)
  1121. goto PMVfast8_Terminate_with_Refine;
  1122. }
  1123. /* 
  1124.    Step 5: Calculate SAD for motion vectors taken from left block, top, top-right, and Previous frame block. 
  1125.    Also calculate (0,0) but do not subtract offset. 
  1126.    Let MinSAD be the smallest SAD up to this point. 
  1127.    If MV is (0,0) subtract offset. ******** WHAT'S THIS 'OFFSET' ??? ***********
  1128. */
  1129. // the prediction might be even better than mv16
  1130. CHECK_MV8_CANDIDATE(pmv[0].x,pmv[0].y);
  1131. // (0,0) is always possible
  1132. CHECK_MV8_ZERO;
  1133. // previous frame MV is always possible
  1134. CHECK_MV8_CANDIDATE(pMB->mvs[iSubBlock].x,pMB->mvs[iSubBlock].y);
  1135. // left neighbour, if allowed
  1136. if (psad[1] != MV_MAX_ERROR) 
  1137. {
  1138. if (!(MotionFlags & PMV_HALFPEL8 ))
  1139. { pmv[1].x = EVEN(pmv[1].x);
  1140. pmv[1].y = EVEN(pmv[1].y);
  1141. }
  1142. CHECK_MV8_CANDIDATE(pmv[1].x,pmv[1].y);
  1143. }
  1144. // top neighbour, if allowed
  1145. if (psad[2] != MV_MAX_ERROR) 
  1146. {
  1147. if (!(MotionFlags & PMV_HALFPEL8 ))
  1148. { pmv[2].x = EVEN(pmv[2].x);
  1149. pmv[2].y = EVEN(pmv[2].y);
  1150. }
  1151. CHECK_MV8_CANDIDATE(pmv[2].x,pmv[2].y);
  1152. // top right neighbour, if allowed
  1153. if (psad[3] != MV_MAX_ERROR) 
  1154. {
  1155. if (!(MotionFlags & PMV_HALFPEL8 ))
  1156. { pmv[3].x = EVEN(pmv[3].x);
  1157. pmv[3].y = EVEN(pmv[3].y);
  1158. }
  1159. CHECK_MV8_CANDIDATE(pmv[3].x,pmv[3].y);
  1160. }
  1161. }
  1162. /* Step 6: If MinSAD <= thresa goto Step 10. 
  1163.    If Motion Vector equal to Previous frame motion vector and MinSAD<PrevFrmSAD goto Step 10. 
  1164. */
  1165. if ( (iMinSAD <= threshA) || ( MVequal(*currMV,pMB->mvs[iSubBlock]) && (iMinSAD < pMB->sad8[iSubBlock]) ) )
  1166. {
  1167. if (MotionFlags & PMV_QUICKSTOP16) 
  1168. goto PMVfast8_Terminate_without_Refine;
  1169. if (MotionFlags & PMV_EARLYSTOP16)
  1170. goto PMVfast8_Terminate_with_Refine;
  1171. }
  1172. /************ (Diamond Search)  **************/
  1173. /* 
  1174.    Step 7: Perform Diamond search, with either the small or large diamond. 
  1175.    If Found=2 only examine one Diamond pattern, and afterwards goto step 10 
  1176.    Step 8: If small diamond, iterate small diamond search pattern until motion vector lies in the center of the diamond. 
  1177.    If center then goto step 10. 
  1178.    Step 9: If large diamond, iterate large diamond search pattern until motion vector lies in the center. 
  1179.    Refine by using small diamond and goto step 10. 
  1180. */
  1181. backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
  1182. /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
  1183. iSAD = Diamond8_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
  1184.  x, y, 
  1185.  currMV->x, currMV->y, iMinSAD, &newMV, 
  1186.  pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
  1187. if (iSAD < iMinSAD) 
  1188. {
  1189. *currMV = newMV;
  1190. iMinSAD = iSAD;
  1191. }
  1192. if (MotionFlags & PMV_EXTSEARCH8)
  1193. {
  1194. /* extended: search (up to) two more times: orignal prediction and (0,0) */
  1195. if (!(MVequal(pmv[0],backupMV)) )
  1196. {  iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
  1197.   x, y, 
  1198.   pmv[0].x, pmv[0].y, iMinSAD, &newMV, 
  1199.   pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
  1200. if (iSAD < iMinSAD) 
  1201. {
  1202. *currMV = newMV;
  1203. iMinSAD = iSAD;
  1204. }
  1205. }
  1206. if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
  1207. {  iSAD = Diamond16_MainSearch(pRef, pRefH, pRefV, pRefHV, cur,
  1208.   x, y, 
  1209.   0, 0, iMinSAD, &newMV, 
  1210.   pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, iFound);
  1211. if (iSAD < iMinSAD) 
  1212. {
  1213. *currMV = newMV;
  1214. iMinSAD = iSAD;
  1215. }
  1216. }
  1217. }
  1218. /* Step 10: The motion vector is chosen according to the block corresponding to MinSAD.
  1219.    By performing an optional local half-pixel search, we can refine this result even further.
  1220. */
  1221. PMVfast8_Terminate_with_Refine:
  1222. if (MotionFlags & PMV_HALFPELREFINE8)  // perform final half-pel step 
  1223. iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
  1224.  x, y,
  1225.  currMV, iMinSAD, 
  1226.  pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
  1227. PMVfast8_Terminate_without_Refine:
  1228. currPMV->x = currMV->x - pmv[0].x;
  1229. currPMV->y = currMV->y - pmv[0].y;
  1230. return iMinSAD;
  1231. }
  1232. int32_t EPZSSearch16(
  1233. const uint8_t * const pRef,
  1234. const uint8_t * const pRefH,
  1235. const uint8_t * const pRefV,
  1236. const uint8_t * const pRefHV,
  1237. const IMAGE * const pCur,
  1238. const int x, const int y,
  1239. const uint32_t MotionFlags,
  1240. const MBParam * const pParam,
  1241. MACROBLOCK * const pMBs,
  1242. VECTOR * const currMV,
  1243. VECTOR * const currPMV)
  1244. {
  1245.         const uint32_t iWcount = pParam->mb_width;
  1246.         const uint32_t iHcount = pParam->mb_height;
  1247. const int32_t iFcode = pParam->fixed_code;
  1248. const int32_t iQuant = pParam->quant;
  1249. const int32_t iWidth = pParam->width;
  1250. const int32_t iHeight = pParam->height;
  1251. const int32_t iEdgedWidth = pParam->edged_width; 
  1252. const uint8_t * cur = pCur->y + x*16 + y*16*iEdgedWidth;
  1253. int32_t min_dx;
  1254. int32_t max_dx;
  1255. int32_t min_dy;
  1256. int32_t max_dy;
  1257. VECTOR newMV;
  1258. VECTOR backupMV;
  1259. VECTOR pmv[4];
  1260. int32_t psad[8];
  1261. static MACROBLOCK * oldMBs = NULL; 
  1262. MACROBLOCK * const pMB = pMBs + x + y * iWcount;
  1263. MACROBLOCK * oldMB = NULL;
  1264. static int32_t thresh2;
  1265.      int32_t bPredEq;
  1266.      int32_t iMinSAD,iSAD=9999;
  1267. MainSearch16FuncPtr EPZSMainSearchPtr;
  1268. if (oldMBs == NULL)
  1269. { oldMBs = (MACROBLOCK*) calloc(1,iWcount*iHcount*sizeof(MACROBLOCK));
  1270. fprintf(stderr,"allocated %d bytes for oldMBsn",iWcount*iHcount*sizeof(MACROBLOCK));
  1271. }
  1272. oldMB = oldMBs + x + y * iWcount;
  1273. /* Get maximum range */
  1274. get_range(&min_dx, &max_dx, &min_dy, &max_dy,
  1275. x, y, 16, iWidth, iHeight, iFcode);
  1276. /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
  1277. if (!(MotionFlags & PMV_HALFPEL16 ))
  1278. { min_dx = EVEN(min_dx);
  1279.   max_dx = EVEN(max_dx);
  1280.   min_dy = EVEN(min_dy);
  1281.   max_dy = EVEN(max_dy); 
  1282. } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
  1283. bPredEq  = get_pmvdata(pMBs, x, y, iWcount, 0, pmv, psad);
  1284. /* Step 4: Calculate SAD around the Median prediction. 
  1285.         MinSAD=SAD 
  1286.         If Motion Vector equal to Previous frame motion vector 
  1287. and MinSAD<PrevFrmSAD goto Step 10. 
  1288.         If SAD<=256 goto Step 10. 
  1289. */
  1290. // Prepare for main loop 
  1291. *currMV=pmv[0]; /* current best := median prediction */
  1292. if (!(MotionFlags & PMV_HALFPEL16))
  1293. currMV->x = EVEN(currMV->x);
  1294. currMV->y = EVEN(currMV->y);
  1295. }
  1296. if (currMV->x > max_dx) 
  1297. currMV->x=max_dx;
  1298. if (currMV->x < min_dx) 
  1299. currMV->x=min_dx;
  1300. if (currMV->y > max_dy) 
  1301. currMV->y=max_dy;
  1302. if (currMV->y < min_dy) 
  1303. currMV->y=min_dy;
  1304. /***************** This is predictor SET A: only median prediction ******************/ 
  1305. iMinSAD = sad16( cur, 
  1306. get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, iEdgedWidth),
  1307. iEdgedWidth, MV_MAX_ERROR);
  1308.    iMinSAD += calc_delta_16(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
  1309. // thresh1 is fixed to 256 
  1310. if ( (iMinSAD < 256 ) || ( (MVequal(*currMV,pMB->mvs[0])) && (iMinSAD < pMB->sad16) ) )
  1311. {
  1312. if (MotionFlags & PMV_QUICKSTOP16) 
  1313. goto EPZS16_Terminate_without_Refine;
  1314. if (MotionFlags & PMV_EARLYSTOP16) 
  1315. goto EPZS16_Terminate_with_Refine;
  1316. }
  1317. /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/ 
  1318. // previous frame MV 
  1319. CHECK_MV16_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
  1320. // set threshhold based on Min of Prediction and SAD of collocated block
  1321. // CHECK_MV16 always uses iSAD for the SAD of last vector to check, so now iSAD is what we want
  1322. if ((x==0) && (y==0) )
  1323. {
  1324. thresh2 =  512;
  1325. }
  1326. else
  1327. {
  1328. /* T_k = 1.2 * MIN(SAD_top,SAD_left,SAD_topleft,SAD_coll) +128;   [Tourapis, 2002] */
  1329. thresh2 = MIN(psad[0],iSAD)*6/5 + 128;
  1330. }
  1331. // MV=(0,0) is often a good choice
  1332. CHECK_MV16_ZERO;
  1333. // left neighbour, if allowed
  1334. if (x != 0) 
  1335. {
  1336. if (!(MotionFlags & PMV_HALFPEL16 ))
  1337. { pmv[1].x = EVEN(pmv[1].x);
  1338. pmv[1].y = EVEN(pmv[1].y);
  1339. }
  1340. CHECK_MV16_CANDIDATE(pmv[1].x,pmv[1].y);
  1341. }
  1342. // top neighbour, if allowed
  1343. if (y != 0)
  1344. {
  1345. if (!(MotionFlags & PMV_HALFPEL16 ))
  1346. { pmv[2].x = EVEN(pmv[2].x);
  1347. pmv[2].y = EVEN(pmv[2].y);
  1348. }
  1349. CHECK_MV16_CANDIDATE(pmv[2].x,pmv[2].y);
  1350. // top right neighbour, if allowed
  1351. if (x != (iWcount-1))
  1352. {
  1353. if (!(MotionFlags & PMV_HALFPEL16 ))
  1354. { pmv[3].x = EVEN(pmv[3].x);
  1355. pmv[3].y = EVEN(pmv[3].y);
  1356. }
  1357. CHECK_MV16_CANDIDATE(pmv[3].x,pmv[3].y);
  1358. }
  1359. }
  1360. /* Terminate if MinSAD <= T_2 
  1361.    Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1] 
  1362. */
  1363. if ( (iMinSAD <= thresh2) 
  1364. || ( MVequal(*currMV,pMB->mvs[0]) && (iMinSAD <= pMB->sad16) ) )
  1365. {
  1366. if (MotionFlags & PMV_QUICKSTOP16) 
  1367. goto EPZS16_Terminate_without_Refine;
  1368. if (MotionFlags & PMV_EARLYSTOP16) 
  1369. goto EPZS16_Terminate_with_Refine;
  1370. }
  1371. /***** predictor SET C: acceleration MV (new!), neighbours in prev. frame(new!) ****/
  1372. backupMV = pMB->mvs[0];  // last MV
  1373. backupMV.x += (pMB->mvs[0].x - oldMB->mvs[0].x ); // acceleration X
  1374. backupMV.y += (pMB->mvs[0].y - oldMB->mvs[0].y ); // acceleration Y 
  1375. CHECK_MV16_CANDIDATE(backupMV.x,backupMV.y);
  1376. // left neighbour
  1377. if (x != 0)  
  1378. CHECK_MV16_CANDIDATE((oldMB-1)->mvs[0].x,oldMB->mvs[0].y);
  1379. // top neighbour 
  1380. if (y != 0)
  1381. CHECK_MV16_CANDIDATE((oldMB-iWcount)->mvs[0].x,oldMB->mvs[0].y);
  1382. // right neighbour, if allowed (this value is not written yet, so take it from   pMB->mvs 
  1383. if (x != iWcount-1)
  1384. CHECK_MV16_CANDIDATE((pMB+1)->mvs[0].x,oldMB->mvs[0].y);
  1385. // bottom neighbour, dito
  1386. if (y != iHcount-1)
  1387. CHECK_MV16_CANDIDATE((pMB+iWcount)->mvs[0].x,oldMB->mvs[0].y);
  1388. /* Terminate if MinSAD <= T_3 (here T_3 = T_2)  */
  1389. if (iMinSAD <= thresh2)
  1390. {
  1391. if (MotionFlags & PMV_QUICKSTOP16) 
  1392. goto EPZS16_Terminate_without_Refine;
  1393. if (MotionFlags & PMV_EARLYSTOP16) 
  1394. goto EPZS16_Terminate_with_Refine;
  1395. }
  1396. /************ (if Diamond Search)  **************/
  1397. backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
  1398. /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
  1399. if (MotionFlags & PMV_USESQUARES16)
  1400. EPZSMainSearchPtr = Square16_MainSearch;
  1401. else
  1402. EPZSMainSearchPtr = Diamond16_MainSearch;
  1403. iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
  1404. x, y, 
  1405. currMV->x, currMV->y, iMinSAD, &newMV, pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 
  1406. 2, iFcode, iQuant, 0);
  1407. if (iSAD < iMinSAD) 
  1408. {
  1409. *currMV = newMV;
  1410. iMinSAD = iSAD;
  1411. }
  1412. if (MotionFlags & PMV_EXTSEARCH16)
  1413. {
  1414. /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
  1415. if (!(MVequal(pmv[0],backupMV)) )
  1416. iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
  1417. x, y, 
  1418. pmv[0].x, pmv[0].y, iMinSAD, &newMV, 
  1419. pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 2, iFcode, iQuant, 0);
  1420. }
  1421. if (iSAD < iMinSAD) 
  1422. {
  1423. *currMV = newMV;
  1424. iMinSAD = iSAD;
  1425. }
  1426. if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
  1427. iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
  1428. x, y, 
  1429. 0, 0, iMinSAD, &newMV, 
  1430. pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, /*iDiamondSize*/ 2, iFcode, iQuant, 0);
  1431. if (iSAD < iMinSAD) 
  1432. {
  1433. *currMV = newMV;
  1434. iMinSAD = iSAD;
  1435. }
  1436. }
  1437. }
  1438. /***************  Choose best MV found     **************/
  1439. EPZS16_Terminate_with_Refine:
  1440. if (MotionFlags & PMV_HALFPELREFINE16)  // perform final half-pel step 
  1441. iMinSAD = Halfpel16_Refine( pRef, pRefH, pRefV, pRefHV, cur,
  1442. x, y,
  1443. currMV, iMinSAD, 
  1444. pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
  1445. EPZS16_Terminate_without_Refine:
  1446. *oldMB = *pMB;
  1447. currPMV->x = currMV->x - pmv[0].x;
  1448. currPMV->y = currMV->y - pmv[0].y;
  1449. return iMinSAD;
  1450. }
  1451. int32_t EPZSSearch8(
  1452. const uint8_t * const pRef,
  1453. const uint8_t * const pRefH,
  1454. const uint8_t * const pRefV,
  1455. const uint8_t * const pRefHV,
  1456. const IMAGE * const pCur,
  1457. const int x, const int y,
  1458. const int start_x, int start_y,
  1459. const uint32_t MotionFlags,
  1460. const MBParam * const pParam,
  1461. MACROBLOCK * const pMBs,
  1462. VECTOR * const currMV,
  1463. VECTOR * const currPMV)
  1464. {
  1465.         const uint32_t iWcount = pParam->mb_width;
  1466. const int32_t iFcode = pParam->fixed_code;
  1467. const int32_t iQuant = pParam->quant;
  1468. const int32_t iWidth = pParam->width;
  1469. const int32_t iHeight = pParam->height;
  1470. const int32_t iEdgedWidth = pParam->edged_width; 
  1471. const uint8_t * cur = pCur->y + x*8 + y*8*iEdgedWidth;
  1472. int32_t iDiamondSize=1;
  1473. int32_t min_dx;
  1474. int32_t max_dx;
  1475. int32_t min_dy;
  1476. int32_t max_dy;
  1477. VECTOR newMV;
  1478. VECTOR backupMV;
  1479. VECTOR pmv[4];
  1480. int32_t psad[8];
  1481. const int32_t iSubBlock = ((y&1)<<1) + (x&1);
  1482. MACROBLOCK * const pMB = pMBs + (x>>1) + (y>>1) * iWcount;
  1483.      int32_t bPredEq;
  1484.      int32_t iMinSAD,iSAD=9999;
  1485. MainSearch8FuncPtr EPZSMainSearchPtr;
  1486. /* Get maximum range */
  1487. get_range(&min_dx, &max_dx, &min_dy, &max_dy,
  1488. x, y, 8, iWidth, iHeight, iFcode);
  1489. /* we work with abs. MVs, not relative to prediction, so get_range is called relative to 0,0 */
  1490. if (!(MotionFlags & PMV_HALFPEL8 ))
  1491. { min_dx = EVEN(min_dx);
  1492.   max_dx = EVEN(max_dx);
  1493.   min_dy = EVEN(min_dy);
  1494.   max_dy = EVEN(max_dy); 
  1495. } /* because we might use something like IF (dx>max_dx) THEN dx=max_dx; */
  1496. bPredEq  = get_pmvdata(pMBs, x>>1, y>>1, iWcount, iSubBlock, pmv, psad);
  1497. /* Step 4: Calculate SAD around the Median prediction. 
  1498.         MinSAD=SAD 
  1499.         If Motion Vector equal to Previous frame motion vector 
  1500. and MinSAD<PrevFrmSAD goto Step 10. 
  1501.         If SAD<=256 goto Step 10. 
  1502. */
  1503. // Prepare for main loop 
  1504. if (!(MotionFlags & PMV_HALFPEL8))
  1505. currMV->x = EVEN(currMV->x);
  1506. currMV->y = EVEN(currMV->y);
  1507. }
  1508. if (currMV->x > max_dx) 
  1509. currMV->x=max_dx;
  1510. if (currMV->x < min_dx) 
  1511. currMV->x=min_dx;
  1512. if (currMV->y > max_dy) 
  1513. currMV->y=max_dy;
  1514. if (currMV->y < min_dy) 
  1515. currMV->y=min_dy;
  1516. /***************** This is predictor SET A: only median prediction ******************/ 
  1517. iMinSAD = sad8( cur, 
  1518. get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 8, currMV, iEdgedWidth),
  1519. iEdgedWidth);
  1520.    iMinSAD += calc_delta_8(currMV->x-pmv[0].x, currMV->y-pmv[0].y, (uint8_t)iFcode) * iQuant;
  1521. // thresh1 is fixed to 256 
  1522. if (iMinSAD < 256/4 )
  1523. {
  1524. if (MotionFlags & PMV_QUICKSTOP8) 
  1525. goto EPZS8_Terminate_without_Refine;
  1526. if (MotionFlags & PMV_EARLYSTOP8) 
  1527. goto EPZS8_Terminate_with_Refine;
  1528. }
  1529. /************** This is predictor SET B: (0,0), prev.frame MV, neighbours **************/ 
  1530. // previous frame MV 
  1531. CHECK_MV8_CANDIDATE(pMB->mvs[0].x,pMB->mvs[0].y);
  1532. // MV=(0,0) is often a good choice
  1533. CHECK_MV8_ZERO;
  1534. /* Terminate if MinSAD <= T_2 
  1535.    Terminate if MV[t] == MV[t-1] and MinSAD[t] <= MinSAD[t-1] 
  1536. */
  1537. if (iMinSAD < 512/4)  /* T_2 == 512/4 hardcoded */
  1538. {
  1539. if (MotionFlags & PMV_QUICKSTOP8) 
  1540. goto EPZS8_Terminate_without_Refine;
  1541. if (MotionFlags & PMV_EARLYSTOP8) 
  1542. goto EPZS8_Terminate_with_Refine;
  1543. }
  1544. /************ (if Diamond Search)  **************/
  1545. backupMV = *currMV; /* save best prediction, actually only for EXTSEARCH */
  1546. if (!(MotionFlags & PMV_HALFPELDIAMOND8))
  1547. iDiamondSize *= 2;
  1548. /* default: use best prediction as starting point for one call of PMVfast_MainSearch */
  1549. // if (MotionFlags & PMV_USESQUARES8)
  1550. // EPZSMainSearchPtr = Square8_MainSearch;
  1551. // else
  1552. EPZSMainSearchPtr = Diamond8_MainSearch;
  1553. iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
  1554. x, y, 
  1555. currMV->x, currMV->y, iMinSAD, &newMV, 
  1556. pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, 
  1557. iDiamondSize, iFcode, iQuant, 00);
  1558. if (iSAD < iMinSAD) 
  1559. {
  1560. *currMV = newMV;
  1561. iMinSAD = iSAD;
  1562. }
  1563. if (MotionFlags & PMV_EXTSEARCH8)
  1564. {
  1565. /* extended mode: search (up to) two more times: orignal prediction and (0,0) */
  1566. if (!(MVequal(pmv[0],backupMV)) )
  1567. iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
  1568. x, y, 
  1569. pmv[0].x, pmv[0].y, iMinSAD, &newMV, 
  1570. pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
  1571. if (iSAD < iMinSAD) 
  1572. {
  1573. *currMV = newMV;
  1574. iMinSAD = iSAD;
  1575. }
  1576. }
  1577. if ( (!(MVzero(pmv[0]))) && (!(MVzero(backupMV))) )
  1578. iSAD = (*EPZSMainSearchPtr)(pRef, pRefH, pRefV, pRefHV, cur,
  1579. x, y, 
  1580. 0, 0, iMinSAD, &newMV, 
  1581. pmv, min_dx, max_dx, min_dy, max_dy, iEdgedWidth, iDiamondSize, iFcode, iQuant, 0);
  1582. if (iSAD < iMinSAD) 
  1583. {
  1584. *currMV = newMV;
  1585. iMinSAD = iSAD;
  1586. }
  1587. }
  1588. }
  1589. /***************  Choose best MV found     **************/
  1590. EPZS8_Terminate_with_Refine:
  1591. if (MotionFlags & PMV_HALFPELREFINE8)  // perform final half-pel step 
  1592. iMinSAD = Halfpel8_Refine( pRef, pRefH, pRefV, pRefHV, cur,
  1593. x, y,
  1594. currMV, iMinSAD, 
  1595. pmv, min_dx, max_dx, min_dy, max_dy, iFcode, iQuant, iEdgedWidth);
  1596. EPZS8_Terminate_without_Refine:
  1597. currPMV->x = currMV->x - pmv[0].x;
  1598. currPMV->y = currMV->y - pmv[0].y;
  1599. return iMinSAD;
  1600. }