Statistics
| Branch: | Revision:

ffmpeg / libavcodec / motion_est.c @ c42612f1

History | View | Annotate | Download (55.9 KB)

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 int pix_norm(UINT8 * pix1, UINT8 * pix2, int line_size)
67
{
68
    int s, i, j;
69
    UINT32 *sq = squareTbl + 256;
70

    
71
    s = 0;
72
    for (i = 0; i < 16; i++) {
73
        for (j = 0; j < 16; j += 8) {
74
            s += sq[pix1[0] - pix2[0]];
75
            s += sq[pix1[1] - pix2[1]];
76
            s += sq[pix1[2] - pix2[2]];
77
            s += sq[pix1[3] - pix2[3]];
78
            s += sq[pix1[4] - pix2[4]];
79
            s += sq[pix1[5] - pix2[5]];
80
            s += sq[pix1[6] - pix2[6]];
81
            s += sq[pix1[7] - pix2[7]];
82
            pix1 += 8;
83
            pix2 += 8;
84
        }
85
        pix1 += line_size - 16;
86
        pix2 += line_size - 16;
87
    }
88
    return s;
89
}
90

    
91
static void no_motion_search(MpegEncContext * s,
92
                             int *mx_ptr, int *my_ptr)
93
{
94
    *mx_ptr = 16 * s->mb_x;
95
    *my_ptr = 16 * s->mb_y;
96
}
97

    
98
static int full_motion_search(MpegEncContext * s,
99
                              int *mx_ptr, int *my_ptr, int range,
100
                              int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
101
{
102
    int x1, y1, x2, y2, xx, yy, x, y;
103
    int mx, my, dmin, d;
104
    UINT8 *pix;
105

    
106
    xx = 16 * s->mb_x;
107
    yy = 16 * s->mb_y;
108
    x1 = xx - range + 1;        /* we loose one pixel to avoid boundary pb with half pixel pred */
109
    if (x1 < xmin)
110
        x1 = xmin;
111
    x2 = xx + range - 1;
112
    if (x2 > xmax)
113
        x2 = xmax;
114
    y1 = yy - range + 1;
115
    if (y1 < ymin)
116
        y1 = ymin;
117
    y2 = yy + range - 1;
118
    if (y2 > ymax)
119
        y2 = ymax;
120
    pix = s->new_picture[0] + (yy * s->linesize) + xx;
121
    dmin = 0x7fffffff;
122
    mx = 0;
123
    my = 0;
124
    for (y = y1; y <= y2; y++) {
125
        for (x = x1; x <= x2; x++) {
126
            d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x,
127
                             s->linesize);
128
            if (d < dmin ||
129
                (d == dmin &&
130
                 (abs(x - xx) + abs(y - yy)) <
131
                 (abs(mx - xx) + abs(my - yy)))) {
132
                dmin = d;
133
                mx = x;
134
                my = y;
135
            }
136
        }
137
    }
138

    
139
    *mx_ptr = mx;
140
    *my_ptr = my;
141

    
142
#if 0
143
    if (*mx_ptr < -(2 * range) || *mx_ptr >= (2 * range) ||
144
        *my_ptr < -(2 * range) || *my_ptr >= (2 * range)) {
145
        fprintf(stderr, "error %d %d\n", *mx_ptr, *my_ptr);
146
    }
147
#endif
148
    return dmin;
149
}
150

    
151

    
152
static int log_motion_search(MpegEncContext * s,
153
                             int *mx_ptr, int *my_ptr, int range,
154
                             int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
155
{
156
    int x1, y1, x2, y2, xx, yy, x, y;
157
    int mx, my, dmin, d;
158
    UINT8 *pix;
159

    
160
    xx = s->mb_x << 4;
161
    yy = s->mb_y << 4;
162

    
163
    /* Left limit */
164
    x1 = xx - range;
165
    if (x1 < xmin)
166
        x1 = xmin;
167

    
168
    /* Right limit */
169
    x2 = xx + range;
170
    if (x2 > xmax)
171
        x2 = xmax;
172

    
173
    /* Upper limit */
174
    y1 = yy - range;
175
    if (y1 < ymin)
176
        y1 = ymin;
177

    
178
    /* Lower limit */
179
    y2 = yy + range;
180
    if (y2 > ymax)
181
        y2 = ymax;
182

    
183
    pix = s->new_picture[0] + (yy * s->linesize) + xx;
184
    dmin = 0x7fffffff;
185
    mx = 0;
186
    my = 0;
187

    
188
    do {
189
        for (y = y1; y <= y2; y += range) {
190
            for (x = x1; x <= x2; x += range) {
191
                d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, s->linesize);
192
                if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
193
                    dmin = d;
194
                    mx = x;
195
                    my = y;
196
                }
197
            }
198
        }
199

    
200
        range = range >> 1;
201

    
202
        x1 = mx - range;
203
        if (x1 < xmin)
204
            x1 = xmin;
205

    
206
        x2 = mx + range;
207
        if (x2 > xmax)
208
            x2 = xmax;
209

    
210
        y1 = my - range;
211
        if (y1 < ymin)
212
            y1 = ymin;
213

    
214
        y2 = my + range;
215
        if (y2 > ymax)
216
            y2 = ymax;
217

    
218
    } while (range >= 1);
219

    
220
#ifdef DEBUG
221
    fprintf(stderr, "log       - MX: %d\tMY: %d\n", mx, my);
222
#endif
223
    *mx_ptr = mx;
224
    *my_ptr = my;
225
    return dmin;
226
}
227

    
228
static int phods_motion_search(MpegEncContext * s,
229
                               int *mx_ptr, int *my_ptr, int range,
230
                               int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
231
{
232
    int x1, y1, x2, y2, xx, yy, x, y, lastx, d;
233
    int mx, my, dminx, dminy;
234
    UINT8 *pix;
235

    
236
    xx = s->mb_x << 4;
237
    yy = s->mb_y << 4;
238

    
239
    /* Left limit */
240
    x1 = xx - range;
241
    if (x1 < xmin)
242
        x1 = xmin;
243

    
244
    /* Right limit */
245
    x2 = xx + range;
246
    if (x2 > xmax)
247
        x2 = xmax;
248

    
249
    /* Upper limit */
250
    y1 = yy - range;
251
    if (y1 < ymin)
252
        y1 = ymin;
253

    
254
    /* Lower limit */
255
    y2 = yy + range;
256
    if (y2 > ymax)
257
        y2 = ymax;
258

    
259
    pix = s->new_picture[0] + (yy * s->linesize) + xx;
260
    mx = 0;
261
    my = 0;
262

    
263
    x = xx;
264
    y = yy;
265
    do {
266
        dminx = 0x7fffffff;
267
        dminy = 0x7fffffff;
268

    
269
        lastx = x;
270
        for (x = x1; x <= x2; x += range) {
271
            d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, s->linesize);
272
            if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
273
                dminx = d;
274
                mx = x;
275
            }
276
        }
277

    
278
        x = lastx;
279
        for (y = y1; y <= y2; y += range) {
280
            d = pix_abs16x16(pix, ref_picture + (y * s->linesize) + x, s->linesize);
281
            if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
282
                dminy = d;
283
                my = y;
284
            }
285
        }
286

    
287
        range = range >> 1;
288

    
289
        x = mx;
290
        y = my;
291
        x1 = mx - range;
292
        if (x1 < xmin)
293
            x1 = xmin;
294

    
295
        x2 = mx + range;
296
        if (x2 > xmax)
297
            x2 = xmax;
298

    
299
        y1 = my - range;
300
        if (y1 < ymin)
301
            y1 = ymin;
302

    
303
        y2 = my + range;
304
        if (y2 > ymax)
305
            y2 = ymax;
306

    
307
    } while (range >= 1);
308

    
309
#ifdef DEBUG
310
    fprintf(stderr, "phods     - MX: %d\tMY: %d\n", mx, my);
311
#endif
312

    
313
    /* half pixel search */
314
    *mx_ptr = mx;
315
    *my_ptr = my;
316
    return dminy;
317
}
318

    
319

    
320
#define Z_THRESHOLD 256
321

    
322
#define CHECK_MV(x,y)\
323
{\
324
    const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
325
    const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
326
    if(map[index]!=key){\
327
        d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\
328
        d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
329
        COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
330
        map[index]= key;\
331
        score_map[index]= d;\
332
    }\
333
}
334

    
335
#define CHECK_MV_DIR(x,y,new_dir)\
336
{\
337
    const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
338
    const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
339
    if(map[index]!=key){\
340
        d = pix_abs(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\
341
        d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
342
        if(d<dmin){\
343
            best[0]=x;\
344
            best[1]=y;\
345
            dmin=d;\
346
            next_dir= new_dir;\
347
        }\
348
        map[index]= key;\
349
        score_map[index]= d;\
350
    }\
351
}
352

    
353
#define CHECK_MV4(x,y)\
354
{\
355
    const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
356
    const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
357
    if(map[index]!=key){\
358
        d = pix_abs8x8(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);\
359
        d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
360
        COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
361
        map[index]= key;\
362
        score_map[index]= d;\
363
    }\
364
}
365

    
366
#define check(x,y,S,v)\
367
if( (x)<(xmin<<(S)) ) printf("%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\
368
if( (x)>(xmax<<(S)) ) printf("%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\
369
if( (y)<(ymin<<(S)) ) printf("%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\
370
if( (y)>(ymax<<(S)) ) printf("%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\
371

    
372

    
373
static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
374
                                       UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
375
                                       int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
376
                                       int xmin, int ymin, int xmax, int ymax, int shift,
377
                                       uint32_t *map, uint16_t *score_map, int map_generation,
378
                                       op_pixels_abs_func pix_abs)
379
{
380
    int next_dir=-1;
381

    
382
    for(;;){
383
        int d;
384
        const int dir= next_dir;
385
        const int x= best[0];
386
        const int y= best[1];
387
        next_dir=-1;
388

    
389
//printf("%d", dir);
390
        if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y  , 0)
391
        if(dir!=3 && y>ymin) CHECK_MV_DIR(x  , y-1, 1)
392
        if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y  , 2)
393
        if(dir!=1 && y<ymax) CHECK_MV_DIR(x  , y+1, 3)
394

    
395
        if(next_dir==-1){
396
            return dmin;
397
        }
398
    }
399

    
400
/*    for(;;){
401
        int d;
402
        const int x= best[0];
403
        const int y= best[1];
404
        const int last_min=dmin;
405
        if(x>xmin) CHECK_MV(x-1, y  )
406
        if(y>xmin) CHECK_MV(x  , y-1)
407
        if(x<xmax) CHECK_MV(x+1, y  )
408
        if(y<xmax) CHECK_MV(x  , y+1)
409
        if(x>xmin && y>ymin) CHECK_MV(x-1, y-1)
410
        if(x>xmin && y<ymax) CHECK_MV(x-1, y+1)
411
        if(x<xmax && y>ymin) CHECK_MV(x+1, y-1)
412
        if(x<xmax && y<ymax) CHECK_MV(x+1, y+1)
413
        if(x-1>xmin) CHECK_MV(x-2, y  )
414
        if(y-1>xmin) CHECK_MV(x  , y-2)
415
        if(x+1<xmax) CHECK_MV(x+2, y  )
416
        if(y+1<xmax) CHECK_MV(x  , y+2)
417
        if(x-1>xmin && y-1>ymin) CHECK_MV(x-2, y-2)
418
        if(x-1>xmin && y+1<ymax) CHECK_MV(x-2, y+2)
419
        if(x+1<xmax && y-1>ymin) CHECK_MV(x+2, y-2)
420
        if(x+1<xmax && y+1<ymax) CHECK_MV(x+2, y+2)
421
        if(dmin==last_min) return dmin;
422
    }
423
    */
424
}
425

    
426
#if 1
427
#define SNAKE_1 3
428
#define SNAKE_2 2
429
#else
430
#define SNAKE_1 7
431
#define SNAKE_2 3
432
#endif
433
static inline int snake_search(MpegEncContext * s, int *best, int dmin,
434
                                       UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
435
                                       int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
436
                                       int xmin, int ymin, int xmax, int ymax, int shift,
437
                                       uint32_t *map, uint16_t *score_map,int map_generation,
438
                                       op_pixels_abs_func pix_abs)
439
{
440
    int dir=0;
441
    int c=1;
442
    static int x_dir[8]= {1,1,0,-1,-1,-1, 0, 1};
443
    static int y_dir[8]= {0,1,1, 1, 0,-1,-1,-1};
444
    int fails=0;
445
    int last_d[2]={dmin, dmin};
446

    
447
/*static int good=0;
448
static int bad=0;
449
static int point=0;
450

451
point++;
452
if(256*256*256*64%point==0)
453
{
454
    printf("%d %d %d\n", good, bad, point);
455
}*/
456

    
457
    for(;;){
458
        int x= best[0];
459
        int y= best[1];
460
        int d;
461
        x+=x_dir[dir];
462
        y+=y_dir[dir];
463
        if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){
464
            const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;
465
            const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);
466
            if(map[index]!=key){
467
                d = pix_abs(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride);
468
                d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;
469
                map[index]=key;
470
                score_map[index]=d;
471
            }else
472
                d= dmin+1;
473
        }else{
474
            d = dmin + 10000; //FIXME smarter boundary handling
475
        }
476
        if(d<dmin){
477
            best[0]=x;
478
            best[1]=y;
479
            dmin=d;
480

    
481
            if(last_d[1] - last_d[0] > last_d[0] - d) c= -c;
482
            dir+=c;
483

    
484
            fails=0;
485
//good++;
486
            last_d[1]=last_d[0];
487
            last_d[0]=d;
488
        }else{
489
//bad++;
490
            if(fails){
491
                if(fails>=SNAKE_1+1) return dmin;
492
            }else{
493
                if(dir&1) dir-= c*3;
494
                else      c= -c;
495
//                c= -c;
496
            }
497
            dir+=c*SNAKE_2;
498
            fails++;
499
        }
500
        dir&=7;
501
    }
502
}
503

    
504
static inline int cross_search(MpegEncContext * s, int *best, int dmin,
505
                                       UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
506
                                       int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
507
                                       int xmin, int ymin, int xmax, int ymax, int shift,
508
                                       uint32_t *map, uint16_t *score_map,int map_generation,
509
                                       op_pixels_abs_func pix_abs)
510
{
511
    static int x_dir[4]= {-1, 0, 1, 0};
512
    static int y_dir[4]= { 0,-1, 0, 1};
513
    int improvement[2]={100000, 100000};
514
    int dirs[2]={2, 3};
515
    int dir;
516
    int last_dir= -1;
517
    
518
    for(;;){
519
        dir= dirs[ improvement[0] > improvement[1] ? 0 : 1 ];
520
        if(improvement[dir&1]==-1) return dmin;
521
        
522
        {
523
            const int x= best[0] + x_dir[dir];
524
            const int y= best[1] + y_dir[dir];
525
            const int key= (y<<ME_MAP_MV_BITS) + x + map_generation;
526
            const int index= ((y<<ME_MAP_SHIFT) + x)&(ME_MAP_SIZE-1);
527
            int d;
528
            if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){
529
                if(map[index]!=key){
530
                    d = pix_abs(new_pic, old_pic + x + y*pic_stride, pic_stride);
531
                    d += (mv_penalty[(x<<shift)-pred_x] + mv_penalty[(y<<shift)-pred_y])*quant;
532
                    map[index]=key;
533
                    score_map[index]=d;
534
                    if(d<dmin){
535
                        improvement[dir&1]= dmin-d;
536
                        improvement[(dir&1)^1]++;
537
                        dmin=d;
538
                        best[0]= x;
539
                        best[1]= y;
540
                        last_dir=dir;
541
                        continue;
542
                    }
543
                }else{
544
                    d= score_map[index];
545
                }
546
            }else{
547
                d= dmin + 1000; //FIXME is this a good idea?
548
            }
549
            /* evaluated point was cached or checked and worse */
550

    
551
            if(last_dir==dir){
552
                improvement[dir&1]= -1;
553
            }else{
554
                improvement[dir&1]= d-dmin;
555
                last_dir= dirs[dir&1]= dir^2;
556
            }
557
        }
558
    }
559
}
560

    
561
static inline int update_map_generation(MpegEncContext * s)
562
{
563
    s->me_map_generation+= 1<<(ME_MAP_MV_BITS*2);
564
    if(s->me_map_generation==0){
565
        s->me_map_generation= 1<<(ME_MAP_MV_BITS*2);
566
        memset(s->me_map, 0, sizeof(uint32_t)*ME_MAP_SIZE);
567
    }
568
    return s->me_map_generation;
569
}
570

    
571
static int epzs_motion_search(MpegEncContext * s,
572
                             int *mx_ptr, int *my_ptr,
573
                             int P[10][2], int pred_x, int pred_y,
574
                             int xmin, int ymin, int xmax, int ymax, uint8_t * ref_picture)
575
{
576
    int best[2]={0, 0};
577
    int d, dmin; 
578
    UINT8 *new_pic, *old_pic;
579
    const int pic_stride= s->linesize;
580
    const int pic_xy= (s->mb_y*pic_stride + s->mb_x)*16;
581
    UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
582
    int quant= s->qscale; // qscale of the prev frame
583
    const int shift= 1+s->quarter_sample;
584
    uint32_t *map= s->me_map;
585
    uint16_t *score_map= s->me_score_map;
586
    int map_generation;
587

    
588
    new_pic = s->new_picture[0] + pic_xy;
589
    old_pic = ref_picture + pic_xy;
590
    
591
    map_generation= update_map_generation(s);
592

    
593
    dmin = pix_abs16x16(new_pic, old_pic, pic_stride);
594
    map[0]= map_generation;
595
    score_map[0]= dmin;
596

    
597
    /* first line */
598
    if ((s->mb_y == 0 || s->first_slice_line)) {
599
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
600
        CHECK_MV(P_LAST[0]>>shift, P_LAST[1]>>shift)
601
    }else{
602
        if(dmin<256 && ( P_LEFT[0]    |P_LEFT[1]
603
                        |P_TOP[0]     |P_TOP[1]
604
                        |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){
605
            *mx_ptr= 0;
606
            *my_ptr= 0;
607
            s->skip_me=1;
608
            return dmin;
609
        }
610
        CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
611
        if(dmin>256*2){
612
            CHECK_MV(P_LAST[0]    >>shift, P_LAST[1]    >>shift)
613
            CHECK_MV(P_LEFT[0]    >>shift, P_LEFT[1]    >>shift)
614
            CHECK_MV(P_TOP[0]     >>shift, P_TOP[1]     >>shift)
615
            CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
616
        }
617
    }
618
    if(dmin>256*4){
619
        CHECK_MV(P_LAST_RIGHT[0] >>shift, P_LAST_RIGHT[1] >>shift)
620
        CHECK_MV(P_LAST_BOTTOM[0]>>shift, P_LAST_BOTTOM[1]>>shift)
621
    }
622
#if 0 //doest only slow things down
623
    if(dmin>512*3){
624
        int step;
625
        dmin= score_map[0];
626
        best[0]= best[1]=0;
627
        for(step=128; step>0; step>>=1){
628
            const int step2= step;
629
            int y;
630
            for(y=-step2+best[1]; y<=step2+best[1]; y+=step){
631
                int x;
632
                if(y<ymin || y>ymax) continue;
633

634
                for(x=-step2+best[0]; x<=step2+best[0]; x+=step){
635
                    if(x<xmin || x>xmax) continue;
636
                    if(x==best[0] && y==best[1]) continue;
637
                    CHECK_MV(x,y)
638
                }
639
            }
640
        }
641
    }
642
#endif
643
//check(best[0],best[1],0, b0)
644
    if(s->me_method==ME_EPZS)
645
        dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride, 
646
                                   pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, 
647
                                   shift, map, score_map, map_generation, pix_abs16x16);
648
    else
649
        dmin=         cross_search(s, best, dmin, new_pic, old_pic, pic_stride, 
650
                                   pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, 
651
                                   shift, map, score_map, map_generation, pix_abs16x16);
652
//check(best[0],best[1],0, b1)
653
    *mx_ptr= best[0];
654
    *my_ptr= best[1];    
655

    
656
//    printf("%d %d %d \n", best[0], best[1], dmin);
657
    return dmin;
658
}
659

    
660
static int epzs_motion_search4(MpegEncContext * s, int block,
661
                             int *mx_ptr, int *my_ptr,
662
                             int P[10][2], int pred_x, int pred_y,
663
                             int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
664
{
665
    int best[2]={0, 0};
666
    int d, dmin; 
667
    UINT8 *new_pic, *old_pic;
668
    const int pic_stride= s->linesize;
669
    const int pic_xy= ((s->mb_y*2 + (block>>1))*pic_stride + s->mb_x*2 + (block&1))*8;
670
    UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
671
    int quant= s->qscale; // qscale of the prev frame
672
    const int shift= 1+s->quarter_sample;
673
    uint32_t *map= s->me_map;
674
    uint16_t *score_map= s->me_score_map;
675
    int map_generation;
676

    
677
    new_pic = s->new_picture[0] + pic_xy;
678
    old_pic = ref_picture + pic_xy;
679

    
680
    map_generation= update_map_generation(s);
681

    
682
    dmin = 1000000;
683
//printf("%d %d %d %d //",xmin, ymin, xmax, ymax); 
684
    /* first line */
685
    if ((s->mb_y == 0 || s->first_slice_line) && block<2) {
686
        CHECK_MV4(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
687
        CHECK_MV4(P_LAST[0]>>shift, P_LAST[1]>>shift)
688
        CHECK_MV4(P_MV1[0]>>shift, P_MV1[1]>>shift)
689
    }else{
690
        CHECK_MV4(P_MV1[0]>>shift, P_MV1[1]>>shift)
691
        //FIXME try some early stop
692
        if(dmin>64*2){
693
            CHECK_MV4(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
694
            CHECK_MV4(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
695
            CHECK_MV4(P_TOP[0]>>shift, P_TOP[1]>>shift)
696
            CHECK_MV4(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
697
            CHECK_MV4(P_LAST[0]>>shift, P_LAST[1]>>shift)
698
        }
699
    }
700
    if(dmin>64*4){
701
        CHECK_MV4(P_LAST_RIGHT[0]>>shift, P_LAST_RIGHT[1]>>shift)
702
        CHECK_MV4(P_LAST_BOTTOM[0]>>shift, P_LAST_BOTTOM[1]>>shift)
703
    }
704

    
705
    if(s->me_method==ME_EPZS)
706
        dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride, 
707
                                   pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, 
708
                                   shift, map, score_map, map_generation, pix_abs8x8);
709
    else
710
        dmin=         cross_search(s, best, dmin, new_pic, old_pic, pic_stride, 
711
                                   pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, 
712
                                   shift, map, score_map, map_generation, pix_abs8x8);
713

    
714
    *mx_ptr= best[0];
715
    *my_ptr= best[1];    
716

    
717
//    printf("%d %d %d \n", best[0], best[1], dmin);
718
    return dmin;
719
}
720

    
721
#define CHECK_HALF_MV(suffix, x, y) \
722
{\
723
    d= pix_abs_ ## suffix(pix, ptr+((x)>>1), s->linesize);\
724
    d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\
725
    COPY3_IF_LT(dminh, d, dx, x, dy, y)\
726
}
727

    
728
    
729
/* The idea would be to make half pel ME after Inter/Intra decision to 
730
   save time. */
731
static inline int halfpel_motion_search(MpegEncContext * s,
732
                                  int *mx_ptr, int *my_ptr, int dmin,
733
                                  int xmin, int ymin, int xmax, int ymax,
734
                                  int pred_x, int pred_y, uint8_t *ref_picture,
735
                                  op_pixels_abs_func pix_abs_x2, 
736
                                  op_pixels_abs_func pix_abs_y2, op_pixels_abs_func pix_abs_xy2, int n)
737
{
738
    UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
739
    const int quant= s->qscale;
740
    int mx, my, xx, yy, dminh;
741
    UINT8 *pix, *ptr;
742

    
743
    if(s->skip_me){
744
        *mx_ptr = 0;
745
        *my_ptr = 0;
746
        return dmin;
747
    }else
748

    
749
    xx = 16 * s->mb_x + 8*(n&1);
750
    yy = 16 * s->mb_y + 8*(n>>1);
751
    pix =  s->new_picture[0] + (yy * s->linesize) + xx;
752

    
753
    mx = *mx_ptr;
754
    my = *my_ptr;
755
    ptr = ref_picture + ((yy + my) * s->linesize) + (xx + mx);
756
    
757
    dminh = dmin;
758

    
759
    if (mx > xmin && mx < xmax && 
760
        my > ymin && my < ymax) {
761
        int dx=0, dy=0;
762
        int d, pen_x, pen_y; 
763

    
764
        mx<<=1;
765
        my<<=1;
766
        
767
        pen_x= pred_x + mx;
768
        pen_y= pred_y + my;
769

    
770
        ptr-= s->linesize;
771
        CHECK_HALF_MV(xy2, -1, -1)
772
        CHECK_HALF_MV(y2 ,  0, -1)
773
        CHECK_HALF_MV(xy2, +1, -1)
774
        
775
        ptr+= s->linesize;
776
        CHECK_HALF_MV(x2 , -1,  0)
777
        CHECK_HALF_MV(x2 , +1,  0)
778
        CHECK_HALF_MV(xy2, -1, +1)
779
        CHECK_HALF_MV(y2 ,  0, +1)
780
        CHECK_HALF_MV(xy2, +1, +1)
781

    
782
        mx+=dx;
783
        my+=dy;
784
    }else{
785
        mx<<=1;
786
        my<<=1;
787
    }
788

    
789
    *mx_ptr = mx;
790
    *my_ptr = my;
791
    return dminh;
792
}
793

    
794
static inline int fast_halfpel_motion_search(MpegEncContext * s,
795
                                  int *mx_ptr, int *my_ptr, int dmin,
796
                                  int xmin, int ymin, int xmax, int ymax,
797
                                  int pred_x, int pred_y, uint8_t *ref_picture,
798
                                  op_pixels_abs_func pix_abs_x2, 
799
                                  op_pixels_abs_func pix_abs_y2, op_pixels_abs_func pix_abs_xy2, int n)
800
{
801
    UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
802
    uint16_t *score_map= s->me_score_map;
803
    const int quant= s->qscale;
804
    int mx, my, xx, yy, dminh;
805
    UINT8 *pix, *ptr;
806

    
807
    if(s->skip_me){
808
//    printf("S");
809
        *mx_ptr = 0;
810
        *my_ptr = 0;
811
        return dmin;
812
    }
813
//    printf("N");
814
        
815
    xx = 16 * s->mb_x + 8*(n&1);
816
    yy = 16 * s->mb_y + 8*(n>>1);
817
    pix =  s->new_picture[0] + (yy * s->linesize) + xx;
818

    
819
    mx = *mx_ptr;
820
    my = *my_ptr;
821
    ptr = ref_picture + ((yy + my) * s->linesize) + (xx + mx);
822
    
823
    dminh = dmin;
824

    
825
    if (mx > xmin && mx < xmax && 
826
        my > ymin && my < ymax) {
827
        int dx=0, dy=0;
828
        int d, pen_x, pen_y; 
829
        const int index= (my<<ME_MAP_SHIFT) + mx;
830
        const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
831
        const int l= score_map[(index- 1               )&(ME_MAP_SIZE-1)];
832
        const int r= score_map[(index+ 1               )&(ME_MAP_SIZE-1)];
833
        const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
834
        mx<<=1;
835
        my<<=1;
836

    
837
        
838
        pen_x= pred_x + mx;
839
        pen_y= pred_y + my;
840

    
841
        ptr-= s->linesize;
842
        if(t<=b){
843
            CHECK_HALF_MV(y2 ,  0, -1)
844
            if(l<=r){
845
                CHECK_HALF_MV(xy2, -1, -1)
846
                if(t+r<=b+l){
847
                    CHECK_HALF_MV(xy2, +1, -1)
848
                    ptr+= s->linesize;
849
                }else{
850
                    ptr+= s->linesize;
851
                    CHECK_HALF_MV(xy2, -1, +1)
852
                }
853
                CHECK_HALF_MV(x2 , -1,  0)
854
            }else{
855
                CHECK_HALF_MV(xy2, +1, -1)
856
                if(t+l<=b+r){
857
                    CHECK_HALF_MV(xy2, -1, -1)
858
                    ptr+= s->linesize;
859
                }else{
860
                    ptr+= s->linesize;
861
                    CHECK_HALF_MV(xy2, +1, +1)
862
                }
863
                CHECK_HALF_MV(x2 , +1,  0)
864
            }
865
        }else{
866
            if(l<=r){
867
                if(t+l<=b+r){
868
                    CHECK_HALF_MV(xy2, -1, -1)
869
                    ptr+= s->linesize;
870
                }else{
871
                    ptr+= s->linesize;
872
                    CHECK_HALF_MV(xy2, +1, +1)
873
                }
874
                CHECK_HALF_MV(x2 , -1,  0)
875
                CHECK_HALF_MV(xy2, -1, +1)
876
            }else{
877
                if(t+r<=b+l){
878
                    CHECK_HALF_MV(xy2, +1, -1)
879
                    ptr+= s->linesize;
880
                }else{
881
                    ptr+= s->linesize;
882
                    CHECK_HALF_MV(xy2, -1, +1)
883
                }
884
                CHECK_HALF_MV(x2 , +1,  0)
885
                CHECK_HALF_MV(xy2, +1, +1)
886
            }
887
            CHECK_HALF_MV(y2 ,  0, +1)
888
        }
889
        mx+=dx;
890
        my+=dy;
891

    
892
    }else{
893
        mx<<=1;
894
        my<<=1;
895
    }
896

    
897
    *mx_ptr = mx;
898
    *my_ptr = my;
899
    return dminh;
900
}
901

    
902
static inline void set_p_mv_tables(MpegEncContext * s, int mx, int my, int mv4)
903
{
904
    const int xy= s->mb_x + 1 + (s->mb_y + 1)*(s->mb_width + 2);
905
    
906
    s->p_mv_table[xy][0] = mx;
907
    s->p_mv_table[xy][1] = my;
908

    
909
    /* has allready been set to the 4 MV if 4MV is done */
910
    if(mv4){
911
        int mot_xy= s->block_index[0];
912

    
913
        s->motion_val[mot_xy  ][0]= mx;
914
        s->motion_val[mot_xy  ][1]= my;
915
        s->motion_val[mot_xy+1][0]= mx;
916
        s->motion_val[mot_xy+1][1]= my;
917

    
918
        mot_xy += s->block_wrap[0];
919
        s->motion_val[mot_xy  ][0]= mx;
920
        s->motion_val[mot_xy  ][1]= my;
921
        s->motion_val[mot_xy+1][0]= mx;
922
        s->motion_val[mot_xy+1][1]= my;
923
    }
924
}
925

    
926
static inline void get_limits(MpegEncContext *s, int *range, int *xmin, int *ymin, int *xmax, int *ymax, int f_code)
927
{
928
    *range = 8 * (1 << (f_code - 1));
929
    /* XXX: temporary kludge to avoid overflow for msmpeg4 */
930
    if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
931
        *range *= 2;
932

    
933
    if (s->unrestricted_mv) {
934
        *xmin = -16;
935
        *ymin = -16;
936
        if (s->h263_plus)
937
            *range *= 2;
938
        if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){
939
            *xmax = s->mb_width*16;
940
            *ymax = s->mb_height*16;
941
        }else {
942
            /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise 
943
                    (cuz the drawn edge isnt large enough))*/
944
            *xmax = s->width;
945
            *ymax = s->height;
946
        }
947
    } else {
948
        *xmin = 0;
949
        *ymin = 0;
950
        *xmax = s->mb_width*16 - 16;
951
        *ymax = s->mb_height*16 - 16;
952
    }
953
}
954

    
955
static inline int mv4_search(MpegEncContext *s, int xmin, int ymin, int xmax, int ymax, int mx, int my, int shift)
956
{
957
    int block;
958
    int P[10][2];
959
    uint8_t *ref_picture= s->last_picture[0];
960
    int dmin_sum=0;
961

    
962
    for(block=0; block<4; block++){
963
        int mx4, my4;
964
        int pred_x4, pred_y4;
965
        int dmin4;
966
        static const int off[4]= {2, 1, 1, -1};
967
        const int mot_stride = s->block_wrap[0];
968
        const int mot_xy = s->block_index[block];
969
//        const int block_x= (block&1);
970
//        const int block_y= (block>>1);
971
#if 1 // this saves us a bit of cliping work and shouldnt affect compression in a negative way
972
        const int rel_xmin4= xmin;
973
        const int rel_xmax4= xmax;
974
        const int rel_ymin4= ymin;
975
        const int rel_ymax4= ymax;
976
#else
977
        const int rel_xmin4= xmin - block_x*8;
978
        const int rel_xmax4= xmax - block_x*8 + 8;
979
        const int rel_ymin4= ymin - block_y*8;
980
        const int rel_ymax4= ymax - block_y*8 + 8;
981
#endif
982
        P_LAST[0] = s->motion_val[mot_xy    ][0];
983
        P_LAST[1] = s->motion_val[mot_xy    ][1];
984
        P_LEFT[0] = s->motion_val[mot_xy - 1][0];
985
        P_LEFT[1] = s->motion_val[mot_xy - 1][1];
986
        P_LAST_RIGHT[0] = s->motion_val[mot_xy + 1][0];
987
        P_LAST_RIGHT[1] = s->motion_val[mot_xy + 1][1];
988
        P_LAST_BOTTOM[0]= s->motion_val[mot_xy + 1*mot_stride][0];
989
        P_LAST_BOTTOM[1]= s->motion_val[mot_xy + 1*mot_stride][1];
990

    
991
        if(P_LEFT[0]       > (rel_xmax4<<shift)) P_LEFT[0]       = (rel_xmax4<<shift);
992
        if(P_LAST_RIGHT[0] < (rel_xmin4<<shift)) P_LAST_RIGHT[0] = (rel_xmin4<<shift);
993
        if(P_LAST_BOTTOM[1]< (rel_ymin4<<shift)) P_LAST_BOTTOM[1]= (rel_ymin4<<shift);
994

    
995
        /* special case for first line */
996
        if ((s->mb_y == 0 || s->first_slice_line) && block<2) {
997
            pred_x4= P_LEFT[0];
998
            pred_y4= P_LEFT[1];
999
        } else {
1000
            P_TOP[0]      = s->motion_val[mot_xy - mot_stride             ][0];
1001
            P_TOP[1]      = s->motion_val[mot_xy - mot_stride             ][1];
1002
            P_TOPRIGHT[0] = s->motion_val[mot_xy - mot_stride + off[block]][0];
1003
            P_TOPRIGHT[1] = s->motion_val[mot_xy - mot_stride + off[block]][1];
1004
            if(P_TOP[1]      > (rel_ymax4<<shift)) P_TOP[1]     = (rel_ymax4<<shift);
1005
            if(P_TOPRIGHT[0] < (rel_xmin4<<shift)) P_TOPRIGHT[0]= (rel_xmin4<<shift);
1006
            if(P_TOPRIGHT[0] > (rel_xmax4<<shift)) P_TOPRIGHT[0]= (rel_xmax4<<shift);
1007
            if(P_TOPRIGHT[1] > (rel_ymax4<<shift)) P_TOPRIGHT[1]= (rel_ymax4<<shift);
1008
    
1009
            P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1010
            P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1011

    
1012
            if(s->out_format == FMT_H263){
1013
                pred_x4 = P_MEDIAN[0];
1014
                pred_y4 = P_MEDIAN[1];
1015
            }else { /* mpeg1 at least */
1016
                pred_x4= P_LEFT[0];
1017
                pred_y4= P_LEFT[1];
1018
            }
1019
        }
1020
        P_MV1[0]= mx;
1021
        P_MV1[1]= my;
1022

    
1023
        dmin4 = epzs_motion_search4(s, block, &mx4, &my4, P, pred_x4, pred_y4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, ref_picture);
1024

    
1025
        dmin4= fast_halfpel_motion_search(s, &mx4, &my4, dmin4, rel_xmin4, rel_ymin4, rel_xmax4, rel_ymax4, 
1026
                                   pred_x4, pred_y4, ref_picture, pix_abs8x8_x2, 
1027
                                   pix_abs8x8_y2, pix_abs8x8_xy2, block);
1028
 
1029
        s->motion_val[ s->block_index[block] ][0]= mx4;
1030
        s->motion_val[ s->block_index[block] ][1]= my4;
1031
        dmin_sum+= dmin4;
1032
    }
1033
    return dmin_sum;
1034
}
1035

    
1036
void ff_estimate_p_frame_motion(MpegEncContext * s,
1037
                                int mb_x, int mb_y)
1038
{
1039
    UINT8 *pix, *ppix;
1040
    int sum, varc, vard, mx, my, range, dmin, xx, yy;
1041
    int xmin, ymin, xmax, ymax;
1042
    int rel_xmin, rel_ymin, rel_xmax, rel_ymax;
1043
    int pred_x=0, pred_y=0;
1044
    int P[10][2];
1045
    const int shift= 1+s->quarter_sample;
1046
    int mb_type=0;
1047
    uint8_t *ref_picture= s->last_picture[0];
1048

    
1049
    get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, s->f_code);
1050
    rel_xmin= xmin - mb_x*16;
1051
    rel_xmax= xmax - mb_x*16;
1052
    rel_ymin= ymin - mb_y*16;
1053
    rel_ymax= ymax - mb_y*16;
1054
    s->skip_me=0;
1055

    
1056
    switch(s->me_method) {
1057
    case ME_ZERO:
1058
    default:
1059
        no_motion_search(s, &mx, &my);
1060
        mx-= mb_x*16;
1061
        my-= mb_y*16;
1062
        dmin = 0;
1063
        break;
1064
    case ME_FULL:
1065
        dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax, ref_picture);
1066
        mx-= mb_x*16;
1067
        my-= mb_y*16;
1068
        break;
1069
    case ME_LOG:
1070
        dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture);
1071
        mx-= mb_x*16;
1072
        my-= mb_y*16;
1073
        break;
1074
    case ME_PHODS:
1075
        dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture);
1076
        mx-= mb_x*16;
1077
        my-= mb_y*16;
1078
        break;
1079
    case ME_X1:
1080
    case ME_EPZS:
1081
       {
1082
            const int mot_stride = s->block_wrap[0];
1083
            const int mot_xy = s->block_index[0];
1084

    
1085
            P_LAST[0]       = s->motion_val[mot_xy    ][0];
1086
            P_LAST[1]       = s->motion_val[mot_xy    ][1];
1087
            P_LEFT[0]       = s->motion_val[mot_xy - 1][0];
1088
            P_LEFT[1]       = s->motion_val[mot_xy - 1][1];
1089
            P_LAST_RIGHT[0] = s->motion_val[mot_xy + 2][0];
1090
            P_LAST_RIGHT[1] = s->motion_val[mot_xy + 2][1];
1091
            P_LAST_BOTTOM[0]= s->motion_val[mot_xy + 2*mot_stride][0];
1092
            P_LAST_BOTTOM[1]= s->motion_val[mot_xy + 2*mot_stride][1];
1093

    
1094
            if(P_LEFT[0]       > (rel_xmax<<shift)) P_LEFT[0]       = (rel_xmax<<shift);
1095
            if(P_LAST_RIGHT[0] < (rel_xmin<<shift)) P_LAST_RIGHT[0] = (rel_xmin<<shift);
1096
            if(P_LAST_BOTTOM[1]< (rel_ymin<<shift)) P_LAST_BOTTOM[1]= (rel_ymin<<shift);
1097

    
1098
            /* special case for first line */
1099
            if ((mb_y == 0 || s->first_slice_line)) {
1100
                pred_x= P_LEFT[0];
1101
                pred_y= P_LEFT[1];
1102
            } else {
1103
                P_TOP[0]      = s->motion_val[mot_xy - mot_stride    ][0];
1104
                P_TOP[1]      = s->motion_val[mot_xy - mot_stride    ][1];
1105
                P_TOPRIGHT[0] = s->motion_val[mot_xy - mot_stride + 2][0];
1106
                P_TOPRIGHT[1] = s->motion_val[mot_xy - mot_stride + 2][1];
1107
                if(P_TOP[1]      > (rel_ymax<<shift)) P_TOP[1]     = (rel_ymax<<shift);
1108
                if(P_TOPRIGHT[0] < (rel_xmin<<shift)) P_TOPRIGHT[0]= (rel_xmin<<shift);
1109
                if(P_TOPRIGHT[1] > (rel_ymax<<shift)) P_TOPRIGHT[1]= (rel_ymax<<shift);
1110
        
1111
                P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1112
                P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1113

    
1114
                if(s->out_format == FMT_H263){
1115
                    pred_x = P_MEDIAN[0];
1116
                    pred_y = P_MEDIAN[1];
1117
                }else { /* mpeg1 at least */
1118
                    pred_x= P_LEFT[0];
1119
                    pred_y= P_LEFT[1];
1120
                }
1121
            }
1122
        }
1123
        dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax, ref_picture);
1124
 
1125
        break;
1126
    }
1127

    
1128
    /* intra / predictive decision */
1129
    xx = mb_x * 16;
1130
    yy = mb_y * 16;
1131

    
1132
    pix = s->new_picture[0] + (yy * s->linesize) + xx;
1133
    /* At this point (mx,my) are full-pell and the relative displacement */
1134
    ppix = ref_picture + ((yy+my) * s->linesize) + (xx+mx);
1135
    
1136
    sum = pix_sum(pix, s->linesize);
1137
    
1138
    sum= (sum+8)>>4;
1139
    varc = (pix_norm1(pix, s->linesize) - sum*sum + 500 + 128)>>8;
1140
    vard = (pix_norm(pix, ppix, s->linesize)+128)>>8;
1141

    
1142
//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);
1143
    s->mb_var   [s->mb_width * mb_y + mb_x] = varc;
1144
    s->mc_mb_var[s->mb_width * mb_y + mb_x] = vard;
1145
    s->mb_mean  [s->mb_width * mb_y + mb_x] = (sum+7)>>4;
1146
    s->mb_var_sum    += varc;
1147
    s->mc_mb_var_sum += vard;
1148
//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);
1149
    
1150
#if 0
1151
    printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
1152
           varc, s->avg_mb_var, sum, vard, mx - xx, my - yy);
1153
#endif
1154
    if(s->flags&CODEC_FLAG_HQ){
1155
        if (vard <= 64 || vard < varc)
1156
            s->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
1157
        else
1158
            s->scene_change_score+= 20;
1159

    
1160
        if (vard*2 + 200 > varc)
1161
            mb_type|= MB_TYPE_INTRA;
1162
        if (varc*2 + 200 > vard){
1163
            mb_type|= MB_TYPE_INTER;
1164
            if(s->me_method >= ME_EPZS)
1165
                fast_halfpel_motion_search(s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax, 
1166
                                           pred_x, pred_y, ref_picture, pix_abs16x16_x2, pix_abs16x16_y2, 
1167
                                           pix_abs16x16_xy2, 0);
1168
            else
1169
                halfpel_motion_search(     s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax, 
1170
                                           pred_x, pred_y, ref_picture, pix_abs16x16_x2, pix_abs16x16_y2, 
1171
                                           pix_abs16x16_xy2, 0);                                           
1172
        }else{
1173
            mx <<=1;
1174
            my <<=1;
1175
        }
1176
        if((s->flags&CODEC_FLAG_4MV)
1177
           && !s->skip_me && varc>50 && vard>10){
1178
            mv4_search(s, rel_xmin, rel_ymin, rel_xmax, rel_ymax, mx, my, shift);
1179
            mb_type|=MB_TYPE_INTER4V;
1180

    
1181
            set_p_mv_tables(s, mx, my, 0);
1182
        }else
1183
            set_p_mv_tables(s, mx, my, 1);
1184
    }else{
1185
        if (vard <= 64 || vard < varc) {
1186
            s->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
1187
            mb_type|= MB_TYPE_INTER;
1188
            if (s->me_method != ME_ZERO) {
1189
                if(s->me_method >= ME_EPZS)
1190
                    dmin= fast_halfpel_motion_search(s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax, 
1191
                                           pred_x, pred_y, ref_picture, pix_abs16x16_x2, pix_abs16x16_y2, 
1192
                                           pix_abs16x16_xy2, 0);
1193
                else
1194
                    dmin= halfpel_motion_search(s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax, 
1195
                                           pred_x, pred_y, ref_picture, pix_abs16x16_x2, pix_abs16x16_y2, 
1196
                                           pix_abs16x16_xy2, 0);
1197
                if((s->flags&CODEC_FLAG_4MV)
1198
                   && !s->skip_me && varc>50 && vard>10){
1199
                    int dmin4= mv4_search(s, rel_xmin, rel_ymin, rel_xmax, rel_ymax, mx, my, shift);
1200
                    if(dmin4 + 128 <dmin)
1201
                        mb_type= MB_TYPE_INTER4V;
1202
                }
1203
                set_p_mv_tables(s, mx, my, mb_type!=MB_TYPE_INTER4V);
1204

    
1205
            } else {
1206
                mx <<=1;
1207
                my <<=1;
1208
            }
1209
#if 0
1210
            if (vard < 10) {
1211
                skip++;
1212
                fprintf(stderr,"\nEarly skip: %d vard: %2d varc: %5d dmin: %d", 
1213
                                skip, vard, varc, dmin);
1214
            }
1215
#endif
1216
        }else{
1217
            s->scene_change_score+= 20;
1218
            mb_type|= MB_TYPE_INTRA;
1219
            mx = 0;
1220
            my = 0;
1221
        }
1222
    }
1223

    
1224
    s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
1225
}
1226

    
1227
int ff_estimate_motion_b(MpegEncContext * s,
1228
                       int mb_x, int mb_y, int16_t (*mv_table)[2], uint8_t *ref_picture, int f_code)
1229
{
1230
    int mx, my, range, dmin;
1231
    int xmin, ymin, xmax, ymax;
1232
    int rel_xmin, rel_ymin, rel_xmax, rel_ymax;
1233
    int pred_x=0, pred_y=0;
1234
    int P[10][2];
1235
    const int shift= 1+s->quarter_sample;
1236
    const int mot_stride = s->mb_width + 2;
1237
    const int mot_xy = (mb_y + 1)*mot_stride + mb_x + 1;
1238
    
1239
    get_limits(s, &range, &xmin, &ymin, &xmax, &ymax, f_code);
1240
    rel_xmin= xmin - mb_x*16;
1241
    rel_xmax= xmax - mb_x*16;
1242
    rel_ymin= ymin - mb_y*16;
1243
    rel_ymax= ymax - mb_y*16;
1244

    
1245
    switch(s->me_method) {
1246
    case ME_ZERO:
1247
    default:
1248
        no_motion_search(s, &mx, &my);
1249
        dmin = 0;
1250
        mx-= mb_x*16;
1251
        my-= mb_y*16;
1252
        break;
1253
    case ME_FULL:
1254
        dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax, ref_picture);
1255
        mx-= mb_x*16;
1256
        my-= mb_y*16;
1257
        break;
1258
    case ME_LOG:
1259
        dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture);
1260
        mx-= mb_x*16;
1261
        my-= mb_y*16;
1262
        break;
1263
    case ME_PHODS:
1264
        dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax, ref_picture);
1265
        mx-= mb_x*16;
1266
        my-= mb_y*16;
1267
        break;
1268
    case ME_X1:
1269
    case ME_EPZS:
1270
       {
1271

    
1272
            P_LAST[0]        = mv_table[mot_xy    ][0];
1273
            P_LAST[1]        = mv_table[mot_xy    ][1];
1274
            P_LEFT[0]        = mv_table[mot_xy - 1][0];
1275
            P_LEFT[1]        = mv_table[mot_xy - 1][1];
1276
            P_LAST_RIGHT[0]  = mv_table[mot_xy + 1][0];
1277
            P_LAST_RIGHT[1]  = mv_table[mot_xy + 1][1];
1278
            P_LAST_BOTTOM[0] = mv_table[mot_xy + mot_stride][0];
1279
            P_LAST_BOTTOM[1] = mv_table[mot_xy + mot_stride][1];
1280

    
1281
            if(P_LEFT[0]       > (rel_xmax<<shift)) P_LEFT[0]       = (rel_xmax<<shift);
1282
            if(P_LAST_RIGHT[0] < (rel_xmin<<shift)) P_LAST_RIGHT[0] = (rel_xmin<<shift);
1283
            if(P_LAST_BOTTOM[1]< (rel_ymin<<shift)) P_LAST_BOTTOM[1]= (rel_ymin<<shift);
1284

    
1285
            /* special case for first line */
1286
            if ((mb_y == 0 || s->first_slice_line)) {
1287
            } else {
1288
                P_TOP[0] = mv_table[mot_xy - mot_stride             ][0];
1289
                P_TOP[1] = mv_table[mot_xy - mot_stride             ][1];
1290
                P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1         ][0];
1291
                P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1         ][1];
1292
                if(P_TOP[1] > (rel_ymax<<shift)) P_TOP[1]= (rel_ymax<<shift);
1293
                if(P_TOPRIGHT[0] < (rel_xmin<<shift)) P_TOPRIGHT[0]= (rel_xmin<<shift);
1294
                if(P_TOPRIGHT[1] > (rel_ymax<<shift)) P_TOPRIGHT[1]= (rel_ymax<<shift);
1295
        
1296
                P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1297
                P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1298
            }
1299
            pred_x= P_LEFT[0];
1300
            pred_y= P_LEFT[1];
1301
        }
1302
        dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax, ref_picture);
1303
 
1304
        break;
1305
    }
1306
    
1307
    dmin= fast_halfpel_motion_search(s, &mx, &my, dmin, rel_xmin, rel_ymin, rel_xmax, rel_ymax, 
1308
                                pred_x, pred_y, ref_picture, pix_abs16x16_x2, pix_abs16x16_y2, 
1309
                                pix_abs16x16_xy2, 0);
1310
//printf("%d %d %d %d//", s->mb_x, s->mb_y, mx, my);
1311
//    s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
1312
    mv_table[mot_xy][0]= mx;
1313
    mv_table[mot_xy][1]= my;
1314
    return dmin;
1315
}
1316

    
1317

    
1318
static inline int check_bidir_mv(MpegEncContext * s,
1319
                   int mb_x, int mb_y,
1320
                   int motion_fx, int motion_fy,
1321
                   int motion_bx, int motion_by,
1322
                   int pred_fx, int pred_fy,
1323
                   int pred_bx, int pred_by)
1324
{
1325
    //FIXME optimize?
1326
    //FIXME direct mode penalty
1327
    UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
1328
    uint8_t *dest_y = s->me_scratchpad;
1329
    uint8_t *ptr;
1330
    int dxy;
1331
    int src_x, src_y;
1332
    int fbmin;
1333

    
1334
    fbmin = (mv_penalty[motion_fx-pred_fx] + mv_penalty[motion_fy-pred_fy])*s->qscale;
1335

    
1336
    dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
1337
    src_x = mb_x * 16 + (motion_fx >> 1);
1338
    src_y = mb_y * 16 + (motion_fy >> 1);
1339
    src_x = clip(src_x, -16, s->width);
1340
    if (src_x == s->width)
1341
        dxy&= 2;
1342
    src_y = clip(src_y, -16, s->height);
1343
    if (src_y == s->height)
1344
        dxy&= 1;
1345

    
1346
    ptr = s->last_picture[0] + (src_y * s->linesize) + src_x;
1347
    put_pixels_tab[0][dxy](dest_y    , ptr    , s->linesize, 16);
1348
    
1349
    fbmin += (mv_penalty[motion_bx-pred_bx] + mv_penalty[motion_by-pred_by])*s->qscale;
1350

    
1351
    dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
1352
    src_x = mb_x * 16 + (motion_bx >> 1);
1353
    src_y = mb_y * 16 + (motion_by >> 1);
1354
    src_x = clip(src_x, -16, s->width);
1355
    if (src_x == s->width)
1356
        dxy&= 2;
1357
    src_y = clip(src_y, -16, s->height);
1358
    if (src_y == s->height)
1359
        dxy&= 1;
1360
            
1361
    ptr = s->next_picture[0] + (src_y * s->linesize) + src_x;
1362
    avg_pixels_tab[0][dxy](dest_y    , ptr    , s->linesize, 16);
1363
    
1364
    fbmin += pix_abs16x16(s->new_picture[0] + mb_x*16 + mb_y*16*s->linesize, dest_y, s->linesize);
1365
    return fbmin;
1366
}
1367

    
1368
/* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
1369
static inline int bidir_refine(MpegEncContext * s,
1370
                                  int mb_x, int mb_y)
1371
{
1372
    const int mot_stride = s->mb_width + 2;
1373
    const int xy = (mb_y + 1)*mot_stride + mb_x + 1;
1374
    int fbmin;
1375
    int pred_fx= s->b_bidir_forw_mv_table[xy-1][0];
1376
    int pred_fy= s->b_bidir_forw_mv_table[xy-1][1];
1377
    int pred_bx= s->b_bidir_back_mv_table[xy-1][0];
1378
    int pred_by= s->b_bidir_back_mv_table[xy-1][1];
1379
    int motion_fx= s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0];
1380
    int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1];
1381
    int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0];
1382
    int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1];
1383

    
1384
    //FIXME do refinement and add flag
1385
    
1386
    fbmin= check_bidir_mv(s, mb_x, mb_y, 
1387
                          motion_fx, motion_fy,
1388
                          motion_bx, motion_by,
1389
                          pred_fx, pred_fy,
1390
                          pred_bx, pred_by);
1391

    
1392
   return fbmin;
1393
}
1394

    
1395
static inline int direct_search(MpegEncContext * s,
1396
                                int mb_x, int mb_y)
1397
{
1398
    int P[10][2];
1399
    const int mot_stride = s->mb_width + 2;
1400
    const int mot_xy = (mb_y + 1)*mot_stride + mb_x + 1;
1401
    int dmin, dmin2;
1402
    int motion_fx, motion_fy, motion_bx, motion_by, motion_bx0, motion_by0;
1403
    int motion_dx, motion_dy;
1404
    const int motion_px= s->p_mv_table[mot_xy][0];
1405
    const int motion_py= s->p_mv_table[mot_xy][1];
1406
    const int time_pp= s->pp_time;
1407
    const int time_pb= s->pb_time;
1408
    const int time_bp= time_pp - time_pb;
1409
    int bx, by;
1410
    int mx, my, mx2, my2;
1411
    uint8_t *ref_picture= s->me_scratchpad - (mb_x - 1 + (mb_y - 1)*s->linesize)*16;
1412
    int16_t (*mv_table)[2]= s->b_direct_mv_table;
1413
/*    uint16_t *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; */ // f_code of the prev frame
1414

    
1415
    /* thanks to iso-mpeg the rounding is different for the zero vector, so we need to handle that ... */
1416
    motion_fx= (motion_px*time_pb)/time_pp;
1417
    motion_fy= (motion_py*time_pb)/time_pp;
1418
    motion_bx0= (-motion_px*time_bp)/time_pp;
1419
    motion_by0= (-motion_py*time_bp)/time_pp;
1420
    motion_dx= motion_dy=0;
1421
    dmin2= check_bidir_mv(s, mb_x, mb_y, 
1422
                          motion_fx, motion_fy,
1423
                          motion_bx0, motion_by0,
1424
                          motion_fx, motion_fy,
1425
                          motion_bx0, motion_by0) - s->qscale;
1426

    
1427
    motion_bx= motion_fx - motion_px;
1428
    motion_by= motion_fy - motion_py;
1429
    for(by=-1; by<2; by++){
1430
        for(bx=-1; bx<2; bx++){
1431
            uint8_t *dest_y = s->me_scratchpad + (by+1)*s->linesize*16 + (bx+1)*16;
1432
            uint8_t *ptr;
1433
            int dxy;
1434
            int src_x, src_y;
1435
            const int width= s->width;
1436
            const int height= s->height;
1437

    
1438
            dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
1439
            src_x = (mb_x + bx) * 16 + (motion_fx >> 1);
1440
            src_y = (mb_y + by) * 16 + (motion_fy >> 1);
1441
            src_x = clip(src_x, -16, width);
1442
            if (src_x == width) dxy &= ~1;
1443
            src_y = clip(src_y, -16, height);
1444
            if (src_y == height) dxy &= ~2;
1445

    
1446
            ptr = s->last_picture[0] + (src_y * s->linesize) + src_x;
1447
            put_pixels_tab[0][dxy](dest_y    , ptr    , s->linesize, 16);
1448

    
1449
            dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
1450
            src_x = (mb_x + bx) * 16 + (motion_bx >> 1);
1451
            src_y = (mb_y + by) * 16 + (motion_by >> 1);
1452
            src_x = clip(src_x, -16, width);
1453
            if (src_x == width) dxy &= ~1;
1454
            src_y = clip(src_y, -16, height);
1455
            if (src_y == height) dxy &= ~2;
1456

    
1457
            avg_pixels_tab[0][dxy](dest_y    , ptr    , s->linesize, 16);
1458
        }
1459
    }
1460

    
1461
    P_LAST[0]        = mv_table[mot_xy    ][0];
1462
    P_LAST[1]        = mv_table[mot_xy    ][1];
1463
    P_LEFT[0]        = mv_table[mot_xy - 1][0];
1464
    P_LEFT[1]        = mv_table[mot_xy - 1][1];
1465
    P_LAST_RIGHT[0]  = mv_table[mot_xy + 1][0];
1466
    P_LAST_RIGHT[1]  = mv_table[mot_xy + 1][1];
1467
    P_LAST_BOTTOM[0] = mv_table[mot_xy + mot_stride][0];
1468
    P_LAST_BOTTOM[1] = mv_table[mot_xy + mot_stride][1];
1469
/*
1470
    if(P_LEFT[0]       > (rel_xmax<<shift)) P_LEFT[0]       = (rel_xmax<<shift);
1471
    if(P_LAST_RIGHT[0] < (rel_xmin<<shift)) P_LAST_RIGHT[0] = (rel_xmin<<shift);
1472
    if(P_LAST_BOTTOM[1]< (rel_ymin<<shift)) P_LAST_BOTTOM[1]= (rel_ymin<<shift);
1473
*/
1474
    /* special case for first line */
1475
    if ((mb_y == 0 || s->first_slice_line)) {
1476
    } else {
1477
        P_TOP[0] = mv_table[mot_xy - mot_stride             ][0];
1478
        P_TOP[1] = mv_table[mot_xy - mot_stride             ][1];
1479
        P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1         ][0];
1480
        P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1         ][1];
1481
    
1482
        P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
1483
        P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1484
    }
1485
    dmin = epzs_motion_search(s, &mx, &my, P, 0, 0, -16, -16, 15, 15, ref_picture);
1486
    if(mx==0 && my==0) dmin=99999999; // not representable, due to rounding stuff
1487
    if(dmin2<dmin){ 
1488
        dmin= dmin2;
1489
        mx=0;
1490
        my=0;
1491
    }
1492
#if 1
1493
    mx2= mx= mx*2; 
1494
    my2= my= my*2;
1495
    for(by=-1; by<2; by++){
1496
        if(my2+by < -32) continue;
1497
        for(bx=-1; bx<2; bx++){
1498
            if(bx==0 && by==0) continue;
1499
            if(mx2+bx < -32) continue;
1500
            dmin2= check_bidir_mv(s, mb_x, mb_y, 
1501
                          mx2+bx+motion_fx, my2+by+motion_fy,
1502
                          mx2+bx+motion_bx, my2+by+motion_by,
1503
                          mx2+bx+motion_fx, my2+by+motion_fy,
1504
                          motion_bx, motion_by) - s->qscale;
1505
            
1506
            if(dmin2<dmin){
1507
                dmin=dmin2;
1508
                mx= mx2 + bx;
1509
                my= my2 + by;
1510
            }
1511
        }
1512
    }
1513
#else
1514
    mx*=2; my*=2;
1515
#endif
1516
    if(mx==0 && my==0){
1517
        motion_bx= motion_bx0;
1518
        motion_by= motion_by0;
1519
    }
1520

    
1521
    s->b_direct_mv_table[mot_xy][0]= mx;
1522
    s->b_direct_mv_table[mot_xy][1]= my;
1523
    s->b_direct_forw_mv_table[mot_xy][0]= motion_fx + mx;
1524
    s->b_direct_forw_mv_table[mot_xy][1]= motion_fy + my;
1525
    s->b_direct_back_mv_table[mot_xy][0]= motion_bx + mx;
1526
    s->b_direct_back_mv_table[mot_xy][1]= motion_by + my;
1527
    return dmin;
1528
}
1529

    
1530
void ff_estimate_b_frame_motion(MpegEncContext * s,
1531
                             int mb_x, int mb_y)
1532
{
1533
    const int quant= s->qscale;
1534
    int fmin, bmin, dmin, fbmin;
1535
    int type=0;
1536
    
1537
    dmin= direct_search(s, mb_x, mb_y);
1538

    
1539
    fmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, s->last_picture[0], s->f_code);
1540
    bmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, s->next_picture[0], s->b_code) - quant;
1541
//printf(" %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
1542

    
1543
    fbmin= bidir_refine(s, mb_x, mb_y);
1544

    
1545
    {
1546
        int score= dmin;
1547
        type=MB_TYPE_DIRECT;
1548
        
1549
        if(fmin<score){
1550
            score=fmin;
1551
            type= MB_TYPE_FORWARD; 
1552
        }
1553
        if(bmin<score){
1554
            score=bmin;
1555
            type= MB_TYPE_BACKWARD; 
1556
        }
1557
        if(fbmin<score){
1558
            score=fbmin;
1559
            type= MB_TYPE_BIDIR;
1560
        }
1561
        score= (score*score + 128*256)>>16;
1562
        s->mc_mb_var_sum += score;
1563
        s->mc_mb_var[mb_y*s->mb_width + mb_x] = score; //FIXME use SSD
1564
    }
1565

    
1566
    if(s->flags&CODEC_FLAG_HQ){
1567
        type= MB_TYPE_FORWARD | MB_TYPE_BACKWARD | MB_TYPE_BIDIR | MB_TYPE_DIRECT; //FIXME something smarter
1568
    }
1569

    
1570
/*
1571
{
1572
static int count=0;
1573
static int sum=0;
1574
if(type==MB_TYPE_DIRECT){
1575
  int diff= ABS(s->b_forw_mv_table)
1576
}
1577
}*/
1578

    
1579
    s->mb_type[mb_y*s->mb_width + mb_x]= type;
1580
/*    if(mb_y==0 && mb_x==0) printf("\n");
1581
    if(mb_x==0) printf("\n");
1582
    printf("%d", av_log2(type));
1583
*/
1584
}
1585

    
1586
/* find best f_code for ME which do unlimited searches */
1587
int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type)
1588
{
1589
    if(s->me_method>=ME_EPZS){
1590
        int score[8];
1591
        int i, y;
1592
        UINT8 * fcode_tab= s->fcode_tab;
1593
        int best_fcode=-1;
1594
        int best_score=-10000000;
1595

    
1596
        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
1597

    
1598
        for(y=0; y<s->mb_height; y++){
1599
            int x;
1600
            int xy= (y+1)* (s->mb_width+2) + 1;
1601
            i= y*s->mb_width;
1602
            for(x=0; x<s->mb_width; x++){
1603
                if(s->mb_type[i] & type){
1604
                    int fcode= MAX(fcode_tab[mv_table[xy][0] + MAX_MV],
1605
                                   fcode_tab[mv_table[xy][1] + MAX_MV]);
1606
                    int j;
1607
                    
1608
                    for(j=0; j<fcode && j<8; j++){
1609
                        if(s->pict_type==B_TYPE || s->mc_mb_var[i] < s->mb_var[i])
1610
                            score[j]-= 170;
1611
                    }
1612
                }
1613
                i++;
1614
                xy++;
1615
            }
1616
        }
1617
        
1618
        for(i=1; i<8; i++){
1619
            if(score[i] > best_score){
1620
                best_score= score[i];
1621
                best_fcode= i;
1622
            }
1623
//            printf("%d %d\n", i, score[i]);
1624
        }
1625

    
1626
//    printf("fcode: %d type: %d\n", i, s->pict_type);
1627
        return best_fcode;
1628
/*        for(i=0; i<=MAX_FCODE; i++){
1629
            printf("%d ", mv_num[i]);
1630
        }
1631
        printf("\n");*/
1632
    }else{
1633
        return 1;
1634
    }
1635
}
1636

    
1637
void ff_fix_long_p_mvs(MpegEncContext * s)
1638
{
1639
    const int f_code= s->f_code;
1640
    int y;
1641
    UINT8 * fcode_tab= s->fcode_tab;
1642
//int clip=0;
1643
//int noclip=0;
1644
    /* clip / convert to intra 16x16 type MVs */
1645
    for(y=0; y<s->mb_height; y++){
1646
        int x;
1647
        int xy= (y+1)* (s->mb_width+2)+1;
1648
        int i= y*s->mb_width;
1649
        for(x=0; x<s->mb_width; x++){
1650
            if(s->mb_type[i]&MB_TYPE_INTER){
1651
                if(   fcode_tab[s->p_mv_table[xy][0] + MAX_MV] > f_code
1652
                   || fcode_tab[s->p_mv_table[xy][0] + MAX_MV] == 0
1653
                   || fcode_tab[s->p_mv_table[xy][1] + MAX_MV] > f_code
1654
                   || fcode_tab[s->p_mv_table[xy][1] + MAX_MV] == 0 ){
1655
                    s->mb_type[i] &= ~MB_TYPE_INTER;
1656
                    s->mb_type[i] |= MB_TYPE_INTRA;
1657
                    s->p_mv_table[xy][0] = 0;
1658
                    s->p_mv_table[xy][1] = 0;
1659
//clip++;
1660
                }
1661
//else
1662
//  noclip++;
1663
            }
1664
            xy++;
1665
            i++;
1666
        }
1667
    }
1668
//printf("%d no:%d %d//\n", clip, noclip, f_code);
1669
    if(s->flags&CODEC_FLAG_4MV){
1670
        const int wrap= 2+ s->mb_width*2;
1671

    
1672
        /* clip / convert to intra 8x8 type MVs */
1673
        for(y=0; y<s->mb_height; y++){
1674
            int xy= (y*2 + 1)*wrap + 1;
1675
            int i= y*s->mb_width;
1676
            int x;
1677

    
1678
            for(x=0; x<s->mb_width; x++){
1679
                if(s->mb_type[i]&MB_TYPE_INTER4V){
1680
                    int block;
1681
                    for(block=0; block<4; block++){
1682
                        int off= (block& 1) + (block>>1)*wrap;
1683
                        int mx= s->motion_val[ xy + off ][0];
1684
                        int my= s->motion_val[ xy + off ][1];
1685

    
1686
                        if(   fcode_tab[mx + MAX_MV] > f_code
1687
                           || fcode_tab[mx + MAX_MV] == 0
1688
                           || fcode_tab[my + MAX_MV] > f_code
1689
                           || fcode_tab[my + MAX_MV] == 0 ){
1690
                            s->mb_type[i] &= ~MB_TYPE_INTER4V;
1691
                            s->mb_type[i] |= MB_TYPE_INTRA;
1692
                        }
1693
                    }
1694
                }
1695
                xy+=2;
1696
                i++;
1697
            }
1698
        }
1699
    }
1700
}
1701

    
1702
void ff_fix_long_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, int type)
1703
{
1704
    int y;
1705
    UINT8 * fcode_tab= s->fcode_tab;
1706

    
1707
    /* clip / convert to intra 16x16 type MVs */
1708
    for(y=0; y<s->mb_height; y++){
1709
        int x;
1710
        int xy= (y+1)* (s->mb_width+2)+1;
1711
        int i= y*s->mb_width;
1712
        for(x=0; x<s->mb_width; x++){
1713
            if(   fcode_tab[mv_table[xy][0] + MAX_MV] > f_code
1714
               || fcode_tab[mv_table[xy][0] + MAX_MV] == 0){
1715
                if(mv_table[xy][0]>0) mv_table[xy][0]=  (16<<f_code)-1;
1716
                else                  mv_table[xy][0]= -(16<<f_code);
1717
            }
1718
            if(   fcode_tab[mv_table[xy][1] + MAX_MV] > f_code
1719
               || fcode_tab[mv_table[xy][1] + MAX_MV] == 0){
1720
                if(mv_table[xy][1]>0) mv_table[xy][1]=  (16<<f_code)-1;
1721
                else                  mv_table[xy][1]= -(16<<f_code);
1722
            }
1723
            xy++;
1724
            i++;
1725
        }
1726
    }
1727
}