Statistics
| Branch: | Revision:

ffmpeg / libavcodec / motion_est.c @ 07787186

History | View | Annotate | Download (55.8 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_var_sum    += varc;
1146
    s->mc_mb_var_sum += vard;
1147
//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);
1148
    
1149
#if 0
1150
    printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
1151
           varc, s->avg_mb_var, sum, vard, mx - xx, my - yy);
1152
#endif
1153
    if(s->flags&CODEC_FLAG_HQ){
1154
        if (vard <= 64 || vard < varc)
1155
            s->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
1156
        else
1157
            s->scene_change_score+= 20;
1158

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

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

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

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

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

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

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

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

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

    
1316

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

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

    
1335
    dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
1336
    src_x = mb_x * 16 + (motion_fx >> 1);
1337
    src_y = mb_y * 16 + (motion_fy >> 1);
1338
            
1339
    ptr = s->last_picture[0] + (src_y * s->linesize) + src_x;
1340
    put_pixels_tab[dxy](dest_y    , ptr    , s->linesize, 16);
1341
    put_pixels_tab[dxy](dest_y + 8, ptr + 8, s->linesize, 16);
1342
    
1343
    fbmin += (mv_penalty[motion_bx-pred_bx] + mv_penalty[motion_by-pred_by])*s->qscale;
1344

    
1345
    dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
1346
    src_x = mb_x * 16 + (motion_bx >> 1);
1347
    src_y = mb_y * 16 + (motion_by >> 1);
1348
            
1349
    ptr = s->next_picture[0] + (src_y * s->linesize) + src_x;
1350
    avg_pixels_tab[dxy](dest_y    , ptr    , s->linesize, 16);
1351
    avg_pixels_tab[dxy](dest_y + 8, ptr + 8, s->linesize, 16);
1352
    
1353
    fbmin += pix_abs16x16(s->new_picture[0] + mb_x*16 + mb_y*16*s->linesize, dest_y, s->linesize);
1354
    return fbmin;
1355
}
1356

    
1357
/* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
1358
static inline int bidir_refine(MpegEncContext * s,
1359
                                  int mb_x, int mb_y)
1360
{
1361
    const int mot_stride = s->mb_width + 2;
1362
    const int xy = (mb_y + 1)*mot_stride + mb_x + 1;
1363
    int fbmin;
1364
    int pred_fx= s->b_bidir_forw_mv_table[xy-1][0];
1365
    int pred_fy= s->b_bidir_forw_mv_table[xy-1][1];
1366
    int pred_bx= s->b_bidir_back_mv_table[xy-1][0];
1367
    int pred_by= s->b_bidir_back_mv_table[xy-1][1];
1368
    int motion_fx= s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0];
1369
    int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1];
1370
    int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0];
1371
    int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1];
1372

    
1373
    //FIXME do refinement and add flag
1374
    
1375
    fbmin= check_bidir_mv(s, mb_x, mb_y, 
1376
                          motion_fx, motion_fy,
1377
                          motion_bx, motion_by,
1378
                          pred_fx, pred_fy,
1379
                          pred_bx, pred_by);
1380

    
1381
   return fbmin;
1382
}
1383

    
1384
static inline int direct_search(MpegEncContext * s,
1385
                                int mb_x, int mb_y)
1386
{
1387
    int P[10][2];
1388
    const int mot_stride = s->mb_width + 2;
1389
    const int mot_xy = (mb_y + 1)*mot_stride + mb_x + 1;
1390
    int dmin, dmin2;
1391
    int motion_fx, motion_fy, motion_bx, motion_by, motion_bx0, motion_by0;
1392
    int motion_dx, motion_dy;
1393
    const int motion_px= s->p_mv_table[mot_xy][0];
1394
    const int motion_py= s->p_mv_table[mot_xy][1];
1395
    const int time_pp= s->pp_time;
1396
    const int time_bp= s->bp_time;
1397
    const int time_pb= time_pp - time_bp;
1398
    int bx, by;
1399
    int mx, my, mx2, my2;
1400
    uint8_t *ref_picture= s->me_scratchpad - (mb_x - 1 + (mb_y - 1)*s->linesize)*16;
1401
    int16_t (*mv_table)[2]= s->b_direct_mv_table;
1402
/*    uint16_t *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; */ // f_code of the prev frame
1403

    
1404
    /* thanks to iso-mpeg the rounding is different for the zero vector, so we need to handle that ... */
1405
    motion_fx= (motion_px*time_pb)/time_pp;
1406
    motion_fy= (motion_py*time_pb)/time_pp;
1407
    motion_bx0= (-motion_px*time_bp)/time_pp;
1408
    motion_by0= (-motion_py*time_bp)/time_pp;
1409
    motion_dx= motion_dy=0;
1410
    dmin2= check_bidir_mv(s, mb_x, mb_y, 
1411
                          motion_fx, motion_fy,
1412
                          motion_bx0, motion_by0,
1413
                          motion_fx, motion_fy,
1414
                          motion_bx0, motion_by0) - s->qscale;
1415

    
1416
    motion_bx= motion_fx - motion_px;
1417
    motion_by= motion_fy - motion_py;
1418
    for(by=-1; by<2; by++){
1419
        for(bx=-1; bx<2; bx++){
1420
            uint8_t *dest_y = s->me_scratchpad + (by+1)*s->linesize*16 + (bx+1)*16;
1421
            uint8_t *ptr;
1422
            int dxy;
1423
            int src_x, src_y;
1424
            const int width= s->width;
1425
            const int height= s->height;
1426

    
1427
            dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
1428
            src_x = (mb_x + bx) * 16 + (motion_fx >> 1);
1429
            src_y = (mb_y + by) * 16 + (motion_fy >> 1);
1430
            src_x = clip(src_x, -16, width);
1431
            if (src_x == width) dxy &= ~1;
1432
            src_y = clip(src_y, -16, height);
1433
            if (src_y == height) dxy &= ~2;
1434

    
1435
            ptr = s->last_picture[0] + (src_y * s->linesize) + src_x;
1436
            put_pixels_tab[dxy](dest_y    , ptr    , s->linesize, 16);
1437
            put_pixels_tab[dxy](dest_y + 8, ptr + 8, s->linesize, 16);
1438

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

    
1447
            avg_pixels_tab[dxy](dest_y    , ptr    , s->linesize, 16);
1448
            avg_pixels_tab[dxy](dest_y + 8, ptr + 8, s->linesize, 16);
1449
        }
1450
    }
1451

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

    
1512
    s->b_direct_mv_table[mot_xy][0]= mx;
1513
    s->b_direct_mv_table[mot_xy][1]= my;
1514
    s->b_direct_forw_mv_table[mot_xy][0]= motion_fx + mx;
1515
    s->b_direct_forw_mv_table[mot_xy][1]= motion_fy + my;
1516
    s->b_direct_back_mv_table[mot_xy][0]= motion_bx + mx;
1517
    s->b_direct_back_mv_table[mot_xy][1]= motion_by + my;
1518
    return dmin;
1519
}
1520

    
1521
void ff_estimate_b_frame_motion(MpegEncContext * s,
1522
                             int mb_x, int mb_y)
1523
{
1524
    const int quant= s->qscale;
1525
    int fmin, bmin, dmin, fbmin;
1526
    int type=0;
1527
    
1528
    dmin= direct_search(s, mb_x, mb_y);
1529

    
1530
    fmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, s->last_picture[0], s->f_code);
1531
    bmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, s->next_picture[0], s->b_code) - quant;
1532
//printf(" %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
1533

    
1534
    fbmin= bidir_refine(s, mb_x, mb_y);
1535

    
1536
    {
1537
        int score= dmin;
1538
        type=MB_TYPE_DIRECT;
1539
        
1540
        if(fmin<score){
1541
            score=fmin;
1542
            type= MB_TYPE_FORWARD; 
1543
        }
1544
        if(bmin<score){
1545
            score=bmin;
1546
            type= MB_TYPE_BACKWARD; 
1547
        }
1548
        if(fbmin<score){
1549
            score=fbmin;
1550
            type= MB_TYPE_BIDIR;
1551
        }
1552
        score= (score*score)>>8;
1553
        s->mc_mb_var_sum += score;
1554
        s->mc_mb_var[mb_y*s->mb_width + mb_x] = score; //FIXME use SSD
1555
    }
1556

    
1557
    if(s->flags&CODEC_FLAG_HQ){
1558
        type= MB_TYPE_FORWARD | MB_TYPE_BACKWARD | MB_TYPE_BIDIR | MB_TYPE_DIRECT; //FIXME something smarter
1559
    }
1560

    
1561
/*
1562
{
1563
static int count=0;
1564
static int sum=0;
1565
if(type==MB_TYPE_DIRECT){
1566
  int diff= ABS(s->b_forw_mv_table)
1567
}
1568
}*/
1569

    
1570
    s->mb_type[mb_y*s->mb_width + mb_x]= type;
1571
/*    if(mb_y==0 && mb_x==0) printf("\n");
1572
    if(mb_x==0) printf("\n");
1573
    printf("%d", av_log2(type));
1574
*/
1575
}
1576

    
1577
/* find best f_code for ME which do unlimited searches */
1578
int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type)
1579
{
1580
    if(s->me_method>=ME_EPZS){
1581
        int score[8];
1582
        int i, y;
1583
        UINT8 * fcode_tab= s->fcode_tab;
1584
        int best_fcode=-1;
1585
        int best_score=-10000000;
1586

    
1587
        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
1588

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

    
1617
//    printf("fcode: %d type: %d\n", i, s->pict_type);
1618
        return best_fcode;
1619
/*        for(i=0; i<=MAX_FCODE; i++){
1620
            printf("%d ", mv_num[i]);
1621
        }
1622
        printf("\n");*/
1623
    }else{
1624
        return 1;
1625
    }
1626
}
1627

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

    
1663
        /* clip / convert to intra 8x8 type MVs */
1664
        for(y=0; y<s->mb_height; y++){
1665
            int xy= (y*2 + 1)*wrap + 1;
1666
            int i= y*s->mb_width;
1667
            int x;
1668

    
1669
            for(x=0; x<s->mb_width; x++){
1670
                if(s->mb_type[i]&MB_TYPE_INTER4V){
1671
                    int block;
1672
                    for(block=0; block<4; block++){
1673
                        int off= (block& 1) + (block>>1)*wrap;
1674
                        int mx= s->motion_val[ xy + off ][0];
1675
                        int my= s->motion_val[ xy + off ][1];
1676

    
1677
                        if(   fcode_tab[mx + MAX_MV] > f_code
1678
                           || fcode_tab[mx + MAX_MV] == 0
1679
                           || fcode_tab[my + MAX_MV] > f_code
1680
                           || fcode_tab[my + MAX_MV] == 0 ){
1681
                            s->mb_type[i] &= ~MB_TYPE_INTER4V;
1682
                            s->mb_type[i] |= MB_TYPE_INTRA;
1683
                        }
1684
                    }
1685
                }
1686
                xy+=2;
1687
                i++;
1688
            }
1689
        }
1690
    }
1691
}
1692

    
1693
void ff_fix_long_b_mvs(MpegEncContext * s, int16_t (*mv_table)[2], int f_code, int type)
1694
{
1695
    int y;
1696
    UINT8 * fcode_tab= s->fcode_tab;
1697

    
1698
    /* clip / convert to intra 16x16 type MVs */
1699
    for(y=0; y<s->mb_height; y++){
1700
        int x;
1701
        int xy= (y+1)* (s->mb_width+2)+1;
1702
        int i= y*s->mb_width;
1703
        for(x=0; x<s->mb_width; x++){
1704
            if(s->mb_type[i]&type){
1705
                if(   fcode_tab[mv_table[xy][0] + MAX_MV] > f_code
1706
                   || fcode_tab[mv_table[xy][0] + MAX_MV] == 0
1707
                   || fcode_tab[mv_table[xy][1] + MAX_MV] > f_code
1708
                   || fcode_tab[mv_table[xy][1] + MAX_MV] == 0 ){
1709
                    if(s->mb_type[i]&(~type)) s->mb_type[i] &= ~type;
1710
                    else{
1711
                        mv_table[xy][0] = 0;
1712
                        mv_table[xy][1] = 0;
1713
                        //this is certainly bad FIXME            
1714
                    }
1715
                }
1716
            }
1717
            xy++;
1718
            i++;
1719
        }
1720
    }
1721
}