motion_est_template.c 37.8 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 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * 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
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
20

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

Michael Niedermayer's avatar
Michael Niedermayer committed
26
//lets hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...)
27
#define LOAD_COMMON\
28 29 30 31 32
    uint32_t attribute_unused * const score_map= c->score_map;\
    const int attribute_unused xmin= c->xmin;\
    const int attribute_unused ymin= c->ymin;\
    const int attribute_unused xmax= c->xmax;\
    const int attribute_unused ymax= c->ymax;\
33 34 35
    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
36 37 38 39 40

#define CHECK_HALF_MV(dx, dy, x, y)\
{\
    const int hx= 2*(x)+(dx);\
    const int hy= 2*(y)+(dy);\
41
    d= cmp(s, x, y, dx, dy, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);\
Michael Niedermayer's avatar
Michael Niedermayer committed
42 43 44 45 46
    d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
    COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
}

#if 0
47
static int hpel_motion_search)(MpegEncContext * s,
48
                                  int *mx_ptr, int *my_ptr, int dmin,
49
                                  uint8_t *ref_data[3],
50
                                  int size)
Michael Niedermayer's avatar
Michael Niedermayer committed
51 52 53 54 55
{
    const int xx = 16 * s->mb_x + 8*(n&1);
    const int yy = 16 * s->mb_y + 8*(n>>1);
    const int mx = *mx_ptr;
    const int my = *my_ptr;
56
    const int penalty_factor= c->sub_penalty_factor;
57

58
    LOAD_COMMON
59

Michael Niedermayer's avatar
Michael Niedermayer committed
60 61 62 63 64 65 66 67 68 69 70
 //   INIT;
 //FIXME factorize
    me_cmp_func cmp, chroma_cmp, cmp_sub, chroma_cmp_sub;

    if(s->no_rounding /*FIXME b_type*/){
        hpel_put= &s->dsp.put_no_rnd_pixels_tab[size];
        chroma_hpel_put= &s->dsp.put_no_rnd_pixels_tab[size+1];
    }else{
        hpel_put=& s->dsp.put_pixels_tab[size];
        chroma_hpel_put= &s->dsp.put_pixels_tab[size+1];
    }
71 72
    cmpf= s->dsp.me_cmp[size];
    chroma_cmpf= s->dsp.me_cmp[size+1];
Michael Niedermayer's avatar
Michael Niedermayer committed
73 74 75
    cmp_sub= s->dsp.me_sub_cmp[size];
    chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];

76
    if(c->skip){ //FIXME somehow move up (benchmark)
Michael Niedermayer's avatar
Michael Niedermayer committed
77 78 79 80
        *mx_ptr = 0;
        *my_ptr = 0;
        return dmin;
    }
81

82
    if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
Michael Niedermayer's avatar
Michael Niedermayer committed
83 84 85 86
        CMP_HPEL(dmin, 0, 0, mx, my, size);
        if(mx || my)
            dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor;
    }
87 88

    if (mx > xmin && mx < xmax &&
Michael Niedermayer's avatar
Michael Niedermayer committed
89 90 91
        my > ymin && my < ymax) {
        int bx=2*mx, by=2*my;
        int d= dmin;
92

Michael Niedermayer's avatar
Michael Niedermayer committed
93
        CHECK_HALF_MV(1, 1, mx-1, my-1)
94
        CHECK_HALF_MV(0, 1, mx  , my-1)
Michael Niedermayer's avatar
Michael Niedermayer committed
95 96 97 98
        CHECK_HALF_MV(1, 1, mx  , my-1)
        CHECK_HALF_MV(1, 0, mx-1, my  )
        CHECK_HALF_MV(1, 0, mx  , my  )
        CHECK_HALF_MV(1, 1, mx-1, my  )
99
        CHECK_HALF_MV(0, 1, mx  , my  )
Michael Niedermayer's avatar
Michael Niedermayer committed
100 101
        CHECK_HALF_MV(1, 1, mx  , my  )

102
        assert(bx >= xmin*2 || bx <= xmax*2 || by >= ymin*2 || by <= ymax*2);
Michael Niedermayer's avatar
Michael Niedermayer committed
103 104 105 106 107 108 109 110 111 112 113 114

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

    return dmin;
}

#else
115
static int hpel_motion_search(MpegEncContext * s,
116
                                  int *mx_ptr, int *my_ptr, int dmin,
117 118
                                  int src_index, int ref_index,
                                  int size, int h)
Michael Niedermayer's avatar
Michael Niedermayer committed
119
{
120
    MotionEstContext * const c= &s->me;
Michael Niedermayer's avatar
Michael Niedermayer committed
121
    const int mx = *mx_ptr;
122
    const int my = *my_ptr;
123
    const int penalty_factor= c->sub_penalty_factor;
Michael Niedermayer's avatar
Michael Niedermayer committed
124
    me_cmp_func cmp_sub, chroma_cmp_sub;
125
    int bx=2*mx, by=2*my;
Michael Niedermayer's avatar
Michael Niedermayer committed
126

127
    LOAD_COMMON
128
    int flags= c->sub_flags;
129

Michael Niedermayer's avatar
Michael Niedermayer committed
130 131 132 133 134
 //FIXME factorize

    cmp_sub= s->dsp.me_sub_cmp[size];
    chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];

135
    if(c->skip){ //FIXME move out of hpel?
Michael Niedermayer's avatar
Michael Niedermayer committed
136 137 138 139
        *mx_ptr = 0;
        *my_ptr = 0;
        return dmin;
    }
140

141
    if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
142
        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
143
        if(mx || my || size>0)
Michael Niedermayer's avatar
Michael Niedermayer committed
144 145
            dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor;
    }
146 147

    if (mx > xmin && mx < xmax &&
Michael Niedermayer's avatar
Michael Niedermayer committed
148 149 150
        my > ymin && my < ymax) {
        int d= dmin;
        const int index= (my<<ME_MAP_SHIFT) + mx;
151
        const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
152
                     + (mv_penalty[bx   - pred_x] + mv_penalty[by-2 - pred_y])*c->penalty_factor;
Michael Niedermayer's avatar
Michael Niedermayer committed
153
        const int l= score_map[(index- 1               )&(ME_MAP_SIZE-1)]
154
                     + (mv_penalty[bx-2 - pred_x] + mv_penalty[by   - pred_y])*c->penalty_factor;
Michael Niedermayer's avatar
Michael Niedermayer committed
155
        const int r= score_map[(index+ 1               )&(ME_MAP_SIZE-1)]
156
                     + (mv_penalty[bx+2 - pred_x] + mv_penalty[by   - pred_y])*c->penalty_factor;
Michael Niedermayer's avatar
Michael Niedermayer committed
157
        const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
158
                     + (mv_penalty[bx   - pred_x] + mv_penalty[by+2 - pred_y])*c->penalty_factor;
159

160
#if 1
161
        int key;
162
        int map_generation= c->map_generation;
163
#ifndef NDEBUG
164
        uint32_t *map= c->map;
165
#endif
166 167 168 169 170 171 172 173
        key= ((my-1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
        assert(map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
        key= ((my+1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
        assert(map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
        key= ((my)<<ME_MAP_MV_BITS) + (mx+1) + map_generation;
        assert(map[(index+1)&(ME_MAP_SIZE-1)] == key);
        key= ((my)<<ME_MAP_MV_BITS) + (mx-1) + map_generation;
        assert(map[(index-1)&(ME_MAP_SIZE-1)] == key);
174
#endif
Michael Niedermayer's avatar
Michael Niedermayer committed
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
        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)
        }
        assert(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2);
    }

217 218
    *mx_ptr = bx;
    *my_ptr = by;
219

Michael Niedermayer's avatar
Michael Niedermayer committed
220 221 222 223
    return dmin;
}
#endif

224 225 226 227 228 229 230 231 232 233
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;
}

234 235
int inline ff_get_mb_score(MpegEncContext * s, int mx, int my, int src_index,
                               int ref_index, int size, int h, int add_rate)
236 237
{
//    const int check_luma= s->dsp.me_sub_cmp != s->dsp.mb_cmp;
238 239 240
    MotionEstContext * const c= &s->me;
    const int penalty_factor= c->mb_penalty_factor;
    const int flags= c->mb_flags;
241 242
    const int qpel= flags & FLAG_QPEL;
    const int mask= 1+2*qpel;
243 244 245
    me_cmp_func cmp_sub, chroma_cmp_sub;
    int d;

246
    LOAD_COMMON
247

248 249 250 251
 //FIXME factorize

    cmp_sub= s->dsp.mb_cmp[size];
    chroma_cmp_sub= s->dsp.mb_cmp[size+1];
252

253 254
//    assert(!c->skip);
//    assert(c->avctx->me_sub_cmp != c->avctx->mb_cmp);
255

256
    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);
257
    //FIXME check cbp before adding penalty for (0,0) vector
258
    if(add_rate && (mx || my || size>0))
259
        d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor;
260

261 262 263
    return d;
}

Michael Niedermayer's avatar
Michael Niedermayer committed
264 265 266 267
#define CHECK_QUARTER_MV(dx, dy, x, y)\
{\
    const int hx= 4*(x)+(dx);\
    const int hy= 4*(y)+(dy);\
268
    d= cmp(s, x, y, dx, dy, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
Michael Niedermayer's avatar
Michael Niedermayer committed
269 270 271 272
    d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
    COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
}

273
static int qpel_motion_search(MpegEncContext * s,
274
                                  int *mx_ptr, int *my_ptr, int dmin,
275
                                  int src_index, int ref_index,
276
                                  int size, int h)
Michael Niedermayer's avatar
Michael Niedermayer committed
277
{
278
    MotionEstContext * const c= &s->me;
Michael Niedermayer's avatar
Michael Niedermayer committed
279
    const int mx = *mx_ptr;
280
    const int my = *my_ptr;
281 282
    const int penalty_factor= c->sub_penalty_factor;
    const int map_generation= c->map_generation;
283
    const int subpel_quality= c->avctx->me_subpel_quality;
284
    uint32_t *map= c->map;
285
    me_cmp_func cmpf, chroma_cmpf;
Michael Niedermayer's avatar
Michael Niedermayer committed
286 287
    me_cmp_func cmp_sub, chroma_cmp_sub;

288
    LOAD_COMMON
289
    int flags= c->sub_flags;
290

291 292
    cmpf= s->dsp.me_cmp[size];
    chroma_cmpf= s->dsp.me_cmp[size+1]; //factorize FIXME
Michael Niedermayer's avatar
Michael Niedermayer committed
293 294 295 296 297
 //FIXME factorize

    cmp_sub= s->dsp.me_sub_cmp[size];
    chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];

298
    if(c->skip){ //FIXME somehow move up (benchmark)
Michael Niedermayer's avatar
Michael Niedermayer committed
299 300 301 302
        *mx_ptr = 0;
        *my_ptr = 0;
        return dmin;
    }
303

304
    if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
305
        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
306
        if(mx || my || size>0)
Michael Niedermayer's avatar
Michael Niedermayer committed
307 308
            dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor;
    }
309 310

    if (mx > xmin && mx < xmax &&
Michael Niedermayer's avatar
Michael Niedermayer committed
311 312 313 314 315 316 317 318 319 320 321 322
        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];
323

Michael Niedermayer's avatar
Michael Niedermayer committed
324 325
        memset(best, 64, sizeof(int)*8);
#if 1
326
        if(s->me.dia_size>=2){
Michael Niedermayer's avatar
Michael Niedermayer committed
327 328 329 330 331 332 333
            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
334 335 336 337 338
                    //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
339
                    int i;
340

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

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

345 346
//                    if(nx&1) score-=1024*c->penalty_factor;
//                    if(ny&1) score-=1024*c->penalty_factor;
347

Michael Niedermayer's avatar
Michael Niedermayer committed
348 349 350 351 352 353 354 355 356 357 358 359 360 361
                    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
362
            //FIXME this could overflow (unlikely though)
Michael Niedermayer's avatar
Michael Niedermayer committed
363
            const int cx = 4*(r - l);
364
            const int cx2= r + l - 2*c;
Michael Niedermayer's avatar
Michael Niedermayer committed
365 366 367
            const int cy = 4*(b - t);
            const int cy2= b + t - 2*c;
            int cxy;
368

Michael Niedermayer's avatar
Michael Niedermayer committed
369 370 371
            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{
372
                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
373
            }
374 375 376

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

Michael Niedermayer's avatar
Michael Niedermayer committed
377 378 379 380 381
            assert(16*cx2 + 4*cx + 32*c == 32*r);
            assert(16*cx2 - 4*cx + 32*c == 32*l);
            assert(16*cy2 + 4*cy + 32*c == 32*b);
            assert(16*cy2 - 4*cy + 32*c == 32*t);
            assert(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl);
382

Michael Niedermayer's avatar
Michael Niedermayer committed
383 384
            for(ny= -3; ny <= 3; ny++){
                for(nx= -3; nx <= 3; nx++){
Michael Niedermayer's avatar
Michael Niedermayer committed
385
                    //FIXME this could overflow (unlikely though)
Michael Niedermayer's avatar
Michael Niedermayer committed
386 387
                    int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor
                    int i;
388

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

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

Michael Niedermayer's avatar
Michael Niedermayer committed
395 396 397 398 399 400 401 402 403 404 405
                    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;
                        }
                    }
                }
406
            }
Michael Niedermayer's avatar
Michael Niedermayer committed
407
        }
Michael Niedermayer's avatar
Michael Niedermayer committed
408
        for(i=0; i<subpel_quality; i++){
Michael Niedermayer's avatar
Michael Niedermayer committed
409 410 411 412
            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
413

Michael Niedermayer's avatar
Michael Niedermayer committed
414
#if 0
Michael Niedermayer's avatar
Michael Niedermayer committed
415 416 417 418 419 420 421 422 423
            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)];
//            if(l < r && l < t && l < b && l < tl && l < bl && l < tr && l < br && bl < tl){
            if(tl<br){

//            nx= FFMAX(4*mx - bx, bx - 4*mx);
//            ny= FFMAX(4*my - by, by - 4*my);
424

Michael Niedermayer's avatar
Michael Niedermayer committed
425 426 427 428 429 430
            static int stats[7][7], count;
            count++;
            stats[4*mx - bx + 3][4*my - by + 3]++;
            if(256*256*256*64 % count ==0){
                for(i=0; i<49; i++){
                    if((i%7)==0) printf("\n");
Michael Niedermayer's avatar
Michael Niedermayer committed
431 432 433 434
                    printf("%6d ", stats[0][i]);
                }
                printf("\n");
            }
Michael Niedermayer's avatar
Michael Niedermayer committed
435
            }
Michael Niedermayer's avatar
Michael Niedermayer committed
436 437 438 439
#endif
#else

        CHECK_QUARTER_MV(2, 2, mx-1, my-1)
440
        CHECK_QUARTER_MV(0, 2, mx  , my-1)
Michael Niedermayer's avatar
Michael Niedermayer committed
441 442 443 444 445 446
        CHECK_QUARTER_MV(2, 2, mx  , my-1)
        CHECK_QUARTER_MV(2, 0, mx  , my  )
        CHECK_QUARTER_MV(2, 2, mx  , my  )
        CHECK_QUARTER_MV(0, 2, mx  , my  )
        CHECK_QUARTER_MV(2, 2, mx-1, my  )
        CHECK_QUARTER_MV(2, 0, mx-1, my  )
447

Michael Niedermayer's avatar
Michael Niedermayer committed
448 449
        nx= bx;
        ny= by;
450

Michael Niedermayer's avatar
Michael Niedermayer committed
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
        for(i=0; i<8; i++){
            int ox[8]= {0, 1, 1, 1, 0,-1,-1,-1};
            int oy[8]= {1, 1, 0,-1,-1,-1, 0, 1};
            CHECK_QUARTER_MV((nx + ox[i])&3, (ny + oy[i])&3, (nx + ox[i])>>2, (ny + oy[i])>>2)
        }
#endif
#if 0
        //outer ring
        CHECK_QUARTER_MV(1, 3, mx-1, my-1)
        CHECK_QUARTER_MV(1, 2, mx-1, my-1)
        CHECK_QUARTER_MV(1, 1, mx-1, my-1)
        CHECK_QUARTER_MV(2, 1, mx-1, my-1)
        CHECK_QUARTER_MV(3, 1, mx-1, my-1)
        CHECK_QUARTER_MV(0, 1, mx  , my-1)
        CHECK_QUARTER_MV(1, 1, mx  , my-1)
        CHECK_QUARTER_MV(2, 1, mx  , my-1)
        CHECK_QUARTER_MV(3, 1, mx  , my-1)
        CHECK_QUARTER_MV(3, 2, mx  , my-1)
        CHECK_QUARTER_MV(3, 3, mx  , my-1)
        CHECK_QUARTER_MV(3, 0, mx  , my  )
        CHECK_QUARTER_MV(3, 1, mx  , my  )
        CHECK_QUARTER_MV(3, 2, mx  , my  )
        CHECK_QUARTER_MV(3, 3, mx  , my  )
        CHECK_QUARTER_MV(2, 3, mx  , my  )
        CHECK_QUARTER_MV(1, 3, mx  , my  )
        CHECK_QUARTER_MV(0, 3, mx  , my  )
        CHECK_QUARTER_MV(3, 3, mx-1, my  )
        CHECK_QUARTER_MV(2, 3, mx-1, my  )
        CHECK_QUARTER_MV(1, 3, mx-1, my  )
        CHECK_QUARTER_MV(1, 2, mx-1, my  )
        CHECK_QUARTER_MV(1, 1, mx-1, my  )
        CHECK_QUARTER_MV(1, 0, mx-1, my  )
#endif
        assert(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4);

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

    return dmin;
}


#define CHECK_MV(x,y)\
{\
    const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
    const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
501 502 503 504
    assert((x) >= xmin);\
    assert((x) <= xmax);\
    assert((y) >= ymin);\
    assert((y) <= ymax);\
505
/*printf("check_mv %d %d\n", x, y);*/\
Michael Niedermayer's avatar
Michael Niedermayer committed
506
    if(map[index]!=key){\
507
        d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
Michael Niedermayer's avatar
Michael Niedermayer committed
508 509 510
        map[index]= key;\
        score_map[index]= d;\
        d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
511
/*printf("score:%d\n", d);*/\
Michael Niedermayer's avatar
Michael Niedermayer committed
512 513 514 515
        COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
    }\
}

516 517
#define CHECK_CLIPED_MV(ax,ay)\
{\
518 519 520 521 522
    const int x= ax;\
    const int y= ay;\
    const int x2= FFMAX(xmin, FFMIN(x, xmax));\
    const int y2= FFMAX(ymin, FFMIN(y, ymax));\
    CHECK_MV(x2, y2)\
523 524
}

Michael Niedermayer's avatar
Michael Niedermayer committed
525 526 527 528
#define CHECK_MV_DIR(x,y,new_dir)\
{\
    const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
    const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
529
/*printf("check_mv_dir %d %d %d\n", x, y, new_dir);*/\
Michael Niedermayer's avatar
Michael Niedermayer committed
530
    if(map[index]!=key){\
531
        d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
Michael Niedermayer's avatar
Michael Niedermayer committed
532 533 534
        map[index]= key;\
        score_map[index]= d;\
        d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
535
/*printf("score:%d\n", d);*/\
Michael Niedermayer's avatar
Michael Niedermayer committed
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
        if(d<dmin){\
            best[0]=x;\
            best[1]=y;\
            dmin=d;\
            next_dir= new_dir;\
        }\
    }\
}

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

551
#define LOAD_COMMON2\
552
    uint32_t *map= c->map;\
553 554
    const int qpel= flags&FLAG_QPEL;\
    const int shift= 1+qpel;\
Michael Niedermayer's avatar
Michael Niedermayer committed
555

556 557 558
static always_inline int small_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
559
{
560
    MotionEstContext * const c= &s->me;
561
    me_cmp_func cmpf, chroma_cmpf;
Michael Niedermayer's avatar
Michael Niedermayer committed
562
    int next_dir=-1;
563
    LOAD_COMMON
564
    LOAD_COMMON2
565
    int map_generation= c->map_generation;
566

567 568
    cmpf= s->dsp.me_cmp[size];
    chroma_cmpf= s->dsp.me_cmp[size+1];
Michael Niedermayer's avatar
Michael Niedermayer committed
569

570 571 572 573
    { /* ensure that the best point is in the MAP as h/qpel refinement needs it */
        const int key= (best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation;
        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
574
            score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
575 576 577 578
            map[index]= key;
        }
    }

Michael Niedermayer's avatar
Michael Niedermayer committed
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597
    for(;;){
        int d;
        const int dir= next_dir;
        const int x= best[0];
        const int y= best[1];
        next_dir=-1;

//printf("%d", dir);
        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;
        }
    }
}

598 599 600
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)
601
{
602
    MotionEstContext * const c= &s->me;
603
    me_cmp_func cmpf, chroma_cmpf;
604
    int dia_size;
605
    LOAD_COMMON
606
    LOAD_COMMON2
607
    int map_generation= c->map_generation;
608

609 610
    cmpf= s->dsp.me_cmp[size];
    chroma_cmpf= s->dsp.me_cmp[size+1];
611 612 613 614 615

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

617 618 619 620 621 622 623
        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;
624

625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655
        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;
#if 0
{
int dx, dy, i;
static int stats[8*8];
dx= ABS(x-best[0]);
dy= ABS(y-best[1]);
if(dy>dx){
    dx^=dy; dy^=dx; dx^=dy;
}
stats[dy*8 + dx] ++;
if(256*256*256*64 % (stats[0]+1)==0){
    for(i=0; i<64; i++){
        if((i&7)==0) printf("\n");
        printf("%8d ", stats[i]);
    }
    printf("\n");
}
}
#endif
    }
656
    return dmin;
657 658 659 660 661 662 663 664
}

#define SAB_CHECK_MV(ax,ay)\
{\
    const int key= ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\
    const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\
/*printf("sab check %d %d\n", ax, ay);*/\
    if(map[index]!=key){\
665
        d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687
        map[index]= key;\
        score_map[index]= d;\
        d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\
/*printf("score: %d\n", d);*/\
        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;\
        }\
    }\
}

688
#define MAX_SAB_SIZE ME_MAP_SIZE
689 690 691
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)
692
{
693
    MotionEstContext * const c= &s->me;
694
    me_cmp_func cmpf, chroma_cmpf;
695
    Minima minima[MAX_SAB_SIZE];
696
    const int minima_count= ABS(c->dia_size);
697
    int i, j;
698
    LOAD_COMMON
699
    LOAD_COMMON2
700
    int map_generation= c->map_generation;
701

702 703
    cmpf= s->dsp.me_cmp[size];
    chroma_cmpf= s->dsp.me_cmp[size+1];
704

705 706 707 708
    for(j=i=0; i<ME_MAP_SIZE; i++){
        uint32_t key= map[i];

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

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

712
        assert(j<MAX_SAB_SIZE); //max j = number of predictors
713

714 715 716 717 718 719 720 721
        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));
        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;
722

723 724
        j++;
    }
725

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

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

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

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

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

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

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

757 758 759 760 761 762 763 764 765
    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)
    }
766
    return dmin;
767 768
}

769 770 771
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
772
{
773
    MotionEstContext * const c= &s->me;
774
    me_cmp_func cmpf, chroma_cmpf;
775
    int dia_size;
776
    LOAD_COMMON
777
    LOAD_COMMON2
778
    int map_generation= c->map_generation;
779

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

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

        start= FFMAX(0, y + dia_size - ymax);
789
        end  = FFMIN(dia_size, xmax - x + 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
790 791 792 793 794 795 796 797
        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);
798
        end  = FFMIN(dia_size, y - ymin + 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
799 800 801 802 803 804 805 806
        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 );
807
        end  = FFMIN(dia_size, x - xmin + 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
808 809 810 811 812 813 814 815
        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 );
816
        end  = FFMIN(dia_size, ymax - y + 1);
Michael Niedermayer's avatar
Michael Niedermayer committed
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 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841
#if 0
{
int dx, dy, i;
static int stats[8*8];
dx= ABS(x-best[0]);
dy= ABS(y-best[1]);
stats[dy*8 + dx] ++;
if(256*256*256*64 % (stats[0]+1)==0){
    for(i=0; i<64; i++){
        if((i&7)==0) printf("\n");
        printf("%6d ", stats[i]);
    }
    printf("\n");
}
}
#endif
Michael Niedermayer's avatar
Michael Niedermayer committed
842
    }
843
    return dmin;
Michael Niedermayer's avatar
Michael Niedermayer committed
844 845
}

846 847 848
static always_inline int diamond_search(MpegEncContext * s, int *best, int dmin,
                                       int src_index, int ref_index, int const penalty_factor,
                                       int size, int h, int flags){
849 850
    MotionEstContext * const c= &s->me;
    if(c->dia_size==-1)
851
        return funny_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
852
    else if(c->dia_size<-1)
853
        return   sab_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
854
    else if(c->dia_size<2)
855 856 857 858 859 860
        return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
    else
        return   var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
}

static always_inline int epzs_motion_search_internal(MpegEncContext * s, int *mx_ptr, int *my_ptr,
861
                             int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2],
862
                             int ref_mv_scale, int flags, int size, int h)
Michael Niedermayer's avatar
Michael Niedermayer committed
863
{
864
    MotionEstContext * const c= &s->me;
Michael Niedermayer's avatar
Michael Niedermayer committed
865
    int best[2]={0, 0};
866
    int d, dmin;
Michael Niedermayer's avatar
Michael Niedermayer committed
867
    int map_generation;
Michael Niedermayer's avatar
Michael Niedermayer committed
868
    int penalty_factor;
869 870
    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
871
    me_cmp_func cmpf, chroma_cmpf;
872

873
    LOAD_COMMON
874
    LOAD_COMMON2
875

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

886
    map_generation= update_map_generation(c);
Michael Niedermayer's avatar
Michael Niedermayer committed
887

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

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

932 933
    if(c->avctx->last_predictor_count){
        const int count= c->avctx->last_predictor_count;
934 935 936 937 938 939 940 941 942 943 944 945 946 947 948
        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
949 950 951
            }
        }
    }
952

Michael Niedermayer's avatar
Michael Niedermayer committed
953
//check(best[0],best[1],0, b0)
954
    dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
Michael Niedermayer's avatar
Michael Niedermayer committed
955 956 957

//check(best[0],best[1],0, b1)
    *mx_ptr= best[0];
958
    *my_ptr= best[1];
Michael Niedermayer's avatar
Michael Niedermayer committed
959 960 961 962 963

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

964
//this function is dedicated to the braindamaged gcc
965
inline int ff_epzs_motion_search(MpegEncContext * s, int *mx_ptr, int *my_ptr,
966
                             int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2],
967
                             int ref_mv_scale, int size, int h)
968
{
969
    MotionEstContext * const c= &s->me;
970
//FIXME convert other functions in the same way if faster
971 972
    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);
973 974
//    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);
975 976
    }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);
977 978 979 980 981
    }
}

static int epzs_motion_search4(MpegEncContext * s,
                             int *mx_ptr, int *my_ptr, int P[10][2],
982
                             int src_index, int ref_index, int16_t (*last_mv)[2],
983
                             int ref_mv_scale)
Michael Niedermayer's avatar
Michael Niedermayer committed
984
{
985
    MotionEstContext * const c= &s->me;
Michael Niedermayer's avatar
Michael Niedermayer committed
986
    int best[2]={0, 0};
987
    int d, dmin;
Michael Niedermayer's avatar
Michael Niedermayer committed
988
    int map_generation;
989
    const int penalty_factor= c->penalty_factor;
Michael Niedermayer's avatar
Michael Niedermayer committed
990
    const int size=1;
991
    const int h=8;
992 993
    const int ref_mv_stride= s->mb_stride;
    const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
994
    me_cmp_func cmpf, chroma_cmpf;
995
    LOAD_COMMON
996
    int flags= c->flags;
997
    LOAD_COMMON2
998

999 1000
    cmpf= s->dsp.me_cmp[size];
    chroma_cmpf= s->dsp.me_cmp[size+1];
Michael Niedermayer's avatar
Michael Niedermayer committed
1001

1002
    map_generation= update_map_generation(c);
Michael Niedermayer's avatar
Michael Niedermayer committed
1003 1004

    dmin = 1000000;
1005
//printf("%d %d %d %d //",xmin, ymin, xmax, ymax);
Michael Niedermayer's avatar
Michael Niedermayer committed
1006
    /* first line */
1007
    if (s->first_slice_line) {
1008
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1009
        CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1010
                        (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
Michael Niedermayer's avatar
Michael Niedermayer committed
1011 1012 1013 1014 1015 1016 1017 1018 1019
        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
        if(dmin>64*2){
            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)
1020
            CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1021
                            (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
Michael Niedermayer's avatar
Michael Niedermayer committed
1022 1023 1024
        }
    }
    if(dmin>64*4){
1025
        CHECK_CLIPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
1026
                        (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1027
        if(s->mb_y+1<s->end_mb_y)  //FIXME replace at least with last_slice_line
1028
            CHECK_CLIPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1029
                            (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
Michael Niedermayer's avatar
Michael Niedermayer committed
1030 1031
    }

1032
    dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1033 1034

    *mx_ptr= best[0];
1035
    *my_ptr= best[1];
1036 1037 1038 1039 1040 1041

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

//try to merge with above FIXME (needs PSNR test)
1042 1043
static int epzs_motion_search2(MpegEncContext * s,
                             int *mx_ptr, int *my_ptr, int P[10][2],
1044
                             int src_index, int ref_index, int16_t (*last_mv)[2],
1045
                             int ref_mv_scale)
1046
{
1047
    MotionEstContext * const c= &s->me;
1048
    int best[2]={0, 0};
1049
    int d, dmin;
1050
    int map_generation;
1051
    const int penalty_factor= c->penalty_factor;
1052 1053 1054 1055
    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;
1056
    me_cmp_func cmpf, chroma_cmpf;
1057
    LOAD_COMMON
1058
    int flags= c->flags;
1059
    LOAD_COMMON2
1060

1061 1062
    cmpf= s->dsp.me_cmp[size];
    chroma_cmpf= s->dsp.me_cmp[size+1];
1063

1064
    map_generation= update_map_generation(c);
1065 1066

    dmin = 1000000;
1067
//printf("%d %d %d %d //",xmin, ymin, xmax, ymax);
1068
    /* first line */
1069
    if (s->first_slice_line) {
1070
        CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
1071
        CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
                        (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
        if(dmin>64*2){
            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)
1082
            CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
1083 1084 1085 1086
                            (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
        }
    }
    if(dmin>64*4){
1087
        CHECK_CLIPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
1088
                        (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
1089
        if(s->mb_y+1<s->end_mb_y)  //FIXME replace at least with last_slice_line
1090
            CHECK_CLIPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
1091
                            (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
1092 1093
    }

1094
    dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
1095

Michael Niedermayer's avatar
Michael Niedermayer committed
1096
    *mx_ptr= best[0];
1097
    *my_ptr= best[1];
Michael Niedermayer's avatar
Michael Niedermayer committed
1098 1099 1100 1101

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