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.

1703 lines
55KB

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