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.

707 lines
18KB

  1. /*
  2. * Motion estimation
  3. * Copyright (c) 2000,2001 Gerard Lantau.
  4. *
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. *
  20. * new Motion Estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>
  21. */
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include "avcodec.h"
  25. #include "dsputil.h"
  26. #include "mpegvideo.h"
  27. static void halfpel_motion_search(MpegEncContext * s,
  28. int *mx_ptr, int *my_ptr, int dmin,
  29. int xmin, int ymin, int xmax, int ymax,
  30. int pred_x, int pred_y);
  31. /* config it to test motion vector encoding (send random vectors) */
  32. //#define CONFIG_TEST_MV_ENCODE
  33. static int pix_sum(UINT8 * pix, int line_size)
  34. {
  35. int s, i, j;
  36. s = 0;
  37. for (i = 0; i < 16; i++) {
  38. for (j = 0; j < 16; j += 8) {
  39. s += pix[0];
  40. s += pix[1];
  41. s += pix[2];
  42. s += pix[3];
  43. s += pix[4];
  44. s += pix[5];
  45. s += pix[6];
  46. s += pix[7];
  47. pix += 8;
  48. }
  49. pix += line_size - 16;
  50. }
  51. return s;
  52. }
  53. static int pix_norm1(UINT8 * pix, int line_size)
  54. {
  55. int s, i, j;
  56. UINT32 *sq = squareTbl + 256;
  57. s = 0;
  58. for (i = 0; i < 16; i++) {
  59. for (j = 0; j < 16; j += 8) {
  60. s += sq[pix[0]];
  61. s += sq[pix[1]];
  62. s += sq[pix[2]];
  63. s += sq[pix[3]];
  64. s += sq[pix[4]];
  65. s += sq[pix[5]];
  66. s += sq[pix[6]];
  67. s += sq[pix[7]];
  68. pix += 8;
  69. }
  70. pix += line_size - 16;
  71. }
  72. return s;
  73. }
  74. static int pix_norm(UINT8 * pix1, UINT8 * pix2, int line_size)
  75. {
  76. int s, i, j;
  77. UINT32 *sq = squareTbl + 256;
  78. s = 0;
  79. for (i = 0; i < 16; i++) {
  80. for (j = 0; j < 16; j += 8) {
  81. s += sq[pix1[0] - pix2[0]];
  82. s += sq[pix1[1] - pix2[1]];
  83. s += sq[pix1[2] - pix2[2]];
  84. s += sq[pix1[3] - pix2[3]];
  85. s += sq[pix1[4] - pix2[4]];
  86. s += sq[pix1[5] - pix2[5]];
  87. s += sq[pix1[6] - pix2[6]];
  88. s += sq[pix1[7] - pix2[7]];
  89. pix1 += 8;
  90. pix2 += 8;
  91. }
  92. pix1 += line_size - 16;
  93. pix2 += line_size - 16;
  94. }
  95. return s;
  96. }
  97. static void no_motion_search(MpegEncContext * s,
  98. int *mx_ptr, int *my_ptr)
  99. {
  100. *mx_ptr = 16 * s->mb_x;
  101. *my_ptr = 16 * s->mb_y;
  102. }
  103. static int full_motion_search(MpegEncContext * s,
  104. int *mx_ptr, int *my_ptr, int range,
  105. int xmin, int ymin, int xmax, int ymax)
  106. {
  107. int x1, y1, x2, y2, xx, yy, x, y;
  108. int mx, my, dmin, d;
  109. UINT8 *pix;
  110. xx = 16 * s->mb_x;
  111. yy = 16 * s->mb_y;
  112. x1 = xx - range + 1; /* we loose one pixel to avoid boundary pb with half pixel pred */
  113. if (x1 < xmin)
  114. x1 = xmin;
  115. x2 = xx + range - 1;
  116. if (x2 > xmax)
  117. x2 = xmax;
  118. y1 = yy - range + 1;
  119. if (y1 < ymin)
  120. y1 = ymin;
  121. y2 = yy + range - 1;
  122. if (y2 > ymax)
  123. y2 = ymax;
  124. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  125. dmin = 0x7fffffff;
  126. mx = 0;
  127. my = 0;
  128. for (y = y1; y <= y2; y++) {
  129. for (x = x1; x <= x2; x++) {
  130. d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x,
  131. s->linesize, 16);
  132. if (d < dmin ||
  133. (d == dmin &&
  134. (abs(x - xx) + abs(y - yy)) <
  135. (abs(mx - xx) + abs(my - yy)))) {
  136. dmin = d;
  137. mx = x;
  138. my = y;
  139. }
  140. }
  141. }
  142. *mx_ptr = mx;
  143. *my_ptr = my;
  144. #if 0
  145. if (*mx_ptr < -(2 * range) || *mx_ptr >= (2 * range) ||
  146. *my_ptr < -(2 * range) || *my_ptr >= (2 * range)) {
  147. fprintf(stderr, "error %d %d\n", *mx_ptr, *my_ptr);
  148. }
  149. #endif
  150. return dmin;
  151. }
  152. static int log_motion_search(MpegEncContext * s,
  153. int *mx_ptr, int *my_ptr, int range,
  154. int xmin, int ymin, int xmax, int ymax)
  155. {
  156. int x1, y1, x2, y2, xx, yy, x, y;
  157. int mx, my, dmin, d;
  158. UINT8 *pix;
  159. xx = s->mb_x << 4;
  160. yy = s->mb_y << 4;
  161. /* Left limit */
  162. x1 = xx - range;
  163. if (x1 < xmin)
  164. x1 = xmin;
  165. /* Right limit */
  166. x2 = xx + range;
  167. if (x2 > xmax)
  168. x2 = xmax;
  169. /* Upper limit */
  170. y1 = yy - range;
  171. if (y1 < ymin)
  172. y1 = ymin;
  173. /* Lower limit */
  174. y2 = yy + range;
  175. if (y2 > ymax)
  176. y2 = ymax;
  177. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  178. dmin = 0x7fffffff;
  179. mx = 0;
  180. my = 0;
  181. do {
  182. for (y = y1; y <= y2; y += range) {
  183. for (x = x1; x <= x2; x += range) {
  184. d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
  185. if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
  186. dmin = d;
  187. mx = x;
  188. my = y;
  189. }
  190. }
  191. }
  192. range = range >> 1;
  193. x1 = mx - range;
  194. if (x1 < xmin)
  195. x1 = xmin;
  196. x2 = mx + range;
  197. if (x2 > xmax)
  198. x2 = xmax;
  199. y1 = my - range;
  200. if (y1 < ymin)
  201. y1 = ymin;
  202. y2 = my + range;
  203. if (y2 > ymax)
  204. y2 = ymax;
  205. } while (range >= 1);
  206. #ifdef DEBUG
  207. fprintf(stderr, "log - MX: %d\tMY: %d\n", mx, my);
  208. #endif
  209. *mx_ptr = mx;
  210. *my_ptr = my;
  211. return dmin;
  212. }
  213. static int phods_motion_search(MpegEncContext * s,
  214. int *mx_ptr, int *my_ptr, int range,
  215. int xmin, int ymin, int xmax, int ymax)
  216. {
  217. int x1, y1, x2, y2, xx, yy, x, y, lastx, d;
  218. int mx, my, dminx, dminy;
  219. UINT8 *pix;
  220. xx = s->mb_x << 4;
  221. yy = s->mb_y << 4;
  222. /* Left limit */
  223. x1 = xx - range;
  224. if (x1 < xmin)
  225. x1 = xmin;
  226. /* Right limit */
  227. x2 = xx + range;
  228. if (x2 > xmax)
  229. x2 = xmax;
  230. /* Upper limit */
  231. y1 = yy - range;
  232. if (y1 < ymin)
  233. y1 = ymin;
  234. /* Lower limit */
  235. y2 = yy + range;
  236. if (y2 > ymax)
  237. y2 = ymax;
  238. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  239. mx = 0;
  240. my = 0;
  241. x = xx;
  242. y = yy;
  243. do {
  244. dminx = 0x7fffffff;
  245. dminy = 0x7fffffff;
  246. lastx = x;
  247. for (x = x1; x <= x2; x += range) {
  248. d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
  249. if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
  250. dminx = d;
  251. mx = x;
  252. }
  253. }
  254. x = lastx;
  255. for (y = y1; y <= y2; y += range) {
  256. d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
  257. if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
  258. dminy = d;
  259. my = y;
  260. }
  261. }
  262. range = range >> 1;
  263. x = mx;
  264. y = my;
  265. x1 = mx - range;
  266. if (x1 < xmin)
  267. x1 = xmin;
  268. x2 = mx + range;
  269. if (x2 > xmax)
  270. x2 = xmax;
  271. y1 = my - range;
  272. if (y1 < ymin)
  273. y1 = ymin;
  274. y2 = my + range;
  275. if (y2 > ymax)
  276. y2 = ymax;
  277. } while (range >= 1);
  278. #ifdef DEBUG
  279. fprintf(stderr, "phods - MX: %d\tMY: %d\n", mx, my);
  280. #endif
  281. /* half pixel search */
  282. *mx_ptr = mx;
  283. *my_ptr = my;
  284. return dminy;
  285. }
  286. #define Z_THRESHOLD 256
  287. #define CHECK_MV(x,y)\
  288. d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
  289. d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
  290. if(d<dmin){\
  291. best[0]=x;\
  292. best[1]=y;\
  293. dmin=d;\
  294. }
  295. #define CHECK_MV_DIR(x,y,new_dir)\
  296. {\
  297. d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
  298. d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
  299. if(d<dmin){\
  300. best[0]=x;\
  301. best[1]=y;\
  302. dmin=d;\
  303. next_dir= new_dir;\
  304. }\
  305. }
  306. static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
  307. UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
  308. int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
  309. int xmin, int ymin, int xmax, int ymax, int shift)
  310. {
  311. int next_dir=-1;
  312. for(;;){
  313. int d;
  314. const int dir= next_dir;
  315. const int x= best[0];
  316. const int y= best[1];
  317. next_dir=-1;
  318. //printf("%d", dir);
  319. if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0)
  320. if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1)
  321. if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2)
  322. if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3)
  323. if(next_dir==-1){
  324. return dmin;
  325. }
  326. }
  327. }
  328. static int epzs_motion_search(MpegEncContext * s,
  329. int *mx_ptr, int *my_ptr,
  330. int P[5][2], int pred_x, int pred_y,
  331. int xmin, int ymin, int xmax, int ymax)
  332. {
  333. int best[2]={0, 0};
  334. int d, dmin;
  335. UINT8 *new_pic, *old_pic;
  336. const int pic_stride= s->linesize;
  337. const int pic_xy= (s->mb_y*pic_stride + s->mb_x)*16;
  338. UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
  339. int quant= s->qscale; // qscale of the prev frame
  340. const int shift= 1+s->quarter_sample;
  341. new_pic = s->new_picture[0] + pic_xy;
  342. old_pic = s->last_picture[0] + pic_xy;
  343. //printf("%d %d %d %d\n", xmin, ymin, xmax, ymax);
  344. dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16);
  345. if(dmin<Z_THRESHOLD){
  346. *mx_ptr= 0;
  347. *my_ptr= 0;
  348. //printf("Z");
  349. return dmin;
  350. }
  351. /* first line */
  352. if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
  353. CHECK_MV(P[1][0]>>shift, P[1][1]>>shift)
  354. }else{
  355. CHECK_MV(P[4][0]>>shift, P[4][1]>>shift)
  356. if(dmin<Z_THRESHOLD){
  357. *mx_ptr= P[4][0]>>shift;
  358. *my_ptr= P[4][1]>>shift;
  359. //printf("M\n");
  360. return dmin;
  361. }
  362. CHECK_MV(P[1][0]>>shift, P[1][1]>>shift)
  363. CHECK_MV(P[2][0]>>shift, P[2][1]>>shift)
  364. CHECK_MV(P[3][0]>>shift, P[3][1]>>shift)
  365. }
  366. CHECK_MV(P[0][0]>>shift, P[0][1]>>shift)
  367. dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride,
  368. pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);
  369. *mx_ptr= best[0];
  370. *my_ptr= best[1];
  371. // printf("%d %d %d \n", best[0], best[1], dmin);
  372. return dmin;
  373. }
  374. #define CHECK_HALF_MV(suffix, x, y) \
  375. d= pix_abs16x16_ ## suffix(pix, ptr+((x)>>1), s->linesize, 16);\
  376. d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\
  377. if(d<dminh){\
  378. dminh= d;\
  379. mx= mx1 + x;\
  380. my= my1 + y;\
  381. }
  382. /* The idea would be to make half pel ME after Inter/Intra decision to
  383. save time. */
  384. static inline void halfpel_motion_search(MpegEncContext * s,
  385. int *mx_ptr, int *my_ptr, int dmin,
  386. int xmin, int ymin, int xmax, int ymax,
  387. int pred_x, int pred_y)
  388. {
  389. UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
  390. const int quant= s->qscale;
  391. int pen_x, pen_y;
  392. int mx, my, mx1, my1, d, xx, yy, dminh;
  393. UINT8 *pix, *ptr;
  394. mx = *mx_ptr;
  395. my = *my_ptr;
  396. ptr = s->last_picture[0] + (my * s->linesize) + mx;
  397. xx = 16 * s->mb_x;
  398. yy = 16 * s->mb_y;
  399. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  400. dminh = dmin;
  401. if (mx > xmin && mx < xmax &&
  402. my > ymin && my < ymax) {
  403. mx= mx1= 2*(mx - xx);
  404. my= my1= 2*(my - yy);
  405. if(dmin < Z_THRESHOLD && mx==0 && my==0){
  406. *mx_ptr = 0;
  407. *my_ptr = 0;
  408. return;
  409. }
  410. pen_x= pred_x + mx;
  411. pen_y= pred_y + my;
  412. ptr-= s->linesize;
  413. CHECK_HALF_MV(xy2, -1, -1)
  414. CHECK_HALF_MV(y2 , 0, -1)
  415. CHECK_HALF_MV(xy2, +1, -1)
  416. ptr+= s->linesize;
  417. CHECK_HALF_MV(x2 , -1, 0)
  418. CHECK_HALF_MV(x2 , +1, 0)
  419. CHECK_HALF_MV(xy2, -1, +1)
  420. CHECK_HALF_MV(y2 , 0, +1)
  421. CHECK_HALF_MV(xy2, +1, +1)
  422. }else{
  423. mx= 2*(mx - xx);
  424. my= 2*(my - yy);
  425. }
  426. *mx_ptr = mx;
  427. *my_ptr = my;
  428. }
  429. #ifndef CONFIG_TEST_MV_ENCODE
  430. int estimate_motion(MpegEncContext * s,
  431. int mb_x, int mb_y,
  432. int *mx_ptr, int *my_ptr)
  433. {
  434. UINT8 *pix, *ppix;
  435. int sum, varc, vard, mx, my, range, dmin, xx, yy;
  436. int xmin, ymin, xmax, ymax;
  437. int rel_xmin, rel_ymin, rel_xmax, rel_ymax;
  438. int pred_x=0, pred_y=0;
  439. int P[5][2];
  440. const int shift= 1+s->quarter_sample;
  441. range = 8 * (1 << (s->f_code - 1));
  442. /* XXX: temporary kludge to avoid overflow for msmpeg4 */
  443. if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
  444. range = range * 2;
  445. if (s->unrestricted_mv) {
  446. xmin = -16;
  447. ymin = -16;
  448. if (s->h263_plus)
  449. range *= 2;
  450. if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){
  451. xmax = s->mb_width*16;
  452. ymax = s->mb_height*16;
  453. }else {
  454. /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise
  455. (cuz the drawn edge isnt large enough))*/
  456. xmax = s->width;
  457. ymax = s->height;
  458. }
  459. } else {
  460. xmin = 0;
  461. ymin = 0;
  462. xmax = s->mb_width*16 - 16;
  463. ymax = s->mb_height*16 - 16;
  464. }
  465. switch(s->full_search) {
  466. case ME_ZERO:
  467. default:
  468. no_motion_search(s, &mx, &my);
  469. dmin = 0;
  470. break;
  471. case ME_FULL:
  472. dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax);
  473. break;
  474. case ME_LOG:
  475. dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
  476. break;
  477. case ME_PHODS:
  478. dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
  479. break;
  480. case ME_X1: // just reserving some space for experiments ...
  481. case ME_EPZS:
  482. rel_xmin= xmin - s->mb_x*16;
  483. rel_xmax= xmax - s->mb_x*16;
  484. rel_ymin= ymin - s->mb_y*16;
  485. rel_ymax= ymax - s->mb_y*16;
  486. if(s->out_format == FMT_H263){
  487. static const int off[4]= {2, 1, 1, -1};
  488. const int mot_stride = s->block_wrap[0];
  489. const int mot_xy = s->block_index[0];
  490. P[0][0] = s->motion_val[mot_xy ][0];
  491. P[0][1] = s->motion_val[mot_xy ][1];
  492. P[1][0] = s->motion_val[mot_xy - 1][0];
  493. P[1][1] = s->motion_val[mot_xy - 1][1];
  494. if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift);
  495. /* special case for first line */
  496. if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
  497. pred_x = P[1][0];
  498. pred_y = P[1][1];
  499. } else {
  500. P[2][0] = s->motion_val[mot_xy - mot_stride ][0];
  501. P[2][1] = s->motion_val[mot_xy - mot_stride ][1];
  502. P[3][0] = s->motion_val[mot_xy - mot_stride + off[0] ][0];
  503. P[3][1] = s->motion_val[mot_xy - mot_stride + off[0] ][1];
  504. if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift);
  505. if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift);
  506. if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift);
  507. P[4][0]= pred_x = mid_pred(P[1][0], P[2][0], P[3][0]);
  508. P[4][1]= pred_y = mid_pred(P[1][1], P[2][1], P[3][1]);
  509. }
  510. }else {
  511. const int xy= s->mb_y*s->mb_width + s->mb_x;
  512. pred_x= s->last_mv[0][0][0];
  513. pred_y= s->last_mv[0][0][1];
  514. P[0][0]= s->mv_table[0][xy ];
  515. P[0][1]= s->mv_table[1][xy ];
  516. if(s->mb_x == 0){
  517. P[1][0]= 0;
  518. P[1][1]= 0;
  519. }else{
  520. P[1][0]= s->mv_table[0][xy-1];
  521. P[1][1]= s->mv_table[1][xy-1];
  522. if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift);
  523. }
  524. if (!(s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
  525. P[2][0] = s->mv_table[0][xy - s->mb_width];
  526. P[2][1] = s->mv_table[1][xy - s->mb_width];
  527. P[3][0] = s->mv_table[0][xy - s->mb_width+1];
  528. P[3][1] = s->mv_table[1][xy - s->mb_width+1];
  529. if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift);
  530. if(P[3][0] > (rel_xmax<<shift)) P[3][0]= (rel_xmax<<shift);
  531. if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift);
  532. if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift);
  533. P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]);
  534. P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]);
  535. }
  536. }
  537. dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax);
  538. mx+= s->mb_x*16;
  539. my+= s->mb_y*16;
  540. break;
  541. }
  542. /* intra / predictive decision */
  543. xx = mb_x * 16;
  544. yy = mb_y * 16;
  545. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  546. /* At this point (mx,my) are full-pell and the absolute displacement */
  547. ppix = s->last_picture[0] + (my * s->linesize) + mx;
  548. sum = pix_sum(pix, s->linesize);
  549. varc = pix_norm1(pix, s->linesize);
  550. vard = pix_norm(pix, ppix, s->linesize);
  551. vard = vard >> 8;
  552. sum = sum >> 8;
  553. varc = (varc >> 8) - (sum * sum);
  554. s->mb_var[s->mb_width * mb_y + mb_x] = varc;
  555. s->avg_mb_var += varc;
  556. s->mc_mb_var += vard;
  557. #if 0
  558. printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
  559. varc, s->avg_mb_var, sum, vard, mx - xx, my - yy);
  560. #endif
  561. if (vard <= 64 || vard < varc) {
  562. if (s->full_search != ME_ZERO) {
  563. halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y);
  564. } else {
  565. mx -= 16 * s->mb_x;
  566. my -= 16 * s->mb_y;
  567. }
  568. *mx_ptr = mx;
  569. *my_ptr = my;
  570. return 0;
  571. } else {
  572. *mx_ptr = 0;
  573. *my_ptr = 0;
  574. return 1;
  575. }
  576. }
  577. #else
  578. /* test version which generates valid random vectors */
  579. int estimate_motion(MpegEncContext * s,
  580. int mb_x, int mb_y,
  581. int *mx_ptr, int *my_ptr)
  582. {
  583. int xx, yy, x1, y1, x2, y2, range;
  584. if ((random() % 10) >= 5) {
  585. range = 8 * (1 << (s->f_code - 1));
  586. if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
  587. range = range * 2;
  588. xx = 16 * s->mb_x;
  589. yy = 16 * s->mb_y;
  590. x1 = xx - range;
  591. if (x1 < 0)
  592. x1 = 0;
  593. x2 = xx + range - 1;
  594. if (x2 > (s->width - 16))
  595. x2 = s->width - 16;
  596. y1 = yy - range;
  597. if (y1 < 0)
  598. y1 = 0;
  599. y2 = yy + range - 1;
  600. if (y2 > (s->height - 16))
  601. y2 = s->height - 16;
  602. *mx_ptr = (random() % (2 * (x2 - x1 + 1))) + 2 * (x1 - xx);
  603. *my_ptr = (random() % (2 * (y2 - y1 + 1))) + 2 * (y1 - yy);
  604. return 0;
  605. } else {
  606. *mx_ptr = 0;
  607. *my_ptr = 0;
  608. return 1;
  609. }
  610. }
  611. #endif