mot_est_mb.c
上传用户:enenge
上传日期:2007-01-08
资源大小:96k
文件大小:25k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /**************************************************************************
  2.  *                                                                        *
  3.  * This code is developed by Adam Li.  This software is an                *
  4.  * implementation of a part of one or more MPEG-4 Video tools as          *
  5.  * specified in ISO/IEC 14496-2 standard.  Those intending to use this    *
  6.  * software module in hardware or software products are advised that its  *
  7.  * use may infringe existing patents or copyrights, and any such use      *
  8.  * would be at such party's own risk.  The original developer of this     *
  9.  * software module and his/her company, and subsequent editors and their  *
  10.  * companies (including Project Mayo), will have no liability for use of  *
  11.  * this software or modifications or derivatives thereof.                 *
  12.  *                                                                        *
  13.  * Project Mayo gives users of the Codec a license to this software       *
  14.  * module or modifications thereof for use in hardware or software        *
  15.  * products claiming conformance to the MPEG-4 Video Standard as          *
  16.  * described in the Open DivX license.                                    *
  17.  *                                                                        *
  18.  * The complete Open DivX license can be found at                         *
  19.  * http://www.projectmayo.com/opendivx/license.php .                      *
  20.  *                                                                        *
  21.  **************************************************************************/
  22. /**************************************************************************
  23.  *
  24.  *  mot_est_mb.c
  25.  *
  26.  *  Copyright (C) 2001  Project Mayo
  27.  *
  28.  *  Adam Li
  29.  *
  30.  *  DivX Advance Research Center <darc@projectmayo.com>
  31.  *
  32.  **************************************************************************/
  33. /* This file contains some functions to do motion estimation and          */
  34. /* for one MacroBlock in one pass.                                        */
  35. /* Some codes of this project come from MoMuSys MPEG-4 implementation.    */
  36. /* Please see seperate acknowledgement file for a list of contributors.   */
  37. #include "mot_util.h"
  38. /* Obtaining if two floating point values are equal*/
  39. #define ABSDOUBLE(x)   (((x) > 0.0001) ? (x) : (((x) < -0.0001) ? -(x): 0.0 ))
  40. #define ARE_EQUAL(x,y) ( (ABSDOUBLE((Float)(x)-(y))>0.1)?(0):(1) )
  41. /* auxiliar define for indexing in MBMotionEstimation */
  42. #define INDEX_BIG(x,y) ((x)+(y)*(vop_width))
  43. #define INDEX_NOR(x,y) ((x)+(y)*(MB_SIZE))
  44. /* ------------------------------------------------------------------------- */
  45. /***********************************************************CommentBegin******
  46.  *
  47.  * -- RangeInSearchArea -- computes the range of the search area
  48.  *
  49.  * Purpose :
  50.  *      computes the range of the search area for the predicted MV's
  51.  *      INSIDE the overlapped zone between reference and current vops
  52.  *
  53.  ***********************************************************CommentEnd********/
  54. static Void
  55. RangeInSearchArea(
  56. Int     i,   /* <-- horizontal MBcoordinate in pixels               */
  57. Int     j,   /* <-- vertical MB coordinate in pixels                */
  58. Int     block,   /* <-- block position (0 16x16; 1-2-3-4 8x8)           */
  59. Int     prev_x,   /* <-- absolute horizontal position of the previous vop*/
  60. Int     prev_y,   /* <-- absolute vertical position of the previous vop  */
  61. Int     vop_width,   /* <-- horizontal vop dimension                        */
  62. Int     vop_height,   /* <-- vertical vop dimension                          */
  63. Int     br_x,   /* <-- absolute horizontal position of the current vop */
  64. Int     br_y,   /* <-- absolute vertical   position of the current vop */
  65. Int     edge,   /* <-- edge arround the reference vop                  */
  66. Int     f_code,   /* <-  MV search range 1/2 (or 1/4) pel: (0=16,) 1=32,2=64,...,7=2048 */
  67. Float   *mv_x_min,   /* <-- min horizontal range                            */
  68. Float   *mv_x_max,   /* <-- max horizontal range                            */
  69. Float   *mv_y_min,   /* <-- min vertical range                              */
  70. Float   *mv_y_max,   /* <-- max vertical range                              */
  71. Int     *out   /* --> the search area does not exist (the reference   */   /*     and current BB does not overlap)                */
  72. )
  73. {
  74. Int   dim_curr_x_max,
  75. dim_curr_y_max,
  76. dim_curr_x_min,
  77. dim_curr_y_min;
  78. Int   dim_prev_x_max,
  79. dim_prev_y_max,
  80. dim_prev_x_min,
  81. dim_prev_y_min;
  82. Int   mb_b_size,
  83. block_x,
  84. block_y;
  85. *out=0;
  86. switch (block)
  87. {
  88. case 0:   /* 8x8 or 16x16 block search */
  89. block_x=0;   /*****************************/
  90. block_y=0;   /** 1 2 ********  0  *********/
  91. mb_b_size=MB_SIZE;   /** 3 4 ********     *********/
  92. break;   /*****************************/
  93. case 1:
  94. block_x=0;
  95. block_y=0;
  96. mb_b_size=B_SIZE;
  97. break;
  98. case 2:
  99. block_x=B_SIZE;
  100. block_y=0;
  101. mb_b_size=B_SIZE;
  102. break;
  103. case 3:
  104. block_x=0;
  105. block_y=B_SIZE;
  106. mb_b_size=B_SIZE;
  107. break;
  108. case 4:
  109. block_x=B_SIZE;
  110. block_y=B_SIZE;
  111. mb_b_size=B_SIZE;
  112. break;
  113. default:
  114. return;
  115. }
  116. /* min x/y */
  117. dim_curr_x_min=(Int)(br_x+i*MB_SIZE+*mv_x_min+block_x);
  118. dim_curr_y_min=(Int)(br_y+j*MB_SIZE+*mv_y_min+block_y);
  119. dim_prev_x_min=prev_x/*-edge*/;
  120. dim_prev_y_min=prev_y/*-edge*/;
  121. /* max x/y */
  122. /*the MB right-pixels inside */
  123. dim_curr_x_max=(Int)(br_x+i*MB_SIZE+*mv_x_max+mb_b_size+block_x);
  124. /*the MB bottom-pixels inside */
  125. dim_curr_y_max=(Int)(br_y+j*MB_SIZE+*mv_y_max+mb_b_size+block_y);
  126. dim_prev_x_max=prev_x+vop_width /*+edge*/;
  127. dim_prev_y_max=prev_y+vop_height/*+edge*/;
  128. /* range x/y min */
  129. if (dim_curr_x_min > dim_prev_x_max)
  130. {
  131. *out=1;
  132. }
  133. else if(dim_curr_x_min < dim_prev_x_min)
  134. {
  135. *mv_x_min = *mv_x_min + ( dim_prev_x_min - dim_curr_x_min ) ;
  136. }
  137. if(!(*out))
  138. {
  139. if (dim_curr_y_min > dim_prev_y_max)
  140. {
  141. *out=1;
  142. }
  143. else if(dim_curr_y_min < dim_prev_y_min)
  144. {
  145. *mv_y_min = *mv_y_min + ( dim_prev_y_min - dim_curr_y_min ) ;
  146. }
  147. }
  148. /* range x/y max */
  149. if(!(*out))
  150. {
  151. if(dim_curr_x_max < dim_prev_x_min)
  152. {
  153. *out=1;
  154. }
  155. if ((!(*out))&&(dim_curr_x_max > dim_prev_x_max))
  156. {
  157. *mv_x_max = *mv_x_max - ( dim_curr_x_max - dim_prev_x_max) ;
  158. }
  159. }
  160. if(!(*out))
  161. {
  162. if(dim_curr_y_max < dim_prev_y_min)
  163. {
  164. *out=1;   /* already set */
  165. }
  166. if ((!(*out))&&(dim_curr_y_max > dim_prev_y_max))
  167. {
  168. *mv_y_max = *mv_y_max - ( dim_curr_y_max - dim_prev_y_max) ;
  169. }
  170. }
  171. if(*mv_x_min>*mv_x_max)
  172. {
  173. *out=1;
  174. }
  175. if ( (!(*out)) && (*mv_y_min>*mv_y_max))
  176. {
  177. *out=1;
  178. }
  179. return;
  180. }
  181. /***********************************************************CommentBegin******
  182.  *
  183.  * -- Obtain_Range -- computes the range of the search area
  184.  *
  185.  * Purpose :
  186.  *      computes the range of the search area for the predicted MV's
  187.  *      (it can be outside the overlapped zone between the reference
  188.  *      and current vops)
  189.  *
  190.  * Return values :
  191.  *      1 on success, 0 on error
  192.  *
  193.  ***********************************************************CommentEnd********/
  194. static Int
  195. Obtain_Range(
  196. Int     f_code,   /* <-- MV search range 1/2 (or 1/4 pel): (0=16,) 1=32,2=64,...,7=2048   */
  197. Int     sr,   /* <-- Serach range (radius)                           */
  198. Int     type,   /* <-- MBM_INTER16==16x16 search; MBM_INTER8==8x8 search */
  199. Float   pmv_x,   /* <-- predicted horizontal motion vector              */
  200. Float   pmv_y,   /* <-- predicted horizontal motion vector              */
  201. Float   *mv_x_min,   /* --> min horizontal range                            */
  202. Float   *mv_x_max,   /* --> max horizontal range                            */
  203. Float   *mv_y_min,   /* --> min vertical range                              */
  204. Float   *mv_y_max,   /* --> max vertical range                              */
  205. Int     quarter_pel   /* <-- quarter pel flag (to allow f_code==0 without sprite) */
  206. )
  207. {
  208. Int    error;
  209. Float  aux_x_min, aux_y_min,
  210. aux_x_max, aux_y_max;
  211. Float  range;
  212. error=0;
  213. if ((f_code==0) && (!quarter_pel))   /* for Low Latency Sprite */
  214. {
  215. *mv_x_min=0;
  216. *mv_x_max=0;
  217. *mv_y_min=0;
  218. *mv_y_max=0;
  219. }
  220. else
  221. {
  222. range = sr;
  223. *mv_x_min=-range; *mv_x_max= range - 0.5f;
  224. *mv_y_min=-range; *mv_y_max= range - 0.5f;
  225. }
  226. if (type==MBM_INTER8)
  227. {
  228. aux_x_min=pmv_x - DEFAULT_8_WIN;
  229. aux_y_min=pmv_y - DEFAULT_8_WIN;
  230. aux_x_max=pmv_x + DEFAULT_8_WIN;
  231. aux_y_max=pmv_y + DEFAULT_8_WIN;
  232. if(*mv_x_min < aux_x_min)
  233. *mv_x_min = aux_x_min;
  234. if(*mv_y_min < aux_y_min)
  235. *mv_y_min = aux_y_min;
  236. if(*mv_x_max > aux_x_max)
  237. *mv_x_max = aux_x_max;
  238. if(*mv_y_max > aux_y_max)
  239. *mv_y_max = aux_y_max;
  240. }
  241. if (error==1)
  242. return(0);
  243. else
  244. return(1);
  245. }
  246. /***********************************************************CommentBegin******
  247.  *
  248.  * -- MBMotionEstimation -- Computes INTEGER PRECISION MV's for a MB
  249.  *
  250.  * Purpose :
  251.  *      Computes INTEGER PRECISION MV's for a MB. Also returns
  252.  *      prediction errors. Requires the whole MVs data images to
  253.  *      obtain prediction for the current MV, which determines search
  254.  *      range
  255.  *
  256.  ***********************************************************CommentEnd********/
  257. Void
  258. MBMotionEstimation(
  259. SInt    *curr,   /* <-- Current vop pointer                          */
  260. SInt    *prev,   /* <-- extended reference picture                   */
  261. Int     br_x,   /* <-- horizontal bounding rectangle coordinate     */
  262. Int     br_y,   /* <-- vertical bounding rectangle coordinate       */
  263. Int     br_width,   /* <-- bounding rectangule width                    */
  264. Int     i,   /* <-- horizontal MBcoordinate in pixels            */
  265. Int     j,   /* <-- vertical MB coordinate in pixels             */
  266. Int     prev_x,   /* <-- absolute horiz. position of previous vop     */
  267. Int     prev_y,   /* <-- absolute verti. position of previous vop     */
  268. Int     vop_width,   /* <-- horizontal vop dimension                     */
  269. Int     vop_height,   /* <-- vertical vop dimension                       */
  270. Int     enable_8x8_mv,   /* <-- 8x8 MV (=1) or only 16x16 MV (=0)            */
  271. Int     edge,   /* <-- edge                                         */
  272. Int     f_code,   /* <-- MV search range 1/2 (or 1/4) pel: (0=16,) 1=32,2=64,...,7=2048*/
  273. Int     sr,   /* <-- search range (corresponds to f_code) UB 990215*/
  274. Float hint_mv_w,                                /* <-- hint seed for horizontal MV                  */
  275. Float hint_mv_h,                                /* <-- hint seed for vertical MV                    */
  276. Float   *mv16_w,   /* --> predicted horizontal 16x16 MV(if approp.)    */
  277. Float   *mv16_h,   /* --> predicted vertical 16x16 MV  (if approp.)    */
  278. Float   *mv8_w,   /* --> predicted horizontal 8x8 MV  (if approp.)    */
  279. Float   *mv8_h,   /* --> predicted vertical 8x8 MV    (if approp.)    */
  280. Int     *min_error,   /* --> Minimum prediction error                     */
  281. SInt    *flags
  282. )
  283. {
  284. Int     x, y;
  285. Int     sad, sad_min=MV_MAX_ERROR;
  286. Int     mv_x, mv_y;
  287. Int     block;
  288. Float   pmv_x, pmv_y;
  289. SInt act_block[MB_SIZE*MB_SIZE];
  290. Float   mv_x_min, mv_x_max,
  291. mv_y_min, mv_y_max;
  292. Int     int_mv_x_min=0, int_mv_x_max=0,
  293. int_mv_y_min=0, int_mv_y_max=0;
  294. Int     pos16, pos8;
  295. Int     mvm_width   = br_width/MB_SIZE;
  296. Int     x_curr      = i*MB_SIZE,
  297. y_curr      = j*MB_SIZE;
  298. Int     hb,vb;
  299. Int     out;
  300. Int     rel_ori_x;
  301. Int     rel_ori_y;
  302. Int     min_error16, min_error8 = 0;
  303. // SInt    *curr = (SInt *)GetImageData(GetVopY(curr_vop));
  304. #ifndef _FULL_SEARCH_   /* PIH (NTU) Fast ME 08/08/99 */
  305. typedef struct
  306. {
  307. Int x;
  308. Int y;
  309. SInt start_nmbr;
  310. } DPoint;
  311. typedef struct
  312. {
  313. DPoint point[8];
  314. } Diamond;
  315. SInt d_type=1,stop_flag=0,pt_nmbr=0,check_pts,total_check_pts=8,mot_dirn=0;
  316. Int d_centre_x=0,d_centre_y=0,check_pt_x,check_pt_y;
  317. Diamond diamond[2]=
  318. {
  319. {
  320. { {0,1,0}, {1,0,0}, {0,-1,0}, {-1,0,0} }
  321. }
  322. ,
  323. {
  324. { {0,2,6}, {1,1,0}, {2,0,0}, {1,-1,2},
  325. {0,-2,2}, {-1,-1,4}, {-2,0,4}, {-1,1,6} }
  326. }
  327. };
  328. #endif
  329. d_centre_x = (int)hint_mv_w;
  330. d_centre_y = (int)hint_mv_h;
  331. rel_ori_x=br_x-prev_x;
  332. rel_ori_y=br_y-prev_y;
  333. /* Load act_block */
  334. LoadArea(curr, x_curr,y_curr,MB_SIZE,MB_SIZE,br_width, act_block);
  335. /* Compute 16x16 integer MVs */
  336. /* Obtain range */
  337. Obtain_Range (f_code, sr, MBM_INTER16,   /* UB 990215 added search range */
  338. 0.0, 0.0, &mv_x_min, &mv_x_max,
  339.   /*UB 990215 added quarter pel support */
  340. &mv_y_min, &mv_y_max, 0/*GetVopQuarterPel(curr_vop)*/);
  341. RangeInSearchArea (i,j,0, prev_x, prev_y, vop_width, vop_height,
  342. br_x, br_y, edge,f_code, &mv_x_min, &mv_x_max,
  343.   /*UB 990215 added quarter pel support */
  344. &mv_y_min, &mv_y_max,&out);
  345. /* Compute */
  346. if(!out)
  347. {
  348. int_mv_x_min=(int)ceil((double)mv_x_min);
  349. int_mv_y_min=(int)ceil((double)mv_y_min);
  350. int_mv_x_max=(int)floor((double)mv_x_max);
  351. int_mv_y_max=(int)floor((double)mv_y_max);
  352. flags[0]=ARE_EQUAL(int_mv_x_min,mv_x_min);
  353. flags[1]=ARE_EQUAL(int_mv_x_max,mv_x_max);
  354. flags[2]=ARE_EQUAL(int_mv_y_min,mv_y_min);
  355. flags[3]=ARE_EQUAL(int_mv_y_max,mv_y_max);
  356. sad_min=MV_MAX_ERROR;
  357. mv_x = mv_y = 2000;   /* A very large MV */
  358. #ifdef _FULL_SEARCH_   /* PIH (NTU)  08/08/99 */
  359. for (y=int_mv_y_min; y<=int_mv_y_max; y++)
  360. for (x=int_mv_x_min; x<=int_mv_x_max; x++)
  361. {
  362. if (x==0 && y==0)
  363. sad=SAD_Macroblock(prev+INDEX_BIG(x_curr+rel_ori_x,
  364. y_curr+rel_ori_y), act_block, 
  365. (vop_width/*+2*edge*/), MV_MAX_ERROR)
  366. - (128 + 1);
  367. else
  368. sad=SAD_Macroblock(prev+INDEX_BIG(x_curr+x+rel_ori_x,
  369. y_curr+y+rel_ori_y), act_block, 
  370. (vop_width/*+2*edge*/), sad_min);
  371. if (sad<sad_min)
  372. {
  373. sad_min=sad;
  374. mv_x=x;
  375. mv_y=y;
  376. }
  377. else if (sad==sad_min)
  378. if((ABS(x)+ABS(y)) < (ABS(mv_x)+ABS(mv_y)))
  379. {
  380. sad_min=sad;
  381. mv_x=x;
  382. mv_y=y;
  383. }
  384. }   /*for*/
  385. #else   /* PIH (NTU) Fast ME 08/08/99 */
  386. sad = SAD_Macroblock(prev+INDEX_BIG(x_curr+rel_ori_x,
  387. y_curr+rel_ori_y), act_block, (vop_width/*+2*edge*/), MV_MAX_ERROR)
  388. - (128 + 1);
  389. if (sad<sad_min)
  390. {
  391. sad_min=sad;
  392. mv_x = mv_y = 0;
  393. }
  394. do
  395. {
  396. check_pts=total_check_pts;
  397. do
  398. {
  399. check_pt_x = diamond[d_type].point[pt_nmbr].x + d_centre_x;
  400. check_pt_y = diamond[d_type].point[pt_nmbr].y + d_centre_y;
  401. /* Restrict the search to the searching window ; Note: This constraint can be removed */
  402. if ( check_pt_x < int_mv_x_min || check_pt_x > int_mv_x_max || check_pt_y < int_mv_y_min || check_pt_y > int_mv_y_max)
  403. {
  404. sad = MV_MAX_ERROR;
  405. }
  406. else
  407. {
  408. sad=SAD_Macroblock(prev+INDEX_BIG(x_curr+check_pt_x+rel_ori_x,
  409. y_curr+check_pt_y+rel_ori_y), act_block, 
  410. (vop_width/*+2*edge*/), sad_min);
  411. #ifdef _SAD_EXHAUS_
  412. fprintf(stdout,"+o+ [%2d,%2d] sad16(%3d,%3d)=%4dn",i,j,x,y,sad);
  413. #endif
  414. }
  415. if (sad<sad_min)
  416. {
  417. sad_min=sad;
  418. mv_x=check_pt_x;
  419. mv_y=check_pt_y;
  420. mot_dirn=pt_nmbr;
  421. }
  422. else if (sad==sad_min)
  423. if((ABS(check_pt_x)+ABS(check_pt_y)) < (ABS(mv_x)+ABS(mv_y)))
  424. {
  425. sad_min=sad;
  426. mv_x=check_pt_x;
  427. mv_y=check_pt_y;
  428. mot_dirn=pt_nmbr;
  429. }
  430. pt_nmbr+=1;
  431. if((pt_nmbr)>= 8) pt_nmbr-=8;
  432. check_pts-=1;
  433. }
  434. while(check_pts>0);
  435. if( d_type == 0)
  436. {
  437. stop_flag = 1;
  438. }
  439. else
  440. {
  441. if( (mv_x == d_centre_x) && (mv_y == d_centre_y) )
  442. {
  443. d_type=0;
  444. pt_nmbr=0;
  445. total_check_pts = 4;
  446. }
  447. else
  448. {
  449. if((mv_x==d_centre_x) ||(mv_y==d_centre_y))
  450. total_check_pts=5;
  451. else
  452. total_check_pts=3;
  453. pt_nmbr=diamond[d_type].point[mot_dirn].start_nmbr;
  454. d_centre_x = mv_x;
  455. d_centre_y = mv_y;
  456. }
  457. }
  458. }
  459. while(stop_flag!=1);
  460. #endif
  461. flags[0]=flags[0] && (mv_x==int_mv_x_min);
  462. flags[1]=flags[1] && (mv_x==int_mv_x_max);
  463. flags[2]=flags[2] && (mv_y==int_mv_y_min);
  464. flags[3]=flags[3] && (mv_y==int_mv_y_max);
  465. }
  466. else
  467. {
  468. mv_x=mv_y=0;
  469. sad_min=MV_MAX_ERROR;
  470. }
  471. /* Store result */
  472. out |=((mv_x==2000)||(mv_y==2000));
  473. if(out)
  474. {
  475. mv_x=mv_y=0;
  476. sad_min=MV_MAX_ERROR;
  477. }
  478. pos16=2*j*2*mvm_width + 2*i;
  479. mv16_w[pos16]=   mv_x; mv16_h[pos16]=   mv_y;
  480. mv16_w[pos16+1]= mv_x; mv16_h[pos16+1]= mv_y;
  481. pos16+=2*mvm_width;
  482. mv16_w[pos16]=   mv_x; mv16_h[pos16]=   mv_y;
  483. mv16_w[pos16+1]= mv_x; mv16_h[pos16+1]= mv_y;
  484. min_error16 = sad_min;
  485. *min_error = min_error16;
  486. /* Compute 8x8 MVs */
  487. if(enable_8x8_mv==1)
  488. {
  489. if(!out)
  490. {
  491. for (block=0;block<4;block++)
  492. {
  493. /* Obtain range */
  494. if(block==0)
  495. {
  496. hb=vb=0;
  497. }
  498. else if (block==1)
  499. {
  500. hb=1;vb=0;
  501. }
  502. else if (block==2)
  503. {
  504. hb=0;vb=1;
  505. }
  506. else
  507. {
  508. hb=vb=1;
  509. }
  510. /* VM 2.*: restrict the search range based on the current 16x16 MV
  511.  *         inside a window around it
  512.  */
  513. pmv_x=mv16_w[pos16]; pmv_y=mv16_h[pos16];
  514.   /* UB 990215 added search range */
  515. Obtain_Range(f_code, sr, MBM_INTER8,
  516. pmv_x, pmv_y, &mv_x_min,
  517.   /*UB 990215 added quarter pel support */
  518. &mv_x_max, &mv_y_min, &mv_y_max, 0 /*GetVopQuarterPel(curr_vop)*/);
  519. RangeInSearchArea(i,j, block+1, prev_x, prev_y,
  520. vop_width, vop_height, br_x, br_y, edge,f_code,
  521.   /*UB 990215 added quarter pel support */
  522. &mv_x_min, &mv_x_max, &mv_y_min,&mv_y_max,&out);
  523. if(!out)
  524. {
  525. int_mv_x_min=(int)ceil((double)mv_x_min);
  526. int_mv_y_min=(int)ceil((double)mv_y_min);
  527. int_mv_x_max=(int)floor((double)mv_x_max);
  528. int_mv_y_max=(int)floor((double)mv_y_max);
  529. flags[4+block*4]=ARE_EQUAL(int_mv_x_min,mv_x_min);
  530. flags[4+block*4+1]=ARE_EQUAL(int_mv_x_max,mv_x_max);
  531. flags[4+block*4+2]=ARE_EQUAL(int_mv_y_min,mv_y_min);
  532. flags[4+block*4+3]=ARE_EQUAL(int_mv_y_max,mv_y_max);
  533. sad_min=MV_MAX_ERROR;
  534. mv_x = mv_y = 2000;   /* A very large MV */
  535. for (y=int_mv_y_min; y<=int_mv_y_max; y++)
  536. for (x=int_mv_x_min; x<=int_mv_x_max; x++)
  537. {
  538. sad=SAD_Block(prev+
  539. INDEX_BIG(x_curr + x + 8*(block==1||block==3)+rel_ori_x,
  540. y_curr + y + 8*(block==2||block==3)+rel_ori_y),
  541. act_block+INDEX_NOR(8*(block==1||block==3),
  542. 8*(block==2||block==3)),
  543. (vop_width /*+2*edge*/), sad_min);
  544. if (sad<sad_min)
  545. {
  546. sad_min=sad;
  547. mv_x=x;
  548. mv_y=y;
  549. }
  550. else if (sad==sad_min)
  551. if((ABS(x)+ABS(y)) < (ABS(mv_x)+ABS(mv_y)))
  552. {
  553. sad_min=sad;
  554. mv_x=x;
  555. mv_y=y;
  556. }
  557. }   /*for*/
  558. flags[4+block*4]   = flags[4+block*4]   && (mv_x==int_mv_x_min);
  559. flags[4+block*4+1] = flags[4+block*4+1] && (mv_x==int_mv_x_max);
  560. flags[4+block*4+2] = flags[4+block*4+2] && (mv_y==int_mv_y_min);
  561. flags[4+block*4+3] = flags[4+block*4+3] && (mv_y==int_mv_y_max);
  562. }
  563. else
  564. {
  565. mv_x=mv_y=0;
  566. sad_min=MV_MAX_ERROR;
  567. /* punish the OUTER blocks with MV_MAX_ERROR in order to
  568.    be INTRA CODED */
  569. }
  570. /* Store result */
  571. if(block==0)
  572. {
  573. pos8=2*j*2*mvm_width + 2*i;
  574. min_error8 += sad_min;
  575. }
  576. else if (block==1)
  577. {
  578. pos8=2*j*2*mvm_width + 2*i+1;
  579. min_error8 += sad_min;
  580. }
  581. else if (block==2)
  582. {
  583. pos8=(2*j+1)*2*mvm_width + 2*i;
  584. min_error8 += sad_min;
  585. }
  586. else
  587. {
  588. pos8=(2*j+1)*2*mvm_width + 2*i+1;
  589. min_error8 += sad_min;
  590. }
  591. /* Store result: absolute coordinates (note that in restricted mode
  592.    pmv is (0,0)) */
  593. mv8_w[pos8]=mv_x;
  594. mv8_h[pos8]=mv_y;
  595. }   /*for block*/
  596. if (min_error8 < *min_error)
  597. *min_error = min_error8;
  598. }
  599. else
  600. {   /* all the four blocks are out */
  601. pos8=2*j*2*mvm_width + 2*i;      mv8_w[pos8]=mv8_h[pos8]=0.0;
  602. pos8=2*j*2*mvm_width + 2*i+1;    mv8_w[pos8]=mv8_h[pos8]=0.0;
  603. pos8=(2*j+1)*2*mvm_width + 2*i;  mv8_w[pos8]=mv8_h[pos8]=0.0;
  604. pos8=(2*j+1)*2*mvm_width + 2*i+1;mv8_w[pos8]=mv8_h[pos8]=0.0;
  605. min_error8 = MV_MAX_ERROR;
  606. }
  607. }   /* enable_8x8_mv*/
  608. }
  609. /***********************************************************CommentBegin******
  610.  *
  611.  * -- FindSubPel -- Computes MV with half-pixel accurary
  612.  *
  613.  * Purpose :
  614.  *      Computes MV with sub-pixel accurary for a 16x16 or 8x8 block
  615.  *
  616.  * Description :
  617.  *    1) The preference for the 16x16 null motion vector must be applied
  618.  *       again (now, the SAD is recomputed for the recontructed interpolated
  619.  *       reference)
  620.  *
  621.  ***********************************************************CommentEnd********/
  622. Void
  623. FindSubPel(
  624. Int    x,   /* <-- horizontal block coordinate in pixels            */
  625. Int    y,   /* <-- vertical blocl coordinate in pixels              */
  626. SInt   *prev,                                     /* <-- interpolated reference vop                       */
  627. SInt   *curr,                                   /* <-- current block                                    */   
  628. Int    bs_x,                 /* <-- hor. block size (8/16)                           */
  629. Int    bs_y,   /* <-- vert. block size (8/16)                          */
  630. Int    comp,   /* <-- block position in MB (0,1,2,3)                   */
  631. Int    rel_x,   /* <-- relative horiz. position between curr & prev vops*/
  632. Int    rel_y,   /* <-- relative verti. position between curr & prev vops*/
  633. Int    pels,   /* <-- vop width                                        */
  634. Int    lines,   /* <-- vop height                                       */
  635. Int    edge,   /* <-- edge                                             */
  636. SInt   *flags,   /* <-- flags                                            */
  637. SInt   *curr_comp_mb,                             /* <-> motion compensated current mb                    */
  638. Float  *mvx,   /* <-> horizontal motion vector                         */
  639. Float  *mvy,   /* <-> vertical motion vector                           */
  640. Int    *min_error   /* --> prediction error                                 */
  641. )
  642. {
  643. static PixPoint search[9] = 
  644. {
  645. {0, 0}, {-1, -1}, {0, -1}, {1, -1},
  646. {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}
  647. };
  648. /* searching map
  649. 1 2 3
  650. 4 0 5
  651. 6 7 8
  652. */
  653. Int i, m, n;
  654. Int new_x, new_y,
  655. lx, size_x;   /* MW QPEL 07-JUL-1998 */
  656. Int min_pos;
  657. Int AE, AE_min;
  658. Int flag_pos;
  659. SInt *pRef, *pComp;
  660. int flag_search[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
  661. Int SubDimension = 2;
  662. lx = 2*(pels /*+ 2*edge*/);
  663. new_x = (Int)((x + *mvx + rel_x)*(SubDimension));
  664. new_y = (Int)((y + *mvy + rel_y)*(SubDimension));
  665. new_x += ((comp&1)<<3)*SubDimension;
  666. new_y += ((comp&2)<<2)*SubDimension;
  667. size_x=16;
  668. /** in 1-pixel search we check if we are inside the range; so don't check
  669. it again
  670. **/
  671. /* avoids trying outside the reference image */
  672. /* we also check with flags if we are inside */
  673. /* search range (1==don't make 1/x search by */
  674. /* this side                                 */
  675. if (bs_x==8)   
  676. flag_pos=4+comp*4;
  677. else   /* ==16*/
  678. flag_pos=0;
  679. if (((new_x/SubDimension) <= 0/*-edge*/) || *(flags+flag_pos)) {
  680. flag_search[1] = flag_search[4] = flag_search[6] = 0;
  681. } else if  (((new_x/SubDimension) >= (pels - bs_x /*+ edge*/)) || *(flags+flag_pos+1)) {
  682. flag_search[3] = flag_search[5] = flag_search[8] = 0;
  683. };
  684. if (((new_y/SubDimension) <= 0/*-edge*/) || *(flags+flag_pos+2)) {
  685. flag_search[1] = flag_search[2] = flag_search[3] = 0;
  686. } else if  (((new_y/SubDimension) >= (lines- bs_y /*+ edge*/)) || *(flags+flag_pos+3)) {
  687. flag_search[6] = flag_search[7] = flag_search[8] = 0;
  688. };
  689. AE_min = MV_MAX_ERROR;
  690. min_pos = 0;
  691. for (i = 0; i < 9; i++)
  692. {
  693. if (flag_search[i])
  694. {
  695. AE = 0;
  696. /* estimate on the already interpolated half-pel image */
  697. pRef = prev + new_x + search[i].x + (new_y + search[i].y) * lx;
  698. pComp = curr;
  699. n = bs_y;
  700. while (n--) {
  701. m = bs_x;
  702. while (m--) {
  703. AE += abs((Int)*pRef - (Int)*pComp);
  704. pRef += 2;
  705. pComp ++;
  706. }
  707. pRef += 2 * lx - 2 * bs_x;
  708. pComp += size_x - bs_x;
  709. }
  710. if (i==0 && bs_y==16 && *mvx==0 && *mvy==0)
  711. AE -= (128 + 1);
  712. if (AE < AE_min)
  713. {
  714. AE_min = AE;
  715. min_pos = i;
  716. }
  717. }
  718. /* else don't look outside the reference */
  719. }
  720. /* Store optimal values */
  721. *min_error = AE_min;
  722. *mvx += ((Float)search[min_pos].x)/(Float)(SubDimension);
  723. *mvy += ((Float)search[min_pos].y)/(Float)(SubDimension);
  724. // generate comp mb data for the minimum point
  725. pRef = prev + new_x + search[min_pos].x + (new_y + search[min_pos].y) * lx;
  726. pComp = curr_comp_mb;
  727. n = bs_y;
  728. while (n--) {
  729. m = bs_x;
  730. while (m--) {
  731. *(pComp ++) = *pRef;
  732. pRef += 2;
  733. }
  734. pRef += 2 * lx - 2 * bs_x;
  735. pComp += 16 - bs_x;
  736. }
  737. return;
  738. }