mot_est_mb.c
上传用户:lq790611
上传日期:2014-03-13
资源大小:166k
文件大小:23k
源码类别:

视频捕捉/采集

开发平台:

Visual C++

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