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