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.

808 lines
22KB

  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. {\
  289. d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
  290. d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
  291. if(d<dmin){\
  292. best[0]=x;\
  293. best[1]=y;\
  294. dmin=d;\
  295. }\
  296. }
  297. #define CHECK_MV_DIR(x,y,new_dir)\
  298. {\
  299. d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
  300. d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
  301. if(d<dmin){\
  302. best[0]=x;\
  303. best[1]=y;\
  304. dmin=d;\
  305. next_dir= new_dir;\
  306. }\
  307. }
  308. #define check(x,y,S,v)\
  309. if( (x)<(xmin<<(S)) ) printf("%d %d %d %d xmin" #v, (x), (y), s->mb_x, s->mb_y);\
  310. if( (x)>(xmax<<(S)) ) printf("%d %d %d %d xmax" #v, (x), (y), s->mb_x, s->mb_y);\
  311. if( (y)<(ymin<<(S)) ) printf("%d %d %d %d ymin" #v, (x), (y), s->mb_x, s->mb_y);\
  312. if( (y)>(ymax<<(S)) ) printf("%d %d %d %d ymax" #v, (x), (y), s->mb_x, s->mb_y);\
  313. static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
  314. UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
  315. int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
  316. int xmin, int ymin, int xmax, int ymax, int shift)
  317. {
  318. int next_dir=-1;
  319. for(;;){
  320. int d;
  321. const int dir= next_dir;
  322. const int x= best[0];
  323. const int y= best[1];
  324. next_dir=-1;
  325. //printf("%d", dir);
  326. if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0)
  327. if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1)
  328. if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2)
  329. if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3)
  330. if(next_dir==-1){
  331. return dmin;
  332. }
  333. }
  334. /* for(;;){
  335. int d;
  336. const int x= best[0];
  337. const int y= best[1];
  338. const int last_min=dmin;
  339. if(x>xmin) CHECK_MV(x-1, y )
  340. if(y>xmin) CHECK_MV(x , y-1)
  341. if(x<xmax) CHECK_MV(x+1, y )
  342. if(y<xmax) CHECK_MV(x , y+1)
  343. if(x>xmin && y>ymin) CHECK_MV(x-1, y-1)
  344. if(x>xmin && y<ymax) CHECK_MV(x-1, y+1)
  345. if(x<xmax && y>ymin) CHECK_MV(x+1, y-1)
  346. if(x<xmax && y<ymax) CHECK_MV(x+1, y+1)
  347. if(x-1>xmin) CHECK_MV(x-2, y )
  348. if(y-1>xmin) CHECK_MV(x , y-2)
  349. if(x+1<xmax) CHECK_MV(x+2, y )
  350. if(y+1<xmax) CHECK_MV(x , y+2)
  351. if(x-1>xmin && y-1>ymin) CHECK_MV(x-2, y-2)
  352. if(x-1>xmin && y+1<ymax) CHECK_MV(x-2, y+2)
  353. if(x+1<xmax && y-1>ymin) CHECK_MV(x+2, y-2)
  354. if(x+1<xmax && y+1<ymax) CHECK_MV(x+2, y+2)
  355. if(dmin==last_min) return dmin;
  356. }
  357. */
  358. }
  359. static inline int snake_search(MpegEncContext * s, int *best, int dmin,
  360. UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
  361. int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
  362. int xmin, int ymin, int xmax, int ymax, int shift)
  363. {
  364. int dir=0;
  365. int c=1;
  366. static int x_dir[8]= {1,1,0,-1,-1,-1, 0, 1};
  367. static int y_dir[8]= {0,1,1, 1, 0,-1,-1,-1};
  368. int fails=0;
  369. int last_d[2]={dmin, dmin};
  370. /*static int good=0;
  371. static int bad=0;
  372. static int point=0;
  373. point++;
  374. if(256*256*256*64%point==0)
  375. {
  376. printf("%d %d %d\n", good, bad, point);
  377. }*/
  378. for(;;){
  379. int x= best[0];
  380. int y= best[1];
  381. int d;
  382. x+=x_dir[dir];
  383. y+=y_dir[dir];
  384. if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){
  385. d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);
  386. d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;
  387. }else{
  388. d = dmin + 10000; //FIXME smarter boundary handling
  389. }
  390. if(d<dmin){
  391. best[0]=x;
  392. best[1]=y;
  393. dmin=d;
  394. if(last_d[1] - last_d[0] > last_d[0] - d) c= -c;
  395. dir+=c;
  396. fails=0;
  397. //good++;
  398. last_d[1]=last_d[0];
  399. last_d[0]=d;
  400. }else{
  401. //bad++;
  402. if(fails){
  403. if(fails>=3) return dmin;
  404. }else{
  405. c= -c;
  406. }
  407. dir+=c*2;
  408. fails++;
  409. }
  410. dir&=7;
  411. }
  412. }
  413. static int epzs_motion_search(MpegEncContext * s,
  414. int *mx_ptr, int *my_ptr,
  415. int P[5][2], int pred_x, int pred_y,
  416. int xmin, int ymin, int xmax, int ymax)
  417. {
  418. int best[2]={0, 0};
  419. int d, dmin;
  420. UINT8 *new_pic, *old_pic;
  421. const int pic_stride= s->linesize;
  422. const int pic_xy= (s->mb_y*pic_stride + s->mb_x)*16;
  423. UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
  424. int quant= s->qscale; // qscale of the prev frame
  425. const int shift= 1+s->quarter_sample;
  426. new_pic = s->new_picture[0] + pic_xy;
  427. old_pic = s->last_picture[0] + pic_xy;
  428. dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16);
  429. if(dmin<Z_THRESHOLD){
  430. *mx_ptr= 0;
  431. *my_ptr= 0;
  432. //printf("Z");
  433. return dmin;
  434. }
  435. /* first line */
  436. if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
  437. CHECK_MV(P[1][0]>>shift, P[1][1]>>shift)
  438. }else{
  439. CHECK_MV(P[4][0]>>shift, P[4][1]>>shift)
  440. if(dmin<Z_THRESHOLD){
  441. *mx_ptr= P[4][0]>>shift;
  442. *my_ptr= P[4][1]>>shift;
  443. //printf("M\n");
  444. return dmin;
  445. }
  446. CHECK_MV(P[1][0]>>shift, P[1][1]>>shift)
  447. CHECK_MV(P[2][0]>>shift, P[2][1]>>shift)
  448. CHECK_MV(P[3][0]>>shift, P[3][1]>>shift)
  449. }
  450. CHECK_MV(P[0][0]>>shift, P[0][1]>>shift)
  451. //check(best[0],best[1],0, b0)
  452. if(s->full_search==ME_EPZS)
  453. dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride,
  454. pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);
  455. else
  456. dmin= snake_search(s, best, dmin, new_pic, old_pic, pic_stride,
  457. pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);
  458. //check(best[0],best[1],0, b1)
  459. *mx_ptr= best[0];
  460. *my_ptr= best[1];
  461. // printf("%d %d %d \n", best[0], best[1], dmin);
  462. return dmin;
  463. }
  464. #define CHECK_HALF_MV(suffix, x, y) \
  465. d= pix_abs16x16_ ## suffix(pix, ptr+((x)>>1), s->linesize, 16);\
  466. d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\
  467. if(d<dminh){\
  468. dminh= d;\
  469. mx= mx1 + x;\
  470. my= my1 + y;\
  471. }
  472. /* The idea would be to make half pel ME after Inter/Intra decision to
  473. save time. */
  474. static inline void halfpel_motion_search(MpegEncContext * s,
  475. int *mx_ptr, int *my_ptr, int dmin,
  476. int xmin, int ymin, int xmax, int ymax,
  477. int pred_x, int pred_y)
  478. {
  479. UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
  480. const int quant= s->qscale;
  481. int pen_x, pen_y;
  482. int mx, my, mx1, my1, d, xx, yy, dminh;
  483. UINT8 *pix, *ptr;
  484. mx = *mx_ptr;
  485. my = *my_ptr;
  486. ptr = s->last_picture[0] + (my * s->linesize) + mx;
  487. xx = 16 * s->mb_x;
  488. yy = 16 * s->mb_y;
  489. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  490. dminh = dmin;
  491. if (mx > xmin && mx < xmax &&
  492. my > ymin && my < ymax) {
  493. mx= mx1= 2*(mx - xx);
  494. my= my1= 2*(my - yy);
  495. if(dmin < Z_THRESHOLD && mx==0 && my==0){
  496. *mx_ptr = 0;
  497. *my_ptr = 0;
  498. return;
  499. }
  500. pen_x= pred_x + mx;
  501. pen_y= pred_y + my;
  502. ptr-= s->linesize;
  503. CHECK_HALF_MV(xy2, -1, -1)
  504. CHECK_HALF_MV(y2 , 0, -1)
  505. CHECK_HALF_MV(xy2, +1, -1)
  506. ptr+= s->linesize;
  507. CHECK_HALF_MV(x2 , -1, 0)
  508. CHECK_HALF_MV(x2 , +1, 0)
  509. CHECK_HALF_MV(xy2, -1, +1)
  510. CHECK_HALF_MV(y2 , 0, +1)
  511. CHECK_HALF_MV(xy2, +1, +1)
  512. }else{
  513. mx= 2*(mx - xx);
  514. my= 2*(my - yy);
  515. }
  516. *mx_ptr = mx;
  517. *my_ptr = my;
  518. }
  519. #ifndef CONFIG_TEST_MV_ENCODE
  520. int estimate_motion(MpegEncContext * s,
  521. int mb_x, int mb_y,
  522. int *mx_ptr, int *my_ptr)
  523. {
  524. UINT8 *pix, *ppix;
  525. int sum, varc, vard, mx, my, range, dmin, xx, yy;
  526. int xmin, ymin, xmax, ymax;
  527. int rel_xmin, rel_ymin, rel_xmax, rel_ymax;
  528. int pred_x=0, pred_y=0;
  529. int P[5][2];
  530. const int shift= 1+s->quarter_sample;
  531. range = 8 * (1 << (s->f_code - 1));
  532. /* XXX: temporary kludge to avoid overflow for msmpeg4 */
  533. if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
  534. range = range * 2;
  535. if (s->unrestricted_mv) {
  536. xmin = -16;
  537. ymin = -16;
  538. if (s->h263_plus)
  539. range *= 2;
  540. if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){
  541. xmax = s->mb_width*16;
  542. ymax = s->mb_height*16;
  543. }else {
  544. /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise
  545. (cuz the drawn edge isnt large enough))*/
  546. xmax = s->width;
  547. ymax = s->height;
  548. }
  549. } else {
  550. xmin = 0;
  551. ymin = 0;
  552. xmax = s->mb_width*16 - 16;
  553. ymax = s->mb_height*16 - 16;
  554. }
  555. switch(s->full_search) {
  556. case ME_ZERO:
  557. default:
  558. no_motion_search(s, &mx, &my);
  559. dmin = 0;
  560. break;
  561. case ME_FULL:
  562. dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax);
  563. break;
  564. case ME_LOG:
  565. dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
  566. break;
  567. case ME_PHODS:
  568. dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
  569. break;
  570. case ME_X1: // just reserving some space for experiments ...
  571. case ME_EPZS:
  572. rel_xmin= xmin - s->mb_x*16;
  573. rel_xmax= xmax - s->mb_x*16;
  574. rel_ymin= ymin - s->mb_y*16;
  575. rel_ymax= ymax - s->mb_y*16;
  576. if(s->out_format == FMT_H263){
  577. static const int off[4]= {2, 1, 1, -1};
  578. const int mot_stride = s->mb_width*2 + 2;
  579. const int mot_xy = (s->mb_y*2 + 1)*mot_stride + s->mb_x*2 + 1;
  580. P[0][0] = s->motion_val[mot_xy ][0];
  581. P[0][1] = s->motion_val[mot_xy ][1];
  582. P[1][0] = s->motion_val[mot_xy - 1][0];
  583. P[1][1] = s->motion_val[mot_xy - 1][1];
  584. if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift);
  585. /* special case for first line */
  586. if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
  587. pred_x = P[1][0];
  588. pred_y = P[1][1];
  589. } else {
  590. P[2][0] = s->motion_val[mot_xy - mot_stride ][0];
  591. P[2][1] = s->motion_val[mot_xy - mot_stride ][1];
  592. P[3][0] = s->motion_val[mot_xy - mot_stride + off[0] ][0];
  593. P[3][1] = s->motion_val[mot_xy - mot_stride + off[0] ][1];
  594. if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift);
  595. if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift);
  596. if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift);
  597. P[4][0]= pred_x = mid_pred(P[1][0], P[2][0], P[3][0]);
  598. P[4][1]= pred_y = mid_pred(P[1][1], P[2][1], P[3][1]);
  599. }
  600. }else {
  601. const int xy= s->mb_y*s->mb_width + s->mb_x;
  602. pred_x= s->last_mv[0][0][0];
  603. pred_y= s->last_mv[0][0][1];
  604. P[0][0]= s->mv_table[0][xy ];
  605. P[0][1]= s->mv_table[1][xy ];
  606. if(s->mb_x == 0){
  607. P[1][0]= 0;
  608. P[1][1]= 0;
  609. }else{
  610. P[1][0]= s->mv_table[0][xy-1];
  611. P[1][1]= s->mv_table[1][xy-1];
  612. if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift);
  613. }
  614. if (!(s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
  615. P[2][0] = s->mv_table[0][xy - s->mb_width];
  616. P[2][1] = s->mv_table[1][xy - s->mb_width];
  617. P[3][0] = s->mv_table[0][xy - s->mb_width+1];
  618. P[3][1] = s->mv_table[1][xy - s->mb_width+1];
  619. if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift);
  620. if(P[3][0] > (rel_xmax<<shift)) P[3][0]= (rel_xmax<<shift);
  621. if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift);
  622. if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift);
  623. P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]);
  624. P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]);
  625. }
  626. }
  627. dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax);
  628. mx+= s->mb_x*16;
  629. my+= s->mb_y*16;
  630. break;
  631. }
  632. /* intra / predictive decision */
  633. xx = mb_x * 16;
  634. yy = mb_y * 16;
  635. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  636. /* At this point (mx,my) are full-pell and the absolute displacement */
  637. ppix = s->last_picture[0] + (my * s->linesize) + mx;
  638. sum = pix_sum(pix, s->linesize);
  639. varc = pix_norm1(pix, s->linesize);
  640. vard = pix_norm(pix, ppix, s->linesize);
  641. vard = vard >> 8;
  642. sum = sum >> 8;
  643. varc = (varc >> 8) - (sum * sum);
  644. s->mb_var[s->mb_width * mb_y + mb_x] = varc;
  645. s->avg_mb_var += varc;
  646. s->mc_mb_var += vard;
  647. #if 0
  648. printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
  649. varc, s->avg_mb_var, sum, vard, mx - xx, my - yy);
  650. #endif
  651. if (vard <= 64 || vard < varc) {
  652. if (s->full_search != ME_ZERO) {
  653. halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y);
  654. } else {
  655. mx -= 16 * s->mb_x;
  656. my -= 16 * s->mb_y;
  657. }
  658. // check(mx + 32*s->mb_x, my + 32*s->mb_y, 1, end)
  659. *mx_ptr = mx;
  660. *my_ptr = my;
  661. return 0;
  662. } else {
  663. *mx_ptr = 0;
  664. *my_ptr = 0;
  665. return 1;
  666. }
  667. }
  668. #else
  669. /* test version which generates valid random vectors */
  670. int estimate_motion(MpegEncContext * s,
  671. int mb_x, int mb_y,
  672. int *mx_ptr, int *my_ptr)
  673. {
  674. int xx, yy, x1, y1, x2, y2, range;
  675. if ((random() % 10) >= 5) {
  676. range = 8 * (1 << (s->f_code - 1));
  677. if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
  678. range = range * 2;
  679. xx = 16 * s->mb_x;
  680. yy = 16 * s->mb_y;
  681. x1 = xx - range;
  682. if (x1 < 0)
  683. x1 = 0;
  684. x2 = xx + range - 1;
  685. if (x2 > (s->width - 16))
  686. x2 = s->width - 16;
  687. y1 = yy - range;
  688. if (y1 < 0)
  689. y1 = 0;
  690. y2 = yy + range - 1;
  691. if (y2 > (s->height - 16))
  692. y2 = s->height - 16;
  693. *mx_ptr = (random() % (2 * (x2 - x1 + 1))) + 2 * (x1 - xx);
  694. *my_ptr = (random() % (2 * (y2 - y1 + 1))) + 2 * (y1 - yy);
  695. return 0;
  696. } else {
  697. *mx_ptr = 0;
  698. *my_ptr = 0;
  699. return 1;
  700. }
  701. }
  702. #endif