motion_est_template.c 37.5 KB
Newer Older
Michael Niedermayer's avatar
Michael Niedermayer committed
1
/*
2
 * Motion estimation
3
 * Copyright (c) 2002-2004 Michael Niedermayer
Michael Niedermayer's avatar
Michael Niedermayer committed
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
Michael Niedermayer's avatar
Michael Niedermayer committed
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
Michael Niedermayer's avatar
Michael Niedermayer committed
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
Michael Niedermayer's avatar
Michael Niedermayer committed
13 14 15 16 17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * 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
Michael Niedermayer's avatar
Michael Niedermayer committed
20
 */
21

Michael Niedermayer's avatar
Michael Niedermayer committed
22
/**
23
 * @file
Michael Niedermayer's avatar
Michael Niedermayer committed
24 25
 * Motion estimation template.
 */
26

27
#include "libavutil/qsort.h"
28 29
#include "mpegvideo.h"

30
//Let us hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...)
31
#define LOAD_COMMON\
32 33 34 35 36
    uint32_t av_unused * const score_map= c->score_map;\
    const int av_unused xmin= c->xmin;\
    const int av_unused ymin= c->ymin;\
    const int av_unused xmax= c->xmax;\
    const int av_unused ymax= c->ymax;\
37 38 39
    uint8_t *mv_penalty= c->current_mv_penalty;\
    const int pred_x= c->pred_x;\
    const int pred_y= c->pred_y;\
Michael Niedermayer's avatar
Michael Niedermayer committed
40 41 42 43 44

#define CHECK_HALF_MV(dx, dy, x, y)\
{\
    const int hx= 2*(x)+(dx);\
    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);\
Michael Niedermayer's avatar
Michael Niedermayer committed
46 47 48 49
    d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
    COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
}

50
static int hpel_motion_search(MpegEncContext * s,
51
                                  int *mx_ptr, int *my_ptr, int dmin,
52 53
                                  int src_index, int ref_index,
                                  int size, int h)
Michael Niedermayer's avatar
Michael Niedermayer committed
54
{
55
    MotionEstContext * const c= &s->me;
Michael Niedermayer's avatar
Michael Niedermayer committed
56
    const int mx = *mx_ptr;
57
    const int my = *my_ptr;
58
    const int penalty_factor= c->sub_penalty_factor;
Michael Niedermayer's avatar
Michael Niedermayer committed
59
    me_cmp_func cmp_sub, chroma_cmp_sub;
60
    int bx=2*mx, by=2*my;
Michael Niedermayer's avatar
Michael Niedermayer committed
61

62
    LOAD_COMMON
63
    int flags= c->sub_flags;
64

Michael Niedermayer's avatar
Michael Niedermayer committed
65 66
 //FIXME factorize

67 68
    cmp_sub        = s->mecc.me_sub_cmp[size];
    chroma_cmp_sub = s->mecc.me_sub_cmp[size + 1];
Michael Niedermayer's avatar
Michael Niedermayer committed
69

70
    if(c->skip){ //FIXME move out of hpel?
Michael Niedermayer's avatar
Michael Niedermayer committed
71 72 73 74
        *mx_ptr = 0;
        *my_ptr = 0;
        return dmin;
    }
75

76
    if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
77
        dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
Michael Niedermayer's avatar
Michael Niedermayer committed
78
        if(mx || my || size>0)
Michael Niedermayer's avatar
Michael Niedermayer committed
79 80
            dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor;
    }
81 82

    if (mx > xmin && mx < xmax &&
Michael Niedermayer's avatar
Michael Niedermayer committed
83 84 85
        my > ymin && my < ymax) {
        int d= dmin;
        const int index= (my<<ME_MAP_SHIFT) + mx;
86
        const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
87
                     + (mv_penalty[bx   - pred_x] + mv_penalty[by-2 - pred_y])*c->penalty_factor;
Michael Niedermayer's avatar
Michael Niedermayer committed
88
        const int l= score_map[(index- 1               )&(ME_MAP_SIZE-1)]
89
                     + (mv_penalty[bx-2 - pred_x] + mv_penalty[by   - pred_y])*c->penalty_factor;
Michael Niedermayer's avatar
Michael Niedermayer committed
90
        const int r= score_map[(index+ 1               )&(ME_MAP_SIZE-1)]
91
                     + (mv_penalty[bx+2 - pred_x] + mv_penalty[by   - pred_y])*c->penalty_factor;
Michael Niedermayer's avatar
Michael Niedermayer committed
92
        const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
93
                     + (mv_penalty[bx   - pred_x] + mv_penalty[by+2 - pred_y])*c->penalty_factor;
94

95
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1
96 97
        unsigned key;
        unsigned map_generation= c->map_generation;
98
        key= ((my-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)<<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)<<ME_MAP_MV_BITS) + (mx+1) + map_generation;
103
        av_assert2(c->map[(index+1)&(ME_MAP_SIZE-1)] == key);
104
        key= ((my)<<ME_MAP_MV_BITS) + (mx-1) + map_generation;
105
        av_assert2(c->map[(index-1)&(ME_MAP_SIZE-1)] == key);
106
#endif
Michael Niedermayer's avatar
Michael Niedermayer committed
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
        if(t<=b){
            CHECK_HALF_MV(0, 1, mx  ,my-1)
            if(l<=r){
                CHECK_HALF_MV(1, 1, mx-1, my-1)
                if(t+r<=b+l){
                    CHECK_HALF_MV(1, 1, mx  , my-1)
                }else{
                    CHECK_HALF_MV(1, 1, mx-1, my  )
                }
                CHECK_HALF_MV(1, 0, mx-1, my  )
            }else{
                CHECK_HALF_MV(1, 1, mx  , my-1)
                if(t+l<=b+r){
                    CHECK_HALF_MV(1, 1, mx-1, my-1)
                }else{
                    CHECK_HALF_MV(1, 1, mx  , my  )
                }
                CHECK_HALF_MV(1, 0, mx  , my  )
            }
        }else{
            if(l<=r){
                if(t+l<=b+r){
                    CHECK_HALF_MV(1, 1, mx-1, my-1)
                }else{
                    CHECK_HALF_MV(1, 1, mx  , my  )
                }
                CHECK_HALF_MV(1, 0, mx-1, my)
                CHECK_HALF_MV(1, 1, mx-1, my)
            }else{
                if(t+r<=b+l){
                    CHECK_HALF_MV(1, 1, mx  , my-1)
                }else{
                    CHECK_HALF_MV(1, 1, mx-1, my)
                }
                CHECK_HALF_MV(1, 0, mx  , my)
                CHECK_HALF_MV(1, 1, mx  , my)
            }
            CHECK_HALF_MV(0, 1, mx  , my)
        }
146
        av_assert2(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2);
Michael Niedermayer's avatar
Michael Niedermayer committed
147 148
    }

149 150
    *mx_ptr = bx;
    *my_ptr = by;
151

Michael Niedermayer's avatar
Michael Niedermayer committed
152 153 154
    return dmin;
}

155 156 157 158 159 160 161 162 163 164
static int no_sub_motion_search(MpegEncContext * s,
          int *mx_ptr, int *my_ptr, int dmin,
                                  int src_index, int ref_index,
                                  int size, int h)
{
    (*mx_ptr)<<=1;
    (*my_ptr)<<=1;
    return dmin;
}

165 166 167
static inline int get_mb_score(MpegEncContext *s, int mx, int my,
                               int src_index, int ref_index, int size,
                               int h, int add_rate)
168
{
169 170 171
    MotionEstContext * const c= &s->me;
    const int penalty_factor= c->mb_penalty_factor;
    const int flags= c->mb_flags;
172 173
    const int qpel= flags & FLAG_QPEL;
    const int mask= 1+2*qpel;
174 175 176
    me_cmp_func cmp_sub, chroma_cmp_sub;
    int d;

177
    LOAD_COMMON
178

179 180
 //FIXME factorize

181 182
    cmp_sub        = s->mecc.mb_cmp[size];
    chroma_cmp_sub = s->mecc.mb_cmp[size + 1];
183

184
    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
    if(add_rate && (mx || my || size>0))
187
        d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor;
188

189 190 191
    return d;
}

192 193 194 195 196 197
int ff_get_mb_score(MpegEncContext *s, int mx, int my, int src_index,
                    int ref_index, int size, int h, int add_rate)
{
    return get_mb_score(s, mx, my, src_index, ref_index, size, h, add_rate);
}

Michael Niedermayer's avatar
Michael Niedermayer committed
198 199 200 201
#define CHECK_QUARTER_MV(dx, dy, x, y)\
{\
    const int hx= 4*(x)+(dx);\
    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);\
Michael Niedermayer's avatar
Michael Niedermayer committed
203 204 205 206
    d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
    COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
}

207
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)
Michael Niedermayer's avatar
Michael Niedermayer committed
211
{
212
    MotionEstContext * const c= &s->me;
Michael Niedermayer's avatar
Michael Niedermayer committed
213
    const int mx = *mx_ptr;
214
    const int my = *my_ptr;
215
    const int penalty_factor= c->sub_penalty_factor;
216
    const unsigned map_generation = c->map_generation;
217
    const int subpel_quality= c->avctx->me_subpel_quality;
218
    uint32_t *map= c->map;
219
    me_cmp_func cmpf, chroma_cmpf;
Michael Niedermayer's avatar
Michael Niedermayer committed
220 221
    me_cmp_func cmp_sub, chroma_cmp_sub;

222
    LOAD_COMMON
223
    int flags= c->sub_flags;
224

225 226
    cmpf        = s->mecc.me_cmp[size];
    chroma_cmpf = s->mecc.me_cmp[size + 1]; // FIXME: factorize
Michael Niedermayer's avatar
Michael Niedermayer committed
227 228
 //FIXME factorize

229 230
    cmp_sub        = s->mecc.me_sub_cmp[size];
    chroma_cmp_sub = s->mecc.me_sub_cmp[size + 1];
Michael Niedermayer's avatar
Michael Niedermayer committed
231

232
    if(c->skip){ //FIXME somehow move up (benchmark)
Michael Niedermayer's avatar
Michael Niedermayer committed
233 234 235 236
        *mx_ptr = 0;
        *my_ptr = 0;
        return dmin;
    }
237

238
    if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
239
        dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
Michael Niedermayer's avatar
Michael Niedermayer committed
240
        if(mx || my || size>0)
Michael Niedermayer's avatar
Michael Niedermayer committed
241 242
            dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor;
    }
243 244

    if (mx > xmin && mx < xmax &&
Michael Niedermayer's avatar
Michael Niedermayer committed
245 246 247 248 249 250 251 252 253 254 255 256
        my > ymin && my < ymax) {
        int bx=4*mx, by=4*my;
        int d= dmin;
        int i, nx, ny;
        const int index= (my<<ME_MAP_SHIFT) + mx;
        const int t= score_map[(index-(1<<ME_MAP_SHIFT)  )&(ME_MAP_SIZE-1)];
        const int l= score_map[(index- 1                 )&(ME_MAP_SIZE-1)];
        const int r= score_map[(index+ 1                 )&(ME_MAP_SIZE-1)];
        const int b= score_map[(index+(1<<ME_MAP_SHIFT)  )&(ME_MAP_SIZE-1)];
        const int c= score_map[(index                    )&(ME_MAP_SIZE-1)];
        int best[8];
        int best_pos[8][2];
257

Michael Niedermayer's avatar
Michael Niedermayer committed
258
        memset(best, 64, sizeof(int)*8);
259
        if(s->me.dia_size>=2){
Michael Niedermayer's avatar
Michael Niedermayer committed
260 261 262 263 264 265 266
            const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
            const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
            const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
            const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];

            for(ny= -3; ny <= 3; ny++){
                for(nx= -3; nx <= 3; nx++){
Michael Niedermayer's avatar
Michael Niedermayer committed
267 268 269 270 271
                    //FIXME this could overflow (unlikely though)
                    const int64_t t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t;
                    const int64_t c2= nx*nx*( r +  l - 2*c) + 4*nx*( r- l) + 32*c;
                    const int64_t b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b;
                    int score= (ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2 + 512)>>10;
Michael Niedermayer's avatar
Michael Niedermayer committed
272
                    int i;
273

Michael Niedermayer's avatar
Michael Niedermayer committed
274
                    if((nx&3)==0 && (ny&3)==0) continue;
275

Michael Niedermayer's avatar
Michael Niedermayer committed
276
                    score += (mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
277

278 279
//                    if(nx&1) score-=1024*c->penalty_factor;
//                    if(ny&1) score-=1024*c->penalty_factor;
280

Michael Niedermayer's avatar
Michael Niedermayer committed
281 282 283 284 285 286 287 288 289 290 291 292 293 294
                    for(i=0; i<8; i++){
                        if(score < best[i]){
                            memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
                            memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
                            best[i]= score;
                            best_pos[i][0]= nx + 4*mx;
                            best_pos[i][1]= ny + 4*my;
                            break;
                        }
                    }
                }
            }
        }else{
            int tl;
Michael Niedermayer's avatar
Michael Niedermayer committed
295
            //FIXME this could overflow (unlikely though)
Michael Niedermayer's avatar
Michael Niedermayer committed
296
            const int cx = 4*(r - l);
297
            const int cx2= r + l - 2*c;
Michael Niedermayer's avatar
Michael Niedermayer committed
298 299 300
            const int cy = 4*(b - t);
            const int cy2= b + t - 2*c;
            int cxy;
301

302
            if(map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == ((my-1)<<ME_MAP_MV_BITS) + (mx-1) + map_generation){
Michael Niedermayer's avatar
Michael Niedermayer committed
303 304
                tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
            }else{
305
                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
Michael Niedermayer's avatar
Michael Niedermayer committed
306
            }
307 308 309

            cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c;

310 311 312 313 314
            av_assert2(16*cx2 + 4*cx + 32*c == 32*r);
            av_assert2(16*cx2 - 4*cx + 32*c == 32*l);
            av_assert2(16*cy2 + 4*cy + 32*c == 32*b);
            av_assert2(16*cy2 - 4*cy + 32*c == 32*t);
            av_assert2(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl);
315

Michael Niedermayer's avatar
Michael Niedermayer committed
316 317
            for(ny= -3; ny <= 3; ny++){
                for(nx= -3; nx <= 3; nx++){
Michael Niedermayer's avatar
Michael Niedermayer committed
318
                    //FIXME this could overflow (unlikely though)
Michael Niedermayer's avatar
Michael Niedermayer committed
319 320
                    int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor
                    int i;
321

Michael Niedermayer's avatar
Michael Niedermayer committed
322
                    if((nx&3)==0 && (ny&3)==0) continue;
323

Michael Niedermayer's avatar
Michael Niedermayer committed
324
                    score += 32*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
325 326
//                    if(nx&1) score-=32*c->penalty_factor;
  //                  if(ny&1) score-=32*c->penalty_factor;
327

Michael Niedermayer's avatar
Michael Niedermayer committed
328 329 330 331 332 333 334 335 336 337 338
                    for(i=0; i<8; i++){
                        if(score < best[i]){
                            memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
                            memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
                            best[i]= score;
                            best_pos[i][0]= nx + 4*mx;
                            best_pos[i][1]= ny + 4*my;
                            break;
                        }
                    }
                }
339
            }
Michael Niedermayer's avatar
Michael Niedermayer committed
340
        }
Michael Niedermayer's avatar
Michael Niedermayer committed
341
        for(i=0; i<subpel_quality; i++){
Michael Niedermayer's avatar
Michael Niedermayer committed
342 343 344 345
            nx= best_pos[i][0];
            ny= best_pos[i][1];
            CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2)
        }
Michael Niedermayer's avatar
Michael Niedermayer committed
346

347
        av_assert2(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4);
Michael Niedermayer's avatar
Michael Niedermayer committed
348 349 350 351 352 353 354 355 356 357 358 359 360 361

        *mx_ptr = bx;
        *my_ptr = by;
    }else{
        *mx_ptr =4*mx;
        *my_ptr =4*my;
    }

    return dmin;
}


#define CHECK_MV(x,y)\
{\
362 363
    const unsigned key = ((unsigned)(y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
    const int index= (((unsigned)(y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
364 365 366 367
    av_assert2((x) >= xmin);\
    av_assert2((x) <= xmax);\
    av_assert2((y) >= ymin);\
    av_assert2((y) <= ymax);\
Michael Niedermayer's avatar
Michael Niedermayer committed
368
    if(map[index]!=key){\
369
        d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
Michael Niedermayer's avatar
Michael Niedermayer committed
370 371
        map[index]= key;\
        score_map[index]= d;\
372
        d += (mv_penalty[((x)*(1<<shift))-pred_x] + mv_penalty[((y)*(1<<shift))-pred_y])*penalty_factor;\
Michael Niedermayer's avatar
Michael Niedermayer committed
373 374 375 376
        COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
    }\
}

377
#define CHECK_CLIPPED_MV(ax,ay)\
378
{\
379 380 381 382 383
    const int Lx= ax;\
    const int Ly= ay;\
    const int Lx2= FFMAX(xmin, FFMIN(Lx, xmax));\
    const int Ly2= FFMAX(ymin, FFMIN(Ly, ymax));\
    CHECK_MV(Lx2, Ly2)\
384 385
}

Michael Niedermayer's avatar
Michael Niedermayer committed
386 387
#define CHECK_MV_DIR(x,y,new_dir)\
{\
388 389
    const unsigned key = ((unsigned)(y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
    const int index= (((unsigned)(y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
Michael Niedermayer's avatar
Michael Niedermayer committed
390
    if(map[index]!=key){\
391
        d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
Michael Niedermayer's avatar
Michael Niedermayer committed
392 393
        map[index]= key;\
        score_map[index]= d;\
394
        d += (mv_penalty[(int)((unsigned)(x)<<shift)-pred_x] + mv_penalty[(int)((unsigned)(y)<<shift)-pred_y])*penalty_factor;\
Michael Niedermayer's avatar
Michael Niedermayer committed
395 396 397 398 399 400 401 402 403 404
        if(d<dmin){\
            best[0]=x;\
            best[1]=y;\
            dmin=d;\
            next_dir= new_dir;\
        }\
    }\
}

#define check(x,y,S,v)\
405 406 407 408
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);\
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);\
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);\
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);\
Michael Niedermayer's avatar
Michael Niedermayer committed
409

410
#define LOAD_COMMON2\
411
    uint32_t *map= c->map;\
412 413
    const int qpel= flags&FLAG_QPEL;\
    const int shift= 1+qpel;\
Michael Niedermayer's avatar
Michael Niedermayer committed
414

415
static av_always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
416
                                       int src_index, int ref_index, const int penalty_factor,
417
                                       int size, int h, int flags)
Michael Niedermayer's avatar
Michael Niedermayer committed
418
{
419
    MotionEstContext * const c= &s->me;
420
    me_cmp_func cmpf, chroma_cmpf;
Michael Niedermayer's avatar
Michael Niedermayer committed
421
    int next_dir=-1;
422
    LOAD_COMMON
423
    LOAD_COMMON2
424
    unsigned map_generation = c->map_generation;
425

426 427
    cmpf        = s->mecc.me_cmp[size];
    chroma_cmpf = s->mecc.me_cmp[size + 1];
Michael Niedermayer's avatar
Michael Niedermayer committed
428

429
    { /* ensure that the best point is in the MAP as h/qpel refinement needs it */
430 431
        const unsigned key = ((unsigned)best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation;
        const int index= (((unsigned)best[1]<<ME_MAP_SHIFT) + best[0])&(ME_MAP_SIZE-1);
432
        if (map[index] != key) { // this will be executed only very rarely
433
            score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
434 435 436 437
            map[index]= key;
        }
    }

Michael Niedermayer's avatar
Michael Niedermayer committed
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
    for(;;){
        int d;
        const int dir= next_dir;
        const int x= best[0];
        const int y= best[1];
        next_dir=-1;

        if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y  , 0)
        if(dir!=3 && y>ymin) CHECK_MV_DIR(x  , y-1, 1)
        if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y  , 2)
        if(dir!=1 && y<ymax) CHECK_MV_DIR(x  , y+1, 3)

        if(next_dir==-1){
            return dmin;
        }
    }
}

456
static int funny_diamond_search(MpegEncContext * s, int *best, int dmin,
457
                                       int src_index, int ref_index, const int penalty_factor,
458
                                       int size, int h, int flags)
459
{
460
    MotionEstContext * const c= &s->me;
461
    me_cmp_func cmpf, chroma_cmpf;
462
    int dia_size;
463
    LOAD_COMMON
464
    LOAD_COMMON2
465
    unsigned map_generation = c->map_generation;
466

467 468
    cmpf        = s->mecc.me_cmp[size];
    chroma_cmpf = s->mecc.me_cmp[size + 1];
469 470 471 472 473

    for(dia_size=1; dia_size<=4; dia_size++){
        int dir;
        const int x= best[0];
        const int y= best[1];
474

475 476 477 478 479 480 481
        if(dia_size&(dia_size-1)) continue;

        if(   x + dia_size > xmax
           || x - dia_size < xmin
           || y + dia_size > ymax
           || y - dia_size < ymin)
           continue;
482

483 484 485 486 487 488 489 490 491 492 493 494
        for(dir= 0; dir<dia_size; dir+=2){
            int d;

            CHECK_MV(x + dir           , y + dia_size - dir);
            CHECK_MV(x + dia_size - dir, y - dir           );
            CHECK_MV(x - dir           , y - dia_size + dir);
            CHECK_MV(x - dia_size + dir, y + dir           );
        }

        if(x!=best[0] || y!=best[1])
            dia_size=0;
    }
495
    return dmin;
496 497
}

Michael Niedermayer's avatar
Michael Niedermayer committed
498
static int hex_search(MpegEncContext * s, int *best, int dmin,
499
                                       int src_index, int ref_index, const int penalty_factor,
Michael Niedermayer's avatar
Michael Niedermayer committed
500 501 502 503 504 505
                                       int size, int h, int flags, int dia_size)
{
    MotionEstContext * const c= &s->me;
    me_cmp_func cmpf, chroma_cmpf;
    LOAD_COMMON
    LOAD_COMMON2
506
    unsigned map_generation = c->map_generation;
507 508
    int x,y,d;
    const int dec= dia_size & (dia_size-1);
Michael Niedermayer's avatar
Michael Niedermayer committed
509

510 511
    cmpf        = s->mecc.me_cmp[size];
    chroma_cmpf = s->mecc.me_cmp[size + 1];
Michael Niedermayer's avatar
Michael Niedermayer committed
512

513
    for(;dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
Michael Niedermayer's avatar
Michael Niedermayer committed
514 515 516
        do{
            x= best[0];
            y= best[1];
517 518 519 520 521 522 523 524

            CHECK_CLIPPED_MV(x  -dia_size    , y);
            CHECK_CLIPPED_MV(x+  dia_size    , y);
            CHECK_CLIPPED_MV(x+( dia_size>>1), y+dia_size);
            CHECK_CLIPPED_MV(x+( dia_size>>1), y-dia_size);
            if(dia_size>1){
                CHECK_CLIPPED_MV(x+(-dia_size>>1), y+dia_size);
                CHECK_CLIPPED_MV(x+(-dia_size>>1), y-dia_size);
Michael Niedermayer's avatar
Michael Niedermayer committed
525 526 527 528 529 530 531 532
            }
        }while(best[0] != x || best[1] != y);
    }

    return dmin;
}

static int l2s_dia_search(MpegEncContext * s, int *best, int dmin,
533
                                       int src_index, int ref_index, const int penalty_factor,
Michael Niedermayer's avatar
Michael Niedermayer committed
534 535 536 537 538 539
                                       int size, int h, int flags)
{
    MotionEstContext * const c= &s->me;
    me_cmp_func cmpf, chroma_cmpf;
    LOAD_COMMON
    LOAD_COMMON2
540
    unsigned map_generation = c->map_generation;
541 542 543
    int x,y,i,d;
    int dia_size= c->dia_size&0xFF;
    const int dec= dia_size & (dia_size-1);
Michael Niedermayer's avatar
Michael Niedermayer committed
544 545 546
    static const int hex[8][2]={{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1},
                                { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}};

547 548
    cmpf        = s->mecc.me_cmp[size];
    chroma_cmpf = s->mecc.me_cmp[size + 1];
Michael Niedermayer's avatar
Michael Niedermayer committed
549

550
    for(; dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
Michael Niedermayer's avatar
Michael Niedermayer committed
551 552 553 554
        do{
            x= best[0];
            y= best[1];
            for(i=0; i<8; i++){
555
                CHECK_CLIPPED_MV(x+hex[i][0]*dia_size, y+hex[i][1]*dia_size);
Michael Niedermayer's avatar
Michael Niedermayer committed
556 557 558 559 560 561
            }
        }while(best[0] != x || best[1] != y);
    }

    x= best[0];
    y= best[1];
562 563 564 565
    CHECK_CLIPPED_MV(x+1, y);
    CHECK_CLIPPED_MV(x, y+1);
    CHECK_CLIPPED_MV(x-1, y);
    CHECK_CLIPPED_MV(x, y-1);
Michael Niedermayer's avatar
Michael Niedermayer committed
566 567 568 569

    return dmin;
}

570
static int umh_search(MpegEncContext * s, int *best, int dmin,
571
                                       int src_index, int ref_index, const int penalty_factor,
572 573 574 575 576 577
                                       int size, int h, int flags)
{
    MotionEstContext * const c= &s->me;
    me_cmp_func cmpf, chroma_cmpf;
    LOAD_COMMON
    LOAD_COMMON2
578
    unsigned map_generation = c->map_generation;
579
    int x,y,x2,y2, i, j, d;
580
    const int dia_size= c->dia_size&0xFE;
581 582 583
    static const int hex[16][2]={{-4,-2}, {-4,-1}, {-4, 0}, {-4, 1}, {-4, 2},
                                 { 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2},
                                 {-2, 3}, { 0, 4}, { 2, 3},
Michael Niedermayer's avatar
Michael Niedermayer committed
584
                                 {-2,-3}, { 0,-4}, { 2,-3},};
585

586 587
    cmpf        = s->mecc.me_cmp[size];
    chroma_cmpf = s->mecc.me_cmp[size + 1];
588 589 590

    x= best[0];
    y= best[1];
591
    for(x2=FFMAX(x-dia_size+1, xmin); x2<=FFMIN(x+dia_size-1,xmax); x2+=2){
592 593
        CHECK_MV(x2, y);
    }
594
    for(y2=FFMAX(y-dia_size/2+1, ymin); y2<=FFMIN(y+dia_size/2-1,ymax); y2+=2){
595 596 597 598 599 600 601 602 603 604 605 606 607
        CHECK_MV(x, y2);
    }

    x= best[0];
    y= best[1];
    for(y2=FFMAX(y-2, ymin); y2<=FFMIN(y+2,ymax); y2++){
        for(x2=FFMAX(x-2, xmin); x2<=FFMIN(x+2,xmax); x2++){
            CHECK_MV(x2, y2);
        }
    }

//FIXME prevent the CLIP stuff

608
    for(j=1; j<=dia_size/4; j++){
609
        for(i=0; i<16; i++){
610
            CHECK_CLIPPED_MV(x+hex[i][0]*j, y+hex[i][1]*j);
611 612 613
        }
    }

614
    return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, 2);
615 616
}

Michael Niedermayer's avatar
Michael Niedermayer committed
617
static int full_search(MpegEncContext * s, int *best, int dmin,
618
                                       int src_index, int ref_index, const int penalty_factor,
Michael Niedermayer's avatar
Michael Niedermayer committed
619 620 621 622 623 624
                                       int size, int h, int flags)
{
    MotionEstContext * const c= &s->me;
    me_cmp_func cmpf, chroma_cmpf;
    LOAD_COMMON
    LOAD_COMMON2
625
    unsigned map_generation = c->map_generation;
Michael Niedermayer's avatar
Michael Niedermayer committed
626 627 628
    int x,y, d;
    const int dia_size= c->dia_size&0xFF;

629 630
    cmpf        = s->mecc.me_cmp[size];
    chroma_cmpf = s->mecc.me_cmp[size + 1];
Michael Niedermayer's avatar
Michael Niedermayer committed
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651

    for(y=FFMAX(-dia_size, ymin); y<=FFMIN(dia_size,ymax); y++){
        for(x=FFMAX(-dia_size, xmin); x<=FFMIN(dia_size,xmax); x++){
            CHECK_MV(x, y);
        }
    }

    x= best[0];
    y= best[1];
    d= dmin;
    CHECK_CLIPPED_MV(x  , y);
    CHECK_CLIPPED_MV(x+1, y);
    CHECK_CLIPPED_MV(x, y+1);
    CHECK_CLIPPED_MV(x-1, y);
    CHECK_CLIPPED_MV(x, y-1);
    best[0]= x;
    best[1]= y;

    return d;
}

652 653
#define SAB_CHECK_MV(ax,ay)\
{\
654
    const unsigned key = ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\
655 656
    const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\
    if(map[index]!=key){\
657
        d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
        map[index]= key;\
        score_map[index]= d;\
        d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\
        if(d < minima[minima_count-1].height){\
            int j=0;\
            \
            while(d >= minima[j].height) j++;\
\
            memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\
\
            minima[j].checked= 0;\
            minima[j].height= d;\
            minima[j].x= ax;\
            minima[j].y= ay;\
            \
            i=-1;\
            continue;\
        }\
    }\
}

679
#define MAX_SAB_SIZE ME_MAP_SIZE
680
static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,
681
                                       int src_index, int ref_index, const int penalty_factor,
682
                                       int size, int h, int flags)
683
{
684
    MotionEstContext * const c= &s->me;
685
    me_cmp_func cmpf, chroma_cmpf;
686
    Minima minima[MAX_SAB_SIZE];
687
    const int minima_count= FFABS(c->dia_size);
688
    int i, j;
689
    LOAD_COMMON
690
    LOAD_COMMON2
691
    unsigned map_generation = c->map_generation;
692

693 694
    av_assert1(minima_count <= MAX_SAB_SIZE);

695 696
    cmpf        = s->mecc.me_cmp[size];
    chroma_cmpf = s->mecc.me_cmp[size + 1];
697

698 699 700 701
    /*Note j<MAX_SAB_SIZE is needed if MAX_SAB_SIZE < ME_MAP_SIZE as j can
      become larger due to MVs overflowing their ME_MAP_MV_BITS bits space in map
     */
    for(j=i=0; i<ME_MAP_SIZE && j<MAX_SAB_SIZE; i++){
702 703 704
        uint32_t key= map[i];

        key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1));
705

706 707
        if ((key & (-(1 << (2 * ME_MAP_MV_BITS)))) != map_generation)
            continue;
708

709 710 711 712 713
        minima[j].height= score_map[i];
        minima[j].x= key & ((1<<ME_MAP_MV_BITS)-1); key>>=ME_MAP_MV_BITS;
        minima[j].y= key & ((1<<ME_MAP_MV_BITS)-1);
        minima[j].x-= (1<<(ME_MAP_MV_BITS-1));
        minima[j].y-= (1<<(ME_MAP_MV_BITS-1));
714 715 716 717 718 719

        // all entries in map should be in range except if the mv overflows their ME_MAP_MV_BITS bits space
        if(   minima[j].x > xmax || minima[j].x < xmin
           || minima[j].y > ymax || minima[j].y < ymin)
            continue;

720 721 722
        minima[j].checked=0;
        if(minima[j].x || minima[j].y)
            minima[j].height+= (mv_penalty[((minima[j].x)<<shift)-pred_x] + mv_penalty[((minima[j].y)<<shift)-pred_y])*penalty_factor;
723

724 725
        j++;
    }
726

727
    AV_QSORT(minima, j, Minima, minima_cmp);
728

729 730 731 732 733
    for(; j<minima_count; j++){
        minima[j].height=256*256*256*64;
        minima[j].checked=0;
        minima[j].x= minima[j].y=0;
    }
734

735 736 737 738
    for(i=0; i<minima_count; i++){
        const int x= minima[i].x;
        const int y= minima[i].y;
        int d;
739

740
        if(minima[i].checked) continue;
741

742 743 744 745 746 747 748 749
        if(   x >= xmax || x <= xmin
           || y >= ymax || y <= ymin)
           continue;

        SAB_CHECK_MV(x-1, y)
        SAB_CHECK_MV(x+1, y)
        SAB_CHECK_MV(x  , y-1)
        SAB_CHECK_MV(x  , y+1)
750

751 752
        minima[i].checked= 1;
    }
753

754 755 756
    best[0]= minima[0].x;
    best[1]= minima[0].y;
    dmin= minima[0].height;
757

758 759 760
    if(   best[0] < xmax && best[0] > xmin
       && best[1] < ymax && best[1] > ymin){
        int d;
761
        // ensure that the reference samples for hpel refinement are in the map
762 763 764 765 766
        CHECK_MV(best[0]-1, best[1])
        CHECK_MV(best[0]+1, best[1])
        CHECK_MV(best[0], best[1]-1)
        CHECK_MV(best[0], best[1]+1)
    }
767
    return dmin;
768 769
}

770
static int var_diamond_search(MpegEncContext * s, int *best, int dmin,
771
                                       int src_index, int ref_index, const int penalty_factor,
772
                                       int size, int h, int flags)
Michael Niedermayer's avatar
Michael Niedermayer committed
773
{
774
    MotionEstContext * const c= &s->me;
775
    me_cmp_func cmpf, chroma_cmpf;
776
    int dia_size;
777
    LOAD_COMMON
778
    LOAD_COMMON2
779
    unsigned map_generation = c->map_generation;
780

781 782
    cmpf        = s->mecc.me_cmp[size];
    chroma_cmpf = s->mecc.me_cmp[size + 1];
Michael Niedermayer's avatar
Michael Niedermayer committed
783

784
    for(dia_size=1; dia_size<=c->dia_size; dia_size++){
Michael Niedermayer's avatar
Michael Niedermayer committed
785 786 787 788 789
        int dir, start, end;
        const int x= best[0];
        const int y= best[1];

        start= FFMAX(0, y + dia_size - ymax);
790
        end  = FFMIN(dia_size, xmax - x + 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
791 792 793 794 795 796 797 798
        for(dir= start; dir<end; dir++){
            int d;

//check(x + dir,y + dia_size - dir,0, a0)
            CHECK_MV(x + dir           , y + dia_size - dir);
        }

        start= FFMAX(0, x + dia_size - xmax);
799
        end  = FFMIN(dia_size, y - ymin + 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
800 801 802 803 804 805 806 807
        for(dir= start; dir<end; dir++){
            int d;

//check(x + dia_size - dir, y - dir,0, a1)
            CHECK_MV(x + dia_size - dir, y - dir           );
        }

        start= FFMAX(0, -y + dia_size + ymin );
808
        end  = FFMIN(dia_size, x - xmin + 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
809 810 811 812 813 814 815 816
        for(dir= start; dir<end; dir++){
            int d;

//check(x - dir,y - dia_size + dir,0, a2)
            CHECK_MV(x - dir           , y - dia_size + dir);
        }

        start= FFMAX(0, -x + dia_size + xmin );
817
        end  = FFMIN(dia_size, ymax - y + 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
818 819 820 821 822 823 824 825 826 827
        for(dir= start; dir<end; dir++){
            int d;

//check(x - dia_size + dir, y + dir,0, a3)
            CHECK_MV(x - dia_size + dir, y + dir           );
        }

        if(x!=best[0] || y!=best[1])
            dia_size=0;
    }
828
    return dmin;
Michael Niedermayer's avatar
Michael Niedermayer committed
829 830
}

831
static av_always_inline int diamond_search(MpegEncContext * s, int *best, int dmin,
832
                                       int src_index, int ref_index, const int penalty_factor,
833
                                       int size, int h, int flags){
834 835
    MotionEstContext * const c= &s->me;
    if(c->dia_size==-1)
836
        return funny_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
837
    else if(c->dia_size<-1)
838
        return   sab_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
839
    else if(c->dia_size<2)
840
        return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
Michael Niedermayer's avatar
Michael Niedermayer committed
841 842
    else if(c->dia_size>1024)
        return          full_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
843 844
    else if(c->dia_size>768)
        return           umh_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
Michael Niedermayer's avatar
Michael Niedermayer committed
845 846 847 848
    else if(c->dia_size>512)
        return           hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, c->dia_size&0xFF);
    else if(c->dia_size>256)
        return       l2s_dia_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
849 850 851 852
    else
        return   var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
}

853
/**
854
   @param P a list of candidate mvs to check before starting the
855 856 857 858
   iterative search. If one of the candidates is close to the optimal mv, then
   it takes fewer iterations. And it increases the chance that we find the
   optimal mv.
 */
859
static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int *mx_ptr, int *my_ptr,
860
                             int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2],
861
                             int ref_mv_scale, int flags, int size, int h)
Michael Niedermayer's avatar
Michael Niedermayer committed
862
{
863
    MotionEstContext * const c= &s->me;
864
    int best[2]={0, 0};      /**< x and y coordinates of the best motion vector.
865
                               i.e. the difference between the position of the
Loren Merritt's avatar
Loren Merritt committed
866
                               block currently being encoded and the position of
867 868
                               the block chosen to predict it from. */
    int d;                   ///< the score (cmp + penalty) of any given mv
869
    int dmin;                /**< the best value of d, i.e. the score
870
                               corresponding to the mv stored in best[]. */
871
    unsigned map_generation;
Michael Niedermayer's avatar
Michael Niedermayer committed
872
    int penalty_factor;
873
    const int ref_mv_stride= s->mb_stride; //pass as arg  FIXME
874
    const int ref_mv_xy = s->mb_x + s->mb_y * ref_mv_stride; // add to last_mv before passing FIXME
875
    me_cmp_func cmpf, chroma_cmpf;
876

877
    LOAD_COMMON
878
    LOAD_COMMON2
879

Michael Niedermayer's avatar
Michael Niedermayer committed
880 881
    if(c->pre_pass){
        penalty_factor= c->pre_penalty_factor;
882 883
        cmpf           = s->mecc.me_pre_cmp[size];
        chroma_cmpf    = s->mecc.me_pre_cmp[size + 1];
Michael Niedermayer's avatar
Michael Niedermayer committed
884 885
    }else{
        penalty_factor= c->penalty_factor;
886 887
        cmpf           = s->mecc.me_cmp[size];
        chroma_cmpf    = s->mecc.me_cmp[size + 1];
Michael Niedermayer's avatar
Michael Niedermayer committed
888
    }
889

890
    map_generation= update_map_generation(c);
Michael Niedermayer's avatar
Michael Niedermayer committed
891

892
    av_assert2(cmpf);
893
    dmin= cmp(s, 0, 0, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
Michael Niedermayer's avatar
Michael Niedermayer committed
894 895
    map[0]= map_generation;
    score_map[0]= dmin;
896 897

    //FIXME precalc first term below?
898 899
    if ((s->pict_type == AV_PICTURE_TYPE_B && !(c->flags & FLAG_DIRECT)) ||
        s->mpv_flags & FF_MPV_FLAG_MV0)
900
        dmin += (mv_penalty[pred_x] + mv_penalty[pred_y])*penalty_factor;
Michael Niedermayer's avatar
Michael Niedermayer committed
901 902

    /* first line */
903
    if (s->first_slice_line) {
Michael Niedermayer's avatar
Michael Niedermayer committed
904
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
905
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
906
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
Michael Niedermayer's avatar
Michael Niedermayer committed
907
    }else{
908 909
        if(dmin<((h*h*s->avctx->mv0_threshold)>>8)
                    && ( P_LEFT[0]    |P_LEFT[1]
Michael Niedermayer's avatar
Michael Niedermayer committed
910
                        |P_TOP[0]     |P_TOP[1]
911
                        |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){
Michael Niedermayer's avatar
Michael Niedermayer committed
912 913
            *mx_ptr= 0;
            *my_ptr= 0;
914
            c->skip=1;
Michael Niedermayer's avatar
Michael Niedermayer committed
915 916
            return dmin;
        }
917
        CHECK_MV(    P_MEDIAN[0] >>shift ,    P_MEDIAN[1] >>shift)
918 919 920 921 922
        CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)  , (P_MEDIAN[1]>>shift)-1)
        CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)  , (P_MEDIAN[1]>>shift)+1)
        CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)-1, (P_MEDIAN[1]>>shift)  )
        CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)+1, (P_MEDIAN[1]>>shift)  )
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
Michael Niedermayer's avatar
Michael Niedermayer committed
923 924 925 926
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
        CHECK_MV(P_LEFT[0]    >>shift, P_LEFT[1]    >>shift)
        CHECK_MV(P_TOP[0]     >>shift, P_TOP[1]     >>shift)
        CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
Michael Niedermayer's avatar
Michael Niedermayer committed
927
    }
928
    if(dmin>h*h*4){
929
        if(c->pre_pass){
930
            CHECK_CLIPPED_MV((last_mv[ref_mv_xy-1][0]*ref_mv_scale + (1<<15))>>16,
931
                            (last_mv[ref_mv_xy-1][1]*ref_mv_scale + (1<<15))>>16)
932
            if(!s->first_slice_line)
933
                CHECK_CLIPPED_MV((last_mv[ref_mv_xy-ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
934
                                (last_mv[ref_mv_xy-ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
935
        }else{
936
            CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
937
                            (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
938
            if(s->mb_y+1<s->end_mb_y)  //FIXME replace at least with last_slice_line
939
                CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
940
                                (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
941
        }
Michael Niedermayer's avatar
Michael Niedermayer committed
942
    }
943

944 945
    if(c->avctx->last_predictor_count){
        const int count= c->avctx->last_predictor_count;
946 947 948 949 950 951 952 953 954 955 956 957 958 959 960
        const int xstart= FFMAX(0, s->mb_x - count);
        const int ystart= FFMAX(0, s->mb_y - count);
        const int xend= FFMIN(s->mb_width , s->mb_x + count + 1);
        const int yend= FFMIN(s->mb_height, s->mb_y + count + 1);
        int mb_y;

        for(mb_y=ystart; mb_y<yend; mb_y++){
            int mb_x;
            for(mb_x=xstart; mb_x<xend; mb_x++){
                const int xy= mb_x + 1 + (mb_y + 1)*ref_mv_stride;
                int mx= (last_mv[xy][0]*ref_mv_scale + (1<<15))>>16;
                int my= (last_mv[xy][1]*ref_mv_scale + (1<<15))>>16;

                if(mx>xmax || mx<xmin || my>ymax || my<ymin) continue;
                CHECK_MV(mx,my)
Michael Niedermayer's avatar
Michael Niedermayer committed
961 962 963
            }
        }
    }
964

Michael Niedermayer's avatar
Michael Niedermayer committed
965
//check(best[0],best[1],0, b0)
966
    dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
Michael Niedermayer's avatar
Michael Niedermayer committed
967 968 969

//check(best[0],best[1],0, b1)
    *mx_ptr= best[0];
970
    *my_ptr= best[1];
Michael Niedermayer's avatar
Michael Niedermayer committed
971 972 973 974

    return dmin;
}

975
//this function is dedicated to the brain damaged gcc
976 977 978 979
int ff_epzs_motion_search(MpegEncContext *s, int *mx_ptr, int *my_ptr,
                          int P[10][2], int src_index, int ref_index,
                          int16_t (*last_mv)[2], int ref_mv_scale,
                          int size, int h)
980
{
981
    MotionEstContext * const c= &s->me;
982
//FIXME convert other functions in the same way if faster
983 984
    if(c->flags==0 && h==16 && size==0){
        return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, 0, 0, 16);
985 986
//    case FLAG_QPEL:
//        return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, FLAG_QPEL);
987 988
    }else{
        return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, c->flags, size, h);
989 990 991 992 993
    }
}

static int epzs_motion_search2(MpegEncContext * s,
                             int *mx_ptr, int *my_ptr, int P[10][2],
994
                             int src_index, int ref_index, int16_t (*last_mv)[2],
995
                             int ref_mv_scale, const int size)
996
{
997
    MotionEstContext * const c= &s->me;
998
    int best[2]={0, 0};
999
    int d, dmin;
1000
    unsigned map_generation;
1001
    const int penalty_factor= c->penalty_factor;
1002 1003 1004
    const int h=8;
    const int ref_mv_stride= s->mb_stride;
    const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
1005
    me_cmp_func cmpf, chroma_cmpf;
1006
    LOAD_COMMON
1007
    int flags= c->flags;
1008
    LOAD_COMMON2
1009

1010 1011
    cmpf        = s->mecc.me_cmp[size];
    chroma_cmpf = s->mecc.me_cmp[size + 1];
1012

1013
    map_generation= update_map_generation(c);
1014 1015

    dmin = 1000000;
1016

1017
    /* first line */
1018
    if (s->first_slice_line) {
1019
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1020
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1021 1022 1023 1024 1025
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
        CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
    }else{
        CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
        //FIXME try some early stop
Michael Niedermayer's avatar
Michael Niedermayer committed
1026 1027 1028 1029
        CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
        CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
        CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
1030
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
Michael Niedermayer's avatar
Michael Niedermayer committed
1031
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1032 1033
    }
    if(dmin>64*4){
1034
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
1035
                        (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1036
        if(s->mb_y+1<s->end_mb_y)  //FIXME replace at least with last_slice_line
1037
            CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1038
                            (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1039 1040
    }

1041
    dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1042

Michael Niedermayer's avatar
Michael Niedermayer committed
1043
    *mx_ptr= best[0];
1044
    *my_ptr= best[1];
Michael Niedermayer's avatar
Michael Niedermayer committed
1045 1046 1047

    return dmin;
}