motion_est_template.c 39.6 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 28
#include "mpegvideo.h"

29
//Let us hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...)
30
#define LOAD_COMMON\
31 32 33 34 35
    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;\
36 37 38
    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
39 40 41 42 43

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

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

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

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

66 67
    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
68

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

75
    if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
76
        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
77
        if(mx || my || size>0)
Michael Niedermayer's avatar
Michael Niedermayer committed
78 79
            dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor;
    }
80 81

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

94
#if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1
95 96
        unsigned key;
        unsigned map_generation= c->map_generation;
97
        key= ((my-1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
98
        av_assert2(c->map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
99
        key= ((my+1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
100
        av_assert2(c->map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
101
        key= ((my)<<ME_MAP_MV_BITS) + (mx+1) + map_generation;
102
        av_assert2(c->map[(index+1)&(ME_MAP_SIZE-1)] == key);
103
        key= ((my)<<ME_MAP_MV_BITS) + (mx-1) + map_generation;
104
        av_assert2(c->map[(index-1)&(ME_MAP_SIZE-1)] == key);
105
#endif
Michael Niedermayer's avatar
Michael Niedermayer committed
106 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
        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)
        }
145
        av_assert2(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2);
Michael Niedermayer's avatar
Michael Niedermayer committed
146 147
    }

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

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

154 155 156 157 158 159 160 161 162 163
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;
}

164 165 166
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)
167
{
168 169 170
    MotionEstContext * const c= &s->me;
    const int penalty_factor= c->mb_penalty_factor;
    const int flags= c->mb_flags;
171 172
    const int qpel= flags & FLAG_QPEL;
    const int mask= 1+2*qpel;
173 174 175
    me_cmp_func cmp_sub, chroma_cmp_sub;
    int d;

176
    LOAD_COMMON
177

178 179
 //FIXME factorize

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

183
    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);
184
    //FIXME check cbp before adding penalty for (0,0) vector
185
    if(add_rate && (mx || my || size>0))
186
        d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor;
187

188 189 190
    return d;
}

191 192 193 194 195 196
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
197 198 199 200
#define CHECK_QUARTER_MV(dx, dy, x, y)\
{\
    const int hx= 4*(x)+(dx);\
    const int hy= 4*(y)+(dy);\
201
    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
202 203 204 205
    d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
    COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
}

206
static int qpel_motion_search(MpegEncContext * s,
207
                                  int *mx_ptr, int *my_ptr, int dmin,
208
                                  int src_index, int ref_index,
209
                                  int size, int h)
Michael Niedermayer's avatar
Michael Niedermayer committed
210
{
211
    MotionEstContext * const c= &s->me;
Michael Niedermayer's avatar
Michael Niedermayer committed
212
    const int mx = *mx_ptr;
213
    const int my = *my_ptr;
214
    const int penalty_factor= c->sub_penalty_factor;
215
    const unsigned map_generation = c->map_generation;
216
    const int subpel_quality= c->avctx->me_subpel_quality;
217
    uint32_t *map= c->map;
218
    me_cmp_func cmpf, chroma_cmpf;
Michael Niedermayer's avatar
Michael Niedermayer committed
219 220
    me_cmp_func cmp_sub, chroma_cmp_sub;

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

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

228 229
    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
230

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

237
    if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
238
        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
239
        if(mx || my || size>0)
Michael Niedermayer's avatar
Michael Niedermayer committed
240 241
            dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor;
    }
242 243

    if (mx > xmin && mx < xmax &&
Michael Niedermayer's avatar
Michael Niedermayer committed
244 245 246 247 248 249 250 251 252 253 254 255
        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];
256

Michael Niedermayer's avatar
Michael Niedermayer committed
257
        memset(best, 64, sizeof(int)*8);
258
        if(s->me.dia_size>=2){
Michael Niedermayer's avatar
Michael Niedermayer committed
259 260 261 262 263 264 265
            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
266 267 268 269 270
                    //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
271
                    int i;
272

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

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
280 281 282 283 284 285 286 287 288 289 290 291 292 293
                    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
294
            //FIXME this could overflow (unlikely though)
Michael Niedermayer's avatar
Michael Niedermayer committed
295
            const int cx = 4*(r - l);
296
            const int cx2= r + l - 2*c;
Michael Niedermayer's avatar
Michael Niedermayer committed
297 298 299
            const int cy = 4*(b - t);
            const int cy2= b + t - 2*c;
            int cxy;
300

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

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

309 310 311 312 313
            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);
314

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

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
327 328 329 330 331 332 333 334 335 336 337
                    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;
                        }
                    }
                }
338
            }
Michael Niedermayer's avatar
Michael Niedermayer committed
339
        }
Michael Niedermayer's avatar
Michael Niedermayer committed
340
        for(i=0; i<subpel_quality; i++){
Michael Niedermayer's avatar
Michael Niedermayer committed
341 342 343 344
            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
345

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

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

    return dmin;
}


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

376
#define CHECK_CLIPPED_MV(ax,ay)\
377
{\
378 379 380 381 382
    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)\
383 384
}

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

#define check(x,y,S,v)\
404 405 406 407
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
408

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

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

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
    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;
        }
    }
}

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

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

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

474 475 476 477 478 479 480
        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;
481

482 483 484 485 486 487 488 489 490 491 492 493
        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;
    }
494
    return dmin;
495 496
}

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

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

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

            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
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
            }
        }while(best[0] != x || best[1] != y);
    }

    return dmin;
}

static int l2s_dia_search(MpegEncContext * s, int *best, int dmin,
                                       int src_index, int ref_index, int const penalty_factor,
                                       int size, int h, int flags)
{
    MotionEstContext * const c= &s->me;
    me_cmp_func cmpf, chroma_cmpf;
    LOAD_COMMON
    LOAD_COMMON2
539
    unsigned map_generation = c->map_generation;
540 541 542
    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
543 544 545
    static const int hex[8][2]={{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1},
                                { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}};

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

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

    x= best[0];
    y= best[1];
561 562 563 564
    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
565 566 567 568

    return dmin;
}

569 570 571 572 573 574 575 576
static int umh_search(MpegEncContext * s, int *best, int dmin,
                                       int src_index, int ref_index, int const penalty_factor,
                                       int size, int h, int flags)
{
    MotionEstContext * const c= &s->me;
    me_cmp_func cmpf, chroma_cmpf;
    LOAD_COMMON
    LOAD_COMMON2
577
    unsigned map_generation = c->map_generation;
578
    int x,y,x2,y2, i, j, d;
579
    const int dia_size= c->dia_size&0xFE;
580 581 582
    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
583
                                 {-2,-3}, { 0,-4}, { 2,-3},};
584

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

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

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

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

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

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

    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;
}

651 652
#define SAB_CHECK_MV(ax,ay)\
{\
653
    const unsigned key = ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\
654 655
    const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\
    if(map[index]!=key){\
656
        d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677
        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;\
        }\
    }\
}

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

692 693
    av_assert1(minima_count <= MAX_SAB_SIZE);

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

697 698 699 700
    /*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++){
701 702 703
        uint32_t key= map[i];

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

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

707 708 709 710 711
        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));
712 713 714 715 716 717

        // 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;

718 719 720
        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;
721

722 723
        j++;
    }
724

725
    qsort(minima, j, sizeof(Minima), minima_cmp);
726

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

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

738
        if(minima[i].checked) continue;
739

740 741 742 743 744 745 746 747
        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)
748

749 750
        minima[i].checked= 1;
    }
751

752 753 754
    best[0]= minima[0].x;
    best[1]= minima[0].y;
    dmin= minima[0].height;
755

756 757 758 759 760 761 762 763 764
    if(   best[0] < xmax && best[0] > xmin
       && best[1] < ymax && best[1] > ymin){
        int d;
        //ensure that the refernece samples for hpel refinement are in the map
        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)
    }
765
    return dmin;
766 767
}

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

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

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

        start= FFMAX(0, y + dia_size - ymax);
788
        end  = FFMIN(dia_size, xmax - x + 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
789 790 791 792 793 794 795 796
        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);
797
        end  = FFMIN(dia_size, y - ymin + 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
798 799 800 801 802 803 804 805
        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 );
806
        end  = FFMIN(dia_size, x - xmin + 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
807 808 809 810 811 812 813 814
        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 );
815
        end  = FFMIN(dia_size, ymax - y + 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
816 817 818 819 820 821 822 823 824 825
        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;
    }
826
    return dmin;
Michael Niedermayer's avatar
Michael Niedermayer committed
827 828
}

829
static av_always_inline int diamond_search(MpegEncContext * s, int *best, int dmin,
830 831
                                       int src_index, int ref_index, int const penalty_factor,
                                       int size, int h, int flags){
832 833
    MotionEstContext * const c= &s->me;
    if(c->dia_size==-1)
834
        return funny_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
835
    else if(c->dia_size<-1)
836
        return   sab_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
837
    else if(c->dia_size<2)
838
        return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
Michael Niedermayer's avatar
Michael Niedermayer committed
839 840
    else if(c->dia_size>1024)
        return          full_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
841 842
    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
843 844 845 846
    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);
847 848 849 850
    else
        return   var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
}

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

875
    LOAD_COMMON
876
    LOAD_COMMON2
877

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

888
    map_generation= update_map_generation(c);
Michael Niedermayer's avatar
Michael Niedermayer committed
889

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

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

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

942 943
    if(c->avctx->last_predictor_count){
        const int count= c->avctx->last_predictor_count;
944 945 946 947 948 949 950 951 952 953 954 955 956 957 958
        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
959 960 961
            }
        }
    }
962

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

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

    return dmin;
}

973
//this function is dedicated to the braindamaged gcc
974 975 976 977
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)
978
{
979
    MotionEstContext * const c= &s->me;
980
//FIXME convert other functions in the same way if faster
981 982
    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);
983 984
//    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);
985 986
    }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);
987 988 989 990 991
    }
}

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

1009 1010
    cmpf        = s->mecc.me_cmp[size];
    chroma_cmpf = s->mecc.me_cmp[size + 1];
Michael Niedermayer's avatar
Michael Niedermayer committed
1011

1012
    map_generation= update_map_generation(c);
Michael Niedermayer's avatar
Michael Niedermayer committed
1013 1014

    dmin = 1000000;
1015

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

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

    *mx_ptr= best[0];
1043
    *my_ptr= best[1];
1044 1045 1046 1047 1048

    return dmin;
}

//try to merge with above FIXME (needs PSNR test)
1049 1050
static int epzs_motion_search2(MpegEncContext * s,
                             int *mx_ptr, int *my_ptr, int P[10][2],
1051
                             int src_index, int ref_index, int16_t (*last_mv)[2],
1052
                             int ref_mv_scale)
1053
{
1054
    MotionEstContext * const c= &s->me;
1055
    int best[2]={0, 0};
1056
    int d, dmin;
1057
    unsigned map_generation;
1058
    const int penalty_factor= c->penalty_factor;
1059 1060 1061 1062
    const int size=0; //FIXME pass as arg
    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;
1063
    me_cmp_func cmpf, chroma_cmpf;
1064
    LOAD_COMMON
1065
    int flags= c->flags;
1066
    LOAD_COMMON2
1067

1068 1069
    cmpf        = s->mecc.me_cmp[size];
    chroma_cmpf = s->mecc.me_cmp[size + 1];
1070

1071
    map_generation= update_map_generation(c);
1072 1073

    dmin = 1000000;
1074

1075
    /* first line */
1076
    if (s->first_slice_line) {
1077
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1078
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1079 1080 1081 1082 1083
                        (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
1084 1085 1086 1087
        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)
1088
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
Michael Niedermayer's avatar
Michael Niedermayer committed
1089
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
1090 1091
    }
    if(dmin>64*4){
1092
        CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
1093
                        (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1094
        if(s->mb_y+1<s->end_mb_y)  //FIXME replace at least with last_slice_line
1095
            CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1096
                            (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1097 1098
    }

1099
    dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1100

Michael Niedermayer's avatar
Michael Niedermayer committed
1101
    *mx_ptr= best[0];
1102
    *my_ptr= best[1];
Michael Niedermayer's avatar
Michael Niedermayer committed
1103 1104 1105

    return dmin;
}