Statistics
| Branch: | Revision:

ffmpeg / libavcodec / motion_est.c @ 174489bd

History | View | Annotate | Download (20.8 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
#define ABS(a) ((a)>0 ? (a) : -(a))
29
#define INTER_BIAS        257
30

    
31
static void halfpel_motion_search(MpegEncContext * s,
32
                                  int *mx_ptr, int *my_ptr, int dmin,
33
                                  int xmin, int ymin, int xmax, int ymax,
34
                                  int pred_x, int pred_y);
35

    
36
/* config it to test motion vector encoding (send random vectors) */
37
//#define CONFIG_TEST_MV_ENCODE
38

    
39
static int pix_sum(UINT8 * pix, int line_size)
40
{
41
    int s, i, j;
42

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

    
61
static int pix_dev(UINT8 * pix, int line_size, int mean)
62
{
63
    int s, i, j;
64

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

    
83
static int pix_norm1(UINT8 * pix, int line_size)
84
{
85
    int s, i, j;
86
    UINT32 *sq = squareTbl + 256;
87

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

    
106
static int pix_norm(UINT8 * pix1, UINT8 * pix2, int line_size)
107
{
108
    int s, i, j;
109
    UINT32 *sq = squareTbl + 256;
110

    
111
    s = 0;
112
    for (i = 0; i < 16; i++) {
113
        for (j = 0; j < 16; j += 8) {
114
            s += sq[pix1[0] - pix2[0]];
115
            s += sq[pix1[1] - pix2[1]];
116
            s += sq[pix1[2] - pix2[2]];
117
            s += sq[pix1[3] - pix2[3]];
118
            s += sq[pix1[4] - pix2[4]];
119
            s += sq[pix1[5] - pix2[5]];
120
            s += sq[pix1[6] - pix2[6]];
121
            s += sq[pix1[7] - pix2[7]];
122
            pix1 += 8;
123
            pix2 += 8;
124
        }
125
        pix1 += line_size - 16;
126
        pix2 += line_size - 16;
127
    }
128
    return s;
129
}
130

    
131
static void no_motion_search(MpegEncContext * s,
132
                             int *mx_ptr, int *my_ptr)
133
{
134
    *mx_ptr = 16 * s->mb_x;
135
    *my_ptr = 16 * s->mb_y;
136
}
137

    
138
static int full_motion_search(MpegEncContext * s,
139
                              int *mx_ptr, int *my_ptr, int range,
140
                              int xmin, int ymin, int xmax, int ymax)
141
{
142
    int x1, y1, x2, y2, xx, yy, x, y;
143
    int mx, my, dmin, d;
144
    UINT8 *pix;
145

    
146
    xx = 16 * s->mb_x;
147
    yy = 16 * s->mb_y;
148
    x1 = xx - range + 1;        /* we loose one pixel to avoid boundary pb with half pixel pred */
149
    if (x1 < xmin)
150
        x1 = xmin;
151
    x2 = xx + range - 1;
152
    if (x2 > xmax)
153
        x2 = xmax;
154
    y1 = yy - range + 1;
155
    if (y1 < ymin)
156
        y1 = ymin;
157
    y2 = yy + range - 1;
158
    if (y2 > ymax)
159
        y2 = ymax;
160
    pix = s->new_picture[0] + (yy * s->linesize) + xx;
161
    dmin = 0x7fffffff;
162
    mx = 0;
163
    my = 0;
164
    for (y = y1; y <= y2; y++) {
165
        for (x = x1; x <= x2; x++) {
166
            d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x,
167
                             s->linesize, 16);
168
            if (d < dmin ||
169
                (d == dmin &&
170
                 (abs(x - xx) + abs(y - yy)) <
171
                 (abs(mx - xx) + abs(my - yy)))) {
172
                dmin = d;
173
                mx = x;
174
                my = y;
175
            }
176
        }
177
    }
178

    
179
    *mx_ptr = mx;
180
    *my_ptr = my;
181

    
182
#if 0
183
    if (*mx_ptr < -(2 * range) || *mx_ptr >= (2 * range) ||
184
        *my_ptr < -(2 * range) || *my_ptr >= (2 * range)) {
185
        fprintf(stderr, "error %d %d\n", *mx_ptr, *my_ptr);
186
    }
187
#endif
188
    return dmin;
189
}
190

    
191

    
192
static int log_motion_search(MpegEncContext * s,
193
                             int *mx_ptr, int *my_ptr, int range,
194
                             int xmin, int ymin, int xmax, int ymax)
195
{
196
    int x1, y1, x2, y2, xx, yy, x, y;
197
    int mx, my, dmin, d;
198
    UINT8 *pix;
199

    
200
    xx = s->mb_x << 4;
201
    yy = s->mb_y << 4;
202

    
203
    /* Left limit */
204
    x1 = xx - range;
205
    if (x1 < xmin)
206
        x1 = xmin;
207

    
208
    /* Right limit */
209
    x2 = xx + range;
210
    if (x2 > xmax)
211
        x2 = xmax;
212

    
213
    /* Upper limit */
214
    y1 = yy - range;
215
    if (y1 < ymin)
216
        y1 = ymin;
217

    
218
    /* Lower limit */
219
    y2 = yy + range;
220
    if (y2 > ymax)
221
        y2 = ymax;
222

    
223
    pix = s->new_picture[0] + (yy * s->linesize) + xx;
224
    dmin = 0x7fffffff;
225
    mx = 0;
226
    my = 0;
227

    
228
    do {
229
        for (y = y1; y <= y2; y += range) {
230
            for (x = x1; x <= x2; x += range) {
231
                d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
232
                if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
233
                    dmin = d;
234
                    mx = x;
235
                    my = y;
236
                }
237
            }
238
        }
239

    
240
        range = range >> 1;
241

    
242
        x1 = mx - range;
243
        if (x1 < xmin)
244
            x1 = xmin;
245

    
246
        x2 = mx + range;
247
        if (x2 > xmax)
248
            x2 = xmax;
249

    
250
        y1 = my - range;
251
        if (y1 < ymin)
252
            y1 = ymin;
253

    
254
        y2 = my + range;
255
        if (y2 > ymax)
256
            y2 = ymax;
257

    
258
    } while (range >= 1);
259

    
260
#ifdef DEBUG
261
    fprintf(stderr, "log       - MX: %d\tMY: %d\n", mx, my);
262
#endif
263
    *mx_ptr = mx;
264
    *my_ptr = my;
265
    return dmin;
266
}
267

    
268
static int phods_motion_search(MpegEncContext * s,
269
                               int *mx_ptr, int *my_ptr, int range,
270
                               int xmin, int ymin, int xmax, int ymax)
271
{
272
    int x1, y1, x2, y2, xx, yy, x, y, lastx, d;
273
    int mx, my, dminx, dminy;
274
    UINT8 *pix;
275

    
276
    xx = s->mb_x << 4;
277
    yy = s->mb_y << 4;
278

    
279
    /* Left limit */
280
    x1 = xx - range;
281
    if (x1 < xmin)
282
        x1 = xmin;
283

    
284
    /* Right limit */
285
    x2 = xx + range;
286
    if (x2 > xmax)
287
        x2 = xmax;
288

    
289
    /* Upper limit */
290
    y1 = yy - range;
291
    if (y1 < ymin)
292
        y1 = ymin;
293

    
294
    /* Lower limit */
295
    y2 = yy + range;
296
    if (y2 > ymax)
297
        y2 = ymax;
298

    
299
    pix = s->new_picture[0] + (yy * s->linesize) + xx;
300
    mx = 0;
301
    my = 0;
302

    
303
    x = xx;
304
    y = yy;
305
    do {
306
        dminx = 0x7fffffff;
307
        dminy = 0x7fffffff;
308

    
309
        lastx = x;
310
        for (x = x1; x <= x2; x += range) {
311
            d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
312
            if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
313
                dminx = d;
314
                mx = x;
315
            }
316
        }
317

    
318
        x = lastx;
319
        for (y = y1; y <= y2; y += range) {
320
            d = pix_abs16x16(pix, s->last_picture[0] + (y * s->linesize) + x, s->linesize, 16);
321
            if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
322
                dminy = d;
323
                my = y;
324
            }
325
        }
326

    
327
        range = range >> 1;
328

    
329
        x = mx;
330
        y = my;
331
        x1 = mx - range;
332
        if (x1 < xmin)
333
            x1 = xmin;
334

    
335
        x2 = mx + range;
336
        if (x2 > xmax)
337
            x2 = xmax;
338

    
339
        y1 = my - range;
340
        if (y1 < ymin)
341
            y1 = ymin;
342

    
343
        y2 = my + range;
344
        if (y2 > ymax)
345
            y2 = ymax;
346

    
347
    } while (range >= 1);
348

    
349
#ifdef DEBUG
350
    fprintf(stderr, "phods     - MX: %d\tMY: %d\n", mx, my);
351
#endif
352

    
353
    /* half pixel search */
354
    *mx_ptr = mx;
355
    *my_ptr = my;
356
    return dminy;
357
}
358

    
359

    
360
#define Z_THRESHOLD 256
361

    
362
#define CHECK_MV(x,y)\
363
{\
364
    d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
365
    d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
366
    if(d<dmin){\
367
        best[0]=x;\
368
        best[1]=y;\
369
        dmin=d;\
370
    }\
371
}
372

    
373
#define CHECK_MV_DIR(x,y,new_dir)\
374
{\
375
    d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);\
376
    d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;\
377
    if(d<dmin){\
378
        best[0]=x;\
379
        best[1]=y;\
380
        dmin=d;\
381
        next_dir= new_dir;\
382
    }\
383
}
384

    
385
#define check(x,y,S,v)\
386
if( (x)<(xmin<<(S)) ) printf("%d %d %d %d xmin" #v, (x), (y), s->mb_x, s->mb_y);\
387
if( (x)>(xmax<<(S)) ) printf("%d %d %d %d xmax" #v, (x), (y), s->mb_x, s->mb_y);\
388
if( (y)<(ymin<<(S)) ) printf("%d %d %d %d ymin" #v, (x), (y), s->mb_x, s->mb_y);\
389
if( (y)>(ymax<<(S)) ) printf("%d %d %d %d ymax" #v, (x), (y), s->mb_x, s->mb_y);\
390

    
391

    
392
static inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
393
                                       UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
394
                                       int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
395
                                       int xmin, int ymin, int xmax, int ymax, int shift)
396
{
397
    int next_dir=-1;
398

    
399
    for(;;){
400
        int d;
401
        const int dir= next_dir;
402
        const int x= best[0];
403
        const int y= best[1];
404
        next_dir=-1;
405

    
406
//printf("%d", dir);
407
        if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y  , 0)
408
        if(dir!=3 && y>ymin) CHECK_MV_DIR(x  , y-1, 1)
409
        if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y  , 2)
410
        if(dir!=1 && y<ymax) CHECK_MV_DIR(x  , y+1, 3)
411

    
412
        if(next_dir==-1){
413
            return dmin;
414
        }
415
    }
416

    
417
/*    for(;;){
418
        int d;
419
        const int x= best[0];
420
        const int y= best[1];
421
        const int last_min=dmin;
422
        if(x>xmin) CHECK_MV(x-1, y  )
423
        if(y>xmin) CHECK_MV(x  , y-1)
424
        if(x<xmax) CHECK_MV(x+1, y  )
425
        if(y<xmax) CHECK_MV(x  , y+1)
426
        if(x>xmin && y>ymin) CHECK_MV(x-1, y-1)
427
        if(x>xmin && y<ymax) CHECK_MV(x-1, y+1)
428
        if(x<xmax && y>ymin) CHECK_MV(x+1, y-1)
429
        if(x<xmax && y<ymax) CHECK_MV(x+1, y+1)
430
        if(x-1>xmin) CHECK_MV(x-2, y  )
431
        if(y-1>xmin) CHECK_MV(x  , y-2)
432
        if(x+1<xmax) CHECK_MV(x+2, y  )
433
        if(y+1<xmax) CHECK_MV(x  , y+2)
434
        if(x-1>xmin && y-1>ymin) CHECK_MV(x-2, y-2)
435
        if(x-1>xmin && y+1<ymax) CHECK_MV(x-2, y+2)
436
        if(x+1<xmax && y-1>ymin) CHECK_MV(x+2, y-2)
437
        if(x+1<xmax && y+1<ymax) CHECK_MV(x+2, y+2)
438
        if(dmin==last_min) return dmin;
439
    }
440
    */
441
}
442

    
443
static inline int snake_search(MpegEncContext * s, int *best, int dmin,
444
                                       UINT8 *new_pic, UINT8 *old_pic, int pic_stride,
445
                                       int pred_x, int pred_y, UINT16 *mv_penalty, int quant,
446
                                       int xmin, int ymin, int xmax, int ymax, int shift)
447
{
448
    int dir=0;
449
    int c=1;
450
    static int x_dir[8]= {1,1,0,-1,-1,-1, 0, 1};
451
    static int y_dir[8]= {0,1,1, 1, 0,-1,-1,-1};
452
    int fails=0;
453
    int last_d[2]={dmin, dmin};
454

    
455
/*static int good=0;
456
static int bad=0;
457
static int point=0;
458

459
point++;
460
if(256*256*256*64%point==0)
461
{
462
    printf("%d %d %d\n", good, bad, point);
463
}*/
464

    
465
    for(;;){
466
        int x= best[0];
467
        int y= best[1];
468
        int d;
469
        x+=x_dir[dir];
470
        y+=y_dir[dir];
471
        if(x>=xmin && x<=xmax && y>=ymin && y<=ymax){
472
            d = pix_abs16x16(new_pic, old_pic + (x) + (y)*pic_stride, pic_stride, 16);
473
            d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*quant;
474
        }else{
475
            d = dmin + 10000; //FIXME smarter boundary handling
476
        }
477
        if(d<dmin){
478
            best[0]=x;
479
            best[1]=y;
480
            dmin=d;
481

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

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

    
503
static int epzs_motion_search(MpegEncContext * s,
504
                             int *mx_ptr, int *my_ptr,
505
                             int P[5][2], int pred_x, int pred_y,
506
                             int xmin, int ymin, int xmax, int ymax)
507
{
508
    int best[2]={0, 0};
509
    int d, dmin; 
510
    UINT8 *new_pic, *old_pic;
511
    const int pic_stride= s->linesize;
512
    const int pic_xy= (s->mb_y*pic_stride + s->mb_x)*16;
513
    UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
514
    int quant= s->qscale; // qscale of the prev frame
515
    const int shift= 1+s->quarter_sample;
516

    
517
    new_pic = s->new_picture[0] + pic_xy;
518
    old_pic = s->last_picture[0] + pic_xy;
519
   
520
    dmin = pix_abs16x16(new_pic, old_pic, pic_stride, 16);
521
    if(dmin<Z_THRESHOLD){
522
        *mx_ptr= 0;
523
        *my_ptr= 0;
524
//printf("Z");
525
        return dmin;
526
    }
527

    
528
    /* first line */
529
    if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
530
        CHECK_MV(P[1][0]>>shift, P[1][1]>>shift)
531
    }else{
532
        CHECK_MV(P[4][0]>>shift, P[4][1]>>shift)
533
        if(dmin<Z_THRESHOLD){
534
            *mx_ptr= P[4][0]>>shift;
535
            *my_ptr= P[4][1]>>shift;
536
//printf("M\n");
537
            return dmin;
538
        }
539
        CHECK_MV(P[1][0]>>shift, P[1][1]>>shift)
540
        CHECK_MV(P[2][0]>>shift, P[2][1]>>shift)
541
        CHECK_MV(P[3][0]>>shift, P[3][1]>>shift)
542
    }
543
    CHECK_MV(P[0][0]>>shift, P[0][1]>>shift)
544

    
545
//check(best[0],best[1],0, b0)
546
    if(s->full_search==ME_EPZS)
547
        dmin= small_diamond_search(s, best, dmin, new_pic, old_pic, pic_stride, 
548
                                   pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);
549
    else
550
        dmin=         snake_search(s, best, dmin, new_pic, old_pic, pic_stride, 
551
                                   pred_x, pred_y, mv_penalty, quant, xmin, ymin, xmax, ymax, shift);
552
//check(best[0],best[1],0, b1)
553
    *mx_ptr= best[0];
554
    *my_ptr= best[1];    
555

    
556
//    printf("%d %d %d \n", best[0], best[1], dmin);
557
    return dmin;
558
}
559

    
560
#define CHECK_HALF_MV(suffix, x, y) \
561
    d= pix_abs16x16_ ## suffix(pix, ptr+((x)>>1), s->linesize, 16);\
562
    d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*quant;\
563
    if(d<dminh){\
564
        dminh= d;\
565
        mx= mx1 + x;\
566
        my= my1 + y;\
567
    }
568

    
569
/* The idea would be to make half pel ME after Inter/Intra decision to 
570
   save time. */
571
static inline void halfpel_motion_search(MpegEncContext * s,
572
                                  int *mx_ptr, int *my_ptr, int dmin,
573
                                  int xmin, int ymin, int xmax, int ymax,
574
                                  int pred_x, int pred_y)
575
{
576
    UINT16 *mv_penalty= s->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
577
    const int quant= s->qscale;
578
    int pen_x, pen_y;
579
    int mx, my, mx1, my1, d, xx, yy, dminh;
580
    UINT8 *pix, *ptr;
581

    
582
    mx = *mx_ptr;
583
    my = *my_ptr;
584
    ptr = s->last_picture[0] + (my * s->linesize) + mx;
585

    
586
    xx = 16 * s->mb_x;
587
    yy = 16 * s->mb_y;
588
    pix =  s->new_picture[0] + (yy * s->linesize) + xx;
589
    
590
    dminh = dmin;
591

    
592
    if (mx > xmin && mx < xmax && 
593
        my > ymin && my < ymax) {
594

    
595
        mx= mx1= 2*(mx - xx);
596
        my= my1= 2*(my - yy);
597
        if(dmin < Z_THRESHOLD && mx==0 && my==0){
598
            *mx_ptr = 0;
599
            *my_ptr = 0;
600
            return;
601
        }
602
        
603
        pen_x= pred_x + mx;
604
        pen_y= pred_y + my;
605

    
606
        ptr-= s->linesize;
607
        CHECK_HALF_MV(xy2, -1, -1)
608
        CHECK_HALF_MV(y2 ,  0, -1)
609
        CHECK_HALF_MV(xy2, +1, -1)
610
        
611
        ptr+= s->linesize;
612
        CHECK_HALF_MV(x2 , -1,  0)
613
        CHECK_HALF_MV(x2 , +1,  0)
614
        CHECK_HALF_MV(xy2, -1, +1)
615
        CHECK_HALF_MV(y2 ,  0, +1)
616
        CHECK_HALF_MV(xy2, +1, +1)
617
    }else{
618
        mx= 2*(mx - xx);
619
        my= 2*(my - yy);
620
    }
621

    
622
    *mx_ptr = mx;
623
    *my_ptr = my;
624
}
625

    
626
#ifndef CONFIG_TEST_MV_ENCODE
627

    
628
int estimate_motion(MpegEncContext * s,
629
                    int mb_x, int mb_y,
630
                    int *mx_ptr, int *my_ptr)
631
{
632
    UINT8 *pix, *ppix;
633
    int sum, varc, vard, mx, my, range, dmin, xx, yy;
634
    int xmin, ymin, xmax, ymax;
635
    int rel_xmin, rel_ymin, rel_xmax, rel_ymax;
636
    int pred_x=0, pred_y=0;
637
    int P[5][2];
638
    const int shift= 1+s->quarter_sample;
639
    
640
    range = 8 * (1 << (s->f_code - 1));
641
    /* XXX: temporary kludge to avoid overflow for msmpeg4 */
642
    if (s->out_format == FMT_H263 && !s->h263_msmpeg4)
643
        range = range * 2;
644

    
645
    if (s->unrestricted_mv) {
646
        xmin = -16;
647
        ymin = -16;
648
        if (s->h263_plus)
649
            range *= 2;
650
        if(s->avctx==NULL || s->avctx->codec->id!=CODEC_ID_MPEG4){
651
            xmax = s->mb_width*16;
652
            ymax = s->mb_height*16;
653
        }else {
654
            /* XXX: dunno if this is correct but ffmpeg4 decoder wont like it otherwise 
655
                    (cuz the drawn edge isnt large enough))*/
656
            xmax = s->width;
657
            ymax = s->height;
658
        }
659
    } else {
660
        xmin = 0;
661
        ymin = 0;
662
        xmax = s->mb_width*16 - 16;
663
        ymax = s->mb_height*16 - 16;
664
    }
665
    switch(s->full_search) {
666
    case ME_ZERO:
667
    default:
668
        no_motion_search(s, &mx, &my);
669
        dmin = 0;
670
        break;
671
    case ME_FULL:
672
        dmin = full_motion_search(s, &mx, &my, range, xmin, ymin, xmax, ymax);
673
        break;
674
    case ME_LOG:
675
        dmin = log_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
676
        break;
677
    case ME_PHODS:
678
        dmin = phods_motion_search(s, &mx, &my, range / 2, xmin, ymin, xmax, ymax);
679
        break;
680
    case ME_X1:
681
    case ME_EPZS:
682
       {
683
            static const int off[4]= {2, 1, 1, -1};
684
            const int mot_stride = s->mb_width*2 + 2;
685
            const int mot_xy = (s->mb_y*2 + 1)*mot_stride + s->mb_x*2 + 1;
686

    
687
            rel_xmin= xmin - s->mb_x*16;
688
            rel_xmax= xmax - s->mb_x*16;
689
            rel_ymin= ymin - s->mb_y*16;
690
            rel_ymax= ymax - s->mb_y*16;
691

    
692
            P[0][0] = s->motion_val[mot_xy    ][0];
693
            P[0][1] = s->motion_val[mot_xy    ][1];
694
            P[1][0] = s->motion_val[mot_xy - 1][0];
695
            P[1][1] = s->motion_val[mot_xy - 1][1];
696
            if(P[1][0] > (rel_xmax<<shift)) P[1][0]= (rel_xmax<<shift);
697

    
698
            /* special case for first line */
699
            if ((s->mb_y == 0 || s->first_slice_line || s->first_gob_line)) {
700
                P[4][0] = P[1][0];
701
                P[4][1] = P[1][1];
702
            } else {
703
                P[2][0] = s->motion_val[mot_xy - mot_stride             ][0];
704
                P[2][1] = s->motion_val[mot_xy - mot_stride             ][1];
705
                P[3][0] = s->motion_val[mot_xy - mot_stride + off[0]    ][0];
706
                P[3][1] = s->motion_val[mot_xy - mot_stride + off[0]    ][1];
707
                if(P[2][1] > (rel_ymax<<shift)) P[2][1]= (rel_ymax<<shift);
708
                if(P[3][0] < (rel_xmin<<shift)) P[3][0]= (rel_xmin<<shift);
709
                if(P[3][1] > (rel_ymax<<shift)) P[3][1]= (rel_ymax<<shift);
710
        
711
                P[4][0]= mid_pred(P[1][0], P[2][0], P[3][0]);
712
                P[4][1]= mid_pred(P[1][1], P[2][1], P[3][1]);
713
            }
714
            if(s->out_format == FMT_H263){
715
                pred_x = P[4][0];
716
                pred_y = P[4][1];
717
            }else { /* mpeg1 at least */
718
                pred_x= P[1][0];
719
                pred_y= P[1][1];
720
            }
721
        }
722
        dmin = epzs_motion_search(s, &mx, &my, P, pred_x, pred_y, rel_xmin, rel_ymin, rel_xmax, rel_ymax);
723
 
724
        mx+= s->mb_x*16;
725
        my+= s->mb_y*16;
726
        break;
727
    }
728

    
729
    /* intra / predictive decision */
730
    xx = mb_x * 16;
731
    yy = mb_y * 16;
732

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

    
737
    sum = pix_sum(pix, s->linesize);
738
    varc = pix_dev(pix, s->linesize, (sum+128)>>8);
739
    vard = pix_abs16x16(pix, ppix, s->linesize, 16);
740

    
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 + INTER_BIAS) {
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