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.

1728 lines
56KB

  1. /*
  2. * Motion estimation
  3. * Copyright (c) 2000,2001 Fabrice Bellard.
  4. * Copyright (c) 2002 Michael Niedermayer
  5. *
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. * new Motion Estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>
  22. */
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include "avcodec.h"
  26. #include "dsputil.h"
  27. #include "mpegvideo.h"
  28. #define SQ(a) ((a)*(a))
  29. #define INTER_BIAS 257
  30. #define P_LAST P[0]
  31. #define P_LEFT P[1]
  32. #define P_TOP P[2]
  33. #define P_TOPRIGHT P[3]
  34. #define P_MEDIAN P[4]
  35. #define P_LAST_LEFT P[5]
  36. #define P_LAST_RIGHT P[6]
  37. #define P_LAST_TOP P[7]
  38. #define P_LAST_BOTTOM P[8]
  39. #define P_MV1 P[9]
  40. static int pix_dev(UINT8 * pix, int line_size, int mean)
  41. {
  42. int s, i, j;
  43. s = 0;
  44. for (i = 0; i < 16; i++) {
  45. for (j = 0; j < 16; j += 8) {
  46. s += ABS(pix[0]-mean);
  47. s += ABS(pix[1]-mean);
  48. s += ABS(pix[2]-mean);
  49. s += ABS(pix[3]-mean);
  50. s += ABS(pix[4]-mean);
  51. s += ABS(pix[5]-mean);
  52. s += ABS(pix[6]-mean);
  53. s += ABS(pix[7]-mean);
  54. pix += 8;
  55. }
  56. pix += line_size - 16;
  57. }
  58. return s;
  59. }
  60. static int pix_norm(UINT8 * pix1, UINT8 * pix2, int line_size)
  61. {
  62. int s, i, j;
  63. UINT32 *sq = squareTbl + 256;
  64. s = 0;
  65. for (i = 0; i < 16; i++) {
  66. for (j = 0; j < 16; j += 8) {
  67. s += sq[pix1[0] - pix2[0]];
  68. s += sq[pix1[1] - pix2[1]];
  69. s += sq[pix1[2] - pix2[2]];
  70. s += sq[pix1[3] - pix2[3]];
  71. s += sq[pix1[4] - pix2[4]];
  72. s += sq[pix1[5] - pix2[5]];
  73. s += sq[pix1[6] - pix2[6]];
  74. s += sq[pix1[7] - pix2[7]];
  75. pix1 += 8;
  76. pix2 += 8;
  77. }
  78. pix1 += line_size - 16;
  79. pix2 += line_size - 16;
  80. }
  81. return s;
  82. }
  83. static void no_motion_search(MpegEncContext * s,
  84. int *mx_ptr, int *my_ptr)
  85. {
  86. *mx_ptr = 16 * s->mb_x;
  87. *my_ptr = 16 * s->mb_y;
  88. }
  89. static int full_motion_search(MpegEncContext * s,
  90. int *mx_ptr, int *my_ptr, int range,
  91. int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
  92. {
  93. int x1, y1, x2, y2, xx, yy, x, y;
  94. int mx, my, dmin, d;
  95. UINT8 *pix;
  96. xx = 16 * s->mb_x;
  97. yy = 16 * s->mb_y;
  98. x1 = xx - range + 1; /* we loose one pixel to avoid boundary pb with half pixel pred */
  99. if (x1 < xmin)
  100. x1 = xmin;
  101. x2 = xx + range - 1;
  102. if (x2 > xmax)
  103. x2 = xmax;
  104. y1 = yy - range + 1;
  105. if (y1 < ymin)
  106. y1 = ymin;
  107. y2 = yy + range - 1;
  108. if (y2 > ymax)
  109. y2 = ymax;
  110. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  111. dmin = 0x7fffffff;
  112. mx = 0;
  113. my = 0;
  114. for (y = y1; y <= y2; y++) {
  115. for (x = x1; x <= x2; x++) {
  116. d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x,
  117. s->linesize);
  118. if (d < dmin ||
  119. (d == dmin &&
  120. (abs(x - xx) + abs(y - yy)) <
  121. (abs(mx - xx) + abs(my - yy)))) {
  122. dmin = d;
  123. mx = x;
  124. my = y;
  125. }
  126. }
  127. }
  128. *mx_ptr = mx;
  129. *my_ptr = my;
  130. #if 0
  131. if (*mx_ptr < -(2 * range) || *mx_ptr >= (2 * range) ||
  132. *my_ptr < -(2 * range) || *my_ptr >= (2 * range)) {
  133. fprintf(stderr, "error %d %d\n", *mx_ptr, *my_ptr);
  134. }
  135. #endif
  136. return dmin;
  137. }
  138. static int log_motion_search(MpegEncContext * s,
  139. int *mx_ptr, int *my_ptr, int range,
  140. int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
  141. {
  142. int x1, y1, x2, y2, xx, yy, x, y;
  143. int mx, my, dmin, d;
  144. UINT8 *pix;
  145. xx = s->mb_x << 4;
  146. yy = s->mb_y << 4;
  147. /* Left limit */
  148. x1 = xx - range;
  149. if (x1 < xmin)
  150. x1 = xmin;
  151. /* Right limit */
  152. x2 = xx + range;
  153. if (x2 > xmax)
  154. x2 = xmax;
  155. /* Upper limit */
  156. y1 = yy - range;
  157. if (y1 < ymin)
  158. y1 = ymin;
  159. /* Lower limit */
  160. y2 = yy + range;
  161. if (y2 > ymax)
  162. y2 = ymax;
  163. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  164. dmin = 0x7fffffff;
  165. mx = 0;
  166. my = 0;
  167. do {
  168. for (y = y1; y <= y2; y += range) {
  169. for (x = x1; x <= x2; x += range) {
  170. d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, s->linesize);
  171. if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
  172. dmin = d;
  173. mx = x;
  174. my = y;
  175. }
  176. }
  177. }
  178. range = range >> 1;
  179. x1 = mx - range;
  180. if (x1 < xmin)
  181. x1 = xmin;
  182. x2 = mx + range;
  183. if (x2 > xmax)
  184. x2 = xmax;
  185. y1 = my - range;
  186. if (y1 < ymin)
  187. y1 = ymin;
  188. y2 = my + range;
  189. if (y2 > ymax)
  190. y2 = ymax;
  191. } while (range >= 1);
  192. #ifdef DEBUG
  193. fprintf(stderr, "log - MX: %d\tMY: %d\n", mx, my);
  194. #endif
  195. *mx_ptr = mx;
  196. *my_ptr = my;
  197. return dmin;
  198. }
  199. static int phods_motion_search(MpegEncContext * s,
  200. int *mx_ptr, int *my_ptr, int range,
  201. int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
  202. {
  203. int x1, y1, x2, y2, xx, yy, x, y, lastx, d;
  204. int mx, my, dminx, dminy;
  205. UINT8 *pix;
  206. xx = s->mb_x << 4;
  207. yy = s->mb_y << 4;
  208. /* Left limit */
  209. x1 = xx - range;
  210. if (x1 < xmin)
  211. x1 = xmin;
  212. /* Right limit */
  213. x2 = xx + range;
  214. if (x2 > xmax)
  215. x2 = xmax;
  216. /* Upper limit */
  217. y1 = yy - range;
  218. if (y1 < ymin)
  219. y1 = ymin;
  220. /* Lower limit */
  221. y2 = yy + range;
  222. if (y2 > ymax)
  223. y2 = ymax;
  224. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  225. mx = 0;
  226. my = 0;
  227. x = xx;
  228. y = yy;
  229. do {
  230. dminx = 0x7fffffff;
  231. dminy = 0x7fffffff;
  232. lastx = x;
  233. for (x = x1; x <= x2; x += range) {
  234. d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, s->linesize);
  235. if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
  236. dminx = d;
  237. mx = x;
  238. }
  239. }
  240. x = lastx;
  241. for (y = y1; y <= y2; y += range) {
  242. d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, s->linesize);
  243. if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
  244. dminy = d;
  245. my = y;
  246. }
  247. }
  248. range = range >> 1;
  249. x = mx;
  250. y = my;
  251. x1 = mx - range;
  252. if (x1 < xmin)
  253. x1 = xmin;
  254. x2 = mx + range;
  255. if (x2 > xmax)
  256. x2 = xmax;
  257. y1 = my - range;
  258. if (y1 < ymin)
  259. y1 = ymin;
  260. y2 = my + range;
  261. if (y2 > ymax)
  262. y2 = ymax;
  263. } while (range >= 1);
  264. #ifdef DEBUG
  265. fprintf(stderr, "phods - MX: %d\tMY: %d\n", mx, my);
  266. #endif
  267. /* half pixel search */
  268. *mx_ptr = mx;
  269. *my_ptr = my;
  270. return dminy;
  271. }
  272. #define Z_THRESHOLD 256
  273. #define CHECK_MV(x,y)\
  274. {\
  275. const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
  276. const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
  277. if(map[index]!=key){\
  278. d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\
  279. d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
  280. COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
  281. map[index]= key;\
  282. score_map[index]= d;\
  283. }\
  284. }
  285. #define CHECK_MV_DIR(x,y,new_dir)\
  286. {\
  287. const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
  288. const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
  289. if(map[index]!=key){\
  290. d = pix_abs(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\
  291. d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
  292. if(d<dmin){\
  293. best[0]=x;\
  294. best[1]=y;\
  295. dmin=d;\
  296. next_dir= new_dir;\
  297. }\
  298. map[index]= key;\
  299. score_map[index]= d;\
  300. }\
  301. }
  302. #define CHECK_MV4(x,y)\
  303. {\
  304. const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
  305. const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
  306. if(map[index]!=key){\
  307. d = pix_abs8x8(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\
  308. d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
  309. COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
  310. map[index]= key;\
  311. score_map[index]= d;\
  312. }\
  313. }
  314. #define check(x,y,S,v)\
  315. if( (x)<(xmin<<(S)) ) printf("%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\
  316. if( (x)>(xmax<<(S)) ) printf("%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\
  317. if( (y)<(ymin<<(S)) ) printf("%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\
  318. if( (y)>(ymax<<(S)) ) printf("%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\
  319. static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
  320. UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
  321. int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
  322. int xmin, int ymin, int xmax, int ymax, int shift,
  323. uint32_t *map, uint16_t *score_map, int map_generation,
  324. op_pixels_abs_func pix_abs)
  325. {
  326. int next_dir=-1;
  327. for(;;){
  328. int d;
  329. const int dir= next_dir;
  330. const int x= best[0];
  331. const int y= best[1];
  332. next_dir=-1;
  333. //printf("%d", dir);
  334. if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0)
  335. if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1)
  336. if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2)
  337. if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3)
  338. if(next_dir==-1){
  339. return dmin;
  340. }
  341. }
  342. /* for(;;){
  343. int d;
  344. const int x= best[0];
  345. const int y= best[1];
  346. const int last_min=dmin;
  347. if(x>xmin) CHECK_MV(x-1, y )
  348. if(y>xmin) CHECK_MV(x , y-1)
  349. if(x<xmax) CHECK_MV(x+1, y )
  350. if(y<xmax) CHECK_MV(x , y+1)
  351. if(x>xmin && y>ymin) CHECK_MV(x-1, y-1)
  352. if(x>xmin && y<ymax) CHECK_MV(x-1, y+1)
  353. if(x<xmax && y>ymin) CHECK_MV(x+1, y-1)
  354. if(x<xmax && y<ymax) CHECK_MV(x+1, y+1)
  355. if(x-1>xmin) CHECK_MV(x-2, y )
  356. if(y-1>xmin) CHECK_MV(x , y-2)
  357. if(x+1<xmax) CHECK_MV(x+2, y )
  358. if(y+1<xmax) CHECK_MV(x , y+2)
  359. if(x-1>xmin && y-1>ymin) CHECK_MV(x-2, y-2)
  360. if(x-1>xmin && y+1<ymax) CHECK_MV(x-2, y+2)
  361. if(x+1<xmax && y-1>ymin) CHECK_MV(x+2, y-2)
  362. if(x+1<xmax && y+1<ymax) CHECK_MV(x+2, y+2)
  363. if(dmin==last_min) return dmin;
  364. }
  365. */
  366. }
  367. #if 1
  368. #define SNAKE_1 3
  369. #define SNAKE_2 2
  370. #else
  371. #define SNAKE_1 7
  372. #define SNAKE_2 3
  373. #endif
  374. static inline int snake_search(MpegEncContext * s, int *best, int dmin,
  375. UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
  376. int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
  377. int xmin, int ymin, int xmax, int ymax, int shift,
  378. uint32_t *map, uint16_t *score_map,int map_generation,
  379. op_pixels_abs_func pix_abs)
  380. {
  381. int dir=0;
  382. int c=1;
  383. static int x_dir[8]= {1,1,0,-1,-1,-1, 0, 1};
  384. static int y_dir[8]= {0,1,1, 1, 0,-1,-1,-1};
  385. int fails=0;
  386. int last_d[2]={dmin, dmin};
  387. /*static int good=0;
  388. static int bad=0;
  389. static int point=0;
  390. point++;
  391. if(256*256*256*64%point==0)
  392. {
  393. printf("%d %d %d\n", good, bad, point);
  394. }*/
  395. for(;;){
  396. int x= best[0];
  397. int y= best[1];
  398. int d;
  399. x+=x_dir[dir];
  400. y+=y_dir[dir];
  401. if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){
  402. const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;
  403. const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);
  404. if(map[index]!=key){
  405. d = pix_abs(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);
  406. d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;
  407. map[index]=key;
  408. score_map[index]=d;
  409. }else
  410. d= dmin+1;
  411. }else{
  412. d = dmin + 10000; //FIXME smarter boundary handling
  413. }
  414. if(d<dmin){
  415. best[0]=x;
  416. best[1]=y;
  417. dmin=d;
  418. if(last_d[1] - last_d[0] > last_d[0] - d) c= -c;
  419. dir+=c;
  420. fails=0;
  421. //good++;
  422. last_d[1]=last_d[0];
  423. last_d[0]=d;
  424. }else{
  425. //bad++;
  426. if(fails){
  427. if(fails>=SNAKE_1+1) return dmin;
  428. }else{
  429. if(dir&1) dir-= c*3;
  430. else c= -c;
  431. // c= -c;
  432. }
  433. dir+=c*SNAKE_2;
  434. fails++;
  435. }
  436. dir&=7;
  437. }
  438. }
  439. static inline int cross_search(MpegEncContext * s, int *best, int dmin,
  440. UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
  441. int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
  442. int xmin, int ymin, int xmax, int ymax, int shift,
  443. uint32_t *map, uint16_t *score_map,int map_generation,
  444. op_pixels_abs_func pix_abs)
  445. {
  446. static int x_dir[4]= {-1, 0, 1, 0};
  447. static int y_dir[4]= { 0,-1, 0, 1};
  448. int improvement[2]={100000, 100000};
  449. int dirs[2]={2, 3};
  450. int dir;
  451. int last_dir= -1;
  452. for(;;){
  453. dir= dirs[ improvement[0] > improvement[1] ? 0 : 1 ];
  454. if(improvement[dir&1]==-1) return dmin;
  455. {
  456. const int x= best[0] + x_dir[dir];
  457. const int y= best[1] + y_dir[dir];
  458. const int key= (y<<ME_MAP_MV_BITS) + x + map_generation;
  459. const int index= ((y<<ME_MAP_SHIFT) + x)&(ME_MAP_SIZE-1);
  460. int d;
  461. if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){
  462. if(map[index]!=key){
  463. d = pix_abs(new_pic, old_pic + x + y*pic_stride, pic_stride);
  464. d += (mv_penalty[(x<<shift)-pred_x] + mv_penalty[(y<<shift)-pred_y])*quant;
  465. map[index]=key;
  466. score_map[index]=d;
  467. if(d<dmin){
  468. improvement[dir&1]= dmin-d;
  469. improvement[(dir&1)^1]++;
  470. dmin=d;
  471. best[0]= x;
  472. best[1]= y;
  473. last_dir=dir;
  474. continue;
  475. }
  476. }else{
  477. d= score_map[index];
  478. }
  479. }else{
  480. d= dmin + 1000; //FIXME is this a good idea?
  481. }
  482. /* evaluated point was cached or checked and worse */
  483. if(last_dir==dir){
  484. improvement[dir&1]= -1;
  485. }else{
  486. improvement[dir&1]= d-dmin;
  487. last_dir= dirs[dir&1]= dir^2;
  488. }
  489. }
  490. }
  491. }
  492. static inline int update_map_generation(MpegEncContext * s)
  493. {
  494. s->me_map_generation+= 1<<(ME_MAP_MV_BITS*2);
  495. if(s->me_map_generation==0){
  496. s->me_map_generation= 1<<(ME_MAP_MV_BITS*2);
  497. memset(s->me_map, 0, sizeof(uint32_t)*ME_MAP_SIZE);
  498. }
  499. return s->me_map_generation;
  500. }
  501. static int epzs_motion_search(MpegEncContext * s,
  502. int *mx_ptr, int *my_ptr,
  503. int P[10][2], int pred_x, int pred_y,
  504. int xmin, int ymin, int xmax, int ymax, uint8_t * ref_picture)
  505. {
  506. int best[2]={0, 0};
  507. int d, dmin;
  508. UINT8 *new_pic, *old_pic;
  509. const int pic_stride= s->linesize;
  510. const int pic_xy= (s->mb_y*pic_stride + s->mb_x)*16;
  511. UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
  512. int quant= s->qscale; // qscale of the prev frame
  513. const int shift= 1+s->quarter_sample;
  514. uint32_t *map= s->me_map;
  515. uint16_t *score_map= s->me_score_map;
  516. int map_generation;
  517. new_pic = s->new_picture[0] + pic_xy;
  518. old_pic = ref_picture + pic_xy;
  519. map_generation= update_map_generation(s);
  520. dmin = pix_abs16x16(new_pic, old_pic, pic_stride);
  521. map[0]= map_generation;
  522. score_map[0]= dmin;
  523. /* first line */
  524. if ((s->mb_y == 0 || s->first_slice_line)) {
  525. CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
  526. CHECK_MV(P_LAST[0]>>shift, P_LAST[1]>>shift)
  527. }else{
  528. if(dmin<256 && ( P_LEFT[0] |P_LEFT[1]
  529. |P_TOP[0] |P_TOP[1]
  530. |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){
  531. *mx_ptr= 0;
  532. *my_ptr= 0;
  533. s->skip_me=1;
  534. return dmin;
  535. }
  536. CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
  537. if(dmin>256*2){
  538. CHECK_MV(P_LAST[0] >>shift, P_LAST[1] >>shift)
  539. CHECK_MV(P_LEFT[0] >>shift, P_LEFT[1] >>shift)
  540. CHECK_MV(P_TOP[0] >>shift, P_TOP[1] >>shift)
  541. CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
  542. }
  543. }
  544. if(dmin>256*4){
  545. CHECK_MV(P_LAST_RIGHT[0] >>shift, P_LAST_RIGHT[1] >>shift)
  546. CHECK_MV(P_LAST_BOTTOM[0]>>shift, P_LAST_BOTTOM[1]>>shift)
  547. }
  548. #if 0 //doest only slow things down
  549. if(dmin>512*3){
  550. int step;
  551. dmin= score_map[0];
  552. best[0]= best[1]=0;
  553. for(step=128; step>0; step>>=1){
  554. const int step2= step;
  555. int y;
  556. for(y=-step2+best[1]; y<=step2+best[1]; y+=step){
  557. int x;
  558. if(y<ymin || y>ymax) continue;
  559. for(x=-step2+best[0]; x<=step2+best[0]; x+=step){
  560. if(x<xmin || x>xmax) continue;
  561. if(x==best[0] && y==best[1]) continue;
  562. CHECK_MV(x,y)
  563. }
  564. }
  565. }
  566. }
  567. #endif
  568. //check(best[0],best[1],0, b0)
  569. if(s->me_method==ME_EPZS)
  570. dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride,
  571. pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax,
  572. shift, map, score_map, map_generation, pix_abs16x16);
  573. else
  574. dmin= cross_search(s, best, dmin, new_pic, old_pic, pic_stride,
  575. pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax,
  576. shift, map, score_map, map_generation, pix_abs16x16);
  577. //check(best[0],best[1],0, b1)
  578. *mx_ptr= best[0];
  579. *my_ptr= best[1];
  580. // printf("%d %d %d \n", best[0], best[1], dmin);
  581. return dmin;
  582. }
  583. static int epzs_motion_search4(MpegEncContext * s, int block,
  584. int *mx_ptr, int *my_ptr,
  585. int P[10][2], int pred_x, int pred_y,
  586. int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
  587. {
  588. int best[2]={0, 0};
  589. int d, dmin;
  590. UINT8 *new_pic, *old_pic;
  591. const int pic_stride= s->linesize;
  592. const int pic_xy= ((s->mb_y*2 + (block>>1))*pic_stride + s->mb_x*2 + (block&1))*8;
  593. UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
  594. int quant= s->qscale; // qscale of the prev frame
  595. const int shift= 1+s->quarter_sample;
  596. uint32_t *map= s->me_map;
  597. uint16_t *score_map= s->me_score_map;
  598. int map_generation;
  599. new_pic = s->new_picture[0] + pic_xy;
  600. old_pic = ref_picture + pic_xy;
  601. map_generation= update_map_generation(s);
  602. dmin = 1000000;
  603. //printf("%d %d %d %d //",xmin, ymin, xmax, ymax);
  604. /* first line */
  605. if ((s->mb_y == 0 || s->first_slice_line) && block<2) {
  606. CHECK_MV4(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
  607. CHECK_MV4(P_LAST[0]>>shift, P_LAST[1]>>shift)
  608. CHECK_MV4(P_MV1[0]>>shift, P_MV1[1]>>shift)
  609. }else{
  610. CHECK_MV4(P_MV1[0]>>shift, P_MV1[1]>>shift)
  611. //FIXME try some early stop
  612. if(dmin>64*2){
  613. CHECK_MV4(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
  614. CHECK_MV4(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
  615. CHECK_MV4(P_TOP[0]>>shift, P_TOP[1]>>shift)
  616. CHECK_MV4(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
  617. CHECK_MV4(P_LAST[0]>>shift, P_LAST[1]>>shift)
  618. }
  619. }
  620. if(dmin>64*4){
  621. CHECK_MV4(P_LAST_RIGHT[0]>>shift, P_LAST_RIGHT[1]>>shift)
  622. CHECK_MV4(P_LAST_BOTTOM[0]>>shift, P_LAST_BOTTOM[1]>>shift)
  623. }
  624. if(s->me_method==ME_EPZS)
  625. dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride,
  626. pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax,
  627. shift, map, score_map, map_generation, pix_abs8x8);
  628. else
  629. dmin= cross_search(s, best, dmin, new_pic, old_pic, pic_stride,
  630. pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax,
  631. shift, map, score_map, map_generation, pix_abs8x8);
  632. *mx_ptr= best[0];
  633. *my_ptr= best[1];
  634. // printf("%d %d %d \n", best[0], best[1], dmin);
  635. return dmin;
  636. }
  637. #define CHECK_HALF_MV(suffix, x, y) \
  638. {\
  639. d= pix_abs_ ## suffix(pix, ptr+((x)>>1), s->linesize);\
  640. d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\
  641. COPY3_IF_LT(dminh, d, dx, x, dy, y)\
  642. }
  643. /* The idea would be to make half pel ME after Inter/Intra decision to
  644. save time. */
  645. static inline int halfpel_motion_search(MpegEncContext * s,
  646. int *mx_ptr, int *my_ptr, int dmin,
  647. int xmin, int ymin, int xmax, int ymax,
  648. int pred_x, int pred_y, uint8_t *ref_picture,
  649. op_pixels_abs_func pix_abs_x2,
  650. op_pixels_abs_func pix_abs_y2, op_pixels_abs_func pix_abs_xy2, int n)
  651. {
  652. UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
  653. const int quant= s->qscale;
  654. int mx, my, xx, yy, dminh;
  655. UINT8 *pix, *ptr;
  656. if(s->skip_me){
  657. *mx_ptr = 0;
  658. *my_ptr = 0;
  659. return dmin;
  660. }else
  661. xx = 16 * s->mb_x + 8*(n&1);
  662. yy = 16 * s->mb_y + 8*(n>>1);
  663. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  664. mx = *mx_ptr;
  665. my = *my_ptr;
  666. ptr = ref_picture + ((yy + my) * s->linesize) + (xx + mx);
  667. dminh = dmin;
  668. if (mx > xmin && mx < xmax &&
  669. my > ymin && my < ymax) {
  670. int dx=0, dy=0;
  671. int d, pen_x, pen_y;
  672. mx<<=1;
  673. my<<=1;
  674. pen_x= pred_x + mx;
  675. pen_y= pred_y + my;
  676. ptr-= s->linesize;
  677. CHECK_HALF_MV(xy2, -1, -1)
  678. CHECK_HALF_MV(y2 , 0, -1)
  679. CHECK_HALF_MV(xy2, +1, -1)
  680. ptr+= s->linesize;
  681. CHECK_HALF_MV(x2 , -1, 0)
  682. CHECK_HALF_MV(x2 , +1, 0)
  683. CHECK_HALF_MV(xy2, -1, +1)
  684. CHECK_HALF_MV(y2 , 0, +1)
  685. CHECK_HALF_MV(xy2, +1, +1)
  686. mx+=dx;
  687. my+=dy;
  688. }else{
  689. mx<<=1;
  690. my<<=1;
  691. }
  692. *mx_ptr = mx;
  693. *my_ptr = my;
  694. return dminh;
  695. }
  696. static inline int fast_halfpel_motion_search(MpegEncContext * s,
  697. int *mx_ptr, int *my_ptr, int dmin,
  698. int xmin, int ymin, int xmax, int ymax,
  699. int pred_x, int pred_y, uint8_t *ref_picture,
  700. op_pixels_abs_func pix_abs_x2,
  701. op_pixels_abs_func pix_abs_y2, op_pixels_abs_func pix_abs_xy2, int n)
  702. {
  703. UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
  704. uint16_t *score_map= s->me_score_map;
  705. const int quant= s->qscale;
  706. int mx, my, xx, yy, dminh;
  707. UINT8 *pix, *ptr;
  708. if(s->skip_me){
  709. // printf("S");
  710. *mx_ptr = 0;
  711. *my_ptr = 0;
  712. return dmin;
  713. }
  714. // printf("N");
  715. xx = 16 * s->mb_x + 8*(n&1);
  716. yy = 16 * s->mb_y + 8*(n>>1);
  717. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  718. mx = *mx_ptr;
  719. my = *my_ptr;
  720. ptr = ref_picture + ((yy + my) * s->linesize) + (xx + mx);
  721. dminh = dmin;
  722. if (mx > xmin && mx < xmax &&
  723. my > ymin && my < ymax) {
  724. int dx=0, dy=0;
  725. int d, pen_x, pen_y;
  726. const int index= (my<<ME_MAP_SHIFT) + mx;
  727. const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
  728. const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)];
  729. const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)];
  730. const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
  731. mx<<=1;
  732. my<<=1;
  733. pen_x= pred_x + mx;
  734. pen_y= pred_y + my;
  735. ptr-= s->linesize;
  736. if(t<=b){
  737. CHECK_HALF_MV(y2 , 0, -1)
  738. if(l<=r){
  739. CHECK_HALF_MV(xy2, -1, -1)
  740. if(t+r<=b+l){
  741. CHECK_HALF_MV(xy2, +1, -1)
  742. ptr+= s->linesize;
  743. }else{
  744. ptr+= s->linesize;
  745. CHECK_HALF_MV(xy2, -1, +1)
  746. }
  747. CHECK_HALF_MV(x2 , -1, 0)
  748. }else{
  749. CHECK_HALF_MV(xy2, +1, -1)
  750. if(t+l<=b+r){
  751. CHECK_HALF_MV(xy2, -1, -1)
  752. ptr+= s->linesize;
  753. }else{
  754. ptr+= s->linesize;
  755. CHECK_HALF_MV(xy2, +1, +1)
  756. }
  757. CHECK_HALF_MV(x2 , +1, 0)
  758. }
  759. }else{
  760. if(l<=r){
  761. if(t+l<=b+r){
  762. CHECK_HALF_MV(xy2, -1, -1)
  763. ptr+= s->linesize;
  764. }else{
  765. ptr+= s->linesize;
  766. CHECK_HALF_MV(xy2, +1, +1)
  767. }
  768. CHECK_HALF_MV(x2 , -1, 0)
  769. CHECK_HALF_MV(xy2, -1, +1)
  770. }else{
  771. if(t+r<=b+l){
  772. CHECK_HALF_MV(xy2, +1, -1)
  773. ptr+= s->linesize;
  774. }else{
  775. ptr+= s->linesize;
  776. CHECK_HALF_MV(xy2, -1, +1)
  777. }
  778. CHECK_HALF_MV(x2 , +1, 0)
  779. CHECK_HALF_MV(xy2, +1, +1)
  780. }
  781. CHECK_HALF_MV(y2 , 0, +1)
  782. }
  783. mx+=dx;
  784. my+=dy;
  785. }else{
  786. mx<<=1;
  787. my<<=1;
  788. }
  789. *mx_ptr = mx;
  790. *my_ptr = my;
  791. return dminh;
  792. }
  793. static inline void set_p_mv_tables(MpegEncContext * s, int mx, int my, int mv4)
  794. {
  795. const int xy= s->mb_x + 1 + (s->mb_y + 1)*(s->mb_width + 2);
  796. s->p_mv_table[xy][0] = mx;
  797. s->p_mv_table[xy][1] = my;
  798. /* has allready been set to the 4 MV if 4MV is done */
  799. if(mv4){
  800. int mot_xy= s->block_index[0];
  801. s->motion_val[mot_xy ][0]= mx;
  802. s->motion_val[mot_xy ][1]= my;
  803. s->motion_val[mot_xy+1][0]= mx;
  804. s->motion_val[mot_xy+1][1]= my;
  805. mot_xy += s->block_wrap[0];
  806. s->motion_val[mot_xy ][0]= mx;
  807. s->motion_val[mot_xy ][1]= my;
  808. s->motion_val[mot_xy+1][0]= mx;
  809. s->motion_val[mot_xy+1][1]= my;
  810. }
  811. }
  812. static inline void get_limits(MpegEncContext *s, int *range, int *xmin, int *ymin, int *xmax, int *ymax, int f_code)
  813. {
  814. *range = 8 * (1 << (f_code - 1));
  815. /* XXX: temporary kludge to avoid overflow for msmpeg4 */
  816. if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
  817. *range *= 2;
  818. if (s->unrestricted_mv) {
  819. *xmin = -16;
  820. *ymin = -16;
  821. if (s->h263_plus)
  822. *range *= 2;
  823. if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){
  824. *xmax = s->mb_width*16;
  825. *ymax = s->mb_height*16;
  826. }else {
  827. /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise
  828. (cuz the drawn edge isnt large enough))*/
  829. *xmax = s->width;
  830. *ymax = s->height;
  831. }
  832. } else {
  833. *xmin = 0;
  834. *ymin = 0;
  835. *xmax = s->mb_width*16 - 16;
  836. *ymax = s->mb_height*16 - 16;
  837. }
  838. }
  839. static inline int mv4_search(MpegEncContext *s, int xmin, int ymin, int xmax, int ymax, int mx, int my, int shift)
  840. {
  841. int block;
  842. int P[10][2];
  843. uint8_t *ref_picture= s->last_picture[0];
  844. int dmin_sum=0;
  845. for(block=0; block<4; block++){
  846. int mx4, my4;
  847. int pred_x4, pred_y4;
  848. int dmin4;
  849. static const int off[4]= {2, 1, 1, -1};
  850. const int mot_stride = s->block_wrap[0];
  851. const int mot_xy = s->block_index[block];
  852. // const int block_x= (block&1);
  853. // const int block_y= (block>>1);
  854. #if 1 // this saves us a bit of cliping work and shouldnt affect compression in a negative way
  855. const int rel_xmin4= xmin;
  856. const int rel_xmax4= xmax;
  857. const int rel_ymin4= ymin;
  858. const int rel_ymax4= ymax;
  859. #else
  860. const int rel_xmin4= xmin - block_x*8;
  861. const int rel_xmax4= xmax - block_x*8 + 8;
  862. const int rel_ymin4= ymin - block_y*8;
  863. const int rel_ymax4= ymax - block_y*8 + 8;
  864. #endif
  865. P_LAST[0] = s->motion_val[mot_xy ][0];
  866. P_LAST[1] = s->motion_val[mot_xy ][1];
  867. P_LEFT[0] = s->motion_val[mot_xy - 1][0];
  868. P_LEFT[1] = s->motion_val[mot_xy - 1][1];
  869. P_LAST_RIGHT[0] = s->motion_val[mot_xy + 1][0];
  870. P_LAST_RIGHT[1] = s->motion_val[mot_xy + 1][1];
  871. P_LAST_BOTTOM[0]= s->motion_val[mot_xy + 1*mot_stride][0];
  872. P_LAST_BOTTOM[1]= s->motion_val[mot_xy + 1*mot_stride][1];
  873. if(P_LEFT[0] > (rel_xmax4<<shift)) P_LEFT[0] = (rel_xmax4<<shift);
  874. if(P_LAST_RIGHT[0] < (rel_xmin4<<shift)) P_LAST_RIGHT[0] = (rel_xmin4<<shift);
  875. if(P_LAST_BOTTOM[1]< (rel_ymin4<<shift)) P_LAST_BOTTOM[1]= (rel_ymin4<<shift);
  876. /* special case for first line */
  877. if ((s->mb_y == 0 || s->first_slice_line) && block<2) {
  878. pred_x4= P_LEFT[0];
  879. pred_y4= P_LEFT[1];
  880. } else {
  881. P_TOP[0] = s->motion_val[mot_xy - mot_stride ][0];
  882. P_TOP[1] = s->motion_val[mot_xy - mot_stride ][1];
  883. P_TOPRIGHT[0] = s->motion_val[mot_xy - mot_stride + off[block]][0];
  884. P_TOPRIGHT[1] = s->motion_val[mot_xy - mot_stride + off[block]][1];
  885. if(P_TOP[1] > (rel_ymax4<<shift)) P_TOP[1] = (rel_ymax4<<shift);
  886. if(P_TOPRIGHT[0] < (rel_xmin4<<shift)) P_TOPRIGHT[0]= (rel_xmin4<<shift);
  887. if(P_TOPRIGHT[0] > (rel_xmax4<<shift)) P_TOPRIGHT[0]= (rel_xmax4<<shift);
  888. if(P_TOPRIGHT[1] > (rel_ymax4<<shift)) P_TOPRIGHT[1]= (rel_ymax4<<shift);
  889. P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
  890. P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
  891. if(s->out_format == FMT_H263){
  892. pred_x4 = P_MEDIAN[0];
  893. pred_y4 = P_MEDIAN[1];
  894. }else { /* mpeg1 at least */
  895. pred_x4= P_LEFT[0];
  896. pred_y4= P_LEFT[1];
  897. }
  898. }
  899. P_MV1[0]= mx;
  900. P_MV1[1]= my;
  901. dmin4 = epzs_motion_search4(s, block, &mx4, &my4, P, pred_x4, pred_y4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, ref_picture);
  902. dmin4= fast_halfpel_motion_search(s, &mx4, &my4, dmin4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4,
  903. pred_x4, pred_y4, ref_picture, pix_abs8x8_x2,
  904. pix_abs8x8_y2, pix_abs8x8_xy2, block);
  905. s->motion_val[ s->block_index[block] ][0]= mx4;
  906. s->motion_val[ s->block_index[block] ][1]= my4;
  907. dmin_sum+= dmin4;
  908. }
  909. return dmin_sum;
  910. }
  911. void ff_estimate_p_frame_motion(MpegEncContext * s,
  912. int mb_x, int mb_y)
  913. {
  914. UINT8 *pix, *ppix;
  915. int sum, varc, vard, mx, my, range, dmin, xx, yy;
  916. int xmin, ymin, xmax, ymax;
  917. int rel_xmin, rel_ymin, rel_xmax, rel_ymax;
  918. int pred_x=0, pred_y=0;
  919. int P[10][2];
  920. const int shift= 1+s->quarter_sample;
  921. int mb_type=0;
  922. uint8_t *ref_picture= s->last_picture[0];
  923. get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, s->f_code);
  924. rel_xmin= xmin - mb_x*16;
  925. rel_xmax= xmax - mb_x*16;
  926. rel_ymin= ymin - mb_y*16;
  927. rel_ymax= ymax - mb_y*16;
  928. s->skip_me=0;
  929. switch(s->me_method) {
  930. case ME_ZERO:
  931. default:
  932. no_motion_search(s, &mx, &my);
  933. mx-= mb_x*16;
  934. my-= mb_y*16;
  935. dmin = 0;
  936. break;
  937. case ME_FULL:
  938. dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax, ref_picture);
  939. mx-= mb_x*16;
  940. my-= mb_y*16;
  941. break;
  942. case ME_LOG:
  943. dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture);
  944. mx-= mb_x*16;
  945. my-= mb_y*16;
  946. break;
  947. case ME_PHODS:
  948. dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture);
  949. mx-= mb_x*16;
  950. my-= mb_y*16;
  951. break;
  952. case ME_X1:
  953. case ME_EPZS:
  954. {
  955. const int mot_stride = s->block_wrap[0];
  956. const int mot_xy = s->block_index[0];
  957. P_LAST[0] = s->motion_val[mot_xy ][0];
  958. P_LAST[1] = s->motion_val[mot_xy ][1];
  959. P_LEFT[0] = s->motion_val[mot_xy - 1][0];
  960. P_LEFT[1] = s->motion_val[mot_xy - 1][1];
  961. P_LAST_RIGHT[0] = s->motion_val[mot_xy + 2][0];
  962. P_LAST_RIGHT[1] = s->motion_val[mot_xy + 2][1];
  963. P_LAST_BOTTOM[0]= s->motion_val[mot_xy + 2*mot_stride][0];
  964. P_LAST_BOTTOM[1]= s->motion_val[mot_xy + 2*mot_stride][1];
  965. if(P_LEFT[0] > (rel_xmax<<shift)) P_LEFT[0] = (rel_xmax<<shift);
  966. if(P_LAST_RIGHT[0] < (rel_xmin<<shift)) P_LAST_RIGHT[0] = (rel_xmin<<shift);
  967. if(P_LAST_BOTTOM[1]< (rel_ymin<<shift)) P_LAST_BOTTOM[1]= (rel_ymin<<shift);
  968. /* special case for first line */
  969. if ((mb_y == 0 || s->first_slice_line)) {
  970. pred_x= P_LEFT[0];
  971. pred_y= P_LEFT[1];
  972. } else {
  973. P_TOP[0] = s->motion_val[mot_xy - mot_stride ][0];
  974. P_TOP[1] = s->motion_val[mot_xy - mot_stride ][1];
  975. P_TOPRIGHT[0] = s->motion_val[mot_xy - mot_stride + 2][0];
  976. P_TOPRIGHT[1] = s->motion_val[mot_xy - mot_stride + 2][1];
  977. if(P_TOP[1] > (rel_ymax<<shift)) P_TOP[1] = (rel_ymax<<shift);
  978. if(P_TOPRIGHT[0] < (rel_xmin<<shift)) P_TOPRIGHT[0]= (rel_xmin<<shift);
  979. if(P_TOPRIGHT[1] > (rel_ymax<<shift)) P_TOPRIGHT[1]= (rel_ymax<<shift);
  980. P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
  981. P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
  982. if(s->out_format == FMT_H263){
  983. pred_x = P_MEDIAN[0];
  984. pred_y = P_MEDIAN[1];
  985. }else { /* mpeg1 at least */
  986. pred_x= P_LEFT[0];
  987. pred_y= P_LEFT[1];
  988. }
  989. }
  990. }
  991. dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax, ref_picture);
  992. break;
  993. }
  994. /* intra / predictive decision */
  995. xx = mb_x * 16;
  996. yy = mb_y * 16;
  997. pix = s->new_picture[0] + (yy * s->linesize) + xx;
  998. /* At this point (mx,my) are full-pell and the relative displacement */
  999. ppix = ref_picture + ((yy+my) * s->linesize) + (xx+mx);
  1000. sum = pix_sum(pix, s->linesize);
  1001. sum= (sum+8)>>4;
  1002. varc = (pix_norm1(pix, s->linesize) - sum*sum + 500 + 128)>>8;
  1003. vard = (pix_norm(pix, ppix, s->linesize)+128)>>8;
  1004. //printf("%d %d %d %X %X %X\n", s->mb_width, mb_x, mb_y,(int)s, (int)s->mb_var, (int)s->mc_mb_var); fflush(stdout);
  1005. s->mb_var [s->mb_width * mb_y + mb_x] = varc;
  1006. s->mc_mb_var[s->mb_width * mb_y + mb_x] = vard;
  1007. s->mb_mean [s->mb_width * mb_y + mb_x] = (sum+7)>>4;
  1008. s->mb_var_sum += varc;
  1009. s->mc_mb_var_sum += vard;
  1010. //printf("E%d %d %d %X %X %X\n", s->mb_width, mb_x, mb_y,(int)s, (int)s->mb_var, (int)s->mc_mb_var); fflush(stdout);
  1011. #if 0
  1012. printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
  1013. varc, s->avg_mb_var, sum, vard, mx - xx, my - yy);
  1014. #endif
  1015. if(s->flags&CODEC_FLAG_HQ){
  1016. if (vard <= 64 || vard < varc)
  1017. s->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
  1018. else
  1019. s->scene_change_score+= 20;
  1020. if (vard*2 + 200 > varc)
  1021. mb_type|= MB_TYPE_INTRA;
  1022. if (varc*2 + 200 > vard){
  1023. mb_type|= MB_TYPE_INTER;
  1024. if(s->me_method >= ME_EPZS)
  1025. fast_halfpel_motion_search(s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax,
  1026. pred_x, pred_y, ref_picture, pix_abs16x16_x2, pix_abs16x16_y2,
  1027. pix_abs16x16_xy2, 0);
  1028. else
  1029. halfpel_motion_search( s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax,
  1030. pred_x, pred_y, ref_picture, pix_abs16x16_x2, pix_abs16x16_y2,
  1031. pix_abs16x16_xy2, 0);
  1032. }else{
  1033. mx <<=1;
  1034. my <<=1;
  1035. }
  1036. if((s->flags&CODEC_FLAG_4MV)
  1037. && !s->skip_me && varc>50 && vard>10){
  1038. mv4_search(s, rel_xmin, rel_ymin, rel_xmax, rel_ymax, mx, my, shift);
  1039. mb_type|=MB_TYPE_INTER4V;
  1040. set_p_mv_tables(s, mx, my, 0);
  1041. }else
  1042. set_p_mv_tables(s, mx, my, 1);
  1043. }else{
  1044. if (vard <= 64 || vard < varc) {
  1045. s->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
  1046. mb_type|= MB_TYPE_INTER;
  1047. if (s->me_method != ME_ZERO) {
  1048. if(s->me_method >= ME_EPZS)
  1049. dmin= fast_halfpel_motion_search(s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax,
  1050. pred_x, pred_y, ref_picture, pix_abs16x16_x2, pix_abs16x16_y2,
  1051. pix_abs16x16_xy2, 0);
  1052. else
  1053. dmin= halfpel_motion_search(s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax,
  1054. pred_x, pred_y, ref_picture, pix_abs16x16_x2, pix_abs16x16_y2,
  1055. pix_abs16x16_xy2, 0);
  1056. if((s->flags&CODEC_FLAG_4MV)
  1057. && !s->skip_me && varc>50 && vard>10){
  1058. int dmin4= mv4_search(s, rel_xmin, rel_ymin, rel_xmax, rel_ymax, mx, my, shift);
  1059. if(dmin4 + 128 <dmin)
  1060. mb_type= MB_TYPE_INTER4V;
  1061. }
  1062. set_p_mv_tables(s, mx, my, mb_type!=MB_TYPE_INTER4V);
  1063. } else {
  1064. mx <<=1;
  1065. my <<=1;
  1066. }
  1067. #if 0
  1068. if (vard < 10) {
  1069. skip++;
  1070. fprintf(stderr,"\nEarly skip: %d vard: %2d varc: %5d dmin: %d",
  1071. skip, vard, varc, dmin);
  1072. }
  1073. #endif
  1074. }else{
  1075. s->scene_change_score+= 20;
  1076. mb_type|= MB_TYPE_INTRA;
  1077. mx = 0;
  1078. my = 0;
  1079. }
  1080. }
  1081. s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
  1082. }
  1083. int ff_estimate_motion_b(MpegEncContext * s,
  1084. int mb_x, int mb_y, int16_t (*mv_table)[2], uint8_t *ref_picture, int f_code)
  1085. {
  1086. int mx, my, range, dmin;
  1087. int xmin, ymin, xmax, ymax;
  1088. int rel_xmin, rel_ymin, rel_xmax, rel_ymax;
  1089. int pred_x=0, pred_y=0;
  1090. int P[10][2];
  1091. const int shift= 1+s->quarter_sample;
  1092. const int mot_stride = s->mb_width + 2;
  1093. const int mot_xy = (mb_y + 1)*mot_stride + mb_x + 1;
  1094. get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, f_code);
  1095. rel_xmin= xmin - mb_x*16;
  1096. rel_xmax= xmax - mb_x*16;
  1097. rel_ymin= ymin - mb_y*16;
  1098. rel_ymax= ymax - mb_y*16;
  1099. switch(s->me_method) {
  1100. case ME_ZERO:
  1101. default:
  1102. no_motion_search(s, &mx, &my);
  1103. dmin = 0;
  1104. mx-= mb_x*16;
  1105. my-= mb_y*16;
  1106. break;
  1107. case ME_FULL:
  1108. dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax, ref_picture);
  1109. mx-= mb_x*16;
  1110. my-= mb_y*16;
  1111. break;
  1112. case ME_LOG:
  1113. dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture);
  1114. mx-= mb_x*16;
  1115. my-= mb_y*16;
  1116. break;
  1117. case ME_PHODS:
  1118. dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture);
  1119. mx-= mb_x*16;
  1120. my-= mb_y*16;
  1121. break;
  1122. case ME_X1:
  1123. case ME_EPZS:
  1124. {
  1125. P_LAST[0] = mv_table[mot_xy ][0];
  1126. P_LAST[1] = mv_table[mot_xy ][1];
  1127. P_LEFT[0] = mv_table[mot_xy - 1][0];
  1128. P_LEFT[1] = mv_table[mot_xy - 1][1];
  1129. P_LAST_RIGHT[0] = mv_table[mot_xy + 1][0];
  1130. P_LAST_RIGHT[1] = mv_table[mot_xy + 1][1];
  1131. P_LAST_BOTTOM[0] = mv_table[mot_xy + mot_stride][0];
  1132. P_LAST_BOTTOM[1] = mv_table[mot_xy + mot_stride][1];
  1133. if(P_LEFT[0] > (rel_xmax<<shift)) P_LEFT[0] = (rel_xmax<<shift);
  1134. if(P_LAST_RIGHT[0] < (rel_xmin<<shift)) P_LAST_RIGHT[0] = (rel_xmin<<shift);
  1135. if(P_LAST_BOTTOM[1]< (rel_ymin<<shift)) P_LAST_BOTTOM[1]= (rel_ymin<<shift);
  1136. /* special case for first line */
  1137. if ((mb_y == 0 || s->first_slice_line)) {
  1138. } else {
  1139. P_TOP[0] = mv_table[mot_xy - mot_stride ][0];
  1140. P_TOP[1] = mv_table[mot_xy - mot_stride ][1];
  1141. P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1 ][0];
  1142. P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1 ][1];
  1143. if(P_TOP[1] > (rel_ymax<<shift)) P_TOP[1]= (rel_ymax<<shift);
  1144. if(P_TOPRIGHT[0] < (rel_xmin<<shift)) P_TOPRIGHT[0]= (rel_xmin<<shift);
  1145. if(P_TOPRIGHT[1] > (rel_ymax<<shift)) P_TOPRIGHT[1]= (rel_ymax<<shift);
  1146. P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
  1147. P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
  1148. }
  1149. pred_x= P_LEFT[0];
  1150. pred_y= P_LEFT[1];
  1151. }
  1152. dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax, ref_picture);
  1153. break;
  1154. }
  1155. dmin= fast_halfpel_motion_search(s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax,
  1156. pred_x, pred_y, ref_picture, pix_abs16x16_x2, pix_abs16x16_y2,
  1157. pix_abs16x16_xy2, 0);
  1158. //printf("%d %d %d %d//", s->mb_x, s->mb_y, mx, my);
  1159. // s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
  1160. mv_table[mot_xy][0]= mx;
  1161. mv_table[mot_xy][1]= my;
  1162. return dmin;
  1163. }
  1164. static inline int check_bidir_mv(MpegEncContext * s,
  1165. int mb_x, int mb_y,
  1166. int motion_fx, int motion_fy,
  1167. int motion_bx, int motion_by,
  1168. int pred_fx, int pred_fy,
  1169. int pred_bx, int pred_by)
  1170. {
  1171. //FIXME optimize?
  1172. //FIXME direct mode penalty
  1173. UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
  1174. uint8_t *dest_y = s->me_scratchpad;
  1175. uint8_t *ptr;
  1176. int dxy;
  1177. int src_x, src_y;
  1178. int fbmin;
  1179. fbmin = (mv_penalty[motion_fx-pred_fx] + mv_penalty[motion_fy-pred_fy])*s->qscale;
  1180. dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
  1181. src_x = mb_x * 16 + (motion_fx >> 1);
  1182. src_y = mb_y * 16 + (motion_fy >> 1);
  1183. src_x = clip(src_x, -16, s->width);
  1184. if (src_x == s->width)
  1185. dxy&= 2;
  1186. src_y = clip(src_y, -16, s->height);
  1187. if (src_y == s->height)
  1188. dxy&= 1;
  1189. ptr = s->last_picture[0] + (src_y * s->linesize) + src_x;
  1190. put_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16);
  1191. fbmin += (mv_penalty[motion_bx-pred_bx] + mv_penalty[motion_by-pred_by])*s->qscale;
  1192. dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
  1193. src_x = mb_x * 16 + (motion_bx >> 1);
  1194. src_y = mb_y * 16 + (motion_by >> 1);
  1195. src_x = clip(src_x, -16, s->width);
  1196. if (src_x == s->width)
  1197. dxy&= 2;
  1198. src_y = clip(src_y, -16, s->height);
  1199. if (src_y == s->height)
  1200. dxy&= 1;
  1201. ptr = s->next_picture[0] + (src_y * s->linesize) + src_x;
  1202. avg_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16);
  1203. fbmin += pix_abs16x16(s->new_picture[0] + mb_x*16 + mb_y*16*s->linesize, dest_y, s->linesize);
  1204. return fbmin;
  1205. }
  1206. /* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
  1207. static inline int bidir_refine(MpegEncContext * s,
  1208. int mb_x, int mb_y)
  1209. {
  1210. const int mot_stride = s->mb_width + 2;
  1211. const int xy = (mb_y + 1)*mot_stride + mb_x + 1;
  1212. int fbmin;
  1213. int pred_fx= s->b_bidir_forw_mv_table[xy-1][0];
  1214. int pred_fy= s->b_bidir_forw_mv_table[xy-1][1];
  1215. int pred_bx= s->b_bidir_back_mv_table[xy-1][0];
  1216. int pred_by= s->b_bidir_back_mv_table[xy-1][1];
  1217. int motion_fx= s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0];
  1218. int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1];
  1219. int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0];
  1220. int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1];
  1221. //FIXME do refinement and add flag
  1222. fbmin= check_bidir_mv(s, mb_x, mb_y,
  1223. motion_fx, motion_fy,
  1224. motion_bx, motion_by,
  1225. pred_fx, pred_fy,
  1226. pred_bx, pred_by);
  1227. return fbmin;
  1228. }
  1229. static inline int direct_search(MpegEncContext * s,
  1230. int mb_x, int mb_y)
  1231. {
  1232. int P[10][2];
  1233. const int mot_stride = s->mb_width + 2;
  1234. const int mot_xy = (mb_y + 1)*mot_stride + mb_x + 1;
  1235. int dmin, dmin2;
  1236. int motion_fx, motion_fy, motion_bx, motion_by, motion_bx0, motion_by0;
  1237. int motion_dx, motion_dy;
  1238. const int motion_px= s->p_mv_table[mot_xy][0];
  1239. const int motion_py= s->p_mv_table[mot_xy][1];
  1240. const int time_pp= s->pp_time;
  1241. const int time_pb= s->pb_time;
  1242. const int time_bp= time_pp - time_pb;
  1243. int bx, by;
  1244. int mx, my, mx2, my2;
  1245. uint8_t *ref_picture= s->me_scratchpad - (mb_x - 1 + (mb_y - 1)*s->linesize)*16;
  1246. int16_t (*mv_table)[2]= s->b_direct_mv_table;
  1247. /* uint16_t *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; */ // f_code of the prev frame
  1248. /* thanks to iso-mpeg the rounding is different for the zero vector, so we need to handle that ... */
  1249. motion_fx= (motion_px*time_pb)/time_pp;
  1250. motion_fy= (motion_py*time_pb)/time_pp;
  1251. motion_bx0= (-motion_px*time_bp)/time_pp;
  1252. motion_by0= (-motion_py*time_bp)/time_pp;
  1253. motion_dx= motion_dy=0;
  1254. dmin2= check_bidir_mv(s, mb_x, mb_y,
  1255. motion_fx, motion_fy,
  1256. motion_bx0, motion_by0,
  1257. motion_fx, motion_fy,
  1258. motion_bx0, motion_by0) - s->qscale;
  1259. motion_bx= motion_fx - motion_px;
  1260. motion_by= motion_fy - motion_py;
  1261. for(by=-1; by<2; by++){
  1262. for(bx=-1; bx<2; bx++){
  1263. uint8_t *dest_y = s->me_scratchpad + (by+1)*s->linesize*16 + (bx+1)*16;
  1264. uint8_t *ptr;
  1265. int dxy;
  1266. int src_x, src_y;
  1267. const int width= s->width;
  1268. const int height= s->height;
  1269. dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
  1270. src_x = (mb_x + bx) * 16 + (motion_fx >> 1);
  1271. src_y = (mb_y + by) * 16 + (motion_fy >> 1);
  1272. src_x = clip(src_x, -16, width);
  1273. if (src_x == width) dxy &= ~1;
  1274. src_y = clip(src_y, -16, height);
  1275. if (src_y == height) dxy &= ~2;
  1276. ptr = s->last_picture[0] + (src_y * s->linesize) + src_x;
  1277. put_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16);
  1278. dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
  1279. src_x = (mb_x + bx) * 16 + (motion_bx >> 1);
  1280. src_y = (mb_y + by) * 16 + (motion_by >> 1);
  1281. src_x = clip(src_x, -16, width);
  1282. if (src_x == width) dxy &= ~1;
  1283. src_y = clip(src_y, -16, height);
  1284. if (src_y == height) dxy &= ~2;
  1285. avg_pixels_tab[0][dxy](dest_y , ptr , s->linesize, 16);
  1286. }
  1287. }
  1288. P_LAST[0] = mv_table[mot_xy ][0];
  1289. P_LAST[1] = mv_table[mot_xy ][1];
  1290. P_LEFT[0] = mv_table[mot_xy - 1][0];
  1291. P_LEFT[1] = mv_table[mot_xy - 1][1];
  1292. P_LAST_RIGHT[0] = mv_table[mot_xy + 1][0];
  1293. P_LAST_RIGHT[1] = mv_table[mot_xy + 1][1];
  1294. P_LAST_BOTTOM[0] = mv_table[mot_xy + mot_stride][0];
  1295. P_LAST_BOTTOM[1] = mv_table[mot_xy + mot_stride][1];
  1296. /*
  1297. if(P_LEFT[0] > (rel_xmax<<shift)) P_LEFT[0] = (rel_xmax<<shift);
  1298. if(P_LAST_RIGHT[0] < (rel_xmin<<shift)) P_LAST_RIGHT[0] = (rel_xmin<<shift);
  1299. if(P_LAST_BOTTOM[1]< (rel_ymin<<shift)) P_LAST_BOTTOM[1]= (rel_ymin<<shift);
  1300. */
  1301. /* special case for first line */
  1302. if ((mb_y == 0 || s->first_slice_line)) {
  1303. } else {
  1304. P_TOP[0] = mv_table[mot_xy - mot_stride ][0];
  1305. P_TOP[1] = mv_table[mot_xy - mot_stride ][1];
  1306. P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1 ][0];
  1307. P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1 ][1];
  1308. P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
  1309. P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
  1310. }
  1311. dmin = epzs_motion_search(s, &mx, &my, P, 0, 0, -16, -16, 15, 15, ref_picture);
  1312. if(mx==0 && my==0) dmin=99999999; // not representable, due to rounding stuff
  1313. if(dmin2<dmin){
  1314. dmin= dmin2;
  1315. mx=0;
  1316. my=0;
  1317. }
  1318. #if 1
  1319. mx2= mx= mx*2;
  1320. my2= my= my*2;
  1321. for(by=-1; by<2; by++){
  1322. if(my2+by < -32) continue;
  1323. for(bx=-1; bx<2; bx++){
  1324. if(bx==0 && by==0) continue;
  1325. if(mx2+bx < -32) continue;
  1326. dmin2= check_bidir_mv(s, mb_x, mb_y,
  1327. mx2+bx+motion_fx, my2+by+motion_fy,
  1328. mx2+bx+motion_bx, my2+by+motion_by,
  1329. mx2+bx+motion_fx, my2+by+motion_fy,
  1330. motion_bx, motion_by) - s->qscale;
  1331. if(dmin2<dmin){
  1332. dmin=dmin2;
  1333. mx= mx2 + bx;
  1334. my= my2 + by;
  1335. }
  1336. }
  1337. }
  1338. #else
  1339. mx*=2; my*=2;
  1340. #endif
  1341. if(mx==0 && my==0){
  1342. motion_bx= motion_bx0;
  1343. motion_by= motion_by0;
  1344. }
  1345. s->b_direct_mv_table[mot_xy][0]= mx;
  1346. s->b_direct_mv_table[mot_xy][1]= my;
  1347. s->b_direct_forw_mv_table[mot_xy][0]= motion_fx + mx;
  1348. s->b_direct_forw_mv_table[mot_xy][1]= motion_fy + my;
  1349. s->b_direct_back_mv_table[mot_xy][0]= motion_bx + mx;
  1350. s->b_direct_back_mv_table[mot_xy][1]= motion_by + my;
  1351. return dmin;
  1352. }
  1353. void ff_estimate_b_frame_motion(MpegEncContext * s,
  1354. int mb_x, int mb_y)
  1355. {
  1356. const int quant= s->qscale;
  1357. int fmin, bmin, dmin, fbmin;
  1358. int type=0;
  1359. dmin= direct_search(s, mb_x, mb_y);
  1360. fmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, s->last_picture[0], s->f_code);
  1361. bmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, s->next_picture[0], s->b_code) - quant;
  1362. //printf(" %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
  1363. fbmin= bidir_refine(s, mb_x, mb_y);
  1364. {
  1365. int score= dmin;
  1366. type=MB_TYPE_DIRECT;
  1367. if(fmin<score){
  1368. score=fmin;
  1369. type= MB_TYPE_FORWARD;
  1370. }
  1371. if(bmin<score){
  1372. score=bmin;
  1373. type= MB_TYPE_BACKWARD;
  1374. }
  1375. if(fbmin<score){
  1376. score=fbmin;
  1377. type= MB_TYPE_BIDIR;
  1378. }
  1379. score= (score*score + 128*256)>>16;
  1380. s->mc_mb_var_sum += score;
  1381. s->mc_mb_var[mb_y*s->mb_width + mb_x] = score; //FIXME use SSD
  1382. }
  1383. if(s->flags&CODEC_FLAG_HQ){
  1384. type= MB_TYPE_FORWARD | MB_TYPE_BACKWARD | MB_TYPE_BIDIR | MB_TYPE_DIRECT; //FIXME something smarter
  1385. }
  1386. /*
  1387. {
  1388. static int count=0;
  1389. static int sum=0;
  1390. if(type==MB_TYPE_DIRECT){
  1391. int diff= ABS(s->b_forw_mv_table)
  1392. }
  1393. }*/
  1394. s->mb_type[mb_y*s->mb_width + mb_x]= type;
  1395. /* if(mb_y==0 && mb_x==0) printf("\n");
  1396. if(mb_x==0) printf("\n");
  1397. printf("%d", av_log2(type));
  1398. */
  1399. }
  1400. /* find best f_code for ME which do unlimited searches */
  1401. int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type)
  1402. {
  1403. if(s->me_method>=ME_EPZS){
  1404. int score[8];
  1405. int i, y;
  1406. UINT8 * fcode_tab= s->fcode_tab;
  1407. int best_fcode=-1;
  1408. int best_score=-10000000;
  1409. for(i=0; i<8; i++) score[i]= s->mb_num*(8-i); //FIXME *2 and all other too so its the same but nicer
  1410. for(y=0; y<s->mb_height; y++){
  1411. int x;
  1412. int xy= (y+1)* (s->mb_width+2) + 1;
  1413. i= y*s->mb_width;
  1414. for(x=0; x<s->mb_width; x++){
  1415. if(s->mb_type[i] & type){
  1416. int fcode= MAX(fcode_tab[mv_table[xy][0] + MAX_MV],
  1417. fcode_tab[mv_table[xy][1] + MAX_MV]);
  1418. int j;
  1419. for(j=0; j<fcode && j<8; j++){
  1420. if(s->pict_type==B_TYPE || s->mc_mb_var[i] < s->mb_var[i])
  1421. score[j]-= 170;
  1422. }
  1423. }
  1424. i++;
  1425. xy++;
  1426. }
  1427. }
  1428. for(i=1; i<8; i++){
  1429. if(score[i] > best_score){
  1430. best_score= score[i];
  1431. best_fcode= i;
  1432. }
  1433. // printf("%d %d\n", i, score[i]);
  1434. }
  1435. // printf("fcode: %d type: %d\n", i, s->pict_type);
  1436. return best_fcode;
  1437. /* for(i=0; i<=MAX_FCODE; i++){
  1438. printf("%d ", mv_num[i]);
  1439. }
  1440. printf("\n");*/
  1441. }else{
  1442. return 1;
  1443. }
  1444. }
  1445. void ff_fix_long_p_mvs(MpegEncContext * s)
  1446. {
  1447. const int f_code= s->f_code;
  1448. int y;
  1449. UINT8 * fcode_tab= s->fcode_tab;
  1450. //int clip=0;
  1451. //int noclip=0;
  1452. /* clip / convert to intra 16x16 type MVs */
  1453. for(y=0; y<s->mb_height; y++){
  1454. int x;
  1455. int xy= (y+1)* (s->mb_width+2)+1;
  1456. int i= y*s->mb_width;
  1457. for(x=0; x<s->mb_width; x++){
  1458. if(s->mb_type[i]&MB_TYPE_INTER){
  1459. if( fcode_tab[s->p_mv_table[xy][0] + MAX_MV] > f_code
  1460. || fcode_tab[s->p_mv_table[xy][0] + MAX_MV] == 0
  1461. || fcode_tab[s->p_mv_table[xy][1] + MAX_MV] > f_code
  1462. || fcode_tab[s->p_mv_table[xy][1] + MAX_MV] == 0 ){
  1463. s->mb_type[i] &= ~MB_TYPE_INTER;
  1464. s->mb_type[i] |= MB_TYPE_INTRA;
  1465. s->p_mv_table[xy][0] = 0;
  1466. s->p_mv_table[xy][1] = 0;
  1467. //clip++;
  1468. }
  1469. //else
  1470. // noclip++;
  1471. }
  1472. xy++;
  1473. i++;
  1474. }
  1475. }
  1476. //printf("%d no:%d %d//\n", clip, noclip, f_code);
  1477. if(s->flags&CODEC_FLAG_4MV){
  1478. const int wrap= 2+ s->mb_width*2;
  1479. /* clip / convert to intra 8x8 type MVs */
  1480. for(y=0; y<s->mb_height; y++){
  1481. int xy= (y*2 + 1)*wrap + 1;
  1482. int i= y*s->mb_width;
  1483. int x;
  1484. for(x=0; x<s->mb_width; x++){
  1485. if(s->mb_type[i]&MB_TYPE_INTER4V){
  1486. int block;
  1487. for(block=0; block<4; block++){
  1488. int off= (block& 1) + (block>>1)*wrap;
  1489. int mx= s->motion_val[ xy + off ][0];
  1490. int my= s->motion_val[ xy + off ][1];
  1491. if( fcode_tab[mx + MAX_MV] > f_code
  1492. || fcode_tab[mx + MAX_MV] == 0
  1493. || fcode_tab[my + MAX_MV] > f_code
  1494. || fcode_tab[my + MAX_MV] == 0 ){
  1495. s->mb_type[i] &= ~MB_TYPE_INTER4V;
  1496. s->mb_type[i] |= MB_TYPE_INTRA;
  1497. }
  1498. }
  1499. }
  1500. xy+=2;
  1501. i++;
  1502. }
  1503. }
  1504. }
  1505. }
  1506. void ff_fix_long_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, int type)
  1507. {
  1508. int y;
  1509. UINT8 * fcode_tab= s->fcode_tab;
  1510. /* clip / convert to intra 16x16 type MVs */
  1511. for(y=0; y<s->mb_height; y++){
  1512. int x;
  1513. int xy= (y+1)* (s->mb_width+2)+1;
  1514. int i= y*s->mb_width;
  1515. for(x=0; x<s->mb_width; x++){
  1516. if( fcode_tab[mv_table[xy][0] + MAX_MV] > f_code
  1517. || fcode_tab[mv_table[xy][0] + MAX_MV] == 0){
  1518. if(mv_table[xy][0]>0) mv_table[xy][0]= (16<<f_code)-1;
  1519. else mv_table[xy][0]= -(16<<f_code);
  1520. }
  1521. if( fcode_tab[mv_table[xy][1] + MAX_MV] > f_code
  1522. || fcode_tab[mv_table[xy][1] + MAX_MV] == 0){
  1523. if(mv_table[xy][1]>0) mv_table[xy][1]= (16<<f_code)-1;
  1524. else mv_table[xy][1]= -(16<<f_code);
  1525. }
  1526. xy++;
  1527. i++;
  1528. }
  1529. }
  1530. }