Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

884 lines
27 KiB

  1. /* File: sv_h263_motion.c */
  2. /*****************************************************************************
  3. ** Copyright (c) Digital Equipment Corporation, 1995, 1997 **
  4. ** **
  5. ** All Rights Reserved. Unpublished rights reserved under the copyright **
  6. ** laws of the United States. **
  7. ** **
  8. ** The software contained on this media is proprietary to and embodies **
  9. ** the confidential technology of Digital Equipment Corporation. **
  10. ** Possession, use, duplication or dissemination of the software and **
  11. ** media is authorized only pursuant to a valid written license from **
  12. ** Digital Equipment Corporation. **
  13. ** **
  14. ** RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the U.S. **
  15. ** Government is subject to restrictions as set forth in Subparagraph **
  16. ** (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. **
  17. ******************************************************************************/
  18. #include "sv_h263.h"
  19. #include "proto.h"
  20. /*
  21. #define USE_C
  22. */
  23. #ifndef USE_C
  24. #include "perr.h"
  25. #endif
  26. static unsigned char *sv_H263LoadArea(unsigned char *im, int x, int y,
  27. int x_size, int y_size, int lx);
  28. /**********************************************************************
  29. *
  30. * Name: MotionEstimation
  31. * Description: Estimate all motionvectors for one MB
  32. *
  33. * Input: pointers to current an previous image,
  34. * pointers to current slice and current MB
  35. * Returns:
  36. * Side effects: motion vector imformation in MB changed
  37. *
  38. ***********************************************************************/
  39. void sv_H263MotionEstimation(SvH263CompressInfo_t *H263Info,
  40. unsigned char *curr, unsigned char *prev, int x_curr,
  41. int y_curr, int xoff, int yoff, int seek_dist,
  42. H263_MotionVector *MV[6][H263_MBR+1][H263_MBC+2], int *SAD_0)
  43. {
  44. int Min_FRAME[5];
  45. H263_MotionVector MVframe[5];
  46. unsigned char *act_block,*aa,*ii;
  47. unsigned char *search_area, *adv_search_area = NULL, *zero_area = NULL;
  48. int sxy,i,k,j,l;
  49. int ihigh,ilow,jhigh,jlow,h_length,v_length;
  50. int adv_ihigh,adv_ilow,adv_jhigh,adv_jlow,adv_h_length,adv_v_length;
  51. int xmax,ymax,block,sad,lx;
  52. int adv_x_curr, adv_y_curr,xvec,yvec;
  53. xmax = H263Info->pels;
  54. ymax = H263Info->lines;
  55. sxy = seek_dist;
  56. if (!H263Info->long_vectors) {
  57. /* Maximum normal search range centered around _zero-vector_ */
  58. sxy = mmin(15, sxy);
  59. }
  60. else {
  61. /* Maximum extended search range centered around _predictor_ */
  62. sxy = mmin(15 - (2*H263_DEF_8X8_WIN+1), sxy);
  63. /* NB! */
  64. /* It is only possible to transmit motion vectors within
  65. a 15x15 window around the motion vector predictor
  66. for any 8x8 or 16x16 block */
  67. /* The reason for the search window's reduction above with
  68. 2*DEF_8X8_WIN+1 is that the 8x8 search may change the MV
  69. predictor for some of the blocks within the macroblock. When we
  70. impose the limitation above, we are sure that any 8x8 vector we
  71. might find is possible to transmit */
  72. /* We have found that with OBMC, DEF_8X8_WIN should be quite small
  73. for two reasons: (i) a good filtering effect, and (ii) not too
  74. many bits used for transferring the vectors. As can be seen
  75. above this is also useful to avoid a large limitation on the MV
  76. search range */
  77. /* It is possible to make sure the motion vectors found are legal
  78. in other less limiting ways than above, but this would be more
  79. complicated as well as time-consuming. Any good suggestions for
  80. improvement is welcome, though */
  81. #ifdef USE_C
  82. xoff = mmin(16,mmax(-16,xoff));
  83. yoff = mmin(16,mmax(-16,yoff));
  84. #else
  85. xoff = sv_H263lim_S(xoff,-16,16);
  86. yoff = sv_H263lim_S(yoff,-16,16);
  87. #endif
  88. /* There is no need to check if (xoff + x_curr) points outside
  89. the picture, since the Extended Motion Vector Range is
  90. always used together with the Unrestricted MV mode */
  91. }
  92. lx = (H263Info->mv_outside_frame ? H263Info->pels + (H263Info->long_vectors?64:32) : H263Info->pels);
  93. ilow = x_curr + xoff - sxy;
  94. ihigh = x_curr + xoff + sxy;
  95. jlow = y_curr + yoff - sxy;
  96. jhigh = y_curr + yoff + sxy;
  97. if (!H263Info->mv_outside_frame) {
  98. if (ilow<0) ilow = 0;
  99. if (ihigh>xmax-16) ihigh = xmax-16;
  100. if (jlow<0) jlow = 0;
  101. if (jhigh>ymax-16) jhigh = ymax-16;
  102. }
  103. h_length = ihigh - ilow + 16;
  104. v_length = jhigh - jlow + 16;
  105. #if 1
  106. act_block = curr + x_curr + y_curr * H263Info->pels;
  107. search_area = prev + ilow + jlow * lx;
  108. #else
  109. act_block = sv_H263LoadArea(curr, x_curr, y_curr, 16, 16, H263Info->pels);
  110. search_area = sv_H263LoadArea(prev, ilow, jlow, h_length, v_length, lx);
  111. #endif
  112. for (k = 0; k < 5; k++) {
  113. Min_FRAME[k] = INT_MAX;
  114. MVframe[k].x = 0;
  115. MVframe[k].y = 0;
  116. MVframe[k].x_half = 0;
  117. MVframe[k].y_half = 0;
  118. }
  119. /* Zero vector search*/
  120. if (x_curr-ilow < 0 || y_curr-jlow < 0 ||
  121. x_curr-ilow+H263_MB_SIZE > h_length || y_curr-jlow+H263_MB_SIZE > v_length) {
  122. /* in case the zero vector is outside the loaded area in search_area */
  123. #ifndef USE_C
  124. zero_area = prev + x_curr + y_curr * lx;
  125. *SAD_0 = sv_H263PError16x16_S(zero_area, act_block, lx, H263Info->pels, INT_MAX) -
  126. H263_PREF_NULL_VEC;
  127. #else
  128. zero_area = prev + x_curr + y_curr * lx;
  129. *SAD_0 = sv_H263SADMacroblock(zero_area, act_block, lx, H263Info->pels, INT_MAX) -
  130. H263_PREF_NULL_VEC;
  131. #endif
  132. }
  133. else {
  134. /* the zero vector is within search_area */
  135. #ifndef USE_C
  136. ii = search_area + (x_curr-ilow) + (y_curr-jlow)*lx;
  137. *SAD_0 = sv_H263PError16x16_S(ii, act_block, lx, H263Info->pels, INT_MAX) -
  138. H263_PREF_NULL_VEC;
  139. #else
  140. ii = search_area + (x_curr-ilow) + (y_curr-jlow)*lx;
  141. *SAD_0 = sv_H263SADMacroblock(ii, act_block, lx, H263Info->pels, INT_MAX) -
  142. H263_PREF_NULL_VEC;
  143. #endif
  144. }
  145. if (xoff == 0 && yoff == 0) {
  146. Min_FRAME[0] = *SAD_0;
  147. MVframe[0].x = 0;
  148. MVframe[0].y = 0;
  149. }
  150. else {
  151. #ifndef USE_C
  152. ii = search_area + (x_curr+xoff-ilow) + (y_curr+yoff-jlow)*lx;
  153. sad = sv_H263PError16x16_S(ii, act_block, lx, H263Info->pels, Min_FRAME[0]);
  154. #else
  155. ii = search_area + (x_curr+xoff-ilow) + (y_curr+yoff-jlow)*lx;
  156. sad = sv_H263SADMacroblock(ii, act_block, lx, H263Info->pels, Min_FRAME[0]);
  157. #endif
  158. MVframe[0].x = (short)xoff;
  159. MVframe[0].y = (short)yoff;
  160. }
  161. /* NB: if xoff or yoff != 0, the Extended MV Range is used. If we
  162. allow the zero vector to be chosen prior to the half pel search
  163. in this case, the half pel search might lead to a
  164. non-transmittable vector (on the wrong side of zero). If SAD_0
  165. turns out to be the best SAD, the zero-vector will be chosen
  166. after half pel search instead. The zero-vector can be
  167. transmitted in all modes, no matter what the MV predictor is */
  168. /* Spiral search */
  169. for (l = 1; l <= sxy; l++) {
  170. i = x_curr + xoff - l;
  171. j = y_curr + yoff - l;
  172. for (k = 0; k < 8*l; k++) {
  173. if (i>=ilow && i<=ihigh && j>=jlow && j<=jhigh) {
  174. /* 16x16 integer pel MV */
  175. #ifndef USE_C
  176. ii = search_area + (i-ilow) + (j-jlow)*lx;
  177. sad = sv_H263PError16x16_S(ii, act_block, lx, H263Info->pels, Min_FRAME[0]);
  178. #else
  179. ii = search_area + (i-ilow) + (j-jlow)*lx;
  180. sad = sv_H263SADMacroblock(ii, act_block, lx, H263Info->pels, Min_FRAME[0]);
  181. #endif
  182. if (sad < Min_FRAME[0]) {
  183. MVframe[0].x = i - x_curr;
  184. MVframe[0].y = j - y_curr;
  185. Min_FRAME[0] = sad;
  186. }
  187. }
  188. if (k<2*l) i++;
  189. else if (k<4*l) j++;
  190. else if (k<6*l) i--;
  191. else j--;
  192. }
  193. }
  194. if (H263Info->advanced) {
  195. /* Center the 8x8 search around the 16x16 vector. This is
  196. different than in TMN5 where the 8x8 search is also a full
  197. search. The reasons for this is: (i) it is faster, and (ii) it
  198. generally gives better results because of a better OBMC
  199. filtering effect and less bits spent for vectors, and (iii) if
  200. the Extended MV Range is used, the search range around the
  201. motion vector predictor will be less limited */
  202. xvec = MVframe[0].x;
  203. yvec = MVframe[0].y;
  204. if (!H263Info->long_vectors) {
  205. if (xvec > 15 - H263_DEF_8X8_WIN) { xvec = 15 - H263_DEF_8X8_WIN ;}
  206. if (yvec > 15 - H263_DEF_8X8_WIN) { yvec = 15 - H263_DEF_8X8_WIN ;}
  207. if (xvec < -15 + H263_DEF_8X8_WIN) { xvec = -15 + H263_DEF_8X8_WIN ;}
  208. if (yvec < -15 + H263_DEF_8X8_WIN) { yvec = -15 + H263_DEF_8X8_WIN ;}
  209. }
  210. adv_x_curr = x_curr + xvec;
  211. adv_y_curr = y_curr + yvec;
  212. sxy = H263_DEF_8X8_WIN;
  213. adv_ilow = adv_x_curr - sxy;
  214. adv_ihigh = adv_x_curr + sxy;
  215. adv_jlow = adv_y_curr - sxy;
  216. adv_jhigh = adv_y_curr + sxy;
  217. adv_h_length = adv_ihigh - adv_ilow + 16;
  218. adv_v_length = adv_jhigh - adv_jlow + 16;
  219. adv_search_area = sv_H263LoadArea(prev, adv_ilow, adv_jlow,
  220. adv_h_length, adv_v_length, lx);
  221. for (block = 0; block < 4; block++) {
  222. ii = adv_search_area + (adv_x_curr-adv_ilow) + ((block&1)<<3) +
  223. (adv_y_curr-adv_jlow + ((block&2)<<2) )*adv_h_length;
  224. #ifndef USE_C
  225. aa = act_block + ((block&1)<<3) + ((block&2)<<2)*H263Info->pels;
  226. Min_FRAME[block+1] = sv_H263PError8x8_S(ii,aa,adv_h_length,H263Info->pels,Min_FRAME[block+1]);
  227. #else
  228. aa = act_block + ((block&1)<<3) + ((block&2)<<2)*H263Info->pels;
  229. Min_FRAME[block+1] = sv_H263MySADBlock(ii,aa,adv_h_length,H263Info->pels,Min_FRAME[block+1]);
  230. #endif
  231. MVframe[block+1].x = MVframe[0].x;
  232. MVframe[block+1].y = MVframe[0].y;
  233. }
  234. /* Spiral search */
  235. for (l = 1; l <= sxy; l++) {
  236. i = adv_x_curr - l;
  237. j = adv_y_curr - l;
  238. for (k = 0; k < 8*l; k++) {
  239. if (i>=adv_ilow && i<=adv_ihigh && j>=adv_jlow && j<=adv_jhigh) {
  240. /* 8x8 integer pel MVs */
  241. for (block = 0; block < 4; block++) {
  242. ii = adv_search_area + (i-adv_ilow) + ((block&1)<<3) +
  243. (j-adv_jlow + ((block&2)<<2) )*adv_h_length;
  244. #ifndef USE_C
  245. aa = act_block + ((block&1)<<3) + ((block&2)<<2)*H263Info->pels;
  246. sad = sv_H263PError8x8_S(ii, aa, adv_h_length, H263Info->pels, Min_FRAME[block+1]);
  247. #else
  248. aa = act_block + ((block&1)<<3) + ((block&2)<<2)*H263Info->pels;
  249. sad = sv_H263MySADBlock(ii, aa, adv_h_length, H263Info->pels, Min_FRAME[block+1]);
  250. #endif
  251. if (sad < Min_FRAME[block+1]) {
  252. MVframe[block+1].x = i - x_curr;
  253. MVframe[block+1].y = j - y_curr;
  254. Min_FRAME[block+1] = sad;
  255. }
  256. }
  257. }
  258. if (k<2*l) i++;
  259. else if (k<4*l) j++;
  260. else if (k<6*l) i--;
  261. else j--;
  262. }
  263. }
  264. }
  265. i = x_curr/H263_MB_SIZE+1;
  266. j = y_curr/H263_MB_SIZE+1;
  267. if (!H263Info->advanced) {
  268. MV[0][j][i]->x = MVframe[0].x;
  269. MV[0][j][i]->y = MVframe[0].y;
  270. MV[0][j][i]->min_error = (short)Min_FRAME[0];
  271. }
  272. else {
  273. for (k = 0; k < 5; k++) {
  274. MV[k][j][i]->x = MVframe[k].x;
  275. MV[k][j][i]->y = MVframe[k].y;
  276. MV[k][j][i]->min_error = (short)Min_FRAME[k];
  277. }
  278. }
  279. #if 0
  280. ScFree(act_block);
  281. ScFree(search_area);
  282. #endif
  283. if (H263Info->advanced) ScFree(adv_search_area);
  284. return;
  285. }
  286. /**********************************************************************
  287. *
  288. * Name: LoadArea
  289. * Description: fills array with a square of image-data
  290. *
  291. * Input: pointer to image and position, x and y size
  292. * Returns: pointer to area
  293. * Side effects: memory allocated to array
  294. *
  295. ***********************************************************************/
  296. #if 1
  297. static unsigned char *sv_H263LoadArea(unsigned char *im, int x, int y,
  298. int x_size, int y_size, int lx)
  299. {
  300. unsigned char *res = (unsigned char *)ScAlloc(sizeof(char)*x_size*y_size);
  301. register unsigned char *in, *out;
  302. in = im + (y*lx) + x;
  303. out = res;
  304. while (y_size--) {
  305. memcpy(out,in,x_size) ;
  306. in += lx ;
  307. out += x_size;
  308. };
  309. return res;
  310. }
  311. #else
  312. static unsigned char *svH263LoadArea(unsigned char *im, int x, int y,
  313. int x_size, int y_size, int lx)
  314. {
  315. unsigned char *res = (unsigned char *)ScAlloc(sizeof(char)*x_size*y_size);
  316. unsigned char *in;
  317. unsigned char *out;
  318. int i = x_size;
  319. int j = y_size;
  320. in = im + (y*lx) + x;
  321. out = res;
  322. while (j--) {
  323. while (i--)
  324. *out++ = *in++;
  325. i = x_size;
  326. in += lx - x_size;
  327. };
  328. return res;
  329. }
  330. #endif
  331. /**********************************************************************
  332. *
  333. * Name: SAD_Macroblock
  334. * Description: fast way to find the SAD of one vector
  335. *
  336. * Input: pointers to search_area and current block,
  337. * Min_F1/F2/FR
  338. * Returns: sad_f1/f2
  339. * Side effects:
  340. *
  341. ***********************************************************************/
  342. #ifdef USE_C /* replaced by sv_H263PError16x16_S */
  343. int sv_H263SADMacroblock(unsigned char *ii, unsigned char *act_block,
  344. int h_length, int lx2, int Min_FRAME)
  345. {
  346. unsigned char *kk;
  347. int i;
  348. int sad = 0;
  349. kk = act_block;
  350. i = 16;
  351. while (i--) {
  352. sad += (abs(*ii - *kk ) +abs(*(ii+1 ) - *(kk+1) )
  353. +abs(*(ii+2) - *(kk+2) ) +abs(*(ii+3 ) - *(kk+3) )
  354. +abs(*(ii+4) - *(kk+4) ) +abs(*(ii+5 ) - *(kk+5) )
  355. +abs(*(ii+6) - *(kk+6) ) +abs(*(ii+7 ) - *(kk+7) )
  356. +abs(*(ii+8) - *(kk+8) ) +abs(*(ii+9 ) - *(kk+9) )
  357. +abs(*(ii+10)- *(kk+10)) +abs(*(ii+11) - *(kk+11))
  358. +abs(*(ii+12)- *(kk+12)) +abs(*(ii+13) - *(kk+13))
  359. +abs(*(ii+14)- *(kk+14)) +abs(*(ii+15) - *(kk+15)) );
  360. ii += h_length;
  361. kk += lx2;
  362. if (sad > Min_FRAME)
  363. return INT_MAX;
  364. }
  365. return sad;
  366. }
  367. #endif
  368. #ifdef USE_C /* replaced by sv_H263PError8x8_S */
  369. int svH263SAD_Block(unsigned char *ii, unsigned char *act_block,
  370. int h_length, int min_sofar)
  371. {
  372. unsigned char *kk;
  373. int i;
  374. int sad = 0;
  375. kk = act_block;
  376. i = 8;
  377. while (i--) {
  378. sad += (abs(*ii - *kk ) +abs(*(ii+1 ) - *(kk+1) )
  379. +abs(*(ii+2) - *(kk+2) ) +abs(*(ii+3 ) - *(kk+3) )
  380. +abs(*(ii+4) - *(kk+4) ) +abs(*(ii+5 ) - *(kk+5) )
  381. +abs(*(ii+6) - *(kk+6) ) +abs(*(ii+7 ) - *(kk+7) ));
  382. ii += h_length;
  383. kk += 16;
  384. if (sad > min_sofar)
  385. return INT_MAX;
  386. }
  387. return sad;
  388. }
  389. #endif
  390. int sv_H263BError16x16_C(unsigned char *ii, unsigned char *aa, unsigned char *bb,
  391. int width, int min_sofar)
  392. {
  393. unsigned char *ll, *kk;
  394. int i, sad = 0;
  395. kk = aa;
  396. ll = bb;
  397. i = 16;
  398. while (i--) {
  399. sad += (abs(*ii - ((*kk + *ll )>>1)) +
  400. abs(*(ii+1) - ((*(kk+1)+ *(ll+1))>>1)) +
  401. abs(*(ii+2) - ((*(kk+2)+ *(ll+2))>>1)) +
  402. abs(*(ii+3) - ((*(kk+3)+ *(ll+3))>>1)) +
  403. abs(*(ii+4) - ((*(kk+4)+ *(ll+4))>>1)) +
  404. abs(*(ii+5) - ((*(kk+5)+ *(ll+5))>>1)) +
  405. abs(*(ii+6) - ((*(kk+6)+ *(ll+6))>>1)) +
  406. abs(*(ii+7) - ((*(kk+7)+ *(ll+7))>>1)) +
  407. abs(*(ii+8) - ((*(kk+8)+ *(ll+8))>>1)) +
  408. abs(*(ii+9) - ((*(kk+9)+ *(ll+9))>>1)) +
  409. abs(*(ii+10) - ((*(kk+10)+ *(ll+10))>>1)) +
  410. abs(*(ii+11) - ((*(kk+11)+ *(ll+11))>>1)) +
  411. abs(*(ii+12) - ((*(kk+12)+ *(ll+12))>>1)) +
  412. abs(*(ii+13) - ((*(kk+13)+ *(ll+13))>>1)) +
  413. abs(*(ii+14) - ((*(kk+14)+ *(ll+14))>>1)) +
  414. abs(*(ii+15) - ((*(kk+15)+ *(ll+15))>>1)));
  415. ii += width;
  416. kk += width;
  417. ll += width;
  418. if (sad > min_sofar)
  419. return INT_MAX;
  420. }
  421. return sad;
  422. }
  423. /**********************************************************************
  424. *
  425. * Name: FindMB
  426. * Description: Picks out one MB from picture
  427. *
  428. * Input: position of MB to pick out,
  429. * pointer to frame data, empty 16x16 array
  430. * Returns:
  431. * Side effects: fills array with MB data
  432. *
  433. ***********************************************************************/
  434. void sv_H263FindMB(SvH263CompressInfo_t *H263Info, int x, int y, unsigned char *image, short MB[16][16])
  435. {
  436. #ifndef USE_C
  437. sv_H263CtoI16_S((image + y*H263Info->pels + x), &(MB[0][0]), H263Info->pels);
  438. #else
  439. register int m, n;
  440. int xdiff = H263Info->pels - H263_MB_SIZE;
  441. unsigned char *in;
  442. short *out;
  443. in = image + y*H263Info->pels + x;
  444. out = &(MB[0][0]);
  445. m = H263_MB_SIZE;
  446. while (m--) {
  447. n = H263_MB_SIZE;
  448. while (n--) *out++ = *in++;
  449. in += xdiff ;
  450. };
  451. #endif
  452. }
  453. /**********************************************************************
  454. *
  455. * Name: MotionEstimation
  456. * Description: Estimate all motionvectors for one MB
  457. *
  458. * Input: pointers to current an previous image,
  459. * pointers to current slice and current MB
  460. * Returns:
  461. * Side effects: motion vector information in MB changed
  462. *
  463. ***********************************************************************/
  464. void sv_H263FastME(SvH263CompressInfo_t *H263Info,
  465. unsigned char *curr, unsigned char *prev, int x_curr,
  466. int y_curr, int xoff, int yoff, int seek_dist,
  467. short *MVx, short *MVy, short *MVer, int *SAD_0)
  468. {
  469. int Min_FRAME;
  470. H263_MotionVector MVframe;
  471. int sxy,i,k,j;
  472. int ihigh,ilow,jhigh,jlow,h_length,v_length;
  473. unsigned char *act_block,*ii,*search_area, *zero_area = NULL;
  474. int h_lenby2,v_lenby2;
  475. unsigned char *act_block_subs2, *search_area_subs2;
  476. int xmax,ymax,sad;
  477. int xlevel1,ylevel1;
  478. int level1_x_curr,level1_y_curr;
  479. int level0_x_curr,level0_y_curr;
  480. xmax = H263Info->pels;
  481. ymax = H263Info->lines;
  482. sxy = seek_dist;
  483. sxy = mmin(15, sxy);
  484. ilow = x_curr + xoff - sxy;
  485. ihigh = x_curr + xoff + sxy;
  486. jlow = y_curr + yoff - sxy;
  487. jhigh = y_curr + yoff + sxy;
  488. if (ilow<0) ilow = 0;
  489. if (ihigh>xmax-16) ihigh = xmax-16;
  490. if (jlow<0) jlow = 0;
  491. if (jhigh>ymax-16) jhigh = ymax-16;
  492. h_length = ihigh - ilow + 16;
  493. v_length = jhigh - jlow + 16;
  494. act_block = curr + x_curr + y_curr * H263Info->pels;
  495. search_area = prev + ilow + jlow * H263Info->pels;
  496. /* subsampled version for ME level 1 */
  497. h_lenby2 = (h_length-1)>>1;
  498. v_lenby2 = (v_length-1)>>1;
  499. act_block_subs2 = H263Info->block_subs2;
  500. search_area_subs2 = H263Info->srch_area_subs2;
  501. sv_H263LdSubs2Area(curr, x_curr, y_curr, 8, 8, H263Info->pels, act_block_subs2, 8);
  502. sv_H263LdSubs2Area(prev, ilow, jlow, h_lenby2, v_lenby2, H263Info->pels,
  503. search_area_subs2, H263_SRCH_RANGE);
  504. Min_FRAME = INT_MAX;
  505. MVframe.x = 0;
  506. MVframe.y = 0;
  507. MVframe.x_half = 0;
  508. MVframe.y_half = 0;
  509. /* match for zero (or [xoff,yoff]) motion vector on subsampled images */
  510. ii = search_area_subs2 +
  511. ((x_curr+xoff-ilow)>>1) + ((y_curr+yoff-jlow)>>1)*H263_SRCH_RANGE;
  512. #ifndef USE_C
  513. Min_FRAME = sv_H263PEr8_init_S(ii,act_block_subs2,H263_SRCH_RANGE,8);
  514. #else
  515. Min_FRAME = sv_H263MySADBlock(ii,act_block_subs2,H263_SRCH_RANGE,8,INT_MAX);
  516. #endif
  517. MVframe.x = (short)xoff;
  518. MVframe.y = (short)yoff;
  519. /*** +-7 search on subsampled images: ***
  520. *** three-step +-4, +-2, +-1 ***/
  521. /* first step: +- 4 */
  522. /* sxylevel1 = 4; */
  523. i = x_curr + xoff - 8;
  524. j = y_curr + yoff - 8;
  525. for (k = 0; k < 32; k++) {
  526. if (i>=ilow && i<=ihigh && j>=jlow && j<=jhigh) {
  527. /* 8x8 integer pel MV */
  528. ii = search_area_subs2+((i-ilow)>>1) + ((j-jlow)>>1)*H263_SRCH_RANGE;
  529. #ifndef USE_C
  530. sad = sv_H263PError8x8_S(ii,act_block_subs2,H263_SRCH_RANGE,8,Min_FRAME);
  531. #else
  532. sad = sv_H263MySADBlock(ii,act_block_subs2,H263_SRCH_RANGE,8,Min_FRAME);
  533. #endif
  534. if (sad < Min_FRAME) {
  535. MVframe.x = i - x_curr;
  536. MVframe.y = j - y_curr;
  537. Min_FRAME = sad;
  538. }
  539. }
  540. if (k<8) i+=2;
  541. else if (k<16) j+=2;
  542. else if (k<24) i-=2;
  543. else j-=2;
  544. }
  545. /* second step: +- 2 */
  546. /* sxylevel1 = 2; */
  547. level1_x_curr = x_curr + MVframe.x;
  548. level1_y_curr = y_curr + MVframe.y;
  549. i = level1_x_curr - 4;
  550. j = level1_y_curr - 4;
  551. for (k = 0; k < 16; k++) {
  552. if (i>=ilow && i<=ihigh && j>=jlow && j<=jhigh) {
  553. /* 8x8 integer pel MV */
  554. ii = search_area_subs2+((i-ilow)>>1) + ((j-jlow)>>1) * H263_SRCH_RANGE;
  555. #ifndef USE_C
  556. sad = sv_H263PError8x8_S(ii,act_block_subs2,H263_SRCH_RANGE,8,Min_FRAME);
  557. #else
  558. sad = sv_H263MySADBlock(ii,act_block_subs2,H263_SRCH_RANGE,8,Min_FRAME);
  559. #endif
  560. if (sad < Min_FRAME) {
  561. MVframe.x = i - x_curr;
  562. MVframe.y = j - y_curr;
  563. Min_FRAME = sad;
  564. }
  565. }
  566. if (k<4) i+=2;
  567. else if (k<8) j+=2;
  568. else if (k<12) i-=2;
  569. else j-=2;
  570. }
  571. /* third step: +- 1 */
  572. /* sxylevel1 = 1; */
  573. level1_x_curr = x_curr + MVframe.x;
  574. level1_y_curr = y_curr + MVframe.y;
  575. i = level1_x_curr - 2;
  576. j = level1_y_curr - 2;
  577. for (k = 0; k < 8; k++) {
  578. if (i>=ilow && i<=ihigh && j>=jlow && j<=jhigh) {
  579. /* 8x8 integer pel MV */
  580. ii = search_area_subs2+((i-ilow)>>1) + ((j-jlow)>>1) * H263_SRCH_RANGE;
  581. #ifndef USE_C
  582. sad = sv_H263PError8x8_S(ii,act_block_subs2,H263_SRCH_RANGE,8,Min_FRAME);
  583. #else
  584. sad = sv_H263MySADBlock(ii,act_block_subs2,H263_SRCH_RANGE,8,Min_FRAME);
  585. #endif
  586. if (sad < Min_FRAME) {
  587. MVframe.x = i - x_curr;
  588. MVframe.y = j - y_curr;
  589. Min_FRAME = sad;
  590. }
  591. }
  592. if (k<2) i+=2;
  593. else if (k<4) j+=2;
  594. else if (k<6) i-=2;
  595. else j-=2;
  596. }
  597. /* motion vectors after step3 - level1 */
  598. xlevel1=MVframe.x;
  599. ylevel1=MVframe.y;
  600. /* reset */
  601. Min_FRAME = INT_MAX;
  602. MVframe.x = 0;
  603. MVframe.y = 0;
  604. /* Zero vector search*/
  605. if (x_curr-ilow < 0 || y_curr-jlow < 0 ||
  606. x_curr-ilow+H263_MB_SIZE > h_length || y_curr-jlow+H263_MB_SIZE > v_length) {
  607. /* in case the zero vector is outside the loaded area in search_area */
  608. zero_area = sv_H263LoadArea(prev, x_curr, y_curr, 16, 16, H263Info->pels);
  609. #ifndef USE_C
  610. *SAD_0 = sv_H263PError16x16_S(zero_area, act_block, 16, H263Info->pels, INT_MAX) -
  611. H263_PREF_NULL_VEC;
  612. #else
  613. *SAD_0 = sv_H263SADMacroblock(zero_area, act_block, 16, H263Info->pels, INT_MAX) -
  614. H263_PREF_NULL_VEC;
  615. #endif
  616. ScFree(zero_area);
  617. }
  618. else {
  619. /* the zero vector is within search_area */
  620. ii = search_area + (x_curr-ilow) + (y_curr-jlow)*H263Info->pels;
  621. #ifndef USE_C
  622. *SAD_0 = sv_H263PError16x16_S(ii, act_block, H263Info->pels, H263Info->pels, INT_MAX) -
  623. H263_PREF_NULL_VEC;
  624. #else
  625. *SAD_0 = sv_H263SADMacroblock(ii, act_block, H263Info->pels, H263Info->pels, INT_MAX) -
  626. H263_PREF_NULL_VEC;
  627. #endif
  628. }
  629. if (xoff == 0 && yoff == 0) {
  630. Min_FRAME = *SAD_0;
  631. MVframe.x = 0;
  632. MVframe.y = 0;
  633. }
  634. if (xlevel1 == 0 && ylevel1 == 0) {
  635. Min_FRAME = *SAD_0;
  636. MVframe.x = 0;
  637. MVframe.y = 0;
  638. }
  639. else {
  640. ii = search_area + (x_curr+xlevel1-ilow) + (y_curr+ylevel1-jlow)*H263Info->pels;
  641. #ifndef USE_C
  642. sad = sv_H263PError16x16_S(ii, act_block, H263Info->pels, H263Info->pels, Min_FRAME) ;
  643. #else
  644. sad = sv_H263SADMacroblock(ii, act_block, H263Info->pels, H263Info->pels, Min_FRAME) ;
  645. #endif
  646. if (sad < Min_FRAME) {
  647. MVframe.x = (short)xlevel1;
  648. MVframe.y = (short)ylevel1;
  649. Min_FRAME = sad;
  650. }
  651. }
  652. /* NB: if xoff or yoff != 0, the Extended MV Range is used. If we
  653. allow the zero vector to be chosen prior to the half pel search
  654. in this case, the half pel search might lead to a
  655. non-transmittable vector (on the wrong side of zero). If SAD_0
  656. turns out to be the best SAD, the zero-vector will be chosen
  657. after half pel search instead. The zero-vector can be
  658. transmitted in all modes, no matter what the MV predictor is */
  659. /*** +-1 search on full-resolution images ***/
  660. level0_x_curr = x_curr + xlevel1;
  661. level0_y_curr = y_curr + ylevel1;
  662. /* sxylevel0=1; */
  663. i = level0_x_curr - 1;
  664. j = level0_y_curr - 1;
  665. for (k = 0; k < 8; k++) {
  666. if (i>=ilow && i<=ihigh && j>=jlow && j<=jhigh) {
  667. /* 16x16 integer pel MV */
  668. ii = search_area + (i-ilow) + (j-jlow)*H263Info->pels;
  669. #ifndef USE_C
  670. sad = sv_H263PError16x16_S(ii, act_block, H263Info->pels, H263Info->pels, Min_FRAME) ;
  671. #else
  672. sad = sv_H263SADMacroblock(ii, act_block, H263Info->pels, H263Info->pels, Min_FRAME) ;
  673. #endif
  674. if (sad < Min_FRAME) {
  675. MVframe.x = i - x_curr;
  676. MVframe.y = j - y_curr;
  677. Min_FRAME = sad;
  678. }
  679. }
  680. if (k<2) i++;
  681. else if (k<4) j++;
  682. else if (k<6) i--;
  683. else j--;
  684. }
  685. i = x_curr/H263_MB_SIZE+1;
  686. j = y_curr/H263_MB_SIZE+1;
  687. *MVx = MVframe.x;
  688. *MVy = MVframe.y;
  689. *MVer = (short)Min_FRAME;
  690. return;
  691. }
  692. #ifdef USE_C
  693. int sv_H263MySADBlock(unsigned char *ii, unsigned char *act_block,
  694. int h_length, int lx2, int min_sofar)
  695. {
  696. /*
  697. return sv_H263PError8x8_S(ii,act_block,h_length,8,min_sofar);
  698. */
  699. int i;
  700. int sad = 0;
  701. unsigned char *kk;
  702. kk = act_block;
  703. i = 8;
  704. while (i--) {
  705. sad += (abs(*ii - *kk ) +
  706. abs(*(ii+1 ) - *(kk+1) ) +
  707. abs(*(ii+2) - *(kk+2) ) +
  708. abs(*(ii+3 ) - *(kk+3) ) +
  709. abs(*(ii+4) - *(kk+4) ) +
  710. abs(*(ii+5 ) - *(kk+5) ) +
  711. abs(*(ii+6) - *(kk+6) ) +
  712. abs(*(ii+7 ) - *(kk+7) ));
  713. ii += h_length;
  714. kk += lx2;
  715. if (sad > min_sofar)
  716. return INT_MAX;
  717. }
  718. return sad;
  719. }
  720. #endif
  721. /**********************************************************************
  722. *
  723. * Name: LoadArea
  724. * Description: fills array with a square of image-data
  725. *
  726. * Input: pointer to image and position, x and y size
  727. * Returns: pointer to area
  728. * Side effects: memory allocated to array
  729. *
  730. *
  731. ***********************************************************************/
  732. void sv_H263LdSubs2Area(unsigned char *im, int x, int y,
  733. int x_size, int y_size, int lx,
  734. unsigned char *srch_area, int area_length)
  735. {
  736. register unsigned char *in, *out;
  737. register int incrs1, incrs2, i;
  738. x = ((x+1)>>1) << 1; /* subsampled images always correspond to pixels*/
  739. y = ((y+1)>>1) << 1; /* of even coordinates in the original image */
  740. in = im + (y*lx) + x;
  741. out = srch_area;
  742. #ifdef USE_C
  743. incrs1 = (lx - x_size) << 1;
  744. incrs2 = area_length - x_size;
  745. while (y_size--) {
  746. i = x_size;
  747. while (i--) {
  748. *out++ = *in;
  749. in+=2;
  750. }
  751. in += incrs1;
  752. out += incrs2;
  753. };
  754. #else
  755. if(area_length == 8){
  756. sv_H263Subsamp8_S(in, out, y_size, (lx << 1)) ;
  757. }
  758. else {
  759. incrs1 = (lx - x_size) << 1;
  760. incrs2 = area_length - x_size;
  761. while (y_size--) {
  762. i = x_size;
  763. while (i--) {
  764. *out++ = *in;
  765. in+=2;
  766. }
  767. in += incrs1;
  768. out += incrs2;
  769. };
  770. }
  771. #endif
  772. return ;
  773. }
  774.