GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/motion_est_template.c Lines: 311 498 62.4 %
Date: 2021-04-20 15:25:36 Branches: 228 490 46.5 %

Line Branch Exec Source
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
#include "libavutil/qsort.h"
28
#include "mpegvideo.h"
29
30
//Let us hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...)
31
#define LOAD_COMMON\
32
    uint32_t av_unused * const score_map= c->score_map;\
33
    const int av_unused xmin= c->xmin;\
34
    const int av_unused ymin= c->ymin;\
35
    const int av_unused xmax= c->xmax;\
36
    const int av_unused ymax= c->ymax;\
37
    const uint8_t *mv_penalty = c->current_mv_penalty; \
38
    const int pred_x= c->pred_x;\
39
    const int pred_y= c->pred_y;\
40
41
#define CHECK_HALF_MV(dx, dy, x, y)\
42
{\
43
    const int hx= 2*(x)+(dx);\
44
    const int hy= 2*(y)+(dy);\
45
    d= cmp_hpel(s, x, y, dx, dy, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);\
46
    d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
47
    COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
48
}
49
50
597890
static int hpel_motion_search(MpegEncContext * s,
51
                                  int *mx_ptr, int *my_ptr, int dmin,
52
                                  int src_index, int ref_index,
53
                                  int size, int h)
54
{
55
597890
    MotionEstContext * const c= &s->me;
56
597890
    const int mx = *mx_ptr;
57
597890
    const int my = *my_ptr;
58
597890
    const int penalty_factor= c->sub_penalty_factor;
59
    me_cmp_func cmp_sub, chroma_cmp_sub;
60
597890
    int bx=2*mx, by=2*my;
61
62
597890
    LOAD_COMMON
63
597890
    int flags= c->sub_flags;
64
65
 //FIXME factorize
66
67
597890
    cmp_sub        = s->mecc.me_sub_cmp[size];
68
597890
    chroma_cmp_sub = s->mecc.me_sub_cmp[size + 1];
69
70
597890
    if(c->skip){ //FIXME move out of hpel?
71
707
        *mx_ptr = 0;
72
707
        *my_ptr = 0;
73
707
        return dmin;
74
    }
75
76
597183
    if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
77
186511
        dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
78

186511
        if(mx || my || size>0)
79
164395
            dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor;
80
    }
81
82

597183
    if (mx > xmin && mx < xmax &&
83
586234
        my > ymin && my < ymax) {
84
582910
        int d= dmin;
85
582910
        const int index = my * (1 << ME_MAP_SHIFT) + mx;
86
582910
        const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
87
582910
                     + (mv_penalty[bx   - pred_x] + mv_penalty[by-2 - pred_y])*c->penalty_factor;
88
582910
        const int l= score_map[(index- 1               )&(ME_MAP_SIZE-1)]
89
582910
                     + (mv_penalty[bx-2 - pred_x] + mv_penalty[by   - pred_y])*c->penalty_factor;
90
582910
        const int r= score_map[(index+ 1               )&(ME_MAP_SIZE-1)]
91
582910
                     + (mv_penalty[bx+2 - pred_x] + mv_penalty[by   - pred_y])*c->penalty_factor;
92
582910
        const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
93
582910
                     + (mv_penalty[bx   - pred_x] + mv_penalty[by+2 - pred_y])*c->penalty_factor;
94
95
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1
96
        unsigned key;
97
        unsigned map_generation= c->map_generation;
98
        key = (my - 1) * (1 << ME_MAP_MV_BITS) + (mx) + map_generation;
99
        av_assert2(c->map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
100
        key = (my + 1) * (1 << ME_MAP_MV_BITS) + (mx) + map_generation;
101
        av_assert2(c->map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
102
        key = (my) * (1 << ME_MAP_MV_BITS) + (mx + 1) + map_generation;
103
        av_assert2(c->map[(index+1)&(ME_MAP_SIZE-1)] == key);
104
        key = (my) * (1 << ME_MAP_MV_BITS) + (mx - 1) + map_generation;
105
        av_assert2(c->map[(index-1)&(ME_MAP_SIZE-1)] == key);
106
#endif
107
582910
        if(t<=b){
108
289994
            CHECK_HALF_MV(0, 1, mx  ,my-1)
109
289994
            if(l<=r){
110
173072
                CHECK_HALF_MV(1, 1, mx-1, my-1)
111
173072
                if(t+r<=b+l){
112
89741
                    CHECK_HALF_MV(1, 1, mx  , my-1)
113
                }else{
114
83331
                    CHECK_HALF_MV(1, 1, mx-1, my  )
115
                }
116
173072
                CHECK_HALF_MV(1, 0, mx-1, my  )
117
            }else{
118
116922
                CHECK_HALF_MV(1, 1, mx  , my-1)
119
116922
                if(t+l<=b+r){
120
59849
                    CHECK_HALF_MV(1, 1, mx-1, my-1)
121
                }else{
122
57073
                    CHECK_HALF_MV(1, 1, mx  , my  )
123
                }
124
116922
                CHECK_HALF_MV(1, 0, mx  , my  )
125
            }
126
        }else{
127
292916
            if(l<=r){
128
116527
                if(t+l<=b+r){
129
53297
                    CHECK_HALF_MV(1, 1, mx-1, my-1)
130
                }else{
131
63230
                    CHECK_HALF_MV(1, 1, mx  , my  )
132
                }
133
116527
                CHECK_HALF_MV(1, 0, mx-1, my)
134
116527
                CHECK_HALF_MV(1, 1, mx-1, my)
135
            }else{
136
176389
                if(t+r<=b+l){
137
87441
                    CHECK_HALF_MV(1, 1, mx  , my-1)
138
                }else{
139
88948
                    CHECK_HALF_MV(1, 1, mx-1, my)
140
                }
141
176389
                CHECK_HALF_MV(1, 0, mx  , my)
142
176389
                CHECK_HALF_MV(1, 1, mx  , my)
143
            }
144
292916
            CHECK_HALF_MV(0, 1, mx  , my)
145
        }
146
        av_assert2(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2);
147
    }
148
149
597183
    *mx_ptr = bx;
150
597183
    *my_ptr = by;
151
152
597183
    return dmin;
153
}
154
155
106777
static int no_sub_motion_search(MpegEncContext * s,
156
          int *mx_ptr, int *my_ptr, int dmin,
157
                                  int src_index, int ref_index,
158
                                  int size, int h)
159
{
160
106777
    (*mx_ptr) *= 2;
161
106777
    (*my_ptr) *= 2;
162
106777
    return dmin;
163
}
164
165
978979
static inline int get_mb_score(MpegEncContext *s, int mx, int my,
166
                               int src_index, int ref_index, int size,
167
                               int h, int add_rate)
168
{
169
978979
    MotionEstContext * const c= &s->me;
170
978979
    const int penalty_factor= c->mb_penalty_factor;
171
978979
    const int flags= c->mb_flags;
172
978979
    const int qpel= flags & FLAG_QPEL;
173
978979
    const int mask= 1+2*qpel;
174
    me_cmp_func cmp_sub, chroma_cmp_sub;
175
    int d;
176
177
978979
    LOAD_COMMON
178
179
 //FIXME factorize
180
181
978979
    cmp_sub        = s->mecc.mb_cmp[size];
182
978979
    chroma_cmp_sub = s->mecc.mb_cmp[size + 1];
183
184
978979
    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);
185
    //FIXME check cbp before adding penalty for (0,0) vector
186


978979
    if(add_rate && (mx || my || size>0))
187
380650
        d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor;
188
189
978979
    return d;
190
}
191
192
557820
int ff_get_mb_score(MpegEncContext *s, int mx, int my, int src_index,
193
                    int ref_index, int size, int h, int add_rate)
194
{
195
557820
    return get_mb_score(s, mx, my, src_index, ref_index, size, h, add_rate);
196
}
197
198
#define CHECK_QUARTER_MV(dx, dy, x, y)\
199
{\
200
    const int hx= 4*(x)+(dx);\
201
    const int hy= 4*(y)+(dy);\
202
    d= cmp_qpel(s, x, y, dx, dy, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
203
    d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
204
    COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
205
}
206
207
740604
static int qpel_motion_search(MpegEncContext * s,
208
                                  int *mx_ptr, int *my_ptr, int dmin,
209
                                  int src_index, int ref_index,
210
                                  int size, int h)
211
{
212
740604
    MotionEstContext * const c= &s->me;
213
740604
    const int mx = *mx_ptr;
214
740604
    const int my = *my_ptr;
215
740604
    const int penalty_factor= c->sub_penalty_factor;
216
740604
    const unsigned map_generation = c->map_generation;
217
740604
    const int subpel_quality= c->avctx->me_subpel_quality;
218
740604
    uint32_t *map= c->map;
219
    me_cmp_func cmpf, chroma_cmpf;
220
    me_cmp_func cmp_sub, chroma_cmp_sub;
221
222
740604
    LOAD_COMMON
223
740604
    int flags= c->sub_flags;
224
225
740604
    cmpf        = s->mecc.me_cmp[size];
226
740604
    chroma_cmpf = s->mecc.me_cmp[size + 1]; // FIXME: factorize
227
 //FIXME factorize
228
229
740604
    cmp_sub        = s->mecc.me_sub_cmp[size];
230
740604
    chroma_cmp_sub = s->mecc.me_sub_cmp[size + 1];
231
232
740604
    if(c->skip){ //FIXME somehow move up (benchmark)
233
1432
        *mx_ptr = 0;
234
1432
        *my_ptr = 0;
235
1432
        return dmin;
236
    }
237
238
739172
    if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
239
187104
        dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
240

187104
        if(mx || my || size>0)
241
164228
            dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor;
242
    }
243
244

739172
    if (mx > xmin && mx < xmax &&
245
735187
        my > ymin && my < ymax) {
246
734754
        int bx=4*mx, by=4*my;
247
734754
        int d= dmin;
248
        int i, nx, ny;
249
734754
        const int index = my * (1 << ME_MAP_SHIFT) + mx;
250
734754
        const int t= score_map[(index-(1<<ME_MAP_SHIFT)  )&(ME_MAP_SIZE-1)];
251
734754
        const int l= score_map[(index- 1                 )&(ME_MAP_SIZE-1)];
252
734754
        const int r= score_map[(index+ 1                 )&(ME_MAP_SIZE-1)];
253
734754
        const int b= score_map[(index+(1<<ME_MAP_SHIFT)  )&(ME_MAP_SIZE-1)];
254
734754
        const int c= score_map[(index                    )&(ME_MAP_SIZE-1)];
255
        int best[8];
256
        int best_pos[8][2];
257
258
734754
        memset(best, 64, sizeof(int)*8);
259
734754
        if(s->me.dia_size>=2){
260
237970
            const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
261
237970
            const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
262
237970
            const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
263
237970
            const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
264
265
1903760
            for(ny= -3; ny <= 3; ny++){
266
13326320
                for(nx= -3; nx <= 3; nx++){
267
                    //FIXME this could overflow (unlikely though)
268
11660530
                    const int64_t t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t;
269
11660530
                    const int64_t c2= nx*nx*( r +  l - 2*c) + 4*nx*( r- l) + 32*c;
270
11660530
                    const int64_t b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b;
271
11660530
                    int score= (ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2 + 512)>>10;
272
                    int i;
273
274

11660530
                    if((nx&3)==0 && (ny&3)==0) continue;
275
276
11422560
                    score += (mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
277
278
//                    if(nx&1) score-=1024*c->penalty_factor;
279
//                    if(ny&1) score-=1024*c->penalty_factor;
280
281
68376473
                    for(i=0; i<8; i++){
282
62877992
                        if(score < best[i]){
283
5924079
                            memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
284
5924079
                            memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
285
5924079
                            best[i]= score;
286
5924079
                            best_pos[i][0]= nx + 4*mx;
287
5924079
                            best_pos[i][1]= ny + 4*my;
288
5924079
                            break;
289
                        }
290
                    }
291
                }
292
            }
293
        }else{
294
            int tl;
295
            //FIXME this could overflow (unlikely though)
296
496784
            const int cx = 4*(r - l);
297
496784
            const int cx2= r + l - 2*c;
298
496784
            const int cy = 4*(b - t);
299
496784
            const int cy2= b + t - 2*c;
300
            int cxy;
301
302
496784
            if (map[(index - (1 << ME_MAP_SHIFT) - 1) & (ME_MAP_SIZE - 1)] ==
303
496784
                (my - 1) * (1 << ME_MAP_MV_BITS) + (mx - 1) + map_generation) {
304
233720
                tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
305
            }else{
306
263064
                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
307
            }
308
309
496784
            cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c;
310
311
            av_assert2(16*cx2 + 4*cx + 32*c == 32*r);
312
            av_assert2(16*cx2 - 4*cx + 32*c == 32*l);
313
            av_assert2(16*cy2 + 4*cy + 32*c == 32*b);
314
            av_assert2(16*cy2 - 4*cy + 32*c == 32*t);
315
            av_assert2(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl);
316
317
3974272
            for(ny= -3; ny <= 3; ny++){
318
27819904
                for(nx= -3; nx <= 3; nx++){
319
                    //FIXME this could overflow (unlikely though)
320
24342416
                    int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor
321
                    int i;
322
323

24342416
                    if((nx&3)==0 && (ny&3)==0) continue;
324
325
23845632
                    score += 32*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
326
//                    if(nx&1) score-=32*c->penalty_factor;
327
  //                  if(ny&1) score-=32*c->penalty_factor;
328
329
141214169
                    for(i=0; i<8; i++){
330
130006302
                        if(score < best[i]){
331
12637765
                            memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
332
12637765
                            memmove(best_pos[i + 1], best_pos[i], sizeof(best_pos[0]) * (7 - i));
333
12637765
                            best[i]= score;
334
12637765
                            best_pos[i][0]= nx + 4*mx;
335
12637765
                            best_pos[i][1]= ny + 4*my;
336
12637765
                            break;
337
                        }
338
                    }
339
                }
340
            }
341
        }
342
6612786
        for(i=0; i<subpel_quality; i++){
343
5878032
            nx= best_pos[i][0];
344
5878032
            ny= best_pos[i][1];
345
5878032
            CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2)
346
        }
347
348
        av_assert2(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4);
349
350
734754
        *mx_ptr = bx;
351
734754
        *my_ptr = by;
352
    }else{
353
4418
        *mx_ptr =4*mx;
354
4418
        *my_ptr =4*my;
355
    }
356
357
739172
    return dmin;
358
}
359
360
361
#define CHECK_MV(x,y)\
362
{\
363
    const unsigned key = ((unsigned)(y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
364
    const int index= (((unsigned)(y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
365
    av_assert2((x) >= xmin);\
366
    av_assert2((x) <= xmax);\
367
    av_assert2((y) >= ymin);\
368
    av_assert2((y) <= ymax);\
369
    if(map[index]!=key){\
370
        d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
371
        map[index]= key;\
372
        score_map[index]= d;\
373
        d += (mv_penalty[((x)*(1<<shift))-pred_x] + mv_penalty[((y)*(1<<shift))-pred_y])*penalty_factor;\
374
        COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
375
    }\
376
}
377
378
#define CHECK_CLIPPED_MV(ax,ay)\
379
{\
380
    const int Lx= ax;\
381
    const int Ly= ay;\
382
    const int Lx2= FFMAX(xmin, FFMIN(Lx, xmax));\
383
    const int Ly2= FFMAX(ymin, FFMIN(Ly, ymax));\
384
    CHECK_MV(Lx2, Ly2)\
385
}
386
387
#define CHECK_MV_DIR(x,y,new_dir)\
388
{\
389
    const unsigned key = ((unsigned)(y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
390
    const int index= (((unsigned)(y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
391
    if(map[index]!=key){\
392
        d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
393
        map[index]= key;\
394
        score_map[index]= d;\
395
        d += (mv_penalty[(int)((unsigned)(x)<<shift)-pred_x] + mv_penalty[(int)((unsigned)(y)<<shift)-pred_y])*penalty_factor;\
396
        if(d<dmin){\
397
            best[0]=x;\
398
            best[1]=y;\
399
            dmin=d;\
400
            next_dir= new_dir;\
401
        }\
402
    }\
403
}
404
405
#define check(x,y,S,v)\
406
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);\
407
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);\
408
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);\
409
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);\
410
411
#define LOAD_COMMON2\
412
    uint32_t *map= c->map;\
413
    const int qpel= flags&FLAG_QPEL;\
414
    const int shift= 1+qpel;\
415
416
5400956
static av_always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
417
                                       int src_index, int ref_index, const int penalty_factor,
418
                                       int size, int h, int flags)
419
{
420
5400956
    MotionEstContext * const c= &s->me;
421
    me_cmp_func cmpf, chroma_cmpf;
422
5400956
    int next_dir=-1;
423
5400956
    LOAD_COMMON
424
5400956
    LOAD_COMMON2
425
5400956
    unsigned map_generation = c->map_generation;
426
427
5400956
    cmpf        = s->mecc.me_cmp[size];
428
5400956
    chroma_cmpf = s->mecc.me_cmp[size + 1];
429
430
    { /* ensure that the best point is in the MAP as h/qpel refinement needs it */
431
5400956
        const unsigned key = ((unsigned)best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation;
432
5400956
        const int index= (((unsigned)best[1]<<ME_MAP_SHIFT) + best[0])&(ME_MAP_SIZE-1);
433
5400956
        if (map[index] != key) { // this will be executed only very rarely
434
32736
            score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
435
32736
            map[index]= key;
436
        }
437
    }
438
439
1467984
    for(;;){
440
        int d;
441
6868940
        const int dir= next_dir;
442
6868940
        const int x= best[0];
443
6868940
        const int y= best[1];
444
6868940
        next_dir=-1;
445
446


6868940
        if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y  , 0)
447


6868940
        if(dir!=3 && y>ymin) CHECK_MV_DIR(x  , y-1, 1)
448


6868940
        if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y  , 2)
449


6868940
        if(dir!=1 && y<ymax) CHECK_MV_DIR(x  , y+1, 3)
450
451
6868940
        if(next_dir==-1){
452
5400956
            return dmin;
453
        }
454
    }
455
}
456
457
static int funny_diamond_search(MpegEncContext * s, int *best, int dmin,
458
                                       int src_index, int ref_index, const int penalty_factor,
459
                                       int size, int h, int flags)
460
{
461
    MotionEstContext * const c= &s->me;
462
    me_cmp_func cmpf, chroma_cmpf;
463
    int dia_size;
464
    LOAD_COMMON
465
    LOAD_COMMON2
466
    unsigned map_generation = c->map_generation;
467
468
    cmpf        = s->mecc.me_cmp[size];
469
    chroma_cmpf = s->mecc.me_cmp[size + 1];
470
471
    for(dia_size=1; dia_size<=4; dia_size++){
472
        int dir;
473
        const int x= best[0];
474
        const int y= best[1];
475
476
        if(dia_size&(dia_size-1)) continue;
477
478
        if(   x + dia_size > xmax
479
           || x - dia_size < xmin
480
           || y + dia_size > ymax
481
           || y - dia_size < ymin)
482
           continue;
483
484
        for(dir= 0; dir<dia_size; dir+=2){
485
            int d;
486
487
            CHECK_MV(x + dir           , y + dia_size - dir);
488
            CHECK_MV(x + dia_size - dir, y - dir           );
489
            CHECK_MV(x - dir           , y - dia_size + dir);
490
            CHECK_MV(x - dia_size + dir, y + dir           );
491
        }
492
493
        if(x!=best[0] || y!=best[1])
494
            dia_size=0;
495
    }
496
    return dmin;
497
}
498
499
static int hex_search(MpegEncContext * s, int *best, int dmin,
500
                                       int src_index, int ref_index, const int penalty_factor,
501
                                       int size, int h, int flags, int dia_size)
502
{
503
    MotionEstContext * const c= &s->me;
504
    me_cmp_func cmpf, chroma_cmpf;
505
    LOAD_COMMON
506
    LOAD_COMMON2
507
    unsigned map_generation = c->map_generation;
508
    int x,y,d;
509
    const int dec= dia_size & (dia_size-1);
510
511
    cmpf        = s->mecc.me_cmp[size];
512
    chroma_cmpf = s->mecc.me_cmp[size + 1];
513
514
    for(;dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
515
        do{
516
            x= best[0];
517
            y= best[1];
518
519
            CHECK_CLIPPED_MV(x  -dia_size    , y);
520
            CHECK_CLIPPED_MV(x+  dia_size    , y);
521
            CHECK_CLIPPED_MV(x+( dia_size>>1), y+dia_size);
522
            CHECK_CLIPPED_MV(x+( dia_size>>1), y-dia_size);
523
            if(dia_size>1){
524
                CHECK_CLIPPED_MV(x+(-dia_size>>1), y+dia_size);
525
                CHECK_CLIPPED_MV(x+(-dia_size>>1), y-dia_size);
526
            }
527
        }while(best[0] != x || best[1] != y);
528
    }
529
530
    return dmin;
531
}
532
533
static int l2s_dia_search(MpegEncContext * s, int *best, int dmin,
534
                                       int src_index, int ref_index, const int penalty_factor,
535
                                       int size, int h, int flags)
536
{
537
    MotionEstContext * const c= &s->me;
538
    me_cmp_func cmpf, chroma_cmpf;
539
    LOAD_COMMON
540
    LOAD_COMMON2
541
    unsigned map_generation = c->map_generation;
542
    int x,y,i,d;
543
    int dia_size= c->dia_size&0xFF;
544
    const int dec= dia_size & (dia_size-1);
545
    static const int hex[8][2]={{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1},
546
                                { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}};
547
548
    cmpf        = s->mecc.me_cmp[size];
549
    chroma_cmpf = s->mecc.me_cmp[size + 1];
550
551
    for(; dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
552
        do{
553
            x= best[0];
554
            y= best[1];
555
            for(i=0; i<8; i++){
556
                CHECK_CLIPPED_MV(x+hex[i][0]*dia_size, y+hex[i][1]*dia_size);
557
            }
558
        }while(best[0] != x || best[1] != y);
559
    }
560
561
    x= best[0];
562
    y= best[1];
563
    CHECK_CLIPPED_MV(x+1, y);
564
    CHECK_CLIPPED_MV(x, y+1);
565
    CHECK_CLIPPED_MV(x-1, y);
566
    CHECK_CLIPPED_MV(x, y-1);
567
568
    return dmin;
569
}
570
571
static int umh_search(MpegEncContext * s, int *best, int dmin,
572
                                       int src_index, int ref_index, const int penalty_factor,
573
                                       int size, int h, int flags)
574
{
575
    MotionEstContext * const c= &s->me;
576
    me_cmp_func cmpf, chroma_cmpf;
577
    LOAD_COMMON
578
    LOAD_COMMON2
579
    unsigned map_generation = c->map_generation;
580
    int x,y,x2,y2, i, j, d;
581
    const int dia_size= c->dia_size&0xFE;
582
    static const int hex[16][2]={{-4,-2}, {-4,-1}, {-4, 0}, {-4, 1}, {-4, 2},
583
                                 { 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2},
584
                                 {-2, 3}, { 0, 4}, { 2, 3},
585
                                 {-2,-3}, { 0,-4}, { 2,-3},};
586
587
    cmpf        = s->mecc.me_cmp[size];
588
    chroma_cmpf = s->mecc.me_cmp[size + 1];
589
590
    x= best[0];
591
    y= best[1];
592
    for(x2=FFMAX(x-dia_size+1, xmin); x2<=FFMIN(x+dia_size-1,xmax); x2+=2){
593
        CHECK_MV(x2, y);
594
    }
595
    for(y2=FFMAX(y-dia_size/2+1, ymin); y2<=FFMIN(y+dia_size/2-1,ymax); y2+=2){
596
        CHECK_MV(x, y2);
597
    }
598
599
    x= best[0];
600
    y= best[1];
601
    for(y2=FFMAX(y-2, ymin); y2<=FFMIN(y+2,ymax); y2++){
602
        for(x2=FFMAX(x-2, xmin); x2<=FFMIN(x+2,xmax); x2++){
603
            CHECK_MV(x2, y2);
604
        }
605
    }
606
607
//FIXME prevent the CLIP stuff
608
609
    for(j=1; j<=dia_size/4; j++){
610
        for(i=0; i<16; i++){
611
            CHECK_CLIPPED_MV(x+hex[i][0]*j, y+hex[i][1]*j);
612
        }
613
    }
614
615
    return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, 2);
616
}
617
618
static int full_search(MpegEncContext * s, int *best, int dmin,
619
                                       int src_index, int ref_index, const int penalty_factor,
620
                                       int size, int h, int flags)
621
{
622
    MotionEstContext * const c= &s->me;
623
    me_cmp_func cmpf, chroma_cmpf;
624
    LOAD_COMMON
625
    LOAD_COMMON2
626
    unsigned map_generation = c->map_generation;
627
    int x,y, d;
628
    const int dia_size= c->dia_size&0xFF;
629
630
    cmpf        = s->mecc.me_cmp[size];
631
    chroma_cmpf = s->mecc.me_cmp[size + 1];
632
633
    for(y=FFMAX(-dia_size, ymin); y<=FFMIN(dia_size,ymax); y++){
634
        for(x=FFMAX(-dia_size, xmin); x<=FFMIN(dia_size,xmax); x++){
635
            CHECK_MV(x, y);
636
        }
637
    }
638
639
    x= best[0];
640
    y= best[1];
641
    d= dmin;
642
    CHECK_CLIPPED_MV(x  , y);
643
    CHECK_CLIPPED_MV(x+1, y);
644
    CHECK_CLIPPED_MV(x, y+1);
645
    CHECK_CLIPPED_MV(x-1, y);
646
    CHECK_CLIPPED_MV(x, y-1);
647
    best[0]= x;
648
    best[1]= y;
649
650
    return d;
651
}
652
653
#define SAB_CHECK_MV(ax,ay)\
654
{\
655
    const unsigned key = ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\
656
    const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\
657
    if(map[index]!=key){\
658
        d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
659
        map[index]= key;\
660
        score_map[index]= d;\
661
        d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\
662
        if(d < minima[minima_count-1].height){\
663
            int j=0;\
664
            \
665
            while(d >= minima[j].height) j++;\
666
\
667
            memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\
668
\
669
            minima[j].checked= 0;\
670
            minima[j].height= d;\
671
            minima[j].x= ax;\
672
            minima[j].y= ay;\
673
            \
674
            i=-1;\
675
            continue;\
676
        }\
677
    }\
678
}
679
680
#define MAX_SAB_SIZE ME_MAP_SIZE
681
static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,
682
                                       int src_index, int ref_index, const int penalty_factor,
683
                                       int size, int h, int flags)
684
{
685
    MotionEstContext * const c= &s->me;
686
    me_cmp_func cmpf, chroma_cmpf;
687
    Minima minima[MAX_SAB_SIZE];
688
    const int minima_count= FFABS(c->dia_size);
689
    int i, j;
690
    LOAD_COMMON
691
    LOAD_COMMON2
692
    unsigned map_generation = c->map_generation;
693
694
    av_assert1(minima_count <= MAX_SAB_SIZE);
695
696
    cmpf        = s->mecc.me_cmp[size];
697
    chroma_cmpf = s->mecc.me_cmp[size + 1];
698
699
    /*Note j<MAX_SAB_SIZE is needed if MAX_SAB_SIZE < ME_MAP_SIZE as j can
700
      become larger due to MVs overflowing their ME_MAP_MV_BITS bits space in map
701
     */
702
    for(j=i=0; i<ME_MAP_SIZE && j<MAX_SAB_SIZE; i++){
703
        uint32_t key= map[i];
704
705
        key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1));
706
707
        if ((key & (-(1 << (2 * ME_MAP_MV_BITS)))) != map_generation)
708
            continue;
709
710
        minima[j].height= score_map[i];
711
        minima[j].x= key & ((1<<ME_MAP_MV_BITS)-1); key>>=ME_MAP_MV_BITS;
712
        minima[j].y= key & ((1<<ME_MAP_MV_BITS)-1);
713
        minima[j].x-= (1<<(ME_MAP_MV_BITS-1));
714
        minima[j].y-= (1<<(ME_MAP_MV_BITS-1));
715
716
        // all entries in map should be in range except if the mv overflows their ME_MAP_MV_BITS bits space
717
        if(   minima[j].x > xmax || minima[j].x < xmin
718
           || minima[j].y > ymax || minima[j].y < ymin)
719
            continue;
720
721
        minima[j].checked=0;
722
        if(minima[j].x || minima[j].y)
723
            minima[j].height+= (mv_penalty[((minima[j].x)<<shift)-pred_x] + mv_penalty[((minima[j].y)<<shift)-pred_y])*penalty_factor;
724
725
        j++;
726
    }
727
728
    AV_QSORT(minima, j, Minima, minima_cmp);
729
730
    for(; j<minima_count; j++){
731
        minima[j].height=256*256*256*64;
732
        minima[j].checked=0;
733
        minima[j].x= minima[j].y=0;
734
    }
735
736
    for(i=0; i<minima_count; i++){
737
        const int x= minima[i].x;
738
        const int y= minima[i].y;
739
        int d;
740
741
        if(minima[i].checked) continue;
742
743
        if(   x >= xmax || x <= xmin
744
           || y >= ymax || y <= ymin)
745
           continue;
746
747
        SAB_CHECK_MV(x-1, y)
748
        SAB_CHECK_MV(x+1, y)
749
        SAB_CHECK_MV(x  , y-1)
750
        SAB_CHECK_MV(x  , y+1)
751
752
        minima[i].checked= 1;
753
    }
754
755
    best[0]= minima[0].x;
756
    best[1]= minima[0].y;
757
    dmin= minima[0].height;
758
759
    if(   best[0] < xmax && best[0] > xmin
760
       && best[1] < ymax && best[1] > ymin){
761
        int d;
762
        // ensure that the reference samples for hpel refinement are in the map
763
        CHECK_MV(best[0]-1, best[1])
764
        CHECK_MV(best[0]+1, best[1])
765
        CHECK_MV(best[0], best[1]-1)
766
        CHECK_MV(best[0], best[1]+1)
767
    }
768
    return dmin;
769
}
770
771
242321
static int var_diamond_search(MpegEncContext * s, int *best, int dmin,
772
                                       int src_index, int ref_index, const int penalty_factor,
773
                                       int size, int h, int flags)
774
{
775
242321
    MotionEstContext * const c= &s->me;
776
    me_cmp_func cmpf, chroma_cmpf;
777
    int dia_size;
778
242321
    LOAD_COMMON
779
242321
    LOAD_COMMON2
780
242321
    unsigned map_generation = c->map_generation;
781
782
242321
    cmpf        = s->mecc.me_cmp[size];
783
242321
    chroma_cmpf = s->mecc.me_cmp[size + 1];
784
785
994791
    for(dia_size=1; dia_size<=c->dia_size; dia_size++){
786
        int dir, start, end;
787
752470
        const int x= best[0];
788
752470
        const int y= best[1];
789
790
752470
        start= FFMAX(0, y + dia_size - ymax);
791
752470
        end  = FFMIN(dia_size, xmax - x + 1);
792
1786964
        for(dir= start; dir<end; dir++){
793
            int d;
794
795
//check(x + dir,y + dia_size - dir,0, a0)
796
1034494
            CHECK_MV(x + dir           , y + dia_size - dir);
797
        }
798
799
752470
        start= FFMAX(0, x + dia_size - xmax);
800
752470
        end  = FFMIN(dia_size, y - ymin + 1);
801
1786988
        for(dir= start; dir<end; dir++){
802
            int d;
803
804
//check(x + dia_size - dir, y - dir,0, a1)
805
1034518
            CHECK_MV(x + dia_size - dir, y - dir           );
806
        }
807
808
752470
        start= FFMAX(0, -y + dia_size + ymin );
809
752470
        end  = FFMIN(dia_size, x - xmin + 1);
810
1786858
        for(dir= start; dir<end; dir++){
811
            int d;
812
813
//check(x - dir,y - dia_size + dir,0, a2)
814
1034388
            CHECK_MV(x - dir           , y - dia_size + dir);
815
        }
816
817
752470
        start= FFMAX(0, -x + dia_size + xmin );
818
752470
        end  = FFMIN(dia_size, ymax - y + 1);
819
1787010
        for(dir= start; dir<end; dir++){
820
            int d;
821
822
//check(x - dia_size + dir, y + dir,0, a3)
823
1034540
            CHECK_MV(x - dia_size + dir, y + dir           );
824
        }
825
826

752470
        if(x!=best[0] || y!=best[1])
827
228073
            dia_size=0;
828
    }
829
242321
    return dmin;
830
}
831
832
5643277
static av_always_inline int diamond_search(MpegEncContext * s, int *best, int dmin,
833
                                       int src_index, int ref_index, const int penalty_factor,
834
                                       int size, int h, int flags){
835
5643277
    MotionEstContext * const c= &s->me;
836
5643277
    if(c->dia_size==-1)
837
        return funny_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
838
5643277
    else if(c->dia_size<-1)
839
        return   sab_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
840
5643277
    else if(c->dia_size<2)
841
5400956
        return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
842
242321
    else if(c->dia_size>1024)
843
        return          full_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
844
242321
    else if(c->dia_size>768)
845
        return           umh_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
846
242321
    else if(c->dia_size>512)
847
        return           hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, c->dia_size&0xFF);
848
242321
    else if(c->dia_size>256)
849
        return       l2s_dia_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
850
    else
851
242321
        return   var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
852
}
853
854
/**
855
   @param P a list of candidate mvs to check before starting the
856
   iterative search. If one of the candidates is close to the optimal mv, then
857
   it takes fewer iterations. And it increases the chance that we find the
858
   optimal mv.
859
 */
860
3409525
static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int *mx_ptr, int *my_ptr,
861
                             int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2],
862
                             int ref_mv_scale, int flags, int size, int h)
863
{
864
3409525
    MotionEstContext * const c= &s->me;
865
3409525
    int best[2]={0, 0};      /**< x and y coordinates of the best motion vector.
866
                               i.e. the difference between the position of the
867
                               block currently being encoded and the position of
868
                               the block chosen to predict it from. */
869
    int d;                   ///< the score (cmp + penalty) of any given mv
870
    int dmin;                /**< the best value of d, i.e. the score
871
                               corresponding to the mv stored in best[]. */
872
    unsigned map_generation;
873
    int penalty_factor;
874
3409525
    const int ref_mv_stride= s->mb_stride; //pass as arg  FIXME
875
3409525
    const int ref_mv_xy = s->mb_x + s->mb_y * ref_mv_stride; // add to last_mv before passing FIXME
876
    me_cmp_func cmpf, chroma_cmpf;
877
878
3409525
    LOAD_COMMON
879
3409525
    LOAD_COMMON2
880
881
3409525
    if(c->pre_pass){
882
        penalty_factor= c->pre_penalty_factor;
883
        cmpf           = s->mecc.me_pre_cmp[size];
884
        chroma_cmpf    = s->mecc.me_pre_cmp[size + 1];
885
    }else{
886
3409525
        penalty_factor= c->penalty_factor;
887
3409525
        cmpf           = s->mecc.me_cmp[size];
888
3409525
        chroma_cmpf    = s->mecc.me_cmp[size + 1];
889
    }
890
891
3409525
    map_generation= update_map_generation(c);
892
893
    av_assert2(cmpf);
894
3409525
    dmin= cmp(s, 0, 0, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
895
3409525
    map[0]= map_generation;
896
3409525
    score_map[0]= dmin;
897
898
    //FIXME precalc first term below?
899

3409525
    if ((s->pict_type == AV_PICTURE_TYPE_B && !(c->flags & FLAG_DIRECT)) ||
900
2593137
        s->mpv_flags & FF_MPV_FLAG_MV0)
901
955256
        dmin += (mv_penalty[pred_x] + mv_penalty[pred_y])*penalty_factor;
902
903
    /* first line */
904
3409525
    if (s->first_slice_line) {
905
177310
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
906
177310
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
907
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
908
    }else{
909
3232215
        if(dmin<((h*h*s->avctx->mv0_threshold)>>8)
910
120062
                    && ( P_LEFT[0]    |P_LEFT[1]
911
120062
                        |P_TOP[0]     |P_TOP[1]
912
120062
                        |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){
913
98504
            *mx_ptr= 0;
914
98504
            *my_ptr= 0;
915
98504
            c->skip=1;
916
98504
            return dmin;
917
        }
918
3133711
        CHECK_MV(    P_MEDIAN[0] >>shift ,    P_MEDIAN[1] >>shift)
919
3133711
        CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)  , (P_MEDIAN[1]>>shift)-1)
920
3133711
        CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)  , (P_MEDIAN[1]>>shift)+1)
921
3133711
        CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)-1, (P_MEDIAN[1]>>shift)  )
922
3133711
        CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)+1, (P_MEDIAN[1]>>shift)  )
923
3133711
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
924
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
925
3133711
        CHECK_MV(P_LEFT[0]    >>shift, P_LEFT[1]    >>shift)
926
3133711
        CHECK_MV(P_TOP[0]     >>shift, P_TOP[1]     >>shift)
927
3133711
        CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
928
    }
929
3311021
    if(dmin>h*h*4){
930
2415896
        if(c->pre_pass){
931
            CHECK_CLIPPED_MV((last_mv[ref_mv_xy-1][0]*ref_mv_scale + (1<<15))>>16,
932
                            (last_mv[ref_mv_xy-1][1]*ref_mv_scale + (1<<15))>>16)
933
            if(!s->first_slice_line)
934
                CHECK_CLIPPED_MV((last_mv[ref_mv_xy-ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
935
                                (last_mv[ref_mv_xy-ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
936
        }else{
937
2415896
            CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
938
                            (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
939
2415896
            if(s->mb_y+1<s->end_mb_y)  //FIXME replace at least with last_slice_line
940
2002204
                CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
941
                                (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
942
        }
943
    }
944
945
3311021
    if(c->avctx->last_predictor_count){
946
        const int count= c->avctx->last_predictor_count;
947
        const int xstart= FFMAX(0, s->mb_x - count);
948
        const int ystart= FFMAX(0, s->mb_y - count);
949
        const int xend= FFMIN(s->mb_width , s->mb_x + count + 1);
950
        const int yend= FFMIN(s->mb_height, s->mb_y + count + 1);
951
        int mb_y;
952
953
        for(mb_y=ystart; mb_y<yend; mb_y++){
954
            int mb_x;
955
            for(mb_x=xstart; mb_x<xend; mb_x++){
956
                const int xy= mb_x + 1 + (mb_y + 1)*ref_mv_stride;
957
                int mx= (last_mv[xy][0]*ref_mv_scale + (1<<15))>>16;
958
                int my= (last_mv[xy][1]*ref_mv_scale + (1<<15))>>16;
959
960
                if(mx>xmax || mx<xmin || my>ymax || my<ymin) continue;
961
                CHECK_MV(mx,my)
962
            }
963
        }
964
    }
965
966
//check(best[0],best[1],0, b0)
967
3311021
    dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
968
969
//check(best[0],best[1],0, b1)
970
3311021
    *mx_ptr= best[0];
971
3311021
    *my_ptr= best[1];
972
973
3311021
    return dmin;
974
}
975
976
//this function is dedicated to the brain damaged gcc
977
3409525
int ff_epzs_motion_search(MpegEncContext *s, int *mx_ptr, int *my_ptr,
978
                          int P[10][2], int src_index, int ref_index,
979
                          int16_t (*last_mv)[2], int ref_mv_scale,
980
                          int size, int h)
981
{
982
3409525
    MotionEstContext * const c= &s->me;
983
//FIXME convert other functions in the same way if faster
984

3409525
    if(c->flags==0 && h==16 && size==0){
985
2572432
        return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, 0, 0, 16);
986
//    case FLAG_QPEL:
987
//        return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, FLAG_QPEL);
988
    }else{
989
837093
        return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, c->flags, size, h);
990
    }
991
}
992
993
2332256
static int epzs_motion_search2(MpegEncContext * s,
994
                             int *mx_ptr, int *my_ptr, int P[10][2],
995
                             int src_index, int ref_index, int16_t (*last_mv)[2],
996
                             int ref_mv_scale, const int size)
997
{
998
2332256
    MotionEstContext * const c= &s->me;
999
2332256
    int best[2]={0, 0};
1000
    int d, dmin;
1001
    unsigned map_generation;
1002
2332256
    const int penalty_factor= c->penalty_factor;
1003
2332256
    const int h=8;
1004
2332256
    const int ref_mv_stride= s->mb_stride;
1005
2332256
    const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
1006
    me_cmp_func cmpf, chroma_cmpf;
1007
2332256
    LOAD_COMMON
1008
2332256
    int flags= c->flags;
1009
2332256
    LOAD_COMMON2
1010
1011
2332256
    cmpf        = s->mecc.me_cmp[size];
1012
2332256
    chroma_cmpf = s->mecc.me_cmp[size + 1];
1013
1014
2332256
    map_generation= update_map_generation(c);
1015
1016
2332256
    dmin = 1000000;
1017
1018
    /* first line */
1019
2332256
    if (s->first_slice_line) {
1020
181096
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1021
181096
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1022
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1023
181096
        CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1024
    }else{
1025
2151160
        CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
1026
        //FIXME try some early stop
1027
2151160
        CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
1028
2151160
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1029
2151160
        CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
1030
2151160
        CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
1031
2151160
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1032
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1033
    }
1034
2332256
    if(dmin>64*4){
1035
2036249
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
1036
                        (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1037
2036249
        if(s->mb_y+1<s->end_mb_y)  //FIXME replace at least with last_slice_line
1038
1872966
            CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1039
                            (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1040
    }
1041
1042
2332256
    dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1043
1044
2332256
    *mx_ptr= best[0];
1045
2332256
    *my_ptr= best[1];
1046
1047
2332256
    return dmin;
1048
}