Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
 * Motion estimation
3
 * Copyright (c) 2002-2004 Michael Niedermayer
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg 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.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg 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 FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
 
22
/**
23
 * @file
24
 * Motion estimation template.
25
 */
26
 
27
//Let us hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...)
28
#define LOAD_COMMON\
29
    uint32_t av_unused * const score_map= c->score_map;\
30
    const int av_unused xmin= c->xmin;\
31
    const int av_unused ymin= c->ymin;\
32
    const int av_unused xmax= c->xmax;\
33
    const int av_unused ymax= c->ymax;\
34
    uint8_t *mv_penalty= c->current_mv_penalty;\
35
    const int pred_x= c->pred_x;\
36
    const int pred_y= c->pred_y;\
37
 
38
#define CHECK_HALF_MV(dx, dy, x, y)\
39
{\
40
    const int hx= 2*(x)+(dx);\
41
    const int hy= 2*(y)+(dy);\
42
    d= cmp_hpel(s, x, y, dx, dy, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);\
43
    d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
44
    COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
45
}
46
 
47
static int hpel_motion_search(MpegEncContext * s,
48
                                  int *mx_ptr, int *my_ptr, int dmin,
49
                                  int src_index, int ref_index,
50
                                  int size, int h)
51
{
52
    MotionEstContext * const c= &s->me;
53
    const int mx = *mx_ptr;
54
    const int my = *my_ptr;
55
    const int penalty_factor= c->sub_penalty_factor;
56
    me_cmp_func cmp_sub, chroma_cmp_sub;
57
    int bx=2*mx, by=2*my;
58
 
59
    LOAD_COMMON
60
    int flags= c->sub_flags;
61
 
62
 //FIXME factorize
63
 
64
    cmp_sub= s->dsp.me_sub_cmp[size];
65
    chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];
66
 
67
    if(c->skip){ //FIXME move out of hpel?
68
        *mx_ptr = 0;
69
        *my_ptr = 0;
70
        return dmin;
71
    }
72
 
73
    if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
74
        dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
75
        if(mx || my || size>0)
76
            dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor;
77
    }
78
 
79
    if (mx > xmin && mx < xmax &&
80
        my > ymin && my < ymax) {
81
        int d= dmin;
82
        const int index= (my<
83
        const int t= score_map[(index-(1<
84
                     + (mv_penalty[bx   - pred_x] + mv_penalty[by-2 - pred_y])*c->penalty_factor;
85
        const int l= score_map[(index- 1               )&(ME_MAP_SIZE-1)]
86
                     + (mv_penalty[bx-2 - pred_x] + mv_penalty[by   - pred_y])*c->penalty_factor;
87
        const int r= score_map[(index+ 1               )&(ME_MAP_SIZE-1)]
88
                     + (mv_penalty[bx+2 - pred_x] + mv_penalty[by   - pred_y])*c->penalty_factor;
89
        const int b= score_map[(index+(1<
90
                     + (mv_penalty[bx   - pred_x] + mv_penalty[by+2 - pred_y])*c->penalty_factor;
91
 
92
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1
93
        unsigned key;
94
        unsigned map_generation= c->map_generation;
95
        key= ((my-1)<
96
        av_assert2(c->map[(index-(1<
97
        key= ((my+1)<
98
        av_assert2(c->map[(index+(1<
99
        key= ((my)<
100
        av_assert2(c->map[(index+1)&(ME_MAP_SIZE-1)] == key);
101
        key= ((my)<
102
        av_assert2(c->map[(index-1)&(ME_MAP_SIZE-1)] == key);
103
#endif
104
        if(t<=b){
105
            CHECK_HALF_MV(0, 1, mx  ,my-1)
106
            if(l<=r){
107
                CHECK_HALF_MV(1, 1, mx-1, my-1)
108
                if(t+r<=b+l){
109
                    CHECK_HALF_MV(1, 1, mx  , my-1)
110
                }else{
111
                    CHECK_HALF_MV(1, 1, mx-1, my  )
112
                }
113
                CHECK_HALF_MV(1, 0, mx-1, my  )
114
            }else{
115
                CHECK_HALF_MV(1, 1, mx  , my-1)
116
                if(t+l<=b+r){
117
                    CHECK_HALF_MV(1, 1, mx-1, my-1)
118
                }else{
119
                    CHECK_HALF_MV(1, 1, mx  , my  )
120
                }
121
                CHECK_HALF_MV(1, 0, mx  , my  )
122
            }
123
        }else{
124
            if(l<=r){
125
                if(t+l<=b+r){
126
                    CHECK_HALF_MV(1, 1, mx-1, my-1)
127
                }else{
128
                    CHECK_HALF_MV(1, 1, mx  , my  )
129
                }
130
                CHECK_HALF_MV(1, 0, mx-1, my)
131
                CHECK_HALF_MV(1, 1, mx-1, my)
132
            }else{
133
                if(t+r<=b+l){
134
                    CHECK_HALF_MV(1, 1, mx  , my-1)
135
                }else{
136
                    CHECK_HALF_MV(1, 1, mx-1, my)
137
                }
138
                CHECK_HALF_MV(1, 0, mx  , my)
139
                CHECK_HALF_MV(1, 1, mx  , my)
140
            }
141
            CHECK_HALF_MV(0, 1, mx  , my)
142
        }
143
        av_assert2(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2);
144
    }
145
 
146
    *mx_ptr = bx;
147
    *my_ptr = by;
148
 
149
    return dmin;
150
}
151
 
152
static int no_sub_motion_search(MpegEncContext * s,
153
          int *mx_ptr, int *my_ptr, int dmin,
154
                                  int src_index, int ref_index,
155
                                  int size, int h)
156
{
157
    (*mx_ptr)<<=1;
158
    (*my_ptr)<<=1;
159
    return dmin;
160
}
161
 
162
static inline int get_mb_score(MpegEncContext *s, int mx, int my,
163
                               int src_index, int ref_index, int size,
164
                               int h, int add_rate)
165
{
166
//    const int check_luma= s->dsp.me_sub_cmp != s->dsp.mb_cmp;
167
    MotionEstContext * const c= &s->me;
168
    const int penalty_factor= c->mb_penalty_factor;
169
    const int flags= c->mb_flags;
170
    const int qpel= flags & FLAG_QPEL;
171
    const int mask= 1+2*qpel;
172
    me_cmp_func cmp_sub, chroma_cmp_sub;
173
    int d;
174
 
175
    LOAD_COMMON
176
 
177
 //FIXME factorize
178
 
179
    cmp_sub= s->dsp.mb_cmp[size];
180
    chroma_cmp_sub= s->dsp.mb_cmp[size+1];
181
 
182
    d= cmp(s, mx>>(qpel+1), my>>(qpel+1), mx&mask, my&mask, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
183
    //FIXME check cbp before adding penalty for (0,0) vector
184
    if(add_rate && (mx || my || size>0))
185
        d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor;
186
 
187
    return d;
188
}
189
 
190
int ff_get_mb_score(MpegEncContext *s, int mx, int my, int src_index,
191
                    int ref_index, int size, int h, int add_rate)
192
{
193
    return get_mb_score(s, mx, my, src_index, ref_index, size, h, add_rate);
194
}
195
 
196
#define CHECK_QUARTER_MV(dx, dy, x, y)\
197
{\
198
    const int hx= 4*(x)+(dx);\
199
    const int hy= 4*(y)+(dy);\
200
    d= cmp_qpel(s, x, y, dx, dy, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
201
    d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
202
    COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
203
}
204
 
205
static int qpel_motion_search(MpegEncContext * s,
206
                                  int *mx_ptr, int *my_ptr, int dmin,
207
                                  int src_index, int ref_index,
208
                                  int size, int h)
209
{
210
    MotionEstContext * const c= &s->me;
211
    const int mx = *mx_ptr;
212
    const int my = *my_ptr;
213
    const int penalty_factor= c->sub_penalty_factor;
214
    const unsigned map_generation = c->map_generation;
215
    const int subpel_quality= c->avctx->me_subpel_quality;
216
    uint32_t *map= c->map;
217
    me_cmp_func cmpf, chroma_cmpf;
218
    me_cmp_func cmp_sub, chroma_cmp_sub;
219
 
220
    LOAD_COMMON
221
    int flags= c->sub_flags;
222
 
223
    cmpf= s->dsp.me_cmp[size];
224
    chroma_cmpf= s->dsp.me_cmp[size+1]; //factorize FIXME
225
 //FIXME factorize
226
 
227
    cmp_sub= s->dsp.me_sub_cmp[size];
228
    chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];
229
 
230
    if(c->skip){ //FIXME somehow move up (benchmark)
231
        *mx_ptr = 0;
232
        *my_ptr = 0;
233
        return dmin;
234
    }
235
 
236
    if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
237
        dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
238
        if(mx || my || size>0)
239
            dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor;
240
    }
241
 
242
    if (mx > xmin && mx < xmax &&
243
        my > ymin && my < ymax) {
244
        int bx=4*mx, by=4*my;
245
        int d= dmin;
246
        int i, nx, ny;
247
        const int index= (my<
248
        const int t= score_map[(index-(1<
249
        const int l= score_map[(index- 1                 )&(ME_MAP_SIZE-1)];
250
        const int r= score_map[(index+ 1                 )&(ME_MAP_SIZE-1)];
251
        const int b= score_map[(index+(1<
252
        const int c= score_map[(index                    )&(ME_MAP_SIZE-1)];
253
        int best[8];
254
        int best_pos[8][2];
255
 
256
        memset(best, 64, sizeof(int)*8);
257
        if(s->me.dia_size>=2){
258
            const int tl= score_map[(index-(1<
259
            const int bl= score_map[(index+(1<
260
            const int tr= score_map[(index-(1<
261
            const int br= score_map[(index+(1<
262
 
263
            for(ny= -3; ny <= 3; ny++){
264
                for(nx= -3; nx <= 3; nx++){
265
                    //FIXME this could overflow (unlikely though)
266
                    const int64_t t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t;
267
                    const int64_t c2= nx*nx*( r +  l - 2*c) + 4*nx*( r- l) + 32*c;
268
                    const int64_t b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b;
269
                    int score= (ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2 + 512)>>10;
270
                    int i;
271
 
272
                    if((nx&3)==0 && (ny&3)==0) continue;
273
 
274
                    score += (mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
275
 
276
//                    if(nx&1) score-=1024*c->penalty_factor;
277
//                    if(ny&1) score-=1024*c->penalty_factor;
278
 
279
                    for(i=0; i<8; i++){
280
                        if(score < best[i]){
281
                            memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
282
                            memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
283
                            best[i]= score;
284
                            best_pos[i][0]= nx + 4*mx;
285
                            best_pos[i][1]= ny + 4*my;
286
                            break;
287
                        }
288
                    }
289
                }
290
            }
291
        }else{
292
            int tl;
293
            //FIXME this could overflow (unlikely though)
294
            const int cx = 4*(r - l);
295
            const int cx2= r + l - 2*c;
296
            const int cy = 4*(b - t);
297
            const int cy2= b + t - 2*c;
298
            int cxy;
299
 
300
            if(map[(index-(1<
301
                tl= score_map[(index-(1<
302
            }else{
303
                tl= cmp(s, mx-1, my-1, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);//FIXME wrong if chroma me is different
304
            }
305
 
306
            cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c;
307
 
308
            av_assert2(16*cx2 + 4*cx + 32*c == 32*r);
309
            av_assert2(16*cx2 - 4*cx + 32*c == 32*l);
310
            av_assert2(16*cy2 + 4*cy + 32*c == 32*b);
311
            av_assert2(16*cy2 - 4*cy + 32*c == 32*t);
312
            av_assert2(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl);
313
 
314
            for(ny= -3; ny <= 3; ny++){
315
                for(nx= -3; nx <= 3; nx++){
316
                    //FIXME this could overflow (unlikely though)
317
                    int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor
318
                    int i;
319
 
320
                    if((nx&3)==0 && (ny&3)==0) continue;
321
 
322
                    score += 32*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
323
//                    if(nx&1) score-=32*c->penalty_factor;
324
  //                  if(ny&1) score-=32*c->penalty_factor;
325
 
326
                    for(i=0; i<8; i++){
327
                        if(score < best[i]){
328
                            memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
329
                            memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
330
                            best[i]= score;
331
                            best_pos[i][0]= nx + 4*mx;
332
                            best_pos[i][1]= ny + 4*my;
333
                            break;
334
                        }
335
                    }
336
                }
337
            }
338
        }
339
        for(i=0; i
340
            nx= best_pos[i][0];
341
            ny= best_pos[i][1];
342
            CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2)
343
        }
344
 
345
        av_assert2(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4);
346
 
347
        *mx_ptr = bx;
348
        *my_ptr = by;
349
    }else{
350
        *mx_ptr =4*mx;
351
        *my_ptr =4*my;
352
    }
353
 
354
    return dmin;
355
}
356
 
357
 
358
#define CHECK_MV(x,y)\
359
{\
360
    const unsigned key = ((y)<
361
    const int index= (((y)<
362
    av_assert2((x) >= xmin);\
363
    av_assert2((x) <= xmax);\
364
    av_assert2((y) >= ymin);\
365
    av_assert2((y) <= ymax);\
366
    if(map[index]!=key){\
367
        d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
368
        map[index]= key;\
369
        score_map[index]= d;\
370
        d += (mv_penalty[((x)<
371
        COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
372
    }\
373
}
374
 
375
#define CHECK_CLIPPED_MV(ax,ay)\
376
{\
377
    const int Lx= ax;\
378
    const int Ly= ay;\
379
    const int Lx2= FFMAX(xmin, FFMIN(Lx, xmax));\
380
    const int Ly2= FFMAX(ymin, FFMIN(Ly, ymax));\
381
    CHECK_MV(Lx2, Ly2)\
382
}
383
 
384
#define CHECK_MV_DIR(x,y,new_dir)\
385
{\
386
    const unsigned key = ((y)<
387
    const int index= (((y)<
388
    if(map[index]!=key){\
389
        d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
390
        map[index]= key;\
391
        score_map[index]= d;\
392
        d += (mv_penalty[((x)<
393
        if(d
394
            best[0]=x;\
395
            best[1]=y;\
396
            dmin=d;\
397
            next_dir= new_dir;\
398
        }\
399
    }\
400
}
401
 
402
#define check(x,y,S,v)\
403
if( (x)<(xmin<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\
404
if( (x)>(xmax<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\
405
if( (y)<(ymin<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\
406
if( (y)>(ymax<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\
407
 
408
#define LOAD_COMMON2\
409
    uint32_t *map= c->map;\
410
    const int qpel= flags&FLAG_QPEL;\
411
    const int shift= 1+qpel;\
412
 
413
static av_always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
414
                                       int src_index, int ref_index, int const penalty_factor,
415
                                       int size, int h, int flags)
416
{
417
    MotionEstContext * const c= &s->me;
418
    me_cmp_func cmpf, chroma_cmpf;
419
    int next_dir=-1;
420
    LOAD_COMMON
421
    LOAD_COMMON2
422
    unsigned map_generation = c->map_generation;
423
 
424
    cmpf= s->dsp.me_cmp[size];
425
    chroma_cmpf= s->dsp.me_cmp[size+1];
426
 
427
    { /* ensure that the best point is in the MAP as h/qpel refinement needs it */
428
        const unsigned key = (best[1]<
429
        const int index= ((best[1]<
430
        if(map[index]!=key){ //this will be executed only very rarey
431
            score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
432
            map[index]= key;
433
        }
434
    }
435
 
436
    for(;;){
437
        int d;
438
        const int dir= next_dir;
439
        const int x= best[0];
440
        const int y= best[1];
441
        next_dir=-1;
442
 
443
        if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y  , 0)
444
        if(dir!=3 && y>ymin) CHECK_MV_DIR(x  , y-1, 1)
445
        if(dir!=0 && x
446
        if(dir!=1 && y
447
 
448
        if(next_dir==-1){
449
            return dmin;
450
        }
451
    }
452
}
453
 
454
static int funny_diamond_search(MpegEncContext * s, int *best, int dmin,
455
                                       int src_index, int ref_index, int const penalty_factor,
456
                                       int size, int h, int flags)
457
{
458
    MotionEstContext * const c= &s->me;
459
    me_cmp_func cmpf, chroma_cmpf;
460
    int dia_size;
461
    LOAD_COMMON
462
    LOAD_COMMON2
463
    unsigned map_generation = c->map_generation;
464
 
465
    cmpf= s->dsp.me_cmp[size];
466
    chroma_cmpf= s->dsp.me_cmp[size+1];
467
 
468
    for(dia_size=1; dia_size<=4; dia_size++){
469
        int dir;
470
        const int x= best[0];
471
        const int y= best[1];
472
 
473
        if(dia_size&(dia_size-1)) continue;
474
 
475
        if(   x + dia_size > xmax
476
           || x - dia_size < xmin
477
           || y + dia_size > ymax
478
           || y - dia_size < ymin)
479
           continue;
480
 
481
        for(dir= 0; dir
482
            int d;
483
 
484
            CHECK_MV(x + dir           , y + dia_size - dir);
485
            CHECK_MV(x + dia_size - dir, y - dir           );
486
            CHECK_MV(x - dir           , y - dia_size + dir);
487
            CHECK_MV(x - dia_size + dir, y + dir           );
488
        }
489
 
490
        if(x!=best[0] || y!=best[1])
491
            dia_size=0;
492
    }
493
    return dmin;
494
}
495
 
496
static int hex_search(MpegEncContext * s, int *best, int dmin,
497
                                       int src_index, int ref_index, int const penalty_factor,
498
                                       int size, int h, int flags, int dia_size)
499
{
500
    MotionEstContext * const c= &s->me;
501
    me_cmp_func cmpf, chroma_cmpf;
502
    LOAD_COMMON
503
    LOAD_COMMON2
504
    unsigned map_generation = c->map_generation;
505
    int x,y,d;
506
    const int dec= dia_size & (dia_size-1);
507
 
508
    cmpf= s->dsp.me_cmp[size];
509
    chroma_cmpf= s->dsp.me_cmp[size+1];
510
 
511
    for(;dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
512
        do{
513
            x= best[0];
514
            y= best[1];
515
 
516
            CHECK_CLIPPED_MV(x  -dia_size    , y);
517
            CHECK_CLIPPED_MV(x+  dia_size    , y);
518
            CHECK_CLIPPED_MV(x+( dia_size>>1), y+dia_size);
519
            CHECK_CLIPPED_MV(x+( dia_size>>1), y-dia_size);
520
            if(dia_size>1){
521
                CHECK_CLIPPED_MV(x+(-dia_size>>1), y+dia_size);
522
                CHECK_CLIPPED_MV(x+(-dia_size>>1), y-dia_size);
523
            }
524
        }while(best[0] != x || best[1] != y);
525
    }
526
 
527
    return dmin;
528
}
529
 
530
static int l2s_dia_search(MpegEncContext * s, int *best, int dmin,
531
                                       int src_index, int ref_index, int const penalty_factor,
532
                                       int size, int h, int flags)
533
{
534
    MotionEstContext * const c= &s->me;
535
    me_cmp_func cmpf, chroma_cmpf;
536
    LOAD_COMMON
537
    LOAD_COMMON2
538
    unsigned map_generation = c->map_generation;
539
    int x,y,i,d;
540
    int dia_size= c->dia_size&0xFF;
541
    const int dec= dia_size & (dia_size-1);
542
    static const int hex[8][2]={{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1},
543
                                { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}};
544
 
545
    cmpf= s->dsp.me_cmp[size];
546
    chroma_cmpf= s->dsp.me_cmp[size+1];
547
 
548
    for(; dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
549
        do{
550
            x= best[0];
551
            y= best[1];
552
            for(i=0; i<8; i++){
553
                CHECK_CLIPPED_MV(x+hex[i][0]*dia_size, y+hex[i][1]*dia_size);
554
            }
555
        }while(best[0] != x || best[1] != y);
556
    }
557
 
558
    x= best[0];
559
    y= best[1];
560
    CHECK_CLIPPED_MV(x+1, y);
561
    CHECK_CLIPPED_MV(x, y+1);
562
    CHECK_CLIPPED_MV(x-1, y);
563
    CHECK_CLIPPED_MV(x, y-1);
564
 
565
    return dmin;
566
}
567
 
568
static int umh_search(MpegEncContext * s, int *best, int dmin,
569
                                       int src_index, int ref_index, int const penalty_factor,
570
                                       int size, int h, int flags)
571
{
572
    MotionEstContext * const c= &s->me;
573
    me_cmp_func cmpf, chroma_cmpf;
574
    LOAD_COMMON
575
    LOAD_COMMON2
576
    unsigned map_generation = c->map_generation;
577
    int x,y,x2,y2, i, j, d;
578
    const int dia_size= c->dia_size&0xFE;
579
    static const int hex[16][2]={{-4,-2}, {-4,-1}, {-4, 0}, {-4, 1}, {-4, 2},
580
                                 { 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2},
581
                                 {-2, 3}, { 0, 4}, { 2, 3},
582
                                 {-2,-3}, { 0,-4}, { 2,-3},};
583
 
584
    cmpf= s->dsp.me_cmp[size];
585
    chroma_cmpf= s->dsp.me_cmp[size+1];
586
 
587
    x= best[0];
588
    y= best[1];
589
    for(x2=FFMAX(x-dia_size+1, xmin); x2<=FFMIN(x+dia_size-1,xmax); x2+=2){
590
        CHECK_MV(x2, y);
591
    }
592
    for(y2=FFMAX(y-dia_size/2+1, ymin); y2<=FFMIN(y+dia_size/2-1,ymax); y2+=2){
593
        CHECK_MV(x, y2);
594
    }
595
 
596
    x= best[0];
597
    y= best[1];
598
    for(y2=FFMAX(y-2, ymin); y2<=FFMIN(y+2,ymax); y2++){
599
        for(x2=FFMAX(x-2, xmin); x2<=FFMIN(x+2,xmax); x2++){
600
            CHECK_MV(x2, y2);
601
        }
602
    }
603
 
604
//FIXME prevent the CLIP stuff
605
 
606
    for(j=1; j<=dia_size/4; j++){
607
        for(i=0; i<16; i++){
608
            CHECK_CLIPPED_MV(x+hex[i][0]*j, y+hex[i][1]*j);
609
        }
610
    }
611
 
612
    return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, 2);
613
}
614
 
615
static int full_search(MpegEncContext * s, int *best, int dmin,
616
                                       int src_index, int ref_index, int const penalty_factor,
617
                                       int size, int h, int flags)
618
{
619
    MotionEstContext * const c= &s->me;
620
    me_cmp_func cmpf, chroma_cmpf;
621
    LOAD_COMMON
622
    LOAD_COMMON2
623
    unsigned map_generation = c->map_generation;
624
    int x,y, d;
625
    const int dia_size= c->dia_size&0xFF;
626
 
627
    cmpf= s->dsp.me_cmp[size];
628
    chroma_cmpf= s->dsp.me_cmp[size+1];
629
 
630
    for(y=FFMAX(-dia_size, ymin); y<=FFMIN(dia_size,ymax); y++){
631
        for(x=FFMAX(-dia_size, xmin); x<=FFMIN(dia_size,xmax); x++){
632
            CHECK_MV(x, y);
633
        }
634
    }
635
 
636
    x= best[0];
637
    y= best[1];
638
    d= dmin;
639
    CHECK_CLIPPED_MV(x  , y);
640
    CHECK_CLIPPED_MV(x+1, y);
641
    CHECK_CLIPPED_MV(x, y+1);
642
    CHECK_CLIPPED_MV(x-1, y);
643
    CHECK_CLIPPED_MV(x, y-1);
644
    best[0]= x;
645
    best[1]= y;
646
 
647
    return d;
648
}
649
 
650
#define SAB_CHECK_MV(ax,ay)\
651
{\
652
    const unsigned key = ((ay)<
653
    const int index= (((ay)<
654
    if(map[index]!=key){\
655
        d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
656
        map[index]= key;\
657
        score_map[index]= d;\
658
        d += (mv_penalty[((ax)<
659
        if(d < minima[minima_count-1].height){\
660
            int j=0;\
661
            \
662
            while(d >= minima[j].height) j++;\
663
\
664
            memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\
665
\
666
            minima[j].checked= 0;\
667
            minima[j].height= d;\
668
            minima[j].x= ax;\
669
            minima[j].y= ay;\
670
            \
671
            i=-1;\
672
            continue;\
673
        }\
674
    }\
675
}
676
 
677
#define MAX_SAB_SIZE ME_MAP_SIZE
678
static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,
679
                                       int src_index, int ref_index, int const penalty_factor,
680
                                       int size, int h, int flags)
681
{
682
    MotionEstContext * const c= &s->me;
683
    me_cmp_func cmpf, chroma_cmpf;
684
    Minima minima[MAX_SAB_SIZE];
685
    const int minima_count= FFABS(c->dia_size);
686
    int i, j;
687
    LOAD_COMMON
688
    LOAD_COMMON2
689
    unsigned map_generation = c->map_generation;
690
 
691
    av_assert1(minima_count <= MAX_SAB_SIZE);
692
 
693
    cmpf= s->dsp.me_cmp[size];
694
    chroma_cmpf= s->dsp.me_cmp[size+1];
695
 
696
    /*Note j
697
      become larger due to MVs overflowing their ME_MAP_MV_BITS bits space in map
698
     */
699
    for(j=i=0; i
700
        uint32_t key= map[i];
701
 
702
        key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1));
703
 
704
        if((key&((-1)<<(2*ME_MAP_MV_BITS))) != map_generation) continue;
705
 
706
        minima[j].height= score_map[i];
707
        minima[j].x= key & ((1<>=ME_MAP_MV_BITS;
708
        minima[j].y= key & ((1<
709
        minima[j].x-= (1<<(ME_MAP_MV_BITS-1));
710
        minima[j].y-= (1<<(ME_MAP_MV_BITS-1));
711
 
712
        // all entries in map should be in range except if the mv overflows their ME_MAP_MV_BITS bits space
713
        if(   minima[j].x > xmax || minima[j].x < xmin
714
           || minima[j].y > ymax || minima[j].y < ymin)
715
            continue;
716
 
717
        minima[j].checked=0;
718
        if(minima[j].x || minima[j].y)
719
            minima[j].height+= (mv_penalty[((minima[j].x)<
720
 
721
        j++;
722
    }
723
 
724
    qsort(minima, j, sizeof(Minima), minima_cmp);
725
 
726
    for(; j
727
        minima[j].height=256*256*256*64;
728
        minima[j].checked=0;
729
        minima[j].x= minima[j].y=0;
730
    }
731
 
732
    for(i=0; i
733
        const int x= minima[i].x;
734
        const int y= minima[i].y;
735
        int d;
736
 
737
        if(minima[i].checked) continue;
738
 
739
        if(   x >= xmax || x <= xmin
740
           || y >= ymax || y <= ymin)
741
           continue;
742
 
743
        SAB_CHECK_MV(x-1, y)
744
        SAB_CHECK_MV(x+1, y)
745
        SAB_CHECK_MV(x  , y-1)
746
        SAB_CHECK_MV(x  , y+1)
747
 
748
        minima[i].checked= 1;
749
    }
750
 
751
    best[0]= minima[0].x;
752
    best[1]= minima[0].y;
753
    dmin= minima[0].height;
754
 
755
    if(   best[0] < xmax && best[0] > xmin
756
       && best[1] < ymax && best[1] > ymin){
757
        int d;
758
        //ensure that the refernece samples for hpel refinement are in the map
759
        CHECK_MV(best[0]-1, best[1])
760
        CHECK_MV(best[0]+1, best[1])
761
        CHECK_MV(best[0], best[1]-1)
762
        CHECK_MV(best[0], best[1]+1)
763
    }
764
    return dmin;
765
}
766
 
767
static int var_diamond_search(MpegEncContext * s, int *best, int dmin,
768
                                       int src_index, int ref_index, int const penalty_factor,
769
                                       int size, int h, int flags)
770
{
771
    MotionEstContext * const c= &s->me;
772
    me_cmp_func cmpf, chroma_cmpf;
773
    int dia_size;
774
    LOAD_COMMON
775
    LOAD_COMMON2
776
    unsigned map_generation = c->map_generation;
777
 
778
    cmpf= s->dsp.me_cmp[size];
779
    chroma_cmpf= s->dsp.me_cmp[size+1];
780
 
781
    for(dia_size=1; dia_size<=c->dia_size; dia_size++){
782
        int dir, start, end;
783
        const int x= best[0];
784
        const int y= best[1];
785
 
786
        start= FFMAX(0, y + dia_size - ymax);
787
        end  = FFMIN(dia_size, xmax - x + 1);
788
        for(dir= start; dir
789
            int d;
790
 
791
//check(x + dir,y + dia_size - dir,0, a0)
792
            CHECK_MV(x + dir           , y + dia_size - dir);
793
        }
794
 
795
        start= FFMAX(0, x + dia_size - xmax);
796
        end  = FFMIN(dia_size, y - ymin + 1);
797
        for(dir= start; dir
798
            int d;
799
 
800
//check(x + dia_size - dir, y - dir,0, a1)
801
            CHECK_MV(x + dia_size - dir, y - dir           );
802
        }
803
 
804
        start= FFMAX(0, -y + dia_size + ymin );
805
        end  = FFMIN(dia_size, x - xmin + 1);
806
        for(dir= start; dir
807
            int d;
808
 
809
//check(x - dir,y - dia_size + dir,0, a2)
810
            CHECK_MV(x - dir           , y - dia_size + dir);
811
        }
812
 
813
        start= FFMAX(0, -x + dia_size + xmin );
814
        end  = FFMIN(dia_size, ymax - y + 1);
815
        for(dir= start; dir
816
            int d;
817
 
818
//check(x - dia_size + dir, y + dir,0, a3)
819
            CHECK_MV(x - dia_size + dir, y + dir           );
820
        }
821
 
822
        if(x!=best[0] || y!=best[1])
823
            dia_size=0;
824
    }
825
    return dmin;
826
}
827
 
828
static av_always_inline int diamond_search(MpegEncContext * s, int *best, int dmin,
829
                                       int src_index, int ref_index, int const penalty_factor,
830
                                       int size, int h, int flags){
831
    MotionEstContext * const c= &s->me;
832
    if(c->dia_size==-1)
833
        return funny_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
834
    else if(c->dia_size<-1)
835
        return   sab_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
836
    else if(c->dia_size<2)
837
        return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
838
    else if(c->dia_size>1024)
839
        return          full_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
840
    else if(c->dia_size>768)
841
        return           umh_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
842
    else if(c->dia_size>512)
843
        return           hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, c->dia_size&0xFF);
844
    else if(c->dia_size>256)
845
        return       l2s_dia_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
846
    else
847
        return   var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
848
}
849
 
850
/**
851
   @param P a list of candidate mvs to check before starting the
852
   iterative search. If one of the candidates is close to the optimal mv, then
853
   it takes fewer iterations. And it increases the chance that we find the
854
   optimal mv.
855
 */
856
static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int *mx_ptr, int *my_ptr,
857
                             int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2],
858
                             int ref_mv_scale, int flags, int size, int h)
859
{
860
    MotionEstContext * const c= &s->me;
861
    int best[2]={0, 0};      /**< x and y coordinates of the best motion vector.
862
                               i.e. the difference between the position of the
863
                               block currently being encoded and the position of
864
                               the block chosen to predict it from. */
865
    int d;                   ///< the score (cmp + penalty) of any given mv
866
    int dmin;                /**< the best value of d, i.e. the score
867
                               corresponding to the mv stored in best[]. */
868
    unsigned map_generation;
869
    int penalty_factor;
870
    const int ref_mv_stride= s->mb_stride; //pass as arg  FIXME
871
    const int ref_mv_xy= s->mb_x + s->mb_y*ref_mv_stride; //add to last_mv beforepassing FIXME
872
    me_cmp_func cmpf, chroma_cmpf;
873
 
874
    LOAD_COMMON
875
    LOAD_COMMON2
876
 
877
    if(c->pre_pass){
878
        penalty_factor= c->pre_penalty_factor;
879
        cmpf= s->dsp.me_pre_cmp[size];
880
        chroma_cmpf= s->dsp.me_pre_cmp[size+1];
881
    }else{
882
        penalty_factor= c->penalty_factor;
883
        cmpf= s->dsp.me_cmp[size];
884
        chroma_cmpf= s->dsp.me_cmp[size+1];
885
    }
886
 
887
    map_generation= update_map_generation(c);
888
 
889
    av_assert2(cmpf);
890
    dmin= cmp(s, 0, 0, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
891
    map[0]= map_generation;
892
    score_map[0]= dmin;
893
 
894
    //FIXME precalc first term below?
895
    if((s->pict_type == AV_PICTURE_TYPE_B && !(c->flags & FLAG_DIRECT)) || s->flags&CODEC_FLAG_MV0)
896
        dmin += (mv_penalty[pred_x] + mv_penalty[pred_y])*penalty_factor;
897
 
898
    /* first line */
899
    if (s->first_slice_line) {
900
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
901
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
902
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
903
    }else{
904
        if(dmin<((h*h*s->avctx->mv0_threshold)>>8)
905
                    && ( P_LEFT[0]    |P_LEFT[1]
906
                        |P_TOP[0]     |P_TOP[1]
907
                        |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){
908
            *mx_ptr= 0;
909
            *my_ptr= 0;
910
            c->skip=1;
911
            return dmin;
912
        }
913
        CHECK_MV(    P_MEDIAN[0] >>shift ,    P_MEDIAN[1] >>shift)
914
        CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)  , (P_MEDIAN[1]>>shift)-1)
915
        CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)  , (P_MEDIAN[1]>>shift)+1)
916
        CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)-1, (P_MEDIAN[1]>>shift)  )
917
        CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)+1, (P_MEDIAN[1]>>shift)  )
918
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
919
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
920
        CHECK_MV(P_LEFT[0]    >>shift, P_LEFT[1]    >>shift)
921
        CHECK_MV(P_TOP[0]     >>shift, P_TOP[1]     >>shift)
922
        CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
923
    }
924
    if(dmin>h*h*4){
925
        if(c->pre_pass){
926
            CHECK_CLIPPED_MV((last_mv[ref_mv_xy-1][0]*ref_mv_scale + (1<<15))>>16,
927
                            (last_mv[ref_mv_xy-1][1]*ref_mv_scale + (1<<15))>>16)
928
            if(!s->first_slice_line)
929
                CHECK_CLIPPED_MV((last_mv[ref_mv_xy-ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
930
                                (last_mv[ref_mv_xy-ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
931
        }else{
932
            CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
933
                            (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
934
            if(s->mb_y+1end_mb_y)  //FIXME replace at least with last_slice_line
935
                CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
936
                                (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
937
        }
938
    }
939
 
940
    if(c->avctx->last_predictor_count){
941
        const int count= c->avctx->last_predictor_count;
942
        const int xstart= FFMAX(0, s->mb_x - count);
943
        const int ystart= FFMAX(0, s->mb_y - count);
944
        const int xend= FFMIN(s->mb_width , s->mb_x + count + 1);
945
        const int yend= FFMIN(s->mb_height, s->mb_y + count + 1);
946
        int mb_y;
947
 
948
        for(mb_y=ystart; mb_y
949
            int mb_x;
950
            for(mb_x=xstart; mb_x
951
                const int xy= mb_x + 1 + (mb_y + 1)*ref_mv_stride;
952
                int mx= (last_mv[xy][0]*ref_mv_scale + (1<<15))>>16;
953
                int my= (last_mv[xy][1]*ref_mv_scale + (1<<15))>>16;
954
 
955
                if(mx>xmax || mxymax || my
956
                CHECK_MV(mx,my)
957
            }
958
        }
959
    }
960
 
961
//check(best[0],best[1],0, b0)
962
    dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
963
 
964
//check(best[0],best[1],0, b1)
965
    *mx_ptr= best[0];
966
    *my_ptr= best[1];
967
 
968
    return dmin;
969
}
970
 
971
//this function is dedicated to the braindamaged gcc
972
int ff_epzs_motion_search(MpegEncContext *s, int *mx_ptr, int *my_ptr,
973
                          int P[10][2], int src_index, int ref_index,
974
                          int16_t (*last_mv)[2], int ref_mv_scale,
975
                          int size, int h)
976
{
977
    MotionEstContext * const c= &s->me;
978
//FIXME convert other functions in the same way if faster
979
    if(c->flags==0 && h==16 && size==0){
980
        return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, 0, 0, 16);
981
//    case FLAG_QPEL:
982
//        return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, FLAG_QPEL);
983
    }else{
984
        return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, c->flags, size, h);
985
    }
986
}
987
 
988
static int epzs_motion_search4(MpegEncContext * s,
989
                             int *mx_ptr, int *my_ptr, int P[10][2],
990
                             int src_index, int ref_index, int16_t (*last_mv)[2],
991
                             int ref_mv_scale)
992
{
993
    MotionEstContext * const c= &s->me;
994
    int best[2]={0, 0};
995
    int d, dmin;
996
    unsigned map_generation;
997
    const int penalty_factor= c->penalty_factor;
998
    const int size=1;
999
    const int h=8;
1000
    const int ref_mv_stride= s->mb_stride;
1001
    const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
1002
    me_cmp_func cmpf, chroma_cmpf;
1003
    LOAD_COMMON
1004
    int flags= c->flags;
1005
    LOAD_COMMON2
1006
 
1007
    cmpf= s->dsp.me_cmp[size];
1008
    chroma_cmpf= s->dsp.me_cmp[size+1];
1009
 
1010
    map_generation= update_map_generation(c);
1011
 
1012
    dmin = 1000000;
1013
 
1014
    /* first line */
1015
    if (s->first_slice_line) {
1016
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1017
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1018
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1019
        CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1020
    }else{
1021
        CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1022
        //FIXME try some early stop
1023
        CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
1024
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1025
        CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
1026
        CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
1027
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1028
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1029
    }
1030
    if(dmin>64*4){
1031
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
1032
                        (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1033
        if(s->mb_y+1end_mb_y)  //FIXME replace at least with last_slice_line
1034
            CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1035
                            (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1036
    }
1037
 
1038
    dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1039
 
1040
    *mx_ptr= best[0];
1041
    *my_ptr= best[1];
1042
 
1043
    return dmin;
1044
}
1045
 
1046
//try to merge with above FIXME (needs PSNR test)
1047
static int epzs_motion_search2(MpegEncContext * s,
1048
                             int *mx_ptr, int *my_ptr, int P[10][2],
1049
                             int src_index, int ref_index, int16_t (*last_mv)[2],
1050
                             int ref_mv_scale)
1051
{
1052
    MotionEstContext * const c= &s->me;
1053
    int best[2]={0, 0};
1054
    int d, dmin;
1055
    unsigned map_generation;
1056
    const int penalty_factor= c->penalty_factor;
1057
    const int size=0; //FIXME pass as arg
1058
    const int h=8;
1059
    const int ref_mv_stride= s->mb_stride;
1060
    const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
1061
    me_cmp_func cmpf, chroma_cmpf;
1062
    LOAD_COMMON
1063
    int flags= c->flags;
1064
    LOAD_COMMON2
1065
 
1066
    cmpf= s->dsp.me_cmp[size];
1067
    chroma_cmpf= s->dsp.me_cmp[size+1];
1068
 
1069
    map_generation= update_map_generation(c);
1070
 
1071
    dmin = 1000000;
1072
 
1073
    /* first line */
1074
    if (s->first_slice_line) {
1075
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1076
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1077
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1078
        CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1079
    }else{
1080
        CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1081
        //FIXME try some early stop
1082
        CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
1083
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1084
        CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
1085
        CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
1086
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1087
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1088
    }
1089
    if(dmin>64*4){
1090
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
1091
                        (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1092
        if(s->mb_y+1end_mb_y)  //FIXME replace at least with last_slice_line
1093
            CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1094
                            (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1095
    }
1096
 
1097
    dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1098
 
1099
    *mx_ptr= best[0];
1100
    *my_ptr= best[1];
1101
 
1102
    return dmin;
1103
}