mot_est_mb.c
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:15k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. #include "mot_util.h"
  2. #define ABSDOUBLE(x)   (((x) > 0.0001) ? (x) : (((x) < -0.0001) ? -(x): 0.0 ))
  3. #define ARE_EQUAL(x,y) ( (ABSDOUBLE((Float)(x)-(y))>0.1)?(0):(1) )
  4. #define INDEX_BIG(x,y) ((x)+(y)*(vop_width))
  5. #define INDEX_NOR(x,y) ((x)+(y)*(MB_SIZE))
  6. static Void
  7. RangeInSearchArea(
  8. Int     i,   
  9. Int     j,   
  10. Int     block,   
  11. Int     prev_x,   
  12. Int     prev_y,   
  13. Int     vop_width,   
  14. Int     vop_height,   
  15. Int     br_x,   
  16. Int     br_y,   
  17. Int     edge,   
  18. Int     f_code,   
  19. Float   *mv_x_min,   
  20. Float   *mv_x_max,   
  21. Float   *mv_y_min,   
  22. Float   *mv_y_max,   
  23. Int     *out      
  24. )
  25. {
  26. Int   dim_curr_x_max,
  27. dim_curr_y_max,
  28. dim_curr_x_min,
  29. dim_curr_y_min;
  30. Int   dim_prev_x_max,
  31. dim_prev_y_max,
  32. dim_prev_x_min,
  33. dim_prev_y_min;
  34. Int   mb_b_size,
  35. block_x,
  36. block_y;
  37. *out=0;
  38. switch (block)
  39. {
  40. case 0:   
  41. block_x=0;   
  42. block_y=0;   
  43. mb_b_size=MB_SIZE;   
  44. break;   
  45. case 1:
  46. block_x=0;
  47. block_y=0;
  48. mb_b_size=B_SIZE;
  49. break;
  50. case 2:
  51. block_x=B_SIZE;
  52. block_y=0;
  53. mb_b_size=B_SIZE;
  54. break;
  55. case 3:
  56. block_x=0;
  57. block_y=B_SIZE;
  58. mb_b_size=B_SIZE;
  59. break;
  60. case 4:
  61. block_x=B_SIZE;
  62. block_y=B_SIZE;
  63. mb_b_size=B_SIZE;
  64. break;
  65. default:
  66. return;
  67. }
  68. dim_curr_x_min=(Int)(br_x+i*MB_SIZE+*mv_x_min+block_x);
  69. dim_curr_y_min=(Int)(br_y+j*MB_SIZE+*mv_y_min+block_y);
  70. dim_prev_x_min=prev_x;
  71. dim_prev_y_min=prev_y;
  72. dim_curr_x_max=(Int)(br_x+i*MB_SIZE+*mv_x_max+mb_b_size+block_x);
  73. dim_curr_y_max=(Int)(br_y+j*MB_SIZE+*mv_y_max+mb_b_size+block_y);
  74. dim_prev_x_max=prev_x+vop_width ;
  75. dim_prev_y_max=prev_y+vop_height;
  76. if (dim_curr_x_min > dim_prev_x_max)
  77. {
  78. *out=1;
  79. }
  80. else if(dim_curr_x_min < dim_prev_x_min)
  81. {
  82. *mv_x_min = *mv_x_min + ( dim_prev_x_min - dim_curr_x_min ) ;
  83. }
  84. if(!(*out))
  85. {
  86. if (dim_curr_y_min > dim_prev_y_max)
  87. {
  88. *out=1;
  89. }
  90. else if(dim_curr_y_min < dim_prev_y_min)
  91. {
  92. *mv_y_min = *mv_y_min + ( dim_prev_y_min - dim_curr_y_min ) ;
  93. }
  94. }
  95. if(!(*out))
  96. {
  97. if(dim_curr_x_max < dim_prev_x_min)
  98. {
  99. *out=1;
  100. }
  101. if ((!(*out))&&(dim_curr_x_max > dim_prev_x_max))
  102. {
  103. *mv_x_max = *mv_x_max - ( dim_curr_x_max - dim_prev_x_max) ;
  104. }
  105. }
  106. if(!(*out))
  107. {
  108. if(dim_curr_y_max < dim_prev_y_min)
  109. {
  110. *out=1;   
  111. }
  112. if ((!(*out))&&(dim_curr_y_max > dim_prev_y_max))
  113. {
  114. *mv_y_max = *mv_y_max - ( dim_curr_y_max - dim_prev_y_max) ;
  115. }
  116. }
  117. if(*mv_x_min>*mv_x_max)
  118. {
  119. *out=1;
  120. }
  121. if ( (!(*out)) && (*mv_y_min>*mv_y_max))
  122. {
  123. *out=1;
  124. }
  125. return;
  126. }
  127. static Int
  128. Obtain_Range(
  129. Int     f_code,   
  130. Int     sr,   
  131. Int     type,   
  132. Float   pmv_x,   
  133. Float   pmv_y,   
  134. Float   *mv_x_min,   
  135. Float   *mv_x_max,   
  136. Float   *mv_y_min,   
  137. Float   *mv_y_max,   
  138. Int     quarter_pel   
  139. )
  140. {
  141. Int    error;
  142. Float  aux_x_min, aux_y_min,
  143. aux_x_max, aux_y_max;
  144. Float  range;
  145. error=0;
  146. if ((f_code==0) && (!quarter_pel))   
  147. {
  148. *mv_x_min=0;
  149. *mv_x_max=0;
  150. *mv_y_min=0;
  151. *mv_y_max=0;
  152. }
  153. else
  154. {
  155. range = sr;
  156. *mv_x_min=-range; *mv_x_max= range - 0.5f;
  157. *mv_y_min=-range; *mv_y_max= range - 0.5f;
  158. }
  159. if (type==MBM_INTER8)
  160. {
  161. aux_x_min=pmv_x - DEFAULT_8_WIN;
  162. aux_y_min=pmv_y - DEFAULT_8_WIN;
  163. aux_x_max=pmv_x + DEFAULT_8_WIN;
  164. aux_y_max=pmv_y + DEFAULT_8_WIN;
  165. if(*mv_x_min < aux_x_min)
  166. *mv_x_min = aux_x_min;
  167. if(*mv_y_min < aux_y_min)
  168. *mv_y_min = aux_y_min;
  169. if(*mv_x_max > aux_x_max)
  170. *mv_x_max = aux_x_max;
  171. if(*mv_y_max > aux_y_max)
  172. *mv_y_max = aux_y_max;
  173. }
  174. if (error==1)
  175. return(0);
  176. else
  177. return(1);
  178. }
  179. Void
  180. MBMotionEstimation(
  181. SInt    *curr,   
  182. SInt    *prev,   
  183. Int     br_x,   
  184. Int     br_y,   
  185. Int     br_width,   
  186. Int     i,   
  187. Int     j,   
  188. Int     prev_x,   
  189. Int     prev_y,   
  190. Int     vop_width,   
  191. Int     vop_height,   
  192. Int     enable_8x8_mv,   
  193. Int     edge,   
  194. Int     f_code,   
  195. Int     sr,   
  196. Float hint_mv_w,                                
  197. Float hint_mv_h,                                
  198. Float   *mv16_w,   
  199. Float   *mv16_h,   
  200. Float   *mv8_w,   
  201. Float   *mv8_h,   
  202. Int     *min_error,   
  203. SInt    *flags
  204. )
  205. {
  206. Int     x, y;
  207. Int     sad, sad_min=MV_MAX_ERROR;
  208. Int     mv_x, mv_y;
  209. Int     block;
  210. Float   pmv_x, pmv_y;
  211. SInt act_block[MB_SIZE*MB_SIZE];
  212. Float   mv_x_min, mv_x_max,
  213. mv_y_min, mv_y_max;
  214. Int     int_mv_x_min=0, int_mv_x_max=0,
  215. int_mv_y_min=0, int_mv_y_max=0;
  216. Int     pos16, pos8;
  217. Int     mvm_width   = br_width/MB_SIZE;
  218. Int     x_curr      = i*MB_SIZE,
  219. y_curr      = j*MB_SIZE;
  220. Int     hb,vb;
  221. Int     out;
  222. Int     rel_ori_x;
  223. Int     rel_ori_y;
  224. Int     min_error16, min_error8 = 0;
  225. #ifndef _FULL_SEARCH_   
  226. typedef struct
  227. {
  228. Int x;
  229. Int y;
  230. SInt start_nmbr;
  231. } DPoint;
  232. typedef struct
  233. {
  234. DPoint point[8];
  235. } Diamond;
  236. SInt d_type=1,stop_flag=0,pt_nmbr=0,check_pts,total_check_pts=8,mot_dirn=0;
  237. Int d_centre_x=0,d_centre_y=0,check_pt_x,check_pt_y;
  238. Diamond diamond[2]=
  239. {
  240. {
  241. { {0,1,0}, {1,0,0}, {0,-1,0}, {-1,0,0} }
  242. }
  243. ,
  244. {
  245. { {0,2,6}, {1,1,0}, {2,0,0}, {1,-1,2},
  246. {0,-2,2}, {-1,-1,4}, {-2,0,4}, {-1,1,6} }
  247. }
  248. };
  249. #endif
  250. d_centre_x = (int)hint_mv_w;
  251. d_centre_y = (int)hint_mv_h;
  252. rel_ori_x=br_x-prev_x;
  253. rel_ori_y=br_y-prev_y;
  254. LoadArea(curr, x_curr,y_curr,MB_SIZE,MB_SIZE,br_width, act_block);
  255. Obtain_Range (f_code, sr, MBM_INTER16,   
  256. 0.0, 0.0, &mv_x_min, &mv_x_max,
  257.   
  258. &mv_y_min, &mv_y_max, 0);
  259. RangeInSearchArea (i,j,0, prev_x, prev_y, vop_width, vop_height,
  260. br_x, br_y, edge,f_code, &mv_x_min, &mv_x_max,
  261.   
  262. &mv_y_min, &mv_y_max,&out);
  263. if(!out)
  264. {
  265. int_mv_x_min=(int)ceil((double)mv_x_min);
  266. int_mv_y_min=(int)ceil((double)mv_y_min);
  267. int_mv_x_max=(int)floor((double)mv_x_max);
  268. int_mv_y_max=(int)floor((double)mv_y_max);
  269. flags[0]=ARE_EQUAL(int_mv_x_min,mv_x_min);
  270. flags[1]=ARE_EQUAL(int_mv_x_max,mv_x_max);
  271. flags[2]=ARE_EQUAL(int_mv_y_min,mv_y_min);
  272. flags[3]=ARE_EQUAL(int_mv_y_max,mv_y_max);
  273. sad_min=MV_MAX_ERROR;
  274. mv_x = mv_y = 2000;   
  275. #ifdef _FULL_SEARCH_   
  276. for (y=int_mv_y_min; y<=int_mv_y_max; y++)
  277. for (x=int_mv_x_min; x<=int_mv_x_max; x++)
  278. {
  279. if (x==0 && y==0)
  280. sad=SAD_Macroblock(prev+INDEX_BIG(x_curr+rel_ori_x,
  281. y_curr+rel_ori_y), act_block, 
  282. (vop_width), MV_MAX_ERROR)
  283. - (128 + 1);
  284. else
  285. sad=SAD_Macroblock(prev+INDEX_BIG(x_curr+x+rel_ori_x,
  286. y_curr+y+rel_ori_y), act_block, 
  287. (vop_width), sad_min);
  288. if (sad<sad_min)
  289. {
  290. sad_min=sad;
  291. mv_x=x;
  292. mv_y=y;
  293. }
  294. else if (sad==sad_min)
  295. if((ABS(x)+ABS(y)) < (ABS(mv_x)+ABS(mv_y)))
  296. {
  297. sad_min=sad;
  298. mv_x=x;
  299. mv_y=y;
  300. }
  301. }   
  302. #else   
  303. sad = SAD_Macroblock(prev+INDEX_BIG(x_curr+rel_ori_x,
  304. y_curr+rel_ori_y), act_block, (vop_width), MV_MAX_ERROR)
  305. - (128 + 1);
  306. if (sad<sad_min)
  307. {
  308. sad_min=sad;
  309. mv_x = mv_y = 0;
  310. }
  311. do
  312. {
  313. check_pts=total_check_pts;
  314. do
  315. {
  316. check_pt_x = diamond[d_type].point[pt_nmbr].x + d_centre_x;
  317. check_pt_y = diamond[d_type].point[pt_nmbr].y + d_centre_y;
  318. 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)
  319. {
  320. sad = MV_MAX_ERROR;
  321. }
  322. else
  323. {
  324. sad=SAD_Macroblock(prev+INDEX_BIG(x_curr+check_pt_x+rel_ori_x,
  325. y_curr+check_pt_y+rel_ori_y), act_block, 
  326. (vop_width), sad_min);
  327. #ifdef _SAD_EXHAUS_
  328. fprintf(stdout,"+o+ [%2d,%2d] sad16(%3d,%3d)=%4dn",i,j,x,y,sad);
  329. #endif
  330. }
  331. if (sad<sad_min)
  332. {
  333. sad_min=sad;
  334. mv_x=check_pt_x;
  335. mv_y=check_pt_y;
  336. mot_dirn=pt_nmbr;
  337. }
  338. else if (sad==sad_min)
  339. if((ABS(check_pt_x)+ABS(check_pt_y)) < (ABS(mv_x)+ABS(mv_y)))
  340. {
  341. sad_min=sad;
  342. mv_x=check_pt_x;
  343. mv_y=check_pt_y;
  344. mot_dirn=pt_nmbr;
  345. }
  346. pt_nmbr+=1;
  347. if((pt_nmbr)>= 8) pt_nmbr-=8;
  348. check_pts-=1;
  349. }
  350. while(check_pts>0);
  351. if( d_type == 0)
  352. {
  353. stop_flag = 1;
  354. }
  355. else
  356. {
  357. if( (mv_x == d_centre_x) && (mv_y == d_centre_y) )
  358. {
  359. d_type=0;
  360. pt_nmbr=0;
  361. total_check_pts = 4;
  362. }
  363. else
  364. {
  365. if((mv_x==d_centre_x) ||(mv_y==d_centre_y))
  366. total_check_pts=5;
  367. else
  368. total_check_pts=3;
  369. pt_nmbr=diamond[d_type].point[mot_dirn].start_nmbr;
  370. d_centre_x = mv_x;
  371. d_centre_y = mv_y;
  372. }
  373. }
  374. }
  375. while(stop_flag!=1);
  376. #endif
  377. flags[0]=flags[0] && (mv_x==int_mv_x_min);
  378. flags[1]=flags[1] && (mv_x==int_mv_x_max);
  379. flags[2]=flags[2] && (mv_y==int_mv_y_min);
  380. flags[3]=flags[3] && (mv_y==int_mv_y_max);
  381. }
  382. else
  383. {
  384. mv_x=mv_y=0;
  385. sad_min=MV_MAX_ERROR;
  386. }
  387. out |=((mv_x==2000)||(mv_y==2000));
  388. if(out)
  389. {
  390. mv_x=mv_y=0;
  391. sad_min=MV_MAX_ERROR;
  392. }
  393. pos16=2*j*2*mvm_width + 2*i;
  394. mv16_w[pos16]=   mv_x; mv16_h[pos16]=   mv_y;
  395. mv16_w[pos16+1]= mv_x; mv16_h[pos16+1]= mv_y;
  396. pos16+=2*mvm_width;
  397. mv16_w[pos16]=   mv_x; mv16_h[pos16]=   mv_y;
  398. mv16_w[pos16+1]= mv_x; mv16_h[pos16+1]= mv_y;
  399. min_error16 = sad_min;
  400. *min_error = min_error16;
  401. if(enable_8x8_mv==1)
  402. {
  403. if(!out)
  404. {
  405. for (block=0;block<4;block++)
  406. {
  407. if(block==0)
  408. {
  409. hb=vb=0;
  410. }
  411. else if (block==1)
  412. {
  413. hb=1;vb=0;
  414. }
  415. else if (block==2)
  416. {
  417. hb=0;vb=1;
  418. }
  419. else
  420. {
  421. hb=vb=1;
  422. }
  423. pmv_x=mv16_w[pos16]; pmv_y=mv16_h[pos16];
  424.   
  425. Obtain_Range(f_code, sr, MBM_INTER8,
  426. pmv_x, pmv_y, &mv_x_min,
  427.   
  428. &mv_x_max, &mv_y_min, &mv_y_max, 0 );
  429. RangeInSearchArea(i,j, block+1, prev_x, prev_y,
  430. vop_width, vop_height, br_x, br_y, edge,f_code,
  431.   
  432. &mv_x_min, &mv_x_max, &mv_y_min,&mv_y_max,&out);
  433. if(!out)
  434. {
  435. int_mv_x_min=(int)ceil((double)mv_x_min);
  436. int_mv_y_min=(int)ceil((double)mv_y_min);
  437. int_mv_x_max=(int)floor((double)mv_x_max);
  438. int_mv_y_max=(int)floor((double)mv_y_max);
  439. flags[4+block*4]=ARE_EQUAL(int_mv_x_min,mv_x_min);
  440. flags[4+block*4+1]=ARE_EQUAL(int_mv_x_max,mv_x_max);
  441. flags[4+block*4+2]=ARE_EQUAL(int_mv_y_min,mv_y_min);
  442. flags[4+block*4+3]=ARE_EQUAL(int_mv_y_max,mv_y_max);
  443. sad_min=MV_MAX_ERROR;
  444. mv_x = mv_y = 2000;   
  445. for (y=int_mv_y_min; y<=int_mv_y_max; y++)
  446. for (x=int_mv_x_min; x<=int_mv_x_max; x++)
  447. {
  448. sad=SAD_Block(prev+
  449. INDEX_BIG(x_curr + x + 8*(block==1||block==3)+rel_ori_x,
  450. y_curr + y + 8*(block==2||block==3)+rel_ori_y),
  451. act_block+INDEX_NOR(8*(block==1||block==3),
  452. 8*(block==2||block==3)),
  453. (vop_width ), sad_min);
  454. if (sad<sad_min)
  455. {
  456. sad_min=sad;
  457. mv_x=x;
  458. mv_y=y;
  459. }
  460. else if (sad==sad_min)
  461. if((ABS(x)+ABS(y)) < (ABS(mv_x)+ABS(mv_y)))
  462. {
  463. sad_min=sad;
  464. mv_x=x;
  465. mv_y=y;
  466. }
  467. }   
  468. flags[4+block*4]   = flags[4+block*4]   && (mv_x==int_mv_x_min);
  469. flags[4+block*4+1] = flags[4+block*4+1] && (mv_x==int_mv_x_max);
  470. flags[4+block*4+2] = flags[4+block*4+2] && (mv_y==int_mv_y_min);
  471. flags[4+block*4+3] = flags[4+block*4+3] && (mv_y==int_mv_y_max);
  472. }
  473. else
  474. {
  475. mv_x=mv_y=0;
  476. sad_min=MV_MAX_ERROR;
  477. }
  478. if(block==0)
  479. {
  480. pos8=2*j*2*mvm_width + 2*i;
  481. min_error8 += sad_min;
  482. }
  483. else if (block==1)
  484. {
  485. pos8=2*j*2*mvm_width + 2*i+1;
  486. min_error8 += sad_min;
  487. }
  488. else if (block==2)
  489. {
  490. pos8=(2*j+1)*2*mvm_width + 2*i;
  491. min_error8 += sad_min;
  492. }
  493. else
  494. {
  495. pos8=(2*j+1)*2*mvm_width + 2*i+1;
  496. min_error8 += sad_min;
  497. }
  498. mv8_w[pos8]=mv_x;
  499. mv8_h[pos8]=mv_y;
  500. }   
  501. if (min_error8 < *min_error)
  502. *min_error = min_error8;
  503. }
  504. else
  505. {   
  506. pos8=2*j*2*mvm_width + 2*i;      mv8_w[pos8]=mv8_h[pos8]=0.0;
  507. pos8=2*j*2*mvm_width + 2*i+1;    mv8_w[pos8]=mv8_h[pos8]=0.0;
  508. pos8=(2*j+1)*2*mvm_width + 2*i;  mv8_w[pos8]=mv8_h[pos8]=0.0;
  509. pos8=(2*j+1)*2*mvm_width + 2*i+1;mv8_w[pos8]=mv8_h[pos8]=0.0;
  510. min_error8 = MV_MAX_ERROR;
  511. }
  512. }   
  513. }
  514. Void
  515. FindSubPel(
  516. Int    x,   
  517. Int    y,   
  518. SInt   *prev,                                     
  519. SInt   *curr,                                      
  520. Int    bs_x,                 
  521. Int    bs_y,   
  522. Int    comp,   
  523. Int    rel_x,   
  524. Int    rel_y,   
  525. Int    pels,   
  526. Int    lines,   
  527. Int    edge,   
  528. SInt   *flags,   
  529. SInt   *curr_comp_mb,                             
  530. Float  *mvx,   
  531. Float  *mvy,   
  532. Int    *min_error   
  533. )
  534. {
  535. static PixPoint search[9] = 
  536. {
  537. {0, 0}, {-1, -1}, {0, -1}, {1, -1},
  538. {-1, 0}, {1, 0}, {-1, 1}, {0, 1}, {1, 1}
  539. };
  540. Int i, m, n;
  541. Int new_x, new_y,
  542. lx, size_x;   
  543. Int min_pos;
  544. Int AE, AE_min;
  545. Int flag_pos;
  546. SInt *pRef, *pComp;
  547. int flag_search[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1};
  548. Int SubDimension = 2;
  549. lx = 2*(pels );
  550. new_x = (Int)((x + *mvx + rel_x)*(SubDimension));
  551. new_y = (Int)((y + *mvy + rel_y)*(SubDimension));
  552. new_x += ((comp&1)<<3)*SubDimension;
  553. new_y += ((comp&2)<<2)*SubDimension;
  554. size_x=16;
  555. if (bs_x==8)   
  556. flag_pos=4+comp*4;
  557. else   
  558. flag_pos=0;
  559. if (((new_x/SubDimension) <= 0) || *(flags+flag_pos)) {
  560. flag_search[1] = flag_search[4] = flag_search[6] = 0;
  561. } else if  (((new_x/SubDimension) >= (pels - bs_x )) || *(flags+flag_pos+1)) {
  562. flag_search[3] = flag_search[5] = flag_search[8] = 0;
  563. };
  564. if (((new_y/SubDimension) <= 0) || *(flags+flag_pos+2)) {
  565. flag_search[1] = flag_search[2] = flag_search[3] = 0;
  566. } else if  (((new_y/SubDimension) >= (lines- bs_y )) || *(flags+flag_pos+3)) {
  567. flag_search[6] = flag_search[7] = flag_search[8] = 0;
  568. };
  569. AE_min = MV_MAX_ERROR;
  570. min_pos = 0;
  571. for (i = 0; i < 9; i++)
  572. {
  573. if (flag_search[i])
  574. {
  575. AE = 0;
  576. pRef = prev + new_x + search[i].x + (new_y + search[i].y) * lx;
  577. pComp = curr;
  578. n = bs_y;
  579. while (n--) {
  580. m = bs_x;
  581. while (m--) {
  582. AE += abs((Int)*pRef - (Int)*pComp);
  583. pRef += 2;
  584. pComp ++;
  585. }
  586. pRef += 2 * lx - 2 * bs_x;
  587. pComp += size_x - bs_x;
  588. }
  589. if (i==0 && bs_y==16 && *mvx==0 && *mvy==0)
  590. AE -= (128 + 1);
  591. if (AE < AE_min)
  592. {
  593. AE_min = AE;
  594. min_pos = i;
  595. }
  596. }
  597. }
  598. *min_error = AE_min;
  599. *mvx += ((Float)search[min_pos].x)/(Float)(SubDimension);
  600. *mvy += ((Float)search[min_pos].y)/(Float)(SubDimension);
  601. pRef = prev + new_x + search[min_pos].x + (new_y + search[min_pos].y) * lx;
  602. pComp = curr_comp_mb;
  603. n = bs_y;
  604. while (n--) {
  605. m = bs_x;
  606. while (m--) {
  607. *(pComp ++) = *pRef;
  608. pRef += 2;
  609. }
  610. pRef += 2 * lx - 2 * bs_x;
  611. pComp += 16 - bs_x;
  612. }
  613. return;
  614. }