Statistics
| Branch: | Revision:

ffmpeg / libavcodec / motion_est.c @ 11ce8834

History | View | Annotate | Download (21.5 KB)

1
/*
2
 * Motion estimation 
3
 * Copyright (c) 2000,2001 Gerard Lantau.
4
 * 
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
 *
20
 * new Motion Estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>
21
 */
22
#include <stdlib.h>
23
#include <stdio.h>
24
#include "avcodec.h"
25
#include "dsputil.h"
26
#include "mpegvideo.h"
27

    
28
static void halfpel_motion_search(MpegEncContext * s,
29
                                  int *mx_ptr, int *my_ptr, int dmin,
30
                                  int xmin, int ymin, int xmax, int ymax,
31
                                  int pred_x, int pred_y);
32

    
33
/* config it to test motion vector encoding (send random vectors) */
34
//#define CONFIG_TEST_MV_ENCODE
35

    
36
static int pix_sum(UINT8 * pix, int line_size)
37
{
38
    int s, i, j;
39

    
40
    s = 0;
41
    for (i = 0; i < 16; i++) {
42
        for (j = 0; j < 16; j += 8) {
43
            s += pix[0];
44
            s += pix[1];
45
            s += pix[2];
46
            s += pix[3];
47
            s += pix[4];
48
            s += pix[5];
49
            s += pix[6];
50
            s += pix[7];
51
            pix += 8;
52
        }
53
        pix += line_size - 16;
54
    }
55
    return s;
56
}
57

    
58
static int pix_norm1(UINT8 * pix, int line_size)
59
{
60
    int s, i, j;
61
    UINT32 *sq = squareTbl + 256;
62

    
63
    s = 0;
64
    for (i = 0; i < 16; i++) {
65
        for (j = 0; j < 16; j += 8) {
66
            s += sq[pix[0]];
67
            s += sq[pix[1]];
68
            s += sq[pix[2]];
69
            s += sq[pix[3]];
70
            s += sq[pix[4]];
71
            s += sq[pix[5]];
72
            s += sq[pix[6]];
73
            s += sq[pix[7]];
74
            pix += 8;
75
        }
76
        pix += line_size - 16;
77
    }
78
    return s;
79
}
80

    
81
static int pix_norm(UINT8 * pix1, UINT8 * pix2, int line_size)
82
{
83
    int s, i, j;
84
    UINT32 *sq = squareTbl + 256;
85

    
86
    s = 0;
87
    for (i = 0; i < 16; i++) {
88
        for (j = 0; j < 16; j += 8) {
89
            s += sq[pix1[0] - pix2[0]];
90
            s += sq[pix1[1] - pix2[1]];
91
            s += sq[pix1[2] - pix2[2]];
92
            s += sq[pix1[3] - pix2[3]];
93
            s += sq[pix1[4] - pix2[4]];
94
            s += sq[pix1[5] - pix2[5]];
95
            s += sq[pix1[6] - pix2[6]];
96
            s += sq[pix1[7] - pix2[7]];
97
            pix1 += 8;
98
            pix2 += 8;
99
        }
100
        pix1 += line_size - 16;
101
        pix2 += line_size - 16;
102
    }
103
    return s;
104
}
105

    
106
static void no_motion_search(MpegEncContext * s,
107
                             int *mx_ptr, int *my_ptr)
108
{
109
    *mx_ptr = 16 * s->mb_x;
110
    *my_ptr = 16 * s->mb_y;
111
}
112

    
113
static int full_motion_search(MpegEncContext * s,
114
                              int *mx_ptr, int *my_ptr, int range,
115
                              int xmin, int ymin, int xmax, int ymax)
116
{
117
    int x1, y1, x2, y2, xx, yy, x, y;
118
    int mx, my, dmin, d;
119
    UINT8 *pix;
120

    
121
    xx = 16 * s->mb_x;
122
    yy = 16 * s->mb_y;
123
    x1 = xx - range + 1;        /* we loose one pixel to avoid boundary pb with half pixel pred */
124
    if (x1 < xmin)
125
        x1 = xmin;
126
    x2 = xx + range - 1;
127
    if (x2 > xmax)
128
        x2 = xmax;
129
    y1 = yy - range + 1;
130
    if (y1 < ymin)
131
        y1 = ymin;
132
    y2 = yy + range - 1;
133
    if (y2 > ymax)
134
        y2 = ymax;
135
    pix = s->new_picture[0] + (yy * s->linesize) + xx;
136
    dmin = 0x7fffffff;
137
    mx = 0;
138
    my = 0;
139
    for (y = y1; y <= y2; y++) {
140
        for (x = x1; x <= x2; x++) {
141
            d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x,
142
                             s->linesize, 16);
143
            if (d < dmin ||
144
                (d == dmin &&
145
                 (abs(x - xx) + abs(y - yy)) <
146
                 (abs(mx - xx) + abs(my - yy)))) {
147
                dmin = d;
148
                mx = x;
149
                my = y;
150
            }
151
        }
152
    }
153

    
154
    *mx_ptr = mx;
155
    *my_ptr = my;
156

    
157
#if 0
158
    if (*mx_ptr < -(2 * range) || *mx_ptr >= (2 * range) ||
159
        *my_ptr < -(2 * range) || *my_ptr >= (2 * range)) {
160
        fprintf(stderr, "error %d %d\n", *mx_ptr, *my_ptr);
161
    }
162
#endif
163
    return dmin;
164
}
165

    
166

    
167
static int log_motion_search(MpegEncContext * s,
168
                             int *mx_ptr, int *my_ptr, int range,
169
                             int xmin, int ymin, int xmax, int ymax)
170
{
171
    int x1, y1, x2, y2, xx, yy, x, y;
172
    int mx, my, dmin, d;
173
    UINT8 *pix;
174

    
175
    xx = s->mb_x << 4;
176
    yy = s->mb_y << 4;
177

    
178
    /* Left limit */
179
    x1 = xx - range;
180
    if (x1 < xmin)
181
        x1 = xmin;
182

    
183
    /* Right limit */
184
    x2 = xx + range;
185
    if (x2 > xmax)
186
        x2 = xmax;
187

    
188
    /* Upper limit */
189
    y1 = yy - range;
190
    if (y1 < ymin)
191
        y1 = ymin;
192

    
193
    /* Lower limit */
194
    y2 = yy + range;
195
    if (y2 > ymax)
196
        y2 = ymax;
197

    
198
    pix = s->new_picture[0] + (yy * s->linesize) + xx;
199
    dmin = 0x7fffffff;
200
    mx = 0;
201
    my = 0;
202

    
203
    do {
204
        for (y = y1; y <= y2; y += range) {
205
            for (x = x1; x <= x2; x += range) {
206
                d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
207
                if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
208
                    dmin = d;
209
                    mx = x;
210
                    my = y;
211
                }
212
            }
213
        }
214

    
215
        range = range >> 1;
216

    
217
        x1 = mx - range;
218
        if (x1 < xmin)
219
            x1 = xmin;
220

    
221
        x2 = mx + range;
222
        if (x2 > xmax)
223
            x2 = xmax;
224

    
225
        y1 = my - range;
226
        if (y1 < ymin)
227
            y1 = ymin;
228

    
229
        y2 = my + range;
230
        if (y2 > ymax)
231
            y2 = ymax;
232

    
233
    } while (range >= 1);
234

    
235
#ifdef DEBUG
236
    fprintf(stderr, "log       - MX: %d\tMY: %d\n", mx, my);
237
#endif
238
    *mx_ptr = mx;
239
    *my_ptr = my;
240
    return dmin;
241
}
242

    
243
static int phods_motion_search(MpegEncContext * s,
244
                               int *mx_ptr, int *my_ptr, int range,
245
                               int xmin, int ymin, int xmax, int ymax)
246
{
247
    int x1, y1, x2, y2, xx, yy, x, y, lastx, d;
248
    int mx, my, dminx, dminy;
249
    UINT8 *pix;
250

    
251
    xx = s->mb_x << 4;
252
    yy = s->mb_y << 4;
253

    
254
    /* Left limit */
255
    x1 = xx - range;
256
    if (x1 < xmin)
257
        x1 = xmin;
258

    
259
    /* Right limit */
260
    x2 = xx + range;
261
    if (x2 > xmax)
262
        x2 = xmax;
263

    
264
    /* Upper limit */
265
    y1 = yy - range;
266
    if (y1 < ymin)
267
        y1 = ymin;
268

    
269
    /* Lower limit */
270
    y2 = yy + range;
271
    if (y2 > ymax)
272
        y2 = ymax;
273

    
274
    pix = s->new_picture[0] + (yy * s->linesize) + xx;
275
    mx = 0;
276
    my = 0;
277

    
278
    x = xx;
279
    y = yy;
280
    do {
281
        dminx = 0x7fffffff;
282
        dminy = 0x7fffffff;
283

    
284
        lastx = x;
285
        for (x = x1; x <= x2; x += range) {
286
            d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
287
            if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
288
                dminx = d;
289
                mx = x;
290
            }
291
        }
292

    
293
        x = lastx;
294
        for (y = y1; y <= y2; y += range) {
295
            d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
296
            if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
297
                dminy = d;
298
                my = y;
299
            }
300
        }
301

    
302
        range = range >> 1;
303

    
304
        x = mx;
305
        y = my;
306
        x1 = mx - range;
307
        if (x1 < xmin)
308
            x1 = xmin;
309

    
310
        x2 = mx + range;
311
        if (x2 > xmax)
312
            x2 = xmax;
313

    
314
        y1 = my - range;
315
        if (y1 < ymin)
316
            y1 = ymin;
317

    
318
        y2 = my + range;
319
        if (y2 > ymax)
320
            y2 = ymax;
321

    
322
    } while (range >= 1);
323

    
324
#ifdef DEBUG
325
    fprintf(stderr, "phods     - MX: %d\tMY: %d\n", mx, my);
326
#endif
327

    
328
    /* half pixel search */
329
    *mx_ptr = mx;
330
    *my_ptr = my;
331
    return dminy;
332
}
333

    
334

    
335
#define Z_THRESHOLD 256
336

    
337
#define CHECK_MV(x,y)\
338
{\
339
    d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
340
    d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
341
    if(d<dmin){\
342
        best[0]=x;\
343
        best[1]=y;\
344
        dmin=d;\
345
    }\
346
}
347

    
348
#define CHECK_MV_DIR(x,y,new_dir)\
349
{\
350
    d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
351
    d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
352
    if(d<dmin){\
353
        best[0]=x;\
354
        best[1]=y;\
355
        dmin=d;\
356
        next_dir= new_dir;\
357
    }\
358
}
359

    
360
#define check(x,y,S,v)\
361
if( (x)<(xmin<<(S)) ) printf("%d %d %d %d xmin" #v, (x), (y), s->mb_x, s->mb_y);\
362
if( (x)>(xmax<<(S)) ) printf("%d %d %d %d xmax" #v, (x), (y), s->mb_x, s->mb_y);\
363
if( (y)<(ymin<<(S)) ) printf("%d %d %d %d ymin" #v, (x), (y), s->mb_x, s->mb_y);\
364
if( (y)>(ymax<<(S)) ) printf("%d %d %d %d ymax" #v, (x), (y), s->mb_x, s->mb_y);\
365

    
366

    
367
static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
368
                                       UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
369
                                       int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
370
                                       int xmin, int ymin, int xmax, int ymax, int shift)
371
{
372
    int next_dir=-1;
373

    
374
    for(;;){
375
        int d;
376
        const int dir= next_dir;
377
        const int x= best[0];
378
        const int y= best[1];
379
        next_dir=-1;
380

    
381
//printf("%d", dir);
382
        if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y  , 0)
383
        if(dir!=3 && y>ymin) CHECK_MV_DIR(x  , y-1, 1)
384
        if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y  , 2)
385
        if(dir!=1 && y<ymax) CHECK_MV_DIR(x  , y+1, 3)
386

    
387
        if(next_dir==-1){
388
            return dmin;
389
        }
390
    }
391

    
392
/*    for(;;){
393
        int d;
394
        const int x= best[0];
395
        const int y= best[1];
396
        const int last_min=dmin;
397
        if(x>xmin) CHECK_MV(x-1, y  )
398
        if(y>xmin) CHECK_MV(x  , y-1)
399
        if(x<xmax) CHECK_MV(x+1, y  )
400
        if(y<xmax) CHECK_MV(x  , y+1)
401
        if(x>xmin && y>ymin) CHECK_MV(x-1, y-1)
402
        if(x>xmin && y<ymax) CHECK_MV(x-1, y+1)
403
        if(x<xmax && y>ymin) CHECK_MV(x+1, y-1)
404
        if(x<xmax && y<ymax) CHECK_MV(x+1, y+1)
405
        if(x-1>xmin) CHECK_MV(x-2, y  )
406
        if(y-1>xmin) CHECK_MV(x  , y-2)
407
        if(x+1<xmax) CHECK_MV(x+2, y  )
408
        if(y+1<xmax) CHECK_MV(x  , y+2)
409
        if(x-1>xmin && y-1>ymin) CHECK_MV(x-2, y-2)
410
        if(x-1>xmin && y+1<ymax) CHECK_MV(x-2, y+2)
411
        if(x+1<xmax && y-1>ymin) CHECK_MV(x+2, y-2)
412
        if(x+1<xmax && y+1<ymax) CHECK_MV(x+2, y+2)
413
        if(dmin==last_min) return dmin;
414
    }
415
    */
416
}
417

    
418
static inline int snake_search(MpegEncContext * s, int *best, int dmin,
419
                                       UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
420
                                       int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
421
                                       int xmin, int ymin, int xmax, int ymax, int shift)
422
{
423
    int dir=0;
424
    int c=1;
425
    static int x_dir[8]= {1,1,0,-1,-1,-1, 0, 1};
426
    static int y_dir[8]= {0,1,1, 1, 0,-1,-1,-1};
427
    int fails=0;
428
    int last_d[2]={dmin, dmin};
429

    
430
/*static int good=0;
431
static int bad=0;
432
static int point=0;
433

434
point++;
435
if(256*256*256*64%point==0)
436
{
437
    printf("%d %d %d\n", good, bad, point);
438
}*/
439

    
440
    for(;;){
441
        int x= best[0];
442
        int y= best[1];
443
        int d;
444
        x+=x_dir[dir];
445
        y+=y_dir[dir];
446
        if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){
447
            d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);
448
            d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;
449
        }else{
450
            d = dmin + 10000; //FIXME smarter boundary handling
451
        }
452
        if(d<dmin){
453
            best[0]=x;
454
            best[1]=y;
455
            dmin=d;
456

    
457
            if(last_d[1] - last_d[0] > last_d[0] - d) c= -c;
458
            dir+=c;
459

    
460
            fails=0;
461
//good++;
462
            last_d[1]=last_d[0];
463
            last_d[0]=d;
464
        }else{
465
//bad++;
466
            if(fails){
467
                if(fails>=3) return dmin;
468
            }else{
469
                c= -c;
470
            }
471
            dir+=c*2;
472
            fails++;
473
        }
474
        dir&=7;
475
    }
476
}
477

    
478
static int epzs_motion_search(MpegEncContext * s,
479
                             int *mx_ptr, int *my_ptr,
480
                             int P[5][2], int pred_x, int pred_y,
481
                             int xmin, int ymin, int xmax, int ymax)
482
{
483
    int best[2]={0, 0};
484
    int d, dmin; 
485
    UINT8 *new_pic, *old_pic;
486
    const int pic_stride= s->linesize;
487
    const int pic_xy= (s->mb_y*pic_stride + s->mb_x)*16;
488
    UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
489
    int quant= s->qscale; // qscale of the prev frame
490
    const int shift= 1+s->quarter_sample;
491

    
492
    new_pic = s->new_picture[0] + pic_xy;
493
    old_pic = s->last_picture[0] + pic_xy;
494
   
495
    dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16);
496
    if(dmin<Z_THRESHOLD){
497
        *mx_ptr= 0;
498
        *my_ptr= 0;
499
//printf("Z");
500
        return dmin;
501
    }
502

    
503
    /* first line */
504
    if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
505
        CHECK_MV(P[1][0]>>shift, P[1][1]>>shift)
506
    }else{
507
        CHECK_MV(P[4][0]>>shift, P[4][1]>>shift)
508
        if(dmin<Z_THRESHOLD){
509
            *mx_ptr= P[4][0]>>shift;
510
            *my_ptr= P[4][1]>>shift;
511
//printf("M\n");
512
            return dmin;
513
        }
514
        CHECK_MV(P[1][0]>>shift, P[1][1]>>shift)
515
        CHECK_MV(P[2][0]>>shift, P[2][1]>>shift)
516
        CHECK_MV(P[3][0]>>shift, P[3][1]>>shift)
517
    }
518
    CHECK_MV(P[0][0]>>shift, P[0][1]>>shift)
519

    
520
//check(best[0],best[1],0, b0)
521
    if(s->full_search==ME_EPZS)
522
        dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride, 
523
                                   pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);
524
    else
525
        dmin=         snake_search(s, best, dmin, new_pic, old_pic, pic_stride, 
526
                                   pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);
527
//check(best[0],best[1],0, b1)
528
    *mx_ptr= best[0];
529
    *my_ptr= best[1];    
530

    
531
//    printf("%d %d %d \n", best[0], best[1], dmin);
532
    return dmin;
533
}
534

    
535
#define CHECK_HALF_MV(suffix, x, y) \
536
    d= pix_abs16x16_ ## suffix(pix, ptr+((x)>>1), s->linesize, 16);\
537
    d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\
538
    if(d<dminh){\
539
        dminh= d;\
540
        mx= mx1 + x;\
541
        my= my1 + y;\
542
    }
543

    
544
/* The idea would be to make half pel ME after Inter/Intra decision to 
545
   save time. */
546
static inline void halfpel_motion_search(MpegEncContext * s,
547
                                  int *mx_ptr, int *my_ptr, int dmin,
548
                                  int xmin, int ymin, int xmax, int ymax,
549
                                  int pred_x, int pred_y)
550
{
551
    UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
552
    const int quant= s->qscale;
553
    int pen_x, pen_y;
554
    int mx, my, mx1, my1, d, xx, yy, dminh;
555
    UINT8 *pix, *ptr;
556

    
557
    
558
    mx = *mx_ptr;
559
    my = *my_ptr;
560
    ptr = s->last_picture[0] + (my * s->linesize) + mx;
561

    
562
    xx = 16 * s->mb_x;
563
    yy = 16 * s->mb_y;
564
    pix =  s->new_picture[0] + (yy * s->linesize) + xx;
565
    
566
    dminh = dmin;
567

    
568
    if (mx > xmin && mx < xmax && 
569
        my > ymin && my < ymax) {
570

    
571
        mx= mx1= 2*(mx - xx);
572
        my= my1= 2*(my - yy);
573
        if(dmin < Z_THRESHOLD && mx==0 && my==0){
574
            *mx_ptr = 0;
575
            *my_ptr = 0;
576
            return;
577
        }
578
        
579
        pen_x= pred_x + mx;
580
        pen_y= pred_y + my;
581

    
582
        ptr-= s->linesize;
583
        CHECK_HALF_MV(xy2, -1, -1)
584
        CHECK_HALF_MV(y2 ,  0, -1)
585
        CHECK_HALF_MV(xy2, +1, -1)
586
        
587
        ptr+= s->linesize;
588
        CHECK_HALF_MV(x2 , -1,  0)
589
        CHECK_HALF_MV(x2 , +1,  0)
590
        CHECK_HALF_MV(xy2, -1, +1)
591
        CHECK_HALF_MV(y2 ,  0, +1)
592
        CHECK_HALF_MV(xy2, +1, +1)
593
    }else{
594
        mx= 2*(mx - xx);
595
        my= 2*(my - yy);
596
    }
597

    
598
    *mx_ptr = mx;
599
    *my_ptr = my;
600
}
601

    
602
#ifndef CONFIG_TEST_MV_ENCODE
603

    
604
int estimate_motion(MpegEncContext * s,
605
                    int mb_x, int mb_y,
606
                    int *mx_ptr, int *my_ptr)
607
{
608
    UINT8 *pix, *ppix;
609
    int sum, varc, vard, mx, my, range, dmin, xx, yy;
610
    int xmin, ymin, xmax, ymax;
611
    int rel_xmin, rel_ymin, rel_xmax, rel_ymax;
612
    int pred_x=0, pred_y=0;
613
    int P[5][2];
614
    const int shift= 1+s->quarter_sample;
615
    
616
    range = 8 * (1 << (s->f_code - 1));
617
    /* XXX: temporary kludge to avoid overflow for msmpeg4 */
618
    if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
619
        range = range * 2;
620

    
621
    if (s->unrestricted_mv) {
622
        xmin = -16;
623
        ymin = -16;
624
        if (s->h263_plus)
625
            range *= 2;
626
        if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){
627
            xmax = s->mb_width*16;
628
            ymax = s->mb_height*16;
629
        }else {
630
            /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise 
631
                    (cuz the drawn edge isnt large enough))*/
632
            xmax = s->width;
633
            ymax = s->height;
634
        }
635
    } else {
636
        xmin = 0;
637
        ymin = 0;
638
        xmax = s->mb_width*16 - 16;
639
        ymax = s->mb_height*16 - 16;
640
    }
641
    switch(s->full_search) {
642
    case ME_ZERO:
643
    default:
644
        no_motion_search(s, &mx, &my);
645
        dmin = 0;
646
        break;
647
    case ME_FULL:
648
        dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax);
649
        break;
650
    case ME_LOG:
651
        dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
652
        break;
653
    case ME_PHODS:
654
        dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
655
        break;
656
    case ME_X1: // just reserving some space for experiments ...
657
    case ME_EPZS:
658
        rel_xmin= xmin - s->mb_x*16;
659
        rel_xmax= xmax - s->mb_x*16;
660
        rel_ymin= ymin - s->mb_y*16;
661
        rel_ymax= ymax - s->mb_y*16;
662
        if(s->out_format == FMT_H263){
663
            static const int off[4]= {2, 1, 1, -1};
664
            const int mot_stride = s->mb_width*2 + 2;
665
            const int mot_xy = (s->mb_y*2 + 1)*mot_stride + s->mb_x*2 + 1;
666
         
667
            P[0][0] = s->motion_val[mot_xy    ][0];
668
            P[0][1] = s->motion_val[mot_xy    ][1];
669
            P[1][0] = s->motion_val[mot_xy - 1][0];
670
            P[1][1] = s->motion_val[mot_xy - 1][1];
671
            if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift);
672

    
673
            /* special case for first line */
674
            if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
675
                pred_x = P[1][0];
676
                pred_y = P[1][1];
677
            } else {
678
                P[2][0] = s->motion_val[mot_xy - mot_stride             ][0];
679
                P[2][1] = s->motion_val[mot_xy - mot_stride             ][1];
680
                P[3][0] = s->motion_val[mot_xy - mot_stride + off[0]    ][0];
681
                P[3][1] = s->motion_val[mot_xy - mot_stride + off[0]    ][1];
682
                if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift);
683
                if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift);
684
                if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift);
685
        
686
                P[4][0]= pred_x = mid_pred(P[1][0], P[2][0], P[3][0]);
687
                P[4][1]= pred_y = mid_pred(P[1][1], P[2][1], P[3][1]);
688
            }
689
        }else {
690
            const int xy= s->mb_y*s->mb_width + s->mb_x;
691
            pred_x= s->last_mv[0][0][0];
692
            pred_y= s->last_mv[0][0][1];
693

    
694
            P[0][0]= s->mv_table[0][xy  ];
695
            P[0][1]= s->mv_table[1][xy  ];
696
            if(s->mb_x == 0){
697
                P[1][0]= 0;
698
                P[1][1]= 0;
699
            }else{
700
                P[1][0]= s->mv_table[0][xy-1];
701
                P[1][1]= s->mv_table[1][xy-1];
702
                if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift);
703
            }
704
    
705
            if (!(s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
706
                P[2][0] = s->mv_table[0][xy - s->mb_width];
707
                P[2][1] = s->mv_table[1][xy - s->mb_width];
708
                P[3][0] = s->mv_table[0][xy - s->mb_width+1];
709
                P[3][1] = s->mv_table[1][xy - s->mb_width+1];
710
                if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift);
711
                if(P[3][0] > (rel_xmax<<shift)) P[3][0]= (rel_xmax<<shift);
712
                if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift);
713
                if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift);
714
        
715
                P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]);
716
                P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]);
717
            }
718
        }
719
        dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax);
720
 
721
        mx+= s->mb_x*16;
722
        my+= s->mb_y*16;
723
        break;
724
    }
725

    
726
    /* intra / predictive decision */
727
    xx = mb_x * 16;
728
    yy = mb_y * 16;
729

    
730
    pix = s->new_picture[0] + (yy * s->linesize) + xx;
731
    /* At this point (mx,my) are full-pell and the absolute displacement */
732
    ppix = s->last_picture[0] + (my * s->linesize) + mx;
733

    
734
    sum = pix_sum(pix, s->linesize);
735
    varc = pix_norm1(pix, s->linesize);
736
    vard = pix_norm(pix, ppix, s->linesize);
737

    
738
    vard = vard >> 8;
739
    sum = sum >> 8;
740
    varc = (varc >> 8) - (sum * sum);
741
    s->mb_var[s->mb_width * mb_y + mb_x] = varc;
742
    s->avg_mb_var += varc;
743
    s->mc_mb_var += vard;
744
     
745
#if 0
746
    printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
747
           varc, s->avg_mb_var, sum, vard, mx - xx, my - yy);
748
#endif
749
    if (vard <= 64 || vard < varc) {
750
        if (s->full_search != ME_ZERO) {
751
            halfpel_motion_search(s, &mx, &my, dmin, xmin, ymin, xmax, ymax, pred_x, pred_y);
752
        } else {
753
            mx -= 16 * s->mb_x;
754
            my -= 16 * s->mb_y;
755
        }
756
//        check(mx + 32*s->mb_x, my + 32*s->mb_y, 1, end)
757
        
758
        *mx_ptr = mx;
759
        *my_ptr = my;
760
        return 0;
761
    } else {
762
        *mx_ptr = 0;
763
        *my_ptr = 0;
764
        return 1;
765
    }
766
}
767

    
768
#else
769

    
770
/* test version which generates valid random vectors */
771
int estimate_motion(MpegEncContext * s,
772
                    int mb_x, int mb_y,
773
                    int *mx_ptr, int *my_ptr)
774
{
775
    int xx, yy, x1, y1, x2, y2, range;
776

    
777
    if ((random() % 10) >= 5) {
778
        range = 8 * (1 << (s->f_code - 1));
779
        if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
780
            range = range * 2;
781

    
782
        xx = 16 * s->mb_x;
783
        yy = 16 * s->mb_y;
784
        x1 = xx - range;
785
        if (x1 < 0)
786
            x1 = 0;
787
        x2 = xx + range - 1;
788
        if (x2 > (s->width - 16))
789
            x2 = s->width - 16;
790
        y1 = yy - range;
791
        if (y1 < 0)
792
            y1 = 0;
793
        y2 = yy + range - 1;
794
        if (y2 > (s->height - 16))
795
            y2 = s->height - 16;
796

    
797
        *mx_ptr = (random() % (2 * (x2 - x1 + 1))) + 2 * (x1 - xx);
798
        *my_ptr = (random() % (2 * (y2 - y1 + 1))) + 2 * (y1 - yy);
799
        return 0;
800
    } else {
801
        *mx_ptr = 0;
802
        *my_ptr = 0;
803
        return 1;
804
    }
805
}
806

    
807
#endif