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.

814 lines
21KB

  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. #define ABS(a) ((a)>0 ? (a) : -(a))
  28. #define INTER_BIAS 257
  29. static void halfpel_motion_search(MpegEncContext * s,
  30. int *mx_ptr, int *my_ptr, int dmin,
  31. int xmin, int ymin, int xmax, int ymax,
  32. int pred_x, int pred_y);
  33. /* config it to test motion vector encoding (send random vectors) */
  34. //#define CONFIG_TEST_MV_ENCODE
  35. static int pix_sum(UINT8 * pix, int line_size)
  36. {
  37. int s, i, j;
  38. s = 0;
  39. for (i = 0; i < 16; i++) {
  40. for (j = 0; j < 16; j += 8) {
  41. s += pix[0];
  42. s += pix[1];
  43. s += pix[2];
  44. s += pix[3];
  45. s += pix[4];
  46. s += pix[5];
  47. s += pix[6];
  48. s += pix[7];
  49. pix += 8;
  50. }
  51. pix += line_size - 16;
  52. }
  53. return s;
  54. }
  55. static int pix_dev(UINT8 * pix, int line_size, int mean)
  56. {
  57. int s, i, j;
  58. s = 0;
  59. for (i = 0; i < 16; i++) {
  60. for (j = 0; j < 16; j += 8) {
  61. s += ABS(pix[0]-mean);
  62. s += ABS(pix[1]-mean);
  63. s += ABS(pix[2]-mean);
  64. s += ABS(pix[3]-mean);
  65. s += ABS(pix[4]-mean);
  66. s += ABS(pix[5]-mean);
  67. s += ABS(pix[6]-mean);
  68. s += ABS(pix[7]-mean);
  69. pix += 8;
  70. }
  71. pix += line_size - 16;
  72. }
  73. return s;
  74. }
  75. static int pix_norm1(UINT8 * pix, int line_size)
  76. {
  77. int s, i, j;
  78. UINT32 *sq = squareTbl + 256;
  79. s = 0;
  80. for (i = 0; i < 16; i++) {
  81. for (j = 0; j < 16; j += 8) {
  82. s += sq[pix[0]];
  83. s += sq[pix[1]];
  84. s += sq[pix[2]];
  85. s += sq[pix[3]];
  86. s += sq[pix[4]];
  87. s += sq[pix[5]];
  88. s += sq[pix[6]];
  89. s += sq[pix[7]];
  90. pix += 8;
  91. }
  92. pix += line_size - 16;
  93. }
  94. return s;
  95. }
  96. static int pix_norm(UINT8 * pix1, UINT8 * pix2, int line_size)
  97. {
  98. int s, i, j;
  99. UINT32 *sq = squareTbl + 256;
  100. s = 0;
  101. for (i = 0; i < 16; i++) {
  102. for (j = 0; j < 16; j += 8) {
  103. s += sq[pix1[0] - pix2[0]];
  104. s += sq[pix1[1] - pix2[1]];
  105. s += sq[pix1[2] - pix2[2]];
  106. s += sq[pix1[3] - pix2[3]];
  107. s += sq[pix1[4] - pix2[4]];
  108. s += sq[pix1[5] - pix2[5]];
  109. s += sq[pix1[6] - pix2[6]];
  110. s += sq[pix1[7] - pix2[7]];
  111. pix1 += 8;
  112. pix2 += 8;
  113. }
  114. pix1 += line_size - 16;
  115. pix2 += line_size - 16;
  116. }
  117. return s;
  118. }
  119. static void no_motion_search(MpegEncContext * s,
  120. int *mx_ptr, int *my_ptr)
  121. {
  122. *mx_ptr = 16 * s->mb_x;
  123. *my_ptr = 16 * s->mb_y;
  124. }
  125. static int full_motion_search(MpegEncContext * s,
  126. int *mx_ptr, int *my_ptr, int range,
  127. int xmin, int ymin, int xmax, int ymax)
  128. {
  129. int x1, y1, x2, y2, xx, yy, x, y;
  130. int mx, my, dmin, d;
  131. UINT8 *pix;
  132. xx = 16 * s->mb_x;
  133. yy = 16 * s->mb_y;
  134. x1 = xx - range + 1; /* we loose one pixel to avoid boundary pb with half pixel pred */
  135. if (x1 < xmin)
  136. x1 = xmin;
  137. x2 = xx + range - 1;
  138. if (x2 > xmax)
  139. x2 = xmax;
  140. y1 = yy - range + 1;
  141. if (y1 < ymin)
  142. y1 = ymin;
  143. y2 = yy + range - 1;
  144. if (y2 > ymax)
  145. y2 = ymax;
  146. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  147. dmin = 0x7fffffff;
  148. mx = 0;
  149. my = 0;
  150. for (y = y1; y <= y2; y++) {
  151. for (x = x1; x <= x2; x++) {
  152. d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x,
  153. s->linesize, 16);
  154. if (d < dmin ||
  155. (d == dmin &&
  156. (abs(x - xx) + abs(y - yy)) <
  157. (abs(mx - xx) + abs(my - yy)))) {
  158. dmin = d;
  159. mx = x;
  160. my = y;
  161. }
  162. }
  163. }
  164. *mx_ptr = mx;
  165. *my_ptr = my;
  166. #if 0
  167. if (*mx_ptr < -(2 * range) || *mx_ptr >= (2 * range) ||
  168. *my_ptr < -(2 * range) || *my_ptr >= (2 * range)) {
  169. fprintf(stderr, "error %d %d\n", *mx_ptr, *my_ptr);
  170. }
  171. #endif
  172. return dmin;
  173. }
  174. static int log_motion_search(MpegEncContext * s,
  175. int *mx_ptr, int *my_ptr, int range,
  176. int xmin, int ymin, int xmax, int ymax)
  177. {
  178. int x1, y1, x2, y2, xx, yy, x, y;
  179. int mx, my, dmin, d;
  180. UINT8 *pix;
  181. xx = s->mb_x << 4;
  182. yy = s->mb_y << 4;
  183. /* Left limit */
  184. x1 = xx - range;
  185. if (x1 < xmin)
  186. x1 = xmin;
  187. /* Right limit */
  188. x2 = xx + range;
  189. if (x2 > xmax)
  190. x2 = xmax;
  191. /* Upper limit */
  192. y1 = yy - range;
  193. if (y1 < ymin)
  194. y1 = ymin;
  195. /* Lower limit */
  196. y2 = yy + range;
  197. if (y2 > ymax)
  198. y2 = ymax;
  199. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  200. dmin = 0x7fffffff;
  201. mx = 0;
  202. my = 0;
  203. do {
  204. for (y = y1; y <= y2; y += range) {
  205. for (x = x1; x <= x2; x += range) {
  206. d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
  207. if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
  208. dmin = d;
  209. mx = x;
  210. my = y;
  211. }
  212. }
  213. }
  214. range = range >> 1;
  215. x1 = mx - range;
  216. if (x1 < xmin)
  217. x1 = xmin;
  218. x2 = mx + range;
  219. if (x2 > xmax)
  220. x2 = xmax;
  221. y1 = my - range;
  222. if (y1 < ymin)
  223. y1 = ymin;
  224. y2 = my + range;
  225. if (y2 > ymax)
  226. y2 = ymax;
  227. } while (range >= 1);
  228. #ifdef DEBUG
  229. fprintf(stderr, "log - MX: %d\tMY: %d\n", mx, my);
  230. #endif
  231. *mx_ptr = mx;
  232. *my_ptr = my;
  233. return dmin;
  234. }
  235. static int phods_motion_search(MpegEncContext * s,
  236. int *mx_ptr, int *my_ptr, int range,
  237. int xmin, int ymin, int xmax, int ymax)
  238. {
  239. int x1, y1, x2, y2, xx, yy, x, y, lastx, d;
  240. int mx, my, dminx, dminy;
  241. UINT8 *pix;
  242. xx = s->mb_x << 4;
  243. yy = s->mb_y << 4;
  244. /* Left limit */
  245. x1 = xx - range;
  246. if (x1 < xmin)
  247. x1 = xmin;
  248. /* Right limit */
  249. x2 = xx + range;
  250. if (x2 > xmax)
  251. x2 = xmax;
  252. /* Upper limit */
  253. y1 = yy - range;
  254. if (y1 < ymin)
  255. y1 = ymin;
  256. /* Lower limit */
  257. y2 = yy + range;
  258. if (y2 > ymax)
  259. y2 = ymax;
  260. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  261. mx = 0;
  262. my = 0;
  263. x = xx;
  264. y = yy;
  265. do {
  266. dminx = 0x7fffffff;
  267. dminy = 0x7fffffff;
  268. lastx = x;
  269. for (x = x1; x <= x2; x += range) {
  270. d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
  271. if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
  272. dminx = d;
  273. mx = x;
  274. }
  275. }
  276. x = lastx;
  277. for (y = y1; y <= y2; y += range) {
  278. d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
  279. if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
  280. dminy = d;
  281. my = y;
  282. }
  283. }
  284. range = range >> 1;
  285. x = mx;
  286. y = my;
  287. x1 = mx - range;
  288. if (x1 < xmin)
  289. x1 = xmin;
  290. x2 = mx + range;
  291. if (x2 > xmax)
  292. x2 = xmax;
  293. y1 = my - range;
  294. if (y1 < ymin)
  295. y1 = ymin;
  296. y2 = my + range;
  297. if (y2 > ymax)
  298. y2 = ymax;
  299. } while (range >= 1);
  300. #ifdef DEBUG
  301. fprintf(stderr, "phods - MX: %d\tMY: %d\n", mx, my);
  302. #endif
  303. /* half pixel search */
  304. *mx_ptr = mx;
  305. *my_ptr = my;
  306. return dminy;
  307. }
  308. #define Z_THRESHOLD 256
  309. #define CHECK_MV(x,y)\
  310. {\
  311. d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
  312. d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
  313. if(d<dmin){\
  314. best[0]=x;\
  315. best[1]=y;\
  316. dmin=d;\
  317. }\
  318. }
  319. #define CHECK_MV_DIR(x,y,new_dir)\
  320. {\
  321. d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
  322. d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
  323. if(d<dmin){\
  324. best[0]=x;\
  325. best[1]=y;\
  326. dmin=d;\
  327. next_dir= new_dir;\
  328. }\
  329. }
  330. #define check(x,y,S,v)\
  331. if( (x)<(xmin<<(S)) ) printf("%d %d %d %d xmin" #v, (x), (y), s->mb_x, s->mb_y);\
  332. if( (x)>(xmax<<(S)) ) printf("%d %d %d %d xmax" #v, (x), (y), s->mb_x, s->mb_y);\
  333. if( (y)<(ymin<<(S)) ) printf("%d %d %d %d ymin" #v, (x), (y), s->mb_x, s->mb_y);\
  334. if( (y)>(ymax<<(S)) ) printf("%d %d %d %d ymax" #v, (x), (y), s->mb_x, s->mb_y);\
  335. static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
  336. UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
  337. int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
  338. int xmin, int ymin, int xmax, int ymax, int shift)
  339. {
  340. int next_dir=-1;
  341. for(;;){
  342. int d;
  343. const int dir= next_dir;
  344. const int x= best[0];
  345. const int y= best[1];
  346. next_dir=-1;
  347. //printf("%d", dir);
  348. if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0)
  349. if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1)
  350. if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2)
  351. if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3)
  352. if(next_dir==-1){
  353. return dmin;
  354. }
  355. }
  356. /* for(;;){
  357. int d;
  358. const int x= best[0];
  359. const int y= best[1];
  360. const int last_min=dmin;
  361. if(x>xmin) CHECK_MV(x-1, y )
  362. if(y>xmin) CHECK_MV(x , y-1)
  363. if(x<xmax) CHECK_MV(x+1, y )
  364. if(y<xmax) CHECK_MV(x , y+1)
  365. if(x>xmin && y>ymin) CHECK_MV(x-1, y-1)
  366. if(x>xmin && y<ymax) CHECK_MV(x-1, y+1)
  367. if(x<xmax && y>ymin) CHECK_MV(x+1, y-1)
  368. if(x<xmax && y<ymax) CHECK_MV(x+1, y+1)
  369. if(x-1>xmin) CHECK_MV(x-2, y )
  370. if(y-1>xmin) CHECK_MV(x , y-2)
  371. if(x+1<xmax) CHECK_MV(x+2, y )
  372. if(y+1<xmax) CHECK_MV(x , y+2)
  373. if(x-1>xmin && y-1>ymin) CHECK_MV(x-2, y-2)
  374. if(x-1>xmin && y+1<ymax) CHECK_MV(x-2, y+2)
  375. if(x+1<xmax && y-1>ymin) CHECK_MV(x+2, y-2)
  376. if(x+1<xmax && y+1<ymax) CHECK_MV(x+2, y+2)
  377. if(dmin==last_min) return dmin;
  378. }
  379. */
  380. }
  381. static inline int snake_search(MpegEncContext * s, int *best, int dmin,
  382. UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
  383. int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
  384. int xmin, int ymin, int xmax, int ymax, int shift)
  385. {
  386. int dir=0;
  387. int c=1;
  388. static int x_dir[8]= {1,1,0,-1,-1,-1, 0, 1};
  389. static int y_dir[8]= {0,1,1, 1, 0,-1,-1,-1};
  390. int fails=0;
  391. int last_d[2]={dmin, dmin};
  392. /*static int good=0;
  393. static int bad=0;
  394. static int point=0;
  395. point++;
  396. if(256*256*256*64%point==0)
  397. {
  398. printf("%d %d %d\n", good, bad, point);
  399. }*/
  400. for(;;){
  401. int x= best[0];
  402. int y= best[1];
  403. int d;
  404. x+=x_dir[dir];
  405. y+=y_dir[dir];
  406. if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){
  407. d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);
  408. d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;
  409. }else{
  410. d = dmin + 10000; //FIXME smarter boundary handling
  411. }
  412. if(d<dmin){
  413. best[0]=x;
  414. best[1]=y;
  415. dmin=d;
  416. if(last_d[1] - last_d[0] > last_d[0] - d) c= -c;
  417. dir+=c;
  418. fails=0;
  419. //good++;
  420. last_d[1]=last_d[0];
  421. last_d[0]=d;
  422. }else{
  423. //bad++;
  424. if(fails){
  425. if(fails>=3) return dmin;
  426. }else{
  427. c= -c;
  428. }
  429. dir+=c*2;
  430. fails++;
  431. }
  432. dir&=7;
  433. }
  434. }
  435. static int epzs_motion_search(MpegEncContext * s,
  436. int *mx_ptr, int *my_ptr,
  437. int P[5][2], int pred_x, int pred_y,
  438. int xmin, int ymin, int xmax, int ymax)
  439. {
  440. int best[2]={0, 0};
  441. int d, dmin;
  442. UINT8 *new_pic, *old_pic;
  443. const int pic_stride= s->linesize;
  444. const int pic_xy= (s->mb_y*pic_stride + s->mb_x)*16;
  445. UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
  446. int quant= s->qscale; // qscale of the prev frame
  447. const int shift= 1+s->quarter_sample;
  448. new_pic = s->new_picture[0] + pic_xy;
  449. old_pic = s->last_picture[0] + pic_xy;
  450. dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16);
  451. if(dmin<Z_THRESHOLD){
  452. *mx_ptr= 0;
  453. *my_ptr= 0;
  454. //printf("Z");
  455. return dmin;
  456. }
  457. /* first line */
  458. if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
  459. CHECK_MV(P[1][0]>>shift, P[1][1]>>shift)
  460. }else{
  461. CHECK_MV(P[4][0]>>shift, P[4][1]>>shift)
  462. if(dmin<Z_THRESHOLD){
  463. *mx_ptr= P[4][0]>>shift;
  464. *my_ptr= P[4][1]>>shift;
  465. //printf("M\n");
  466. return dmin;
  467. }
  468. CHECK_MV(P[1][0]>>shift, P[1][1]>>shift)
  469. CHECK_MV(P[2][0]>>shift, P[2][1]>>shift)
  470. CHECK_MV(P[3][0]>>shift, P[3][1]>>shift)
  471. }
  472. CHECK_MV(P[0][0]>>shift, P[0][1]>>shift)
  473. //check(best[0],best[1],0, b0)
  474. if(s->full_search==ME_EPZS)
  475. dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride,
  476. pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);
  477. else
  478. dmin= snake_search(s, best, dmin, new_pic, old_pic, pic_stride,
  479. pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);
  480. //check(best[0],best[1],0, b1)
  481. *mx_ptr= best[0];
  482. *my_ptr= best[1];
  483. // printf("%d %d %d \n", best[0], best[1], dmin);
  484. return dmin;
  485. }
  486. #define CHECK_HALF_MV(suffix, x, y) \
  487. d= pix_abs16x16_ ## suffix(pix, ptr+((x)>>1), s->linesize, 16);\
  488. d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\
  489. if(d<dminh){\
  490. dminh= d;\
  491. mx= mx1 + x;\
  492. my= my1 + y;\
  493. }
  494. /* The idea would be to make half pel ME after Inter/Intra decision to
  495. save time. */
  496. static inline void halfpel_motion_search(MpegEncContext * s,
  497. int *mx_ptr, int *my_ptr, int dmin,
  498. int xmin, int ymin, int xmax, int ymax,
  499. int pred_x, int pred_y)
  500. {
  501. UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
  502. const int quant= s->qscale;
  503. int pen_x, pen_y;
  504. int mx, my, mx1, my1, d, xx, yy, dminh;
  505. UINT8 *pix, *ptr;
  506. mx = *mx_ptr;
  507. my = *my_ptr;
  508. ptr = s->last_picture[0] + (my * s->linesize) + mx;
  509. xx = 16 * s->mb_x;
  510. yy = 16 * s->mb_y;
  511. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  512. dminh = dmin;
  513. if (mx > xmin && mx < xmax &&
  514. my > ymin && my < ymax) {
  515. mx= mx1= 2*(mx - xx);
  516. my= my1= 2*(my - yy);
  517. if(dmin < Z_THRESHOLD && mx==0 && my==0){
  518. *mx_ptr = 0;
  519. *my_ptr = 0;
  520. return;
  521. }
  522. pen_x= pred_x + mx;
  523. pen_y= pred_y + my;
  524. ptr-= s->linesize;
  525. CHECK_HALF_MV(xy2, -1, -1)
  526. CHECK_HALF_MV(y2 , 0, -1)
  527. CHECK_HALF_MV(xy2, +1, -1)
  528. ptr+= s->linesize;
  529. CHECK_HALF_MV(x2 , -1, 0)
  530. CHECK_HALF_MV(x2 , +1, 0)
  531. CHECK_HALF_MV(xy2, -1, +1)
  532. CHECK_HALF_MV(y2 , 0, +1)
  533. CHECK_HALF_MV(xy2, +1, +1)
  534. }else{
  535. mx= 2*(mx - xx);
  536. my= 2*(my - yy);
  537. }
  538. *mx_ptr = mx;
  539. *my_ptr = my;
  540. }
  541. #ifndef CONFIG_TEST_MV_ENCODE
  542. int estimate_motion(MpegEncContext * s,
  543. int mb_x, int mb_y,
  544. int *mx_ptr, int *my_ptr)
  545. {
  546. UINT8 *pix, *ppix;
  547. int sum, varc, vard, mx, my, range, dmin, xx, yy;
  548. int xmin, ymin, xmax, ymax;
  549. int rel_xmin, rel_ymin, rel_xmax, rel_ymax;
  550. int pred_x=0, pred_y=0;
  551. int P[5][2];
  552. const int shift= 1+s->quarter_sample;
  553. range = 8 * (1 << (s->f_code - 1));
  554. /* XXX: temporary kludge to avoid overflow for msmpeg4 */
  555. if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
  556. range = range * 2;
  557. if (s->unrestricted_mv) {
  558. xmin = -16;
  559. ymin = -16;
  560. if (s->h263_plus)
  561. range *= 2;
  562. if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){
  563. xmax = s->mb_width*16;
  564. ymax = s->mb_height*16;
  565. }else {
  566. /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise
  567. (cuz the drawn edge isnt large enough))*/
  568. xmax = s->width;
  569. ymax = s->height;
  570. }
  571. } else {
  572. xmin = 0;
  573. ymin = 0;
  574. xmax = s->mb_width*16 - 16;
  575. ymax = s->mb_height*16 - 16;
  576. }
  577. switch(s->full_search) {
  578. case ME_ZERO:
  579. default:
  580. no_motion_search(s, &mx, &my);
  581. dmin = 0;
  582. break;
  583. case ME_FULL:
  584. dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax);
  585. break;
  586. case ME_LOG:
  587. dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
  588. break;
  589. case ME_PHODS:
  590. dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
  591. break;
  592. case ME_X1:
  593. case ME_EPZS:
  594. {
  595. static const int off[4]= {2, 1, 1, -1};
  596. const int mot_stride = s->mb_width*2 + 2;
  597. const int mot_xy = (s->mb_y*2 + 1)*mot_stride + s->mb_x*2 + 1;
  598. rel_xmin= xmin - s->mb_x*16;
  599. rel_xmax= xmax - s->mb_x*16;
  600. rel_ymin= ymin - s->mb_y*16;
  601. rel_ymax= ymax - s->mb_y*16;
  602. P[0][0] = s->motion_val[mot_xy ][0];
  603. P[0][1] = s->motion_val[mot_xy ][1];
  604. P[1][0] = s->motion_val[mot_xy - 1][0];
  605. P[1][1] = s->motion_val[mot_xy - 1][1];
  606. if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift);
  607. /* special case for first line */
  608. if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
  609. P[4][0] = P[1][0];
  610. P[4][1] = P[1][1];
  611. } else {
  612. P[2][0] = s->motion_val[mot_xy - mot_stride ][0];
  613. P[2][1] = s->motion_val[mot_xy - mot_stride ][1];
  614. P[3][0] = s->motion_val[mot_xy - mot_stride + off[0] ][0];
  615. P[3][1] = s->motion_val[mot_xy - mot_stride + off[0] ][1];
  616. if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift);
  617. if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift);
  618. if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift);
  619. P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]);
  620. P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]);
  621. }
  622. if(s->out_format == FMT_H263){
  623. pred_x = P[4][0];
  624. pred_y = P[4][1];
  625. }else { /* mpeg1 at least */
  626. pred_x= P[1][0];
  627. pred_y= P[1][1];
  628. }
  629. }
  630. dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax);
  631. mx+= s->mb_x*16;
  632. my+= s->mb_y*16;
  633. break;
  634. }
  635. /* intra / predictive decision */
  636. xx = mb_x * 16;
  637. yy = mb_y * 16;
  638. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  639. /* At this point (mx,my) are full-pell and the absolute displacement */
  640. ppix = s->last_picture[0] + (my * s->linesize) + mx;
  641. sum = pix_sum(pix, s->linesize);
  642. #if 0
  643. varc = pix_dev(pix, s->linesize, (sum+128)>>8) + INTER_BIAS;
  644. vard = pix_abs16x16(pix, ppix, s->linesize, 16);
  645. #else
  646. sum= (sum+8)>>4;
  647. varc = ((pix_norm1(pix, s->linesize) - sum*sum + 128 + 500)>>8);
  648. vard = (pix_norm(pix, ppix, s->linesize)+128)>>8;
  649. #endif
  650. s->mb_var[s->mb_width * mb_y + mb_x] = varc;
  651. s->avg_mb_var += varc;
  652. s->mc_mb_var += vard;
  653. #if 0
  654. printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
  655. varc, s->avg_mb_var, sum, vard, mx - xx, my - yy);
  656. #endif
  657. if (vard <= 64 || vard < varc) {
  658. if (s->full_search != ME_ZERO) {
  659. halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y);
  660. } else {
  661. mx -= 16 * s->mb_x;
  662. my -= 16 * s->mb_y;
  663. }
  664. // check(mx + 32*s->mb_x, my + 32*s->mb_y, 1, end)
  665. *mx_ptr = mx;
  666. *my_ptr = my;
  667. return 0;
  668. } else {
  669. *mx_ptr = 0;
  670. *my_ptr = 0;
  671. return 1;
  672. }
  673. }
  674. #else
  675. /* test version which generates valid random vectors */
  676. int estimate_motion(MpegEncContext * s,
  677. int mb_x, int mb_y,
  678. int *mx_ptr, int *my_ptr)
  679. {
  680. int xx, yy, x1, y1, x2, y2, range;
  681. if ((random() % 10) >= 5) {
  682. range = 8 * (1 << (s->f_code - 1));
  683. if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
  684. range = range * 2;
  685. xx = 16 * s->mb_x;
  686. yy = 16 * s->mb_y;
  687. x1 = xx - range;
  688. if (x1 < 0)
  689. x1 = 0;
  690. x2 = xx + range - 1;
  691. if (x2 > (s->width - 16))
  692. x2 = s->width - 16;
  693. y1 = yy - range;
  694. if (y1 < 0)
  695. y1 = 0;
  696. y2 = yy + range - 1;
  697. if (y2 > (s->height - 16))
  698. y2 = s->height - 16;
  699. *mx_ptr = (random() % (2 * (x2 - x1 + 1))) + 2 * (x1 - xx);
  700. *my_ptr = (random() % (2 * (y2 - y1 + 1))) + 2 * (y1 - yy);
  701. return 0;
  702. } else {
  703. *mx_ptr = 0;
  704. *my_ptr = 0;
  705. return 1;
  706. }
  707. }
  708. #endif