motion_est.c 65.9 KB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
1 2
/*
 * Motion estimation 
3
 * Copyright (c) 2000,2001 Fabrice Bellard.
4
 * Copyright (c) 2002-2004 Michael Niedermayer
Fabrice Bellard's avatar
Fabrice Bellard committed
5 6
 * 
 *
7 8 9 10
 * 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.
Fabrice Bellard's avatar
Fabrice Bellard committed
11
 *
12
 * This library is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Fabrice Bellard's avatar
Fabrice Bellard committed
16
 *
17 18 19
 * 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 21
 *
 * new Motion Estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>
Fabrice Bellard's avatar
Fabrice Bellard committed
22
 */
Michael Niedermayer's avatar
Michael Niedermayer committed
23 24 25 26 27 28
 
/**
 * @file motion_est.c
 * Motion estimation.
 */
 
Fabrice Bellard's avatar
Fabrice Bellard committed
29 30
#include <stdlib.h>
#include <stdio.h>
31
#include <limits.h>
Fabrice Bellard's avatar
Fabrice Bellard committed
32 33 34 35
#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"

36 37
//#undef NDEBUG
//#include <assert.h>
Michael Niedermayer's avatar
Michael Niedermayer committed
38

39
#define SQ(a) ((a)*(a))
40

41 42 43 44 45 46
#define P_LEFT P[1]
#define P_TOP P[2]
#define P_TOPRIGHT P[3]
#define P_MEDIAN P[4]
#define P_MV1 P[9]

Michael Niedermayer's avatar
Michael Niedermayer committed
47 48
static inline int sad_hpel_motion_search(MpegEncContext * s,
				  int *mx_ptr, int *my_ptr, int dmin,
49 50 51
                                  int pred_x, int pred_y, uint8_t *src_data[3],
                                  uint8_t *ref_data[6], int stride, int uvstride,
                                  int size, int h, uint8_t * const mv_penalty);
Michael Niedermayer's avatar
Michael Niedermayer committed
52 53 54 55 56 57 58 59 60 61 62

static inline int update_map_generation(MpegEncContext * s)
{
    s->me.map_generation+= 1<<(ME_MAP_MV_BITS*2);
    if(s->me.map_generation==0){
        s->me.map_generation= 1<<(ME_MAP_MV_BITS*2);
        memset(s->me.map, 0, sizeof(uint32_t)*ME_MAP_SIZE);
    }
    return s->me.map_generation;
}

63 64 65 66 67 68
/* shape adaptive search stuff */
typedef struct Minima{
    int height;
    int x, y;
    int checked;
}Minima;
Michael Niedermayer's avatar
Michael Niedermayer committed
69

70
static int minima_cmp(const void *a, const void *b){
71 72
    const Minima *da = (const Minima *) a;
    const Minima *db = (const Minima *) b;
73 74 75
    
    return da->height - db->height;
}
Michael Niedermayer's avatar
Michael Niedermayer committed
76 77 78 79 80
                                  
/* SIMPLE */
#define RENAME(a) simple_ ## a

#define CMP(d, x, y, size)\
81
d = cmp(s, src_y, (ref_y) + (x) + (y)*(stride), stride, h);
Michael Niedermayer's avatar
Michael Niedermayer committed
82 83 84 85

#define CMP_HPEL(d, dx, dy, x, y, size)\
{\
    const int dxy= (dx) + 2*(dy);\
86 87
    hpel_put[0][dxy](s->me.scratchpad, (ref_y) + (x) + (y)*(stride), stride, h);\
    d = cmp_sub(s, s->me.scratchpad, src_y, stride, h);\
Michael Niedermayer's avatar
Michael Niedermayer committed
88 89
}

90

Michael Niedermayer's avatar
Michael Niedermayer committed
91 92 93 94
#define CMP_QPEL(d, dx, dy, x, y, size)\
{\
    const int dxy= (dx) + 4*(dy);\
    qpel_put[0][dxy](s->me.scratchpad, (ref_y) + (x) + (y)*(stride), stride);\
95
    d = cmp_sub(s, s->me.scratchpad, src_y, stride, h);\
Michael Niedermayer's avatar
Michael Niedermayer committed
96 97 98 99 100 101 102 103 104 105 106 107 108
}

#include "motion_est_template.c"
#undef RENAME
#undef CMP
#undef CMP_HPEL
#undef CMP_QPEL
#undef INIT

/* SIMPLE CHROMA */
#define RENAME(a) simple_chroma_ ## a

#define CMP(d, x, y, size)\
109
d = cmp(s, src_y, (ref_y) + (x) + (y)*(stride), stride, h);\
Michael Niedermayer's avatar
Michael Niedermayer committed
110 111 112 113
if(chroma_cmp){\
    int dxy= ((x)&1) + 2*((y)&1);\
    int c= ((x)>>1) + ((y)>>1)*uvstride;\
\
114 115 116 117
    chroma_hpel_put[0][dxy](s->me.scratchpad, ref_u + c, uvstride, h>>1);\
    d += chroma_cmp(s, s->me.scratchpad, src_u, uvstride, h>>1);\
    chroma_hpel_put[0][dxy](s->me.scratchpad, ref_v + c, uvstride, h>>1);\
    d += chroma_cmp(s, s->me.scratchpad, src_v, uvstride, h>>1);\
Michael Niedermayer's avatar
Michael Niedermayer committed
118 119 120 121 122
}

#define CMP_HPEL(d, dx, dy, x, y, size)\
{\
    const int dxy= (dx) + 2*(dy);\
123 124
    hpel_put[0][dxy](s->me.scratchpad, (ref_y) + (x) + (y)*(stride), stride, h);\
    d = cmp_sub(s, s->me.scratchpad, src_y, stride, h);\
Michael Niedermayer's avatar
Michael Niedermayer committed
125 126 127
    if(chroma_cmp_sub){\
        int cxy= (dxy) | ((x)&1) | (2*((y)&1));\
        int c= ((x)>>1) + ((y)>>1)*uvstride;\
128 129 130 131
        chroma_hpel_put[0][cxy](s->me.scratchpad, ref_u + c, uvstride, h>>1);\
        d += chroma_cmp_sub(s, s->me.scratchpad, src_u, uvstride, h>>1);\
        chroma_hpel_put[0][cxy](s->me.scratchpad, ref_v + c, uvstride, h>>1);\
        d += chroma_cmp_sub(s, s->me.scratchpad, src_v, uvstride, h>>1);\
Michael Niedermayer's avatar
Michael Niedermayer committed
132 133 134 135 136 137 138
    }\
}

#define CMP_QPEL(d, dx, dy, x, y, size)\
{\
    const int dxy= (dx) + 4*(dy);\
    qpel_put[0][dxy](s->me.scratchpad, (ref_y) + (x) + (y)*(stride), stride);\
139
    d = cmp_sub(s, s->me.scratchpad, src_y, stride, h);\
Michael Niedermayer's avatar
Michael Niedermayer committed
140 141 142 143 144 145 146 147
    if(chroma_cmp_sub){\
        int cxy, c;\
        int cx= (4*(x) + (dx))/2;\
        int cy= (4*(y) + (dy))/2;\
        cx= (cx>>1)|(cx&1);\
        cy= (cy>>1)|(cy&1);\
        cxy= (cx&1) + 2*(cy&1);\
        c= ((cx)>>1) + ((cy)>>1)*uvstride;\
148 149 150 151
        chroma_hpel_put[0][cxy](s->me.scratchpad, ref_u + c, uvstride, h>>1);\
        d += chroma_cmp_sub(s, s->me.scratchpad, src_u, uvstride, h>>1);\
        chroma_hpel_put[0][cxy](s->me.scratchpad, ref_v + c, uvstride, h>>1);\
        d += chroma_cmp_sub(s, s->me.scratchpad, src_v, uvstride, h>>1);\
Michael Niedermayer's avatar
Michael Niedermayer committed
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
    }\
}

#include "motion_est_template.c"
#undef RENAME
#undef CMP
#undef CMP_HPEL
#undef CMP_QPEL
#undef INIT

/* SIMPLE DIRECT HPEL */
#define RENAME(a) simple_direct_hpel_ ## a
//FIXME precalc divisions stuff

#define CMP_DIRECT(d, dx, dy, x, y, size, cmp_func)\
if((x) >= xmin && 2*(x) + (dx) <= 2*xmax && (y) >= ymin && 2*(y) + (dy) <= 2*ymax){\
    const int hx= 2*(x) + (dx);\
    const int hy= 2*(y) + (dy);\
    if(s->mv_type==MV_TYPE_8X8){\
        int i;\
        for(i=0; i<4; i++){\
            int fx = s->me.direct_basis_mv[i][0] + hx;\
            int fy = s->me.direct_basis_mv[i][1] + hy;\
            int bx = hx ? fx - s->me.co_located_mv[i][0] : s->me.co_located_mv[i][0]*(time_pb - time_pp)/time_pp + (i &1)*16;\
            int by = hy ? fy - s->me.co_located_mv[i][1] : s->me.co_located_mv[i][1]*(time_pb - time_pp)/time_pp + (i>>1)*16;\
            int fxy= (fx&1) + 2*(fy&1);\
            int bxy= (bx&1) + 2*(by&1);\
\
            uint8_t *dst= s->me.scratchpad + 8*(i&1) + 8*stride*(i>>1);\
            hpel_put[1][fxy](dst, (ref_y ) + (fx>>1) + (fy>>1)*(stride), stride, 8);\
182
            hpel_avg[1][bxy](dst, (ref_data[3]) + (bx>>1) + (by>>1)*(stride), stride, 8);\
Michael Niedermayer's avatar
Michael Niedermayer committed
183 184 185 186
        }\
    }else{\
        int fx = s->me.direct_basis_mv[0][0] + hx;\
        int fy = s->me.direct_basis_mv[0][1] + hy;\
187 188
        int bx = hx ? fx - s->me.co_located_mv[0][0] : (s->me.co_located_mv[0][0]*(time_pb - time_pp)/time_pp);\
        int by = hy ? fy - s->me.co_located_mv[0][1] : (s->me.co_located_mv[0][1]*(time_pb - time_pp)/time_pp);\
Michael Niedermayer's avatar
Michael Niedermayer committed
189 190
        int fxy= (fx&1) + 2*(fy&1);\
        int bxy= (bx&1) + 2*(by&1);\
191 192 193 194 195 196 197 198 199
        \
        assert((fx>>1) + 16*s->mb_x >= -16);\
        assert((fy>>1) + 16*s->mb_y >= -16);\
        assert((fx>>1) + 16*s->mb_x <= s->width);\
        assert((fy>>1) + 16*s->mb_y <= s->height);\
        assert((bx>>1) + 16*s->mb_x >= -16);\
        assert((by>>1) + 16*s->mb_y >= -16);\
        assert((bx>>1) + 16*s->mb_x <= s->width);\
        assert((by>>1) + 16*s->mb_y <= s->height);\
Michael Niedermayer's avatar
Michael Niedermayer committed
200 201
\
        hpel_put[0][fxy](s->me.scratchpad, (ref_y ) + (fx>>1) + (fy>>1)*(stride), stride, 16);\
202
        hpel_avg[0][bxy](s->me.scratchpad, (ref_data[3]) + (bx>>1) + (by>>1)*(stride), stride, 16);\
Michael Niedermayer's avatar
Michael Niedermayer committed
203
    }\
204
    d = cmp_func(s, s->me.scratchpad, src_y, stride, 16);\
Michael Niedermayer's avatar
Michael Niedermayer committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
}else\
    d= 256*256*256*32;


#define CMP_HPEL(d, dx, dy, x, y, size)\
    CMP_DIRECT(d, dx, dy, x, y, size, cmp_sub)

#define CMP(d, x, y, size)\
    CMP_DIRECT(d, 0, 0, x, y, size, cmp)
    
#include "motion_est_template.c"
#undef RENAME
#undef CMP
#undef CMP_HPEL
#undef CMP_QPEL
#undef INIT
#undef CMP_DIRECT

/* SIMPLE DIRECT QPEL */
#define RENAME(a) simple_direct_qpel_ ## a

#define CMP_DIRECT(d, dx, dy, x, y, size, cmp_func)\
if((x) >= xmin && 4*(x) + (dx) <= 4*xmax && (y) >= ymin && 4*(y) + (dy) <= 4*ymax){\
    const int qx= 4*(x) + (dx);\
    const int qy= 4*(y) + (dy);\
    if(s->mv_type==MV_TYPE_8X8){\
        int i;\
        for(i=0; i<4; i++){\
            int fx = s->me.direct_basis_mv[i][0] + qx;\
            int fy = s->me.direct_basis_mv[i][1] + qy;\
            int bx = qx ? fx - s->me.co_located_mv[i][0] : s->me.co_located_mv[i][0]*(time_pb - time_pp)/time_pp + (i &1)*16;\
            int by = qy ? fy - s->me.co_located_mv[i][1] : s->me.co_located_mv[i][1]*(time_pb - time_pp)/time_pp + (i>>1)*16;\
            int fxy= (fx&3) + 4*(fy&3);\
            int bxy= (bx&3) + 4*(by&3);\
\
            uint8_t *dst= s->me.scratchpad + 8*(i&1) + 8*stride*(i>>1);\
            qpel_put[1][fxy](dst, (ref_y ) + (fx>>2) + (fy>>2)*(stride), stride);\
242
            qpel_avg[1][bxy](dst, (ref_data[3]) + (bx>>2) + (by>>2)*(stride), stride);\
Michael Niedermayer's avatar
Michael Niedermayer committed
243 244 245 246 247 248 249 250 251
        }\
    }else{\
        int fx = s->me.direct_basis_mv[0][0] + qx;\
        int fy = s->me.direct_basis_mv[0][1] + qy;\
        int bx = qx ? fx - s->me.co_located_mv[0][0] : s->me.co_located_mv[0][0]*(time_pb - time_pp)/time_pp;\
        int by = qy ? fy - s->me.co_located_mv[0][1] : s->me.co_located_mv[0][1]*(time_pb - time_pp)/time_pp;\
        int fxy= (fx&3) + 4*(fy&3);\
        int bxy= (bx&3) + 4*(by&3);\
\
252 253 254 255
        qpel_put[1][fxy](s->me.scratchpad               , (ref_y ) + (fx>>2) + (fy>>2)*(stride)               , stride);\
        qpel_put[1][fxy](s->me.scratchpad + 8           , (ref_y ) + (fx>>2) + (fy>>2)*(stride) + 8           , stride);\
        qpel_put[1][fxy](s->me.scratchpad     + 8*stride, (ref_y ) + (fx>>2) + (fy>>2)*(stride)     + 8*stride, stride);\
        qpel_put[1][fxy](s->me.scratchpad + 8 + 8*stride, (ref_y ) + (fx>>2) + (fy>>2)*(stride) + 8 + 8*stride, stride);\
256 257 258 259
        qpel_avg[1][bxy](s->me.scratchpad               , (ref_data[3]) + (bx>>2) + (by>>2)*(stride)               , stride);\
        qpel_avg[1][bxy](s->me.scratchpad + 8           , (ref_data[3]) + (bx>>2) + (by>>2)*(stride) + 8           , stride);\
        qpel_avg[1][bxy](s->me.scratchpad     + 8*stride, (ref_data[3]) + (bx>>2) + (by>>2)*(stride)     + 8*stride, stride);\
        qpel_avg[1][bxy](s->me.scratchpad + 8 + 8*stride, (ref_data[3]) + (bx>>2) + (by>>2)*(stride) + 8 + 8*stride, stride);\
Michael Niedermayer's avatar
Michael Niedermayer committed
260
    }\
261
    d = cmp_func(s, s->me.scratchpad, src_y, stride, 16);\
Michael Niedermayer's avatar
Michael Niedermayer committed
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
}else\
    d= 256*256*256*32;


#define CMP_QPEL(d, dx, dy, x, y, size)\
    CMP_DIRECT(d, dx, dy, x, y, size, cmp_sub)

#define CMP(d, x, y, size)\
    CMP_DIRECT(d, 0, 0, x, y, size, cmp)

#include "motion_est_template.c"
#undef RENAME
#undef CMP
#undef CMP_HPEL
#undef CMP_QPEL
#undef INIT
#undef CMP__DIRECT

static inline int get_penalty_factor(MpegEncContext *s, int type){
281
    switch(type&0xFF){
Michael Niedermayer's avatar
Michael Niedermayer committed
282 283
    default:
    case FF_CMP_SAD:
284
        return s->qscale*2;
Michael Niedermayer's avatar
Michael Niedermayer committed
285
    case FF_CMP_DCT:
286
        return s->qscale*3;
Michael Niedermayer's avatar
Michael Niedermayer committed
287
    case FF_CMP_SATD:
288
        return s->qscale*6;
289
    case FF_CMP_SSE:
290
        return s->qscale*s->qscale*2;
291 292 293
    case FF_CMP_BIT:
        return 1;
    case FF_CMP_RD:
294 295
    case FF_CMP_PSNR:
        return (s->qscale*s->qscale*185 + 64)>>7;
Michael Niedermayer's avatar
Michael Niedermayer committed
296 297 298 299
    }
}

void ff_init_me(MpegEncContext *s){
300 301 302 303
    ff_set_cmp(&s->dsp, s->dsp.me_pre_cmp, s->avctx->me_pre_cmp);
    ff_set_cmp(&s->dsp, s->dsp.me_cmp, s->avctx->me_cmp);
    ff_set_cmp(&s->dsp, s->dsp.me_sub_cmp, s->avctx->me_sub_cmp);
    ff_set_cmp(&s->dsp, s->dsp.mb_cmp, s->avctx->mb_cmp);
Fabrice Bellard's avatar
Fabrice Bellard committed
304

Michael Niedermayer's avatar
Michael Niedermayer committed
305 306 307 308 309 310 311 312
    if(s->flags&CODEC_FLAG_QPEL){
        if(s->avctx->me_sub_cmp&FF_CMP_CHROMA)
            s->me.sub_motion_search= simple_chroma_qpel_motion_search;
        else
            s->me.sub_motion_search= simple_qpel_motion_search;
    }else{
        if(s->avctx->me_sub_cmp&FF_CMP_CHROMA)
            s->me.sub_motion_search= simple_chroma_hpel_motion_search;
313 314 315
        else if(   s->avctx->me_sub_cmp == FF_CMP_SAD 
                && s->avctx->    me_cmp == FF_CMP_SAD 
                && s->avctx->    mb_cmp == FF_CMP_SAD)
316
            s->me.sub_motion_search= sad_hpel_motion_search; // 2050 vs. 2450 cycles
Michael Niedermayer's avatar
Michael Niedermayer committed
317 318 319 320 321 322 323
        else
            s->me.sub_motion_search= simple_hpel_motion_search;
    }

    if(s->avctx->me_cmp&FF_CMP_CHROMA){
        s->me.motion_search[0]= simple_chroma_epzs_motion_search;
        s->me.motion_search[1]= simple_chroma_epzs_motion_search4;
324
        s->me.motion_search[4]= simple_chroma_epzs_motion_search2;
Michael Niedermayer's avatar
Michael Niedermayer committed
325 326 327
    }else{
        s->me.motion_search[0]= simple_epzs_motion_search;
        s->me.motion_search[1]= simple_epzs_motion_search4;
328
        s->me.motion_search[4]= simple_epzs_motion_search2;
Michael Niedermayer's avatar
Michael Niedermayer committed
329
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
330 331 332 333 334 335
    
    if(s->avctx->me_pre_cmp&FF_CMP_CHROMA){
        s->me.pre_motion_search= simple_chroma_epzs_motion_search;
    }else{
        s->me.pre_motion_search= simple_epzs_motion_search;
    }
336 337 338 339 340 341 342 343 344 345 346 347
    
    if(s->flags&CODEC_FLAG_QPEL){
        if(s->avctx->mb_cmp&FF_CMP_CHROMA)
            s->me.get_mb_score= simple_chroma_qpel_get_mb_score;
        else
            s->me.get_mb_score= simple_qpel_get_mb_score;
    }else{
        if(s->avctx->mb_cmp&FF_CMP_CHROMA)
            s->me.get_mb_score= simple_chroma_hpel_get_mb_score;
        else
            s->me.get_mb_score= simple_hpel_get_mb_score;
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
348 349
}
      
350
#if 0
351
static int pix_dev(uint8_t * pix, int line_size, int mean)
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
{
    int s, i, j;

    s = 0;
    for (i = 0; i < 16; i++) {
	for (j = 0; j < 16; j += 8) {
	    s += ABS(pix[0]-mean);
	    s += ABS(pix[1]-mean);
	    s += ABS(pix[2]-mean);
	    s += ABS(pix[3]-mean);
	    s += ABS(pix[4]-mean);
	    s += ABS(pix[5]-mean);
	    s += ABS(pix[6]-mean);
	    s += ABS(pix[7]-mean);
	    pix += 8;
	}
	pix += line_size - 16;
    }
    return s;
}
372
#endif
373

374 375
static inline void no_motion_search(MpegEncContext * s,
				    int *mx_ptr, int *my_ptr)
Fabrice Bellard's avatar
Fabrice Bellard committed
376 377 378 379 380 381 382
{
    *mx_ptr = 16 * s->mb_x;
    *my_ptr = 16 * s->mb_y;
}

static int full_motion_search(MpegEncContext * s,
                              int *mx_ptr, int *my_ptr, int range,
383
                              int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
Fabrice Bellard's avatar
Fabrice Bellard committed
384 385 386
{
    int x1, y1, x2, y2, xx, yy, x, y;
    int mx, my, dmin, d;
387
    uint8_t *pix;
Fabrice Bellard's avatar
Fabrice Bellard committed
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402

    xx = 16 * s->mb_x;
    yy = 16 * s->mb_y;
    x1 = xx - range + 1;	/* we loose one pixel to avoid boundary pb with half pixel pred */
    if (x1 < xmin)
	x1 = xmin;
    x2 = xx + range - 1;
    if (x2 > xmax)
	x2 = xmax;
    y1 = yy - range + 1;
    if (y1 < ymin)
	y1 = ymin;
    y2 = yy + range - 1;
    if (y2 > ymax)
	y2 = ymax;
Michael Niedermayer's avatar
Michael Niedermayer committed
403
    pix = s->new_picture.data[0] + (yy * s->linesize) + xx;
Fabrice Bellard's avatar
Fabrice Bellard committed
404 405 406 407 408
    dmin = 0x7fffffff;
    mx = 0;
    my = 0;
    for (y = y1; y <= y2; y++) {
	for (x = x1; x <= x2; x++) {
409 410
	    d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x,
			     s->linesize, 16);
Fabrice Bellard's avatar
Fabrice Bellard committed
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
	    if (d < dmin ||
		(d == dmin &&
		 (abs(x - xx) + abs(y - yy)) <
		 (abs(mx - xx) + abs(my - yy)))) {
		dmin = d;
		mx = x;
		my = y;
	    }
	}
    }

    *mx_ptr = mx;
    *my_ptr = my;

#if 0
    if (*mx_ptr < -(2 * range) || *mx_ptr >= (2 * range) ||
	*my_ptr < -(2 * range) || *my_ptr >= (2 * range)) {
	fprintf(stderr, "error %d %d\n", *mx_ptr, *my_ptr);
    }
#endif
    return dmin;
}


static int log_motion_search(MpegEncContext * s,
                             int *mx_ptr, int *my_ptr, int range,
437
                             int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
Fabrice Bellard's avatar
Fabrice Bellard committed
438 439 440
{
    int x1, y1, x2, y2, xx, yy, x, y;
    int mx, my, dmin, d;
441
    uint8_t *pix;
Fabrice Bellard's avatar
Fabrice Bellard committed
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465

    xx = s->mb_x << 4;
    yy = s->mb_y << 4;

    /* Left limit */
    x1 = xx - range;
    if (x1 < xmin)
	x1 = xmin;

    /* Right limit */
    x2 = xx + range;
    if (x2 > xmax)
	x2 = xmax;

    /* Upper limit */
    y1 = yy - range;
    if (y1 < ymin)
	y1 = ymin;

    /* Lower limit */
    y2 = yy + range;
    if (y2 > ymax)
	y2 = ymax;

Michael Niedermayer's avatar
Michael Niedermayer committed
466
    pix = s->new_picture.data[0] + (yy * s->linesize) + xx;
Fabrice Bellard's avatar
Fabrice Bellard committed
467 468 469 470 471 472 473
    dmin = 0x7fffffff;
    mx = 0;
    my = 0;

    do {
	for (y = y1; y <= y2; y += range) {
	    for (x = x1; x <= x2; x += range) {
474
		d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x, s->linesize, 16);
Fabrice Bellard's avatar
Fabrice Bellard committed
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 501 502 503 504 505 506 507 508 509 510 511 512
		if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
		    dmin = d;
		    mx = x;
		    my = y;
		}
	    }
	}

	range = range >> 1;

	x1 = mx - range;
	if (x1 < xmin)
	    x1 = xmin;

	x2 = mx + range;
	if (x2 > xmax)
	    x2 = xmax;

	y1 = my - range;
	if (y1 < ymin)
	    y1 = ymin;

	y2 = my + range;
	if (y2 > ymax)
	    y2 = ymax;

    } while (range >= 1);

#ifdef DEBUG
    fprintf(stderr, "log       - MX: %d\tMY: %d\n", mx, my);
#endif
    *mx_ptr = mx;
    *my_ptr = my;
    return dmin;
}

static int phods_motion_search(MpegEncContext * s,
                               int *mx_ptr, int *my_ptr, int range,
513
                               int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
Fabrice Bellard's avatar
Fabrice Bellard committed
514 515 516
{
    int x1, y1, x2, y2, xx, yy, x, y, lastx, d;
    int mx, my, dminx, dminy;
517
    uint8_t *pix;
Fabrice Bellard's avatar
Fabrice Bellard committed
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541

    xx = s->mb_x << 4;
    yy = s->mb_y << 4;

    /* Left limit */
    x1 = xx - range;
    if (x1 < xmin)
	x1 = xmin;

    /* Right limit */
    x2 = xx + range;
    if (x2 > xmax)
	x2 = xmax;

    /* Upper limit */
    y1 = yy - range;
    if (y1 < ymin)
	y1 = ymin;

    /* Lower limit */
    y2 = yy + range;
    if (y2 > ymax)
	y2 = ymax;

Michael Niedermayer's avatar
Michael Niedermayer committed
542
    pix = s->new_picture.data[0] + (yy * s->linesize) + xx;
Fabrice Bellard's avatar
Fabrice Bellard committed
543 544 545 546 547 548 549 550 551 552 553
    mx = 0;
    my = 0;

    x = xx;
    y = yy;
    do {
        dminx = 0x7fffffff;
        dminy = 0x7fffffff;

	lastx = x;
	for (x = x1; x <= x2; x += range) {
554
	    d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x, s->linesize, 16);
Fabrice Bellard's avatar
Fabrice Bellard committed
555 556 557 558 559 560 561 562
	    if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
		dminx = d;
		mx = x;
	    }
	}

	x = lastx;
	for (y = y1; y <= y2; y += range) {
563
	    d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x, s->linesize, 16);
Fabrice Bellard's avatar
Fabrice Bellard committed
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
	    if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
		dminy = d;
		my = y;
	    }
	}

	range = range >> 1;

	x = mx;
	y = my;
	x1 = mx - range;
	if (x1 < xmin)
	    x1 = xmin;

	x2 = mx + range;
	if (x2 > xmax)
	    x2 = xmax;

	y1 = my - range;
	if (y1 < ymin)
	    y1 = ymin;

	y2 = my + range;
	if (y2 > ymax)
	    y2 = ymax;

    } while (range >= 1);

#ifdef DEBUG
    fprintf(stderr, "phods     - MX: %d\tMY: %d\n", mx, my);
#endif

    /* half pixel search */
    *mx_ptr = mx;
    *my_ptr = my;
    return dminy;
}

602 603 604

#define Z_THRESHOLD 256

Michael Niedermayer's avatar
Michael Niedermayer committed
605
#define CHECK_SAD_HALF_MV(suffix, x, y) \
606
{\
607
    d= s->dsp.pix_abs[size][(x?1:0)+(y?2:0)](NULL, pix, ptr+((x)>>1), stride, h);\
Michael Niedermayer's avatar
Michael Niedermayer committed
608
    d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*penalty_factor;\
609 610
    COPY3_IF_LT(dminh, d, dx, x, dy, y)\
}
611

Michael Niedermayer's avatar
Michael Niedermayer committed
612
static inline int sad_hpel_motion_search(MpegEncContext * s,
Fabrice Bellard's avatar
Fabrice Bellard committed
613
				  int *mx_ptr, int *my_ptr, int dmin,
614 615 616
                                  int pred_x, int pred_y, uint8_t *src_data[3],
                                  uint8_t *ref_data[6], int stride, int uvstride,                                  
                                  int size, int h, uint8_t * const mv_penalty)
Fabrice Bellard's avatar
Fabrice Bellard committed
617
{
Michael Niedermayer's avatar
Michael Niedermayer committed
618 619
    uint32_t *score_map= s->me.score_map;
    const int penalty_factor= s->me.sub_penalty_factor;
620
    int mx, my, dminh;
621
    uint8_t *pix, *ptr;
622 623 624 625
    const int xmin= s->me.xmin;
    const int ymin= s->me.ymin;
    const int xmax= s->me.xmax;
    const int ymax= s->me.ymax;
Fabrice Bellard's avatar
Fabrice Bellard committed
626

Michael Niedermayer's avatar
Michael Niedermayer committed
627
    if(s->me.skip){
628 629 630 631 632 633 634
//    printf("S");
        *mx_ptr = 0;
        *my_ptr = 0;
        return dmin;
    }
//    printf("N");
        
635
    pix = src_data[0];
636

637 638
    mx = *mx_ptr;
    my = *my_ptr;
639
    ptr = ref_data[0] + (my * stride) + mx;
640
    
641 642 643 644
    dminh = dmin;

    if (mx > xmin && mx < xmax && 
        my > ymin && my < ymax) {
645 646 647 648 649 650 651 652 653
        int dx=0, dy=0;
        int d, pen_x, pen_y; 
        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)];
        mx<<=1;
        my<<=1;
654 655 656 657 658

        
        pen_x= pred_x + mx;
        pen_y= pred_y + my;

659
        ptr-= stride;
660
        if(t<=b){
Michael Niedermayer's avatar
Michael Niedermayer committed
661
            CHECK_SAD_HALF_MV(y2 , 0, -1)
662
            if(l<=r){
Michael Niedermayer's avatar
Michael Niedermayer committed
663
                CHECK_SAD_HALF_MV(xy2, -1, -1)
664
                if(t+r<=b+l){
Michael Niedermayer's avatar
Michael Niedermayer committed
665
                    CHECK_SAD_HALF_MV(xy2, +1, -1)
666
                    ptr+= stride;
667
                }else{
668
                    ptr+= stride;
Michael Niedermayer's avatar
Michael Niedermayer committed
669
                    CHECK_SAD_HALF_MV(xy2, -1, +1)
670
                }
Michael Niedermayer's avatar
Michael Niedermayer committed
671
                CHECK_SAD_HALF_MV(x2 , -1,  0)
672
            }else{
Michael Niedermayer's avatar
Michael Niedermayer committed
673
                CHECK_SAD_HALF_MV(xy2, +1, -1)
674
                if(t+l<=b+r){
Michael Niedermayer's avatar
Michael Niedermayer committed
675
                    CHECK_SAD_HALF_MV(xy2, -1, -1)
676
                    ptr+= stride;
677
                }else{
678
                    ptr+= stride;
Michael Niedermayer's avatar
Michael Niedermayer committed
679
                    CHECK_SAD_HALF_MV(xy2, +1, +1)
680
                }
Michael Niedermayer's avatar
Michael Niedermayer committed
681
                CHECK_SAD_HALF_MV(x2 , +1,  0)
682 683 684 685
            }
        }else{
            if(l<=r){
                if(t+l<=b+r){
Michael Niedermayer's avatar
Michael Niedermayer committed
686
                    CHECK_SAD_HALF_MV(xy2, -1, -1)
687
                    ptr+= stride;
688
                }else{
689
                    ptr+= stride;
Michael Niedermayer's avatar
Michael Niedermayer committed
690
                    CHECK_SAD_HALF_MV(xy2, +1, +1)
691
                }
Michael Niedermayer's avatar
Michael Niedermayer committed
692 693
                CHECK_SAD_HALF_MV(x2 , -1,  0)
                CHECK_SAD_HALF_MV(xy2, -1, +1)
694 695
            }else{
                if(t+r<=b+l){
Michael Niedermayer's avatar
Michael Niedermayer committed
696
                    CHECK_SAD_HALF_MV(xy2, +1, -1)
697
                    ptr+= stride;
698
                }else{
699
                    ptr+= stride;
Michael Niedermayer's avatar
Michael Niedermayer committed
700
                    CHECK_SAD_HALF_MV(xy2, -1, +1)
701
                }
Michael Niedermayer's avatar
Michael Niedermayer committed
702 703
                CHECK_SAD_HALF_MV(x2 , +1,  0)
                CHECK_SAD_HALF_MV(xy2, +1, +1)
704
            }
Michael Niedermayer's avatar
Michael Niedermayer committed
705
            CHECK_SAD_HALF_MV(y2 ,  0, +1)
706 707 708
        }
        mx+=dx;
        my+=dy;
709 710

    }else{
711 712
        mx<<=1;
        my<<=1;
713 714 715 716
    }

    *mx_ptr = mx;
    *my_ptr = my;
717
    return dminh;
718 719
}

720
static inline void set_p_mv_tables(MpegEncContext * s, int mx, int my, int mv4)
721
{
722
    const int xy= s->mb_x + s->mb_y*s->mb_stride;
723
    
724 725
    s->p_mv_table[xy][0] = mx;
    s->p_mv_table[xy][1] = my;
726 727

    /* has allready been set to the 4 MV if 4MV is done */
728
    if(mv4){
729 730
        int mot_xy= s->block_index[0];

731 732 733 734
        s->current_picture.motion_val[0][mot_xy  ][0]= mx;
        s->current_picture.motion_val[0][mot_xy  ][1]= my;
        s->current_picture.motion_val[0][mot_xy+1][0]= mx;
        s->current_picture.motion_val[0][mot_xy+1][1]= my;
735 736

        mot_xy += s->block_wrap[0];
737 738 739 740
        s->current_picture.motion_val[0][mot_xy  ][0]= mx;
        s->current_picture.motion_val[0][mot_xy  ][1]= my;
        s->current_picture.motion_val[0][mot_xy+1][0]= mx;
        s->current_picture.motion_val[0][mot_xy+1][1]= my;
741 742 743
    }
}

744 745 746
/**
 * get fullpel ME search limits.
 */
747
static inline void get_limits(MpegEncContext *s, int x, int y)
Fabrice Bellard's avatar
Fabrice Bellard committed
748
{
749 750 751 752
/*
    if(s->avctx->me_range) s->me.range= s->avctx->me_range >> 1;
    else                   s->me.range= 16;
*/
Fabrice Bellard's avatar
Fabrice Bellard committed
753
    if (s->unrestricted_mv) {
754 755 756 757
        s->me.xmin = - x - 16;
        s->me.ymin = - y - 16;
        s->me.xmax = - x + s->mb_width *16;
        s->me.ymax = - y + s->mb_height*16;
Fabrice Bellard's avatar
Fabrice Bellard committed
758
    } else {
759 760 761 762
        s->me.xmin = - x;
        s->me.ymin = - y;
        s->me.xmax = - x + s->mb_width *16 - 16;
        s->me.ymax = - y + s->mb_height*16 - 16;
Fabrice Bellard's avatar
Fabrice Bellard committed
763
    }
764 765
}

766
static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift)
767
{
768 769
    const int size= 1;
    const int h=8;
770 771
    int block;
    int P[10][2];
772
    int dmin_sum=0, mx4_sum=0, my4_sum=0;
773
    uint8_t * const mv_penalty= s->me.mv_penalty[s->f_code] + MAX_MV;
774
    int same=1;
775 776 777 778 779 780
    const int stride= s->linesize;
    const int uvstride= s->uvlinesize;
    const int xmin= s->me.xmin;
    const int ymin= s->me.ymin;
    const int xmax= s->me.xmax;
    const int ymax= s->me.ymax;
781 782 783 784 785 786 787 788

    for(block=0; block<4; block++){
        int mx4, my4;
        int pred_x4, pred_y4;
        int dmin4;
        static const int off[4]= {2, 1, 1, -1};
        const int mot_stride = s->block_wrap[0];
        const int mot_xy = s->block_index[block];
789 790 791 792 793 794 795 796 797 798 799 800 801
        const int block_x= (block&1);
        const int block_y= (block>>1);
        uint8_t *src_data[3]= {
            s->new_picture.data[0] + 8*(2*s->mb_x + block_x) + stride  *8*(2*s->mb_y + block_y), //FIXME chroma?
            s->new_picture.data[1] + 4*(2*s->mb_x + block_x) + uvstride*4*(2*s->mb_y + block_y),
            s->new_picture.data[2] + 4*(2*s->mb_x + block_x) + uvstride*4*(2*s->mb_y + block_y)
        };
        uint8_t *ref_data[3]= {
            s->last_picture.data[0] + 8*(2*s->mb_x + block_x) + stride  *8*(2*s->mb_y + block_y), //FIXME chroma?
            s->last_picture.data[1] + 4*(2*s->mb_x + block_x) + uvstride*4*(2*s->mb_y + block_y),
            s->last_picture.data[2] + 4*(2*s->mb_x + block_x) + uvstride*4*(2*s->mb_y + block_y)
        };

802 803
        P_LEFT[0] = s->current_picture.motion_val[0][mot_xy - 1][0];
        P_LEFT[1] = s->current_picture.motion_val[0][mot_xy - 1][1];
804

805
        if(P_LEFT[0]       > (s->me.xmax<<shift)) P_LEFT[0]       = (s->me.xmax<<shift);
806 807

        /* special case for first line */
808
        if (s->mb_y == 0 && block<2) {
809 810 811
            pred_x4= P_LEFT[0];
            pred_y4= P_LEFT[1];
        } else {
812 813 814 815
            P_TOP[0]      = s->current_picture.motion_val[0][mot_xy - mot_stride             ][0];
            P_TOP[1]      = s->current_picture.motion_val[0][mot_xy - mot_stride             ][1];
            P_TOPRIGHT[0] = s->current_picture.motion_val[0][mot_xy - mot_stride + off[block]][0];
            P_TOPRIGHT[1] = s->current_picture.motion_val[0][mot_xy - mot_stride + off[block]][1];
816 817 818 819
            if(P_TOP[1]      > (s->me.ymax<<shift)) P_TOP[1]     = (s->me.ymax<<shift);
            if(P_TOPRIGHT[0] < (s->me.xmin<<shift)) P_TOPRIGHT[0]= (s->me.xmin<<shift);
            if(P_TOPRIGHT[0] > (s->me.xmax<<shift)) P_TOPRIGHT[0]= (s->me.xmax<<shift);
            if(P_TOPRIGHT[1] > (s->me.ymax<<shift)) P_TOPRIGHT[1]= (s->me.ymax<<shift);
820 821 822 823
    
            P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
            P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);

824
//            if(s->out_format == FMT_H263){
825 826
                pred_x4 = P_MEDIAN[0];
                pred_y4 = P_MEDIAN[1];
827
#if 0
828 829 830 831
            }else { /* mpeg1 at least */
                pred_x4= P_LEFT[0];
                pred_y4= P_LEFT[1];
            }
832
#endif
833 834 835 836
        }
        P_MV1[0]= mx;
        P_MV1[1]= my;

837 838
        dmin4 = s->me.motion_search[1](s, &mx4, &my4, P, pred_x4, pred_y4, 
                                       src_data, ref_data, stride, uvstride, s->p_mv_table, (1<<16)>>shift, mv_penalty);
839

840 841
        dmin4= s->me.sub_motion_search(s, &mx4, &my4, dmin4, 
					  pred_x4, pred_y4, src_data, ref_data, stride, uvstride, size, h, mv_penalty);
842
        
843 844
        if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]
           && s->avctx->mb_decision == FF_MB_DECISION_SIMPLE){
845
            int dxy;
846
            const int offset= ((block&1) + (block>>1)*stride)*8;
847 848 849
            uint8_t *dest_y = s->me.scratchpad + offset;

            if(s->quarter_sample){
850
                uint8_t *ref= ref_data[0] + (mx4>>2) + (my4>>2)*stride;
851 852 853
                dxy = ((my4 & 3) << 2) | (mx4 & 3);

                if(s->no_rounding)
854
                    s->dsp.put_no_rnd_qpel_pixels_tab[1][dxy](dest_y   , ref    , s->linesize);
855
                else
856
                    s->dsp.put_qpel_pixels_tab       [1][dxy](dest_y   , ref    , stride);
857
            }else{
858
                uint8_t *ref= ref_data[0] + (mx4>>1) + (my4>>1)*stride;
859 860 861
                dxy = ((my4 & 1) << 1) | (mx4 & 1);

                if(s->no_rounding)
862
                    s->dsp.put_no_rnd_pixels_tab[1][dxy](dest_y    , ref    , stride, h);
863
                else
864
                    s->dsp.put_pixels_tab       [1][dxy](dest_y    , ref    , stride, h);
865 866 867 868 869 870 871 872 873 874 875 876 877
            }
            dmin_sum+= (mv_penalty[mx4-pred_x4] + mv_penalty[my4-pred_y4])*s->me.mb_penalty_factor;
        }else
            dmin_sum+= dmin4;

        if(s->quarter_sample){
            mx4_sum+= mx4/2;
            my4_sum+= my4/2;
        }else{
            mx4_sum+= mx4;
            my4_sum+= my4;
        }
            
878 879
        s->current_picture.motion_val[0][ s->block_index[block] ][0]= mx4;
        s->current_picture.motion_val[0][ s->block_index[block] ][1]= my4;
880 881

        if(mx4 != mx || my4 != my) same=0;
882
    }
883
    
884 885 886
    if(same)
        return INT_MAX;
    
887
    if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){
888
        dmin_sum += s->dsp.mb_cmp[0](s, s->new_picture.data[0] + s->mb_x*16 + s->mb_y*16*stride, s->me.scratchpad, stride, 16);
889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
    }
    
    if(s->avctx->mb_cmp&FF_CMP_CHROMA){
        int dxy;
        int mx, my;
        int offset;

        mx= ff_h263_round_chroma(mx4_sum);
        my= ff_h263_round_chroma(my4_sum);
        dxy = ((my & 1) << 1) | (mx & 1);
        
        offset= (s->mb_x*8 + (mx>>1)) + (s->mb_y*8 + (my>>1))*s->uvlinesize;
       
        if(s->no_rounding){
            s->dsp.put_no_rnd_pixels_tab[1][dxy](s->me.scratchpad    , s->last_picture.data[1] + offset, s->uvlinesize, 8);
            s->dsp.put_no_rnd_pixels_tab[1][dxy](s->me.scratchpad+8  , s->last_picture.data[2] + offset, s->uvlinesize, 8);
        }else{
            s->dsp.put_pixels_tab       [1][dxy](s->me.scratchpad    , s->last_picture.data[1] + offset, s->uvlinesize, 8);
            s->dsp.put_pixels_tab       [1][dxy](s->me.scratchpad+8  , s->last_picture.data[2] + offset, s->uvlinesize, 8);
        }

910 911
        dmin_sum += s->dsp.mb_cmp[1](s, s->new_picture.data[1] + s->mb_x*8 + s->mb_y*8*s->uvlinesize, s->me.scratchpad  , s->uvlinesize, 8);
        dmin_sum += s->dsp.mb_cmp[1](s, s->new_picture.data[2] + s->mb_x*8 + s->mb_y*8*s->uvlinesize, s->me.scratchpad+8, s->uvlinesize, 8);
912 913 914 915 916 917 918 919 920 921
    }

    switch(s->avctx->mb_cmp&0xFF){
    /*case FF_CMP_SSE:
        return dmin_sum+ 32*s->qscale*s->qscale;*/
    case FF_CMP_RD:
        return dmin_sum;
    default:
        return dmin_sum+ 11*s->me.mb_penalty_factor;
    }
922 923
}

924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993
static int interlaced_search(MpegEncContext *s, uint8_t *frame_src_data[3], uint8_t *frame_ref_data[3], 
                             int16_t (*mv_tables[2][2])[2], uint8_t *field_select_tables[2], int f_code, int mx, int my)
{
    const int size=0;
    const int h=8;
    int block;
    int P[10][2];
    uint8_t * const mv_penalty= s->me.mv_penalty[f_code] + MAX_MV;
    int same=1;
    const int stride= 2*s->linesize;
    const int uvstride= 2*s->uvlinesize;
    int dmin_sum= 0;
    const int mot_stride= s->mb_stride;
    const int xy= s->mb_x + s->mb_y*mot_stride;
    
    s->me.ymin>>=1;
    s->me.ymax>>=1;
    
    for(block=0; block<2; block++){
        int field_select;
        int best_dmin= INT_MAX;
        int best_field= -1;

        uint8_t *src_data[3]= {
            frame_src_data[0] + s->  linesize*block,
            frame_src_data[1] + s->uvlinesize*block,
            frame_src_data[2] + s->uvlinesize*block
        };

        for(field_select=0; field_select<2; field_select++){
            int dmin, mx_i, my_i, pred_x, pred_y;
            uint8_t *ref_data[3]= {
                frame_ref_data[0] + s->  linesize*field_select,
                frame_ref_data[1] + s->uvlinesize*field_select,
                frame_ref_data[2] + s->uvlinesize*field_select
            };
            int16_t (*mv_table)[2]= mv_tables[block][field_select];
            
            P_LEFT[0] = mv_table[xy - 1][0];
            P_LEFT[1] = mv_table[xy - 1][1];
            if(P_LEFT[0]       > (s->me.xmax<<1)) P_LEFT[0]       = (s->me.xmax<<1);
            
            pred_x= P_LEFT[0];
            pred_y= P_LEFT[1];
            
            if(s->mb_y){
                P_TOP[0]      = mv_table[xy - mot_stride][0];
                P_TOP[1]      = mv_table[xy - mot_stride][1];
                P_TOPRIGHT[0] = mv_table[xy - mot_stride + 1][0];
                P_TOPRIGHT[1] = mv_table[xy - mot_stride + 1][1];
                if(P_TOP[1]      > (s->me.ymax<<1)) P_TOP[1]     = (s->me.ymax<<1);
                if(P_TOPRIGHT[0] < (s->me.xmin<<1)) P_TOPRIGHT[0]= (s->me.xmin<<1);
                if(P_TOPRIGHT[0] > (s->me.xmax<<1)) P_TOPRIGHT[0]= (s->me.xmax<<1);
                if(P_TOPRIGHT[1] > (s->me.ymax<<1)) P_TOPRIGHT[1]= (s->me.ymax<<1);
    
                P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
                P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
            }
            P_MV1[0]= mx; //FIXME not correct if block != field_select
            P_MV1[1]= my / 2;
            
            dmin = s->me.motion_search[4](s, &mx_i, &my_i, P, pred_x, pred_y, 
                                           src_data, ref_data, stride, uvstride, mv_table, (1<<16)>>1, mv_penalty);

            dmin= s->me.sub_motion_search(s, &mx_i, &my_i, dmin, 
                                           pred_x, pred_y, src_data, ref_data, stride, uvstride, size, h, mv_penalty);
            
            mv_table[xy][0]= mx_i;
            mv_table[xy][1]= my_i;
            
994 995
            if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]
               && s->avctx->mb_decision == FF_MB_DECISION_SIMPLE){
996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
                int dxy;

                //FIXME chroma ME
                uint8_t *ref= ref_data[0] + (mx_i>>1) + (my_i>>1)*stride;
                dxy = ((my_i & 1) << 1) | (mx_i & 1);

                if(s->no_rounding){
                    s->dsp.put_no_rnd_pixels_tab[size][dxy](s->me.scratchpad, ref    , stride, h);
                }else{
                    s->dsp.put_pixels_tab       [size][dxy](s->me.scratchpad, ref    , stride, h);
                }
                dmin= s->dsp.mb_cmp[size](s, src_data[0], s->me.scratchpad, stride, h);
                dmin+= (mv_penalty[mx_i-pred_x] + mv_penalty[my_i-pred_y] + 1)*s->me.mb_penalty_factor;
            }else
                dmin+= s->me.mb_penalty_factor; //field_select bits
                
            dmin += field_select != block; //slightly prefer same field
            
            if(dmin < best_dmin){
                best_dmin= dmin;
                best_field= field_select;
            }
        }
        {
            int16_t (*mv_table)[2]= mv_tables[block][best_field];

            if(mv_table[xy][0] != mx) same=0; //FIXME check if these checks work and are any good at all
            if(mv_table[xy][1]&1) same=0;
            if(mv_table[xy][1]*2 != my) same=0; 
            if(best_field != block) same=0;
        }

        field_select_tables[block][xy]= best_field;
        dmin_sum += best_dmin;
    }
    
    s->me.ymin<<=1;
    s->me.ymax<<=1;

    if(same)
        return INT_MAX;
    
    switch(s->avctx->mb_cmp&0xFF){
    /*case FF_CMP_SSE:
        return dmin_sum+ 32*s->qscale*s->qscale;*/
    case FF_CMP_RD:
        return dmin_sum;
    default:
        return dmin_sum+ 11*s->me.mb_penalty_factor;
    }
}

1048 1049 1050
void ff_estimate_p_frame_motion(MpegEncContext * s,
                                int mb_x, int mb_y)
{
1051
    uint8_t *pix, *ppix;
1052
    int sum, varc, vard, mx, my, dmin, xx, yy;
1053
    int pred_x=0, pred_y=0;
1054
    int P[10][2];
1055 1056
    const int shift= 1+s->quarter_sample;
    int mb_type=0;
Michael Niedermayer's avatar
Michael Niedermayer committed
1057 1058
    uint8_t *ref_picture= s->last_picture.data[0];
    Picture * const pic= &s->current_picture;
1059
    uint8_t * const mv_penalty= s->me.mv_penalty[s->f_code] + MAX_MV;
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072
    const int stride= s->linesize;
    const int uvstride= s->uvlinesize;
    uint8_t *src_data[3]= {
        s->new_picture.data[0] + 16*(mb_x + stride*mb_y),
        s->new_picture.data[1] + 8*(mb_x + uvstride*mb_y),
        s->new_picture.data[2] + 8*(mb_x + uvstride*mb_y)
    };
    uint8_t *ref_data[3]= {
        s->last_picture.data[0] + 16*(mb_x + stride*mb_y),
        s->last_picture.data[1] + 8*(mb_x + uvstride*mb_y),
        s->last_picture.data[2] + 8*(mb_x + uvstride*mb_y)
    };

Michael Niedermayer's avatar
Michael Niedermayer committed
1073 1074 1075 1076
    assert(s->quarter_sample==0 || s->quarter_sample==1);

    s->me.penalty_factor    = get_penalty_factor(s, s->avctx->me_cmp);
    s->me.sub_penalty_factor= get_penalty_factor(s, s->avctx->me_sub_cmp);
1077
    s->me.mb_penalty_factor = get_penalty_factor(s, s->avctx->mb_cmp);
1078

1079
    get_limits(s, 16*mb_x, 16*mb_y);
Michael Niedermayer's avatar
Michael Niedermayer committed
1080
    s->me.skip=0;
1081

1082
    switch(s->me_method) {
Fabrice Bellard's avatar
Fabrice Bellard committed
1083 1084 1085
    case ME_ZERO:
    default:
	no_motion_search(s, &mx, &my);
1086 1087
        mx-= mb_x*16;
        my-= mb_y*16;
Fabrice Bellard's avatar
Fabrice Bellard committed
1088 1089
        dmin = 0;
        break;
1090
#if 0
Fabrice Bellard's avatar
Fabrice Bellard committed
1091
    case ME_FULL:
1092
	dmin = full_motion_search(s, &mx, &my, range, ref_picture);
1093 1094
        mx-= mb_x*16;
        my-= mb_y*16;
Fabrice Bellard's avatar
Fabrice Bellard committed
1095 1096
        break;
    case ME_LOG:
1097
	dmin = log_motion_search(s, &mx, &my, range / 2, ref_picture);
1098 1099
        mx-= mb_x*16;
        my-= mb_y*16;
Fabrice Bellard's avatar
Fabrice Bellard committed
1100 1101
        break;
    case ME_PHODS:
1102
	dmin = phods_motion_search(s, &mx, &my, range / 2, ref_picture);
1103 1104
        mx-= mb_x*16;
        my-= mb_y*16;
Fabrice Bellard's avatar
Fabrice Bellard committed
1105
        break;
1106
#endif
1107
    case ME_X1:
1108
    case ME_EPZS:
1109
       {
1110 1111
            const int mot_stride = s->block_wrap[0];
            const int mot_xy = s->block_index[0];
1112

1113 1114
            P_LEFT[0]       = s->current_picture.motion_val[0][mot_xy - 1][0];
            P_LEFT[1]       = s->current_picture.motion_val[0][mot_xy - 1][1];
1115

1116
            if(P_LEFT[0]       > (s->me.xmax<<shift)) P_LEFT[0]       = (s->me.xmax<<shift);
1117

1118
            if(mb_y) {
1119 1120 1121 1122
                P_TOP[0]      = s->current_picture.motion_val[0][mot_xy - mot_stride    ][0];
                P_TOP[1]      = s->current_picture.motion_val[0][mot_xy - mot_stride    ][1];
                P_TOPRIGHT[0] = s->current_picture.motion_val[0][mot_xy - mot_stride + 2][0];
                P_TOPRIGHT[1] = s->current_picture.motion_val[0][mot_xy - mot_stride + 2][1];
1123 1124 1125
                if(P_TOP[1]      > (s->me.ymax<<shift)) P_TOP[1]     = (s->me.ymax<<shift);
                if(P_TOPRIGHT[0] < (s->me.xmin<<shift)) P_TOPRIGHT[0]= (s->me.xmin<<shift);
                if(P_TOPRIGHT[1] > (s->me.ymax<<shift)) P_TOPRIGHT[1]= (s->me.ymax<<shift);
1126
        
1127 1128 1129 1130 1131 1132 1133 1134 1135 1136
                P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
                P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);

                if(s->out_format == FMT_H263){
                    pred_x = P_MEDIAN[0];
                    pred_y = P_MEDIAN[1];
                }else { /* mpeg1 at least */
                    pred_x= P_LEFT[0];
                    pred_y= P_LEFT[1];
                }
1137 1138 1139
            }else{
                pred_x= P_LEFT[0];
                pred_y= P_LEFT[1];
1140
            }
1141

1142
        }
1143 1144
        dmin = s->me.motion_search[0](s, &mx, &my, P, pred_x, pred_y, 
                                      src_data, ref_data, stride, uvstride, s->p_mv_table, (1<<16)>>shift, mv_penalty);
1145
 
1146
        break;
Fabrice Bellard's avatar
Fabrice Bellard committed
1147 1148 1149 1150 1151 1152
    }

    /* intra / predictive decision */
    xx = mb_x * 16;
    yy = mb_y * 16;

1153
    pix = src_data[0];
1154
    /* At this point (mx,my) are full-pell and the relative displacement */
1155
    ppix = ref_data[0] + (my * s->linesize) + mx;
1156
    
1157
    sum = s->dsp.pix_sum(pix, s->linesize);
1158
    
1159
    varc = (s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)(sum*sum))>>8) + 500 + 128)>>8;
1160
    vard = (s->dsp.sse[0](NULL, pix, ppix, s->linesize, 16)+128)>>8;
1161

1162
//printf("%d %d %d %X %X %X\n", s->mb_width, mb_x, mb_y,(int)s, (int)s->mb_var, (int)s->mc_mb_var); fflush(stdout);
1163 1164 1165 1166
    pic->mb_var   [s->mb_stride * mb_y + mb_x] = varc;
    pic->mc_mb_var[s->mb_stride * mb_y + mb_x] = vard;
    pic->mb_mean  [s->mb_stride * mb_y + mb_x] = (sum+128)>>8;
//    pic->mb_cmp_score[s->mb_stride * mb_y + mb_x] = dmin; 
Michael Niedermayer's avatar
Michael Niedermayer committed
1167 1168
    pic->mb_var_sum    += varc;
    pic->mc_mb_var_sum += vard;
1169
//printf("E%d %d %d %X %X %X\n", s->mb_width, mb_x, mb_y,(int)s, (int)s->mb_var, (int)s->mc_mb_var); fflush(stdout);
1170
    
Fabrice Bellard's avatar
Fabrice Bellard committed
1171
#if 0
1172 1173
    printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
	   varc, s->avg_mb_var, sum, vard, mx - xx, my - yy);
Fabrice Bellard's avatar
Fabrice Bellard committed
1174
#endif
1175
    if(s->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
1176 1177 1178
        if (vard <= 64 || vard < varc)
            s->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
        else
1179
            s->scene_change_score+= s->qscale;
1180

1181
        if (vard*2 + 200 > varc)
1182
            mb_type|= CANDIDATE_MB_TYPE_INTRA;
1183
        if (varc*2 + 200 > vard){
1184 1185 1186
            mb_type|= CANDIDATE_MB_TYPE_INTER;
            s->me.sub_motion_search(s, &mx, &my, dmin,
				   pred_x, pred_y, src_data, ref_data, stride, uvstride, 0, 16, mv_penalty);
1187 1188
            if(s->flags&CODEC_FLAG_MV0)
                if(mx || my)
1189
                    mb_type |= CANDIDATE_MB_TYPE_SKIPED; //FIXME check difference
1190
        }else{
Michael Niedermayer's avatar
Michael Niedermayer committed
1191 1192
            mx <<=shift;
            my <<=shift;
Fabrice Bellard's avatar
Fabrice Bellard committed
1193
        }
1194
        if((s->flags&CODEC_FLAG_4MV)
Michael Niedermayer's avatar
Michael Niedermayer committed
1195
           && !s->me.skip && varc>50 && vard>10){
1196 1197
            if(h263_mv4_search(s, mx, my, shift) < INT_MAX)
                mb_type|=CANDIDATE_MB_TYPE_INTER4V;
1198 1199 1200 1201

            set_p_mv_tables(s, mx, my, 0);
        }else
            set_p_mv_tables(s, mx, my, 1);
1202 1203 1204 1205 1206
        if((s->flags&CODEC_FLAG_INTERLACED_ME)
           && !s->me.skip){ //FIXME varc/d checks
            if(interlaced_search(s, src_data, ref_data, s->p_field_mv_table, s->p_field_select_table, s->f_code, mx, my) < INT_MAX)
                mb_type |= CANDIDATE_MB_TYPE_INTER_I;
        }
1207
    }else{
1208
        int intra_score, i;
1209
        mb_type= CANDIDATE_MB_TYPE_INTER;
1210

1211 1212
        dmin= s->me.sub_motion_search(s, &mx, &my, dmin,
                                    pred_x, pred_y, src_data, ref_data, stride, uvstride, 0, 16, mv_penalty);
1213
        if(s->avctx->me_sub_cmp != s->avctx->mb_cmp && !s->me.skip)
1214
            dmin= s->me.get_mb_score(s, mx, my, pred_x, pred_y, src_data, ref_data, stride, uvstride, mv_penalty);
1215 1216 1217

        if((s->flags&CODEC_FLAG_4MV)
           && !s->me.skip && varc>50 && vard>10){
1218
            int dmin4= h263_mv4_search(s, mx, my, shift);
1219
            if(dmin4 < dmin){
1220
                mb_type= CANDIDATE_MB_TYPE_INTER4V;
1221
                dmin=dmin4;
1222
            }
1223
        }
1224 1225 1226 1227 1228 1229 1230 1231
        if((s->flags&CODEC_FLAG_INTERLACED_ME)
           && !s->me.skip){ //FIXME varc/d checks
            int dmin_i= interlaced_search(s, src_data, ref_data, s->p_field_mv_table, s->p_field_select_table, s->f_code, mx, my);
            if(dmin_i < dmin){
                mb_type = CANDIDATE_MB_TYPE_INTER_I;
                dmin= dmin_i;
            }
        }
1232 1233
                
//        pic->mb_cmp_score[s->mb_stride * mb_y + mb_x] = dmin; 
1234
        set_p_mv_tables(s, mx, my, mb_type!=CANDIDATE_MB_TYPE_INTER4V);
1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249

        /* get intra luma score */
        if((s->avctx->mb_cmp&0xFF)==FF_CMP_SSE){
            intra_score= (varc<<8) - 500; //FIXME dont scale it down so we dont have to fix it
        }else{
            int mean= (sum+128)>>8;
            mean*= 0x01010101;
            
            for(i=0; i<16; i++){
                *(uint32_t*)(&s->me.scratchpad[i*s->linesize+ 0]) = mean;
                *(uint32_t*)(&s->me.scratchpad[i*s->linesize+ 4]) = mean;
                *(uint32_t*)(&s->me.scratchpad[i*s->linesize+ 8]) = mean;
                *(uint32_t*)(&s->me.scratchpad[i*s->linesize+12]) = mean;
            }

1250
            intra_score= s->dsp.mb_cmp[0](s, s->me.scratchpad, pix, s->linesize, 16);
1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
        }
#if 0 //FIXME
        /* get chroma score */
        if(s->avctx->mb_cmp&FF_CMP_CHROMA){
            for(i=1; i<3; i++){
                uint8_t *dest_c;
                int mean;
                
                if(s->out_format == FMT_H263){
                    mean= (s->dc_val[i][mb_x + (mb_y+1)*(s->mb_width+2)] + 4)>>3; //FIXME not exact but simple ;)
                }else{
                    mean= (s->last_dc[i] + 4)>>3;
                }
                dest_c = s->new_picture.data[i] + (mb_y * 8  * (s->uvlinesize)) + mb_x * 8;
                
                mean*= 0x01010101;
                for(i=0; i<8; i++){
                    *(uint32_t*)(&s->me.scratchpad[i*s->uvlinesize+ 0]) = mean;
                    *(uint32_t*)(&s->me.scratchpad[i*s->uvlinesize+ 4]) = mean;
                }
                
                intra_score+= s->dsp.mb_cmp[1](s, s->me.scratchpad, dest_c, s->uvlinesize);
            }                
        }
#endif
        intra_score += s->me.mb_penalty_factor*16;
        
        if(intra_score < dmin){
1279 1280
            mb_type= CANDIDATE_MB_TYPE_INTRA;
            s->current_picture.mb_type[mb_y*s->mb_stride + mb_x]= CANDIDATE_MB_TYPE_INTRA; //FIXME cleanup
1281 1282
        }else
            s->current_picture.mb_type[mb_y*s->mb_stride + mb_x]= 0;
1283
        
1284
        if (vard <= 64 || vard < varc) { //FIXME
1285
            s->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
1286
        }else{
Michael Niedermayer's avatar
Michael Niedermayer committed
1287
            s->scene_change_score+= s->qscale;
1288
        }
Fabrice Bellard's avatar
Fabrice Bellard committed
1289
    }
1290

1291
    s->mb_type[mb_y*s->mb_stride + mb_x]= mb_type;
1292 1293
}

1294 1295 1296
int ff_pre_estimate_p_frame_motion(MpegEncContext * s,
                                    int mb_x, int mb_y)
{
1297
    int mx, my, dmin;
1298 1299 1300
    int pred_x=0, pred_y=0;
    int P[10][2];
    const int shift= 1+s->quarter_sample;
1301
    uint8_t * const mv_penalty= s->me.mv_penalty[s->f_code] + MAX_MV;
1302
    const int xy= mb_x + mb_y*s->mb_stride;
1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314
    const int stride= s->linesize;
    const int uvstride= s->uvlinesize;
    uint8_t *src_data[3]= {
        s->new_picture.data[0] + 16*(mb_x + stride*mb_y),
        s->new_picture.data[1] + 8*(mb_x + uvstride*mb_y),
        s->new_picture.data[2] + 8*(mb_x + uvstride*mb_y)
    };
    uint8_t *ref_data[3]= {
        s->last_picture.data[0] + 16*(mb_x + stride*mb_y),
        s->last_picture.data[1] + 8*(mb_x + uvstride*mb_y),
        s->last_picture.data[2] + 8*(mb_x + uvstride*mb_y)
    };
1315 1316 1317
    
    assert(s->quarter_sample==0 || s->quarter_sample==1);

Michael Niedermayer's avatar
Michael Niedermayer committed
1318
    s->me.pre_penalty_factor    = get_penalty_factor(s, s->avctx->me_pre_cmp);
1319

1320
    get_limits(s, 16*mb_x, 16*mb_y);
1321 1322 1323 1324 1325
    s->me.skip=0;

    P_LEFT[0]       = s->p_mv_table[xy + 1][0];
    P_LEFT[1]       = s->p_mv_table[xy + 1][1];

1326
    if(P_LEFT[0]       < (s->me.xmin<<shift)) P_LEFT[0]       = (s->me.xmin<<shift);
1327 1328 1329 1330 1331

    /* special case for first line */
    if (mb_y == s->mb_height-1) {
        pred_x= P_LEFT[0];
        pred_y= P_LEFT[1];
1332 1333
        P_TOP[0]= P_TOPRIGHT[0]= P_MEDIAN[0]=
        P_TOP[1]= P_TOPRIGHT[1]= P_MEDIAN[1]= 0; //FIXME 
1334
    } else {
1335 1336 1337 1338
        P_TOP[0]      = s->p_mv_table[xy + s->mb_stride    ][0];
        P_TOP[1]      = s->p_mv_table[xy + s->mb_stride    ][1];
        P_TOPRIGHT[0] = s->p_mv_table[xy + s->mb_stride - 1][0];
        P_TOPRIGHT[1] = s->p_mv_table[xy + s->mb_stride - 1][1];
1339 1340 1341
        if(P_TOP[1]      < (s->me.ymin<<shift)) P_TOP[1]     = (s->me.ymin<<shift);
        if(P_TOPRIGHT[0] > (s->me.xmax<<shift)) P_TOPRIGHT[0]= (s->me.xmax<<shift);
        if(P_TOPRIGHT[1] < (s->me.ymin<<shift)) P_TOPRIGHT[1]= (s->me.ymin<<shift);
1342 1343 1344 1345
    
        P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
        P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);

1346 1347
        pred_x = P_MEDIAN[0];
        pred_y = P_MEDIAN[1];
1348
    }
1349 1350
    dmin = s->me.pre_motion_search(s, &mx, &my, P, pred_x, pred_y, 
                                   src_data, ref_data, stride, uvstride, s->p_mv_table, (1<<16)>>shift, mv_penalty);
1351

1352 1353 1354 1355 1356 1357
    s->p_mv_table[xy][0] = mx<<shift;
    s->p_mv_table[xy][1] = my<<shift;
    
    return dmin;
}

1358
static int ff_estimate_motion_b(MpegEncContext * s,
1359 1360
                       int mb_x, int mb_y, int16_t (*mv_table)[2], uint8_t *src_data[3],
                       uint8_t *ref_data[3], int stride, int uvstride, int f_code)
1361
{
1362
    int mx, my, dmin;
1363
    int pred_x=0, pred_y=0;
1364
    int P[10][2];
1365
    const int shift= 1+s->quarter_sample;
1366 1367
    const int mot_stride = s->mb_stride;
    const int mot_xy = mb_y*mot_stride + mb_x;
1368
    uint8_t * const ref_picture= ref_data[0] - 16*s->mb_x - 16*s->mb_y*s->linesize; //FIXME ugly
1369
    uint8_t * const mv_penalty= s->me.mv_penalty[f_code] + MAX_MV;
1370
    int mv_scale;
Michael Niedermayer's avatar
Michael Niedermayer committed
1371 1372 1373
        
    s->me.penalty_factor    = get_penalty_factor(s, s->avctx->me_cmp);
    s->me.sub_penalty_factor= get_penalty_factor(s, s->avctx->me_sub_cmp);
1374
    s->me.mb_penalty_factor = get_penalty_factor(s, s->avctx->mb_cmp);
Michael Niedermayer's avatar
Michael Niedermayer committed
1375

1376
    get_limits(s, 16*mb_x, 16*mb_y);
1377 1378 1379 1380 1381 1382

    switch(s->me_method) {
    case ME_ZERO:
    default:
	no_motion_search(s, &mx, &my);
        dmin = 0;
1383 1384
        mx-= mb_x*16;
        my-= mb_y*16;
1385
        break;
1386
#if 0
1387
    case ME_FULL:
1388
	dmin = full_motion_search(s, &mx, &my, range, ref_picture);
1389 1390
        mx-= mb_x*16;
        my-= mb_y*16;
1391 1392
        break;
    case ME_LOG:
1393
	dmin = log_motion_search(s, &mx, &my, range / 2, ref_picture);
1394 1395
        mx-= mb_x*16;
        my-= mb_y*16;
1396 1397
        break;
    case ME_PHODS:
1398
	dmin = phods_motion_search(s, &mx, &my, range / 2, ref_picture);
1399 1400
        mx-= mb_x*16;
        my-= mb_y*16;
1401
        break;
1402
#endif
1403 1404 1405
    case ME_X1:
    case ME_EPZS:
       {
1406 1407
            P_LEFT[0]        = mv_table[mot_xy - 1][0];
            P_LEFT[1]        = mv_table[mot_xy - 1][1];
1408

1409
            if(P_LEFT[0]       > (s->me.xmax<<shift)) P_LEFT[0]       = (s->me.xmax<<shift);
1410 1411

            /* special case for first line */
1412
            if (mb_y) {
1413 1414 1415 1416
                P_TOP[0] = mv_table[mot_xy - mot_stride             ][0];
                P_TOP[1] = mv_table[mot_xy - mot_stride             ][1];
                P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1         ][0];
                P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1         ][1];
1417 1418 1419
                if(P_TOP[1] > (s->me.ymax<<shift)) P_TOP[1]= (s->me.ymax<<shift);
                if(P_TOPRIGHT[0] < (s->me.xmin<<shift)) P_TOPRIGHT[0]= (s->me.xmin<<shift);
                if(P_TOPRIGHT[1] > (s->me.ymax<<shift)) P_TOPRIGHT[1]= (s->me.ymax<<shift);
1420
        
1421 1422
                P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
                P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
1423
            }
1424 1425
            pred_x= P_LEFT[0];
            pred_y= P_LEFT[1];
1426
        }
1427 1428 1429 1430 1431 1432 1433
        
        if(mv_table == s->b_forw_mv_table){
            mv_scale= (s->pb_time<<16) / (s->pp_time<<shift);
        }else{
            mv_scale= ((s->pb_time - s->pp_time)<<16) / (s->pp_time<<shift);
        }
        
1434 1435
        dmin = s->me.motion_search[0](s, &mx, &my, P, pred_x, pred_y, 
                                      src_data, ref_data, stride, uvstride, s->p_mv_table, mv_scale, mv_penalty);
1436 1437 1438 1439
 
        break;
    }
    
1440 1441
    dmin= s->me.sub_motion_search(s, &mx, &my, dmin,
				   pred_x, pred_y, src_data, ref_data, stride, uvstride, 0, 16, mv_penalty);
1442 1443
                                   
    if(s->avctx->me_sub_cmp != s->avctx->mb_cmp && !s->me.skip)
1444
        dmin= s->me.get_mb_score(s, mx, my, pred_x, pred_y, src_data, ref_data, stride, uvstride, mv_penalty);
1445

1446
//printf("%d %d %d %d//", s->mb_x, s->mb_y, mx, my);
1447 1448 1449
//    s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
    mv_table[mot_xy][0]= mx;
    mv_table[mot_xy][1]= my;
Michael Niedermayer's avatar
Michael Niedermayer committed
1450

1451
    return dmin;
Fabrice Bellard's avatar
Fabrice Bellard committed
1452 1453
}

1454 1455
static inline int check_bidir_mv(MpegEncContext * s, uint8_t *src_data[3], uint8_t *ref_data[6],
                   int stride, int uvstride,
1456 1457 1458
                   int motion_fx, int motion_fy,
                   int motion_bx, int motion_by,
                   int pred_fx, int pred_fy,
1459 1460
                   int pred_bx, int pred_by,
                   int size, int h)
Fabrice Bellard's avatar
Fabrice Bellard committed
1461
{
1462
    //FIXME optimize?
Michael Niedermayer's avatar
Michael Niedermayer committed
1463 1464
    //FIXME move into template?
    //FIXME better f_code prediction (max mv & distance)
1465
    //FIXME pointers
1466
    uint8_t * const mv_penalty= s->me.mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
Michael Niedermayer's avatar
Michael Niedermayer committed
1467
    uint8_t *dest_y = s->me.scratchpad;
1468 1469 1470 1471 1472
    uint8_t *ptr;
    int dxy;
    int src_x, src_y;
    int fbmin;

Michael Niedermayer's avatar
Michael Niedermayer committed
1473 1474
    if(s->quarter_sample){
        dxy = ((motion_fy & 3) << 2) | (motion_fx & 3);
1475 1476
        src_x = motion_fx >> 2;
        src_y = motion_fy >> 2;
Michael Niedermayer's avatar
Michael Niedermayer committed
1477

1478 1479
        ptr = ref_data[0] + (src_y * stride) + src_x;
        s->dsp.put_qpel_pixels_tab[0][dxy](dest_y    , ptr    , stride);
Michael Niedermayer's avatar
Michael Niedermayer committed
1480 1481

        dxy = ((motion_by & 3) << 2) | (motion_bx & 3);
1482 1483
        src_x = motion_bx >> 2;
        src_y = motion_by >> 2;
Michael Niedermayer's avatar
Michael Niedermayer committed
1484
    
1485 1486
        ptr = ref_data[3] + (src_y * stride) + src_x;
        s->dsp.avg_qpel_pixels_tab[size][dxy](dest_y    , ptr    , stride);
Michael Niedermayer's avatar
Michael Niedermayer committed
1487 1488
    }else{
        dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
1489 1490
        src_x = motion_fx >> 1;
        src_y = motion_fy >> 1;
Michael Niedermayer's avatar
Michael Niedermayer committed
1491

1492 1493
        ptr = ref_data[0] + (src_y * stride) + src_x;
        s->dsp.put_pixels_tab[size][dxy](dest_y    , ptr    , stride, h);
Michael Niedermayer's avatar
Michael Niedermayer committed
1494 1495

        dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
1496 1497
        src_x = motion_bx >> 1;
        src_y = motion_by >> 1;
Michael Niedermayer's avatar
Michael Niedermayer committed
1498
    
1499 1500
        ptr = ref_data[3] + (src_y * stride) + src_x;
        s->dsp.avg_pixels_tab[size][dxy](dest_y    , ptr    , stride, h);
Michael Niedermayer's avatar
Michael Niedermayer committed
1501 1502
    }

1503 1504
    fbmin = (mv_penalty[motion_fx-pred_fx] + mv_penalty[motion_fy-pred_fy])*s->me.mb_penalty_factor
           +(mv_penalty[motion_bx-pred_bx] + mv_penalty[motion_by-pred_by])*s->me.mb_penalty_factor
1505
           + s->dsp.mb_cmp[size](s, src_data[0], dest_y, stride, h); //FIXME new_pic
1506 1507 1508 1509 1510
           
    if(s->avctx->mb_cmp&FF_CMP_CHROMA){
    }
    //FIXME CHROMA !!!
           
1511 1512
    return fbmin;
}
1513

1514
/* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
1515 1516
static inline int bidir_refine(MpegEncContext * s, uint8_t *src_data[3], uint8_t *ref_data[6],
                                  int stride, int uvstride,
1517 1518
                                  int mb_x, int mb_y)
{
1519 1520
    const int mot_stride = s->mb_stride;
    const int xy = mb_y *mot_stride + mb_x;
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532
    int fbmin;
    int pred_fx= s->b_bidir_forw_mv_table[xy-1][0];
    int pred_fy= s->b_bidir_forw_mv_table[xy-1][1];
    int pred_bx= s->b_bidir_back_mv_table[xy-1][0];
    int pred_by= s->b_bidir_back_mv_table[xy-1][1];
    int motion_fx= s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0];
    int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1];
    int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0];
    int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1];

    //FIXME do refinement and add flag
    
1533
    fbmin= check_bidir_mv(s, src_data, ref_data, stride, uvstride,
1534 1535 1536
                          motion_fx, motion_fy,
                          motion_bx, motion_by,
                          pred_fx, pred_fy,
1537 1538
                          pred_bx, pred_by,
                          0, 16);
1539 1540 1541 1542

   return fbmin;
}

1543 1544
static inline int direct_search(MpegEncContext * s, uint8_t *src_data[3], uint8_t *ref_data[6],
                                int stride, int uvstride,
1545 1546
                                int mb_x, int mb_y)
{
1547
    int P[10][2];
1548 1549
    const int mot_stride = s->mb_stride;
    const int mot_xy = mb_y*mot_stride + mb_x;
Michael Niedermayer's avatar
Michael Niedermayer committed
1550 1551
    const int shift= 1+s->quarter_sample;
    int dmin, i;
1552
    const int time_pp= s->pp_time;
1553
    const int time_pb= s->pb_time;
Michael Niedermayer's avatar
Michael Niedermayer committed
1554
    int mx, my, xmin, xmax, ymin, ymax;
1555
    int16_t (*mv_table)[2]= s->b_direct_mv_table;
1556
    uint8_t * const mv_penalty= s->me.mv_penalty[1] + MAX_MV;
Michael Niedermayer's avatar
Michael Niedermayer committed
1557 1558 1559 1560
    
    ymin= xmin=(-32)>>shift;
    ymax= xmax=   31>>shift;

1561
    if(IS_8X8(s->next_picture.mb_type[mot_xy])){
Michael Niedermayer's avatar
Michael Niedermayer committed
1562 1563 1564
        s->mv_type= MV_TYPE_8X8;
    }else{
        s->mv_type= MV_TYPE_16X16;
1565
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
1566 1567 1568 1569 1570

    for(i=0; i<4; i++){
        int index= s->block_index[i];
        int min, max;
    
1571 1572
        s->me.co_located_mv[i][0]= s->next_picture.motion_val[0][index][0];
        s->me.co_located_mv[i][1]= s->next_picture.motion_val[0][index][1];
Michael Niedermayer's avatar
Michael Niedermayer committed
1573 1574 1575 1576 1577 1578 1579
        s->me.direct_basis_mv[i][0]= s->me.co_located_mv[i][0]*time_pb/time_pp + ((i& 1)<<(shift+3));
        s->me.direct_basis_mv[i][1]= s->me.co_located_mv[i][1]*time_pb/time_pp + ((i>>1)<<(shift+3));
//        s->me.direct_basis_mv[1][i][0]= s->me.co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(shift+3);
//        s->me.direct_basis_mv[1][i][1]= s->me.co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(shift+3);

        max= FFMAX(s->me.direct_basis_mv[i][0], s->me.direct_basis_mv[i][0] - s->me.co_located_mv[i][0])>>shift;
        min= FFMIN(s->me.direct_basis_mv[i][0], s->me.direct_basis_mv[i][0] - s->me.co_located_mv[i][0])>>shift;
1580 1581
        max+= 16*mb_x + 1; // +-1 is for the simpler rounding
        min+= 16*mb_x - 1;
1582 1583
        xmax= FFMIN(xmax, s->width - max);
        xmin= FFMAX(xmin, - 16     - min);
Michael Niedermayer's avatar
Michael Niedermayer committed
1584 1585 1586

        max= FFMAX(s->me.direct_basis_mv[i][1], s->me.direct_basis_mv[i][1] - s->me.co_located_mv[i][1])>>shift;
        min= FFMIN(s->me.direct_basis_mv[i][1], s->me.direct_basis_mv[i][1] - s->me.co_located_mv[i][1])>>shift;
1587 1588
        max+= 16*mb_y + 1; // +-1 is for the simpler rounding
        min+= 16*mb_y - 1;
1589 1590
        ymax= FFMIN(ymax, s->height - max);
        ymin= FFMAX(ymin, - 16      - min);
Michael Niedermayer's avatar
Michael Niedermayer committed
1591 1592
        
        if(s->mv_type == MV_TYPE_16X16) break;
1593
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
1594 1595 1596 1597 1598 1599 1600 1601 1602
    
    assert(xmax <= 15 && ymax <= 15 && xmin >= -16 && ymin >= -16);
    
    if(xmax < 0 || xmin >0 || ymax < 0 || ymin > 0){
        s->b_direct_mv_table[mot_xy][0]= 0;
        s->b_direct_mv_table[mot_xy][1]= 0;

        return 256*256*256*64;
    }
1603 1604 1605 1606 1607
    
    s->me.xmin= xmin;
    s->me.ymin= ymin;
    s->me.xmax= xmax;
    s->me.ymax= ymax;
Michael Niedermayer's avatar
Michael Niedermayer committed
1608

Michael Niedermayer's avatar
Michael Niedermayer committed
1609 1610 1611 1612
    P_LEFT[0]        = clip(mv_table[mot_xy - 1][0], xmin<<shift, xmax<<shift);
    P_LEFT[1]        = clip(mv_table[mot_xy - 1][1], ymin<<shift, ymax<<shift);

    /* special case for first line */
1613
    if (mb_y) {
Michael Niedermayer's avatar
Michael Niedermayer committed
1614 1615 1616 1617 1618 1619 1620 1621
        P_TOP[0]      = clip(mv_table[mot_xy - mot_stride             ][0], xmin<<shift, xmax<<shift);
        P_TOP[1]      = clip(mv_table[mot_xy - mot_stride             ][1], ymin<<shift, ymax<<shift);
        P_TOPRIGHT[0] = clip(mv_table[mot_xy - mot_stride + 1         ][0], xmin<<shift, xmax<<shift);
        P_TOPRIGHT[1] = clip(mv_table[mot_xy - mot_stride + 1         ][1], ymin<<shift, ymax<<shift);
    
        P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
        P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
    }
1622 1623
 
    //FIXME direct_search  ptr in context!!! (needed for chroma anyway or this will get messy)   
Michael Niedermayer's avatar
Michael Niedermayer committed
1624
    if(s->flags&CODEC_FLAG_QPEL){
1625 1626 1627 1628
        dmin = simple_direct_qpel_epzs_motion_search(s, &mx, &my, P, 0, 0, 
                                                     src_data, ref_data, stride, uvstride, mv_table, 1<<14, mv_penalty);
        dmin = simple_direct_qpel_qpel_motion_search(s, &mx, &my, dmin,
                                                0, 0, src_data, ref_data, stride, uvstride, 0, 16, mv_penalty);
1629 1630
        
        if(s->avctx->me_sub_cmp != s->avctx->mb_cmp && !s->me.skip)
1631
            dmin= simple_direct_qpel_qpel_get_mb_score(s, mx, my, 0, 0, src_data, ref_data, stride, uvstride, mv_penalty);
Michael Niedermayer's avatar
Michael Niedermayer committed
1632
    }else{
1633 1634 1635 1636
        dmin = simple_direct_hpel_epzs_motion_search(s, &mx, &my, P, 0, 0, 
                                                     src_data, ref_data, stride, uvstride, mv_table, 1<<15, mv_penalty);
        dmin = simple_direct_hpel_hpel_motion_search(s, &mx, &my, dmin,
                                                0, 0, src_data, ref_data, stride, uvstride, 0, 16, mv_penalty);
1637 1638

        if(s->avctx->me_sub_cmp != s->avctx->mb_cmp && !s->me.skip)
1639
            dmin= simple_direct_hpel_hpel_get_mb_score(s, mx, my, 0, 0, src_data, ref_data, stride, uvstride, mv_penalty);
1640
    }
1641 1642
    
    get_limits(s, 16*mb_x, 16*mb_y); //restore s->me.?min/max, maybe not needed
1643 1644 1645 1646

    s->b_direct_mv_table[mot_xy][0]= mx;
    s->b_direct_mv_table[mot_xy][1]= my;
    return dmin;
1647 1648 1649 1650 1651
}

void ff_estimate_b_frame_motion(MpegEncContext * s,
                             int mb_x, int mb_y)
{
1652
    const int penalty_factor= s->me.mb_penalty_factor;
1653
    int fmin, bmin, dmin, fbmin, bimin, fimin;
1654
    int type=0;
1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669
    const int stride= s->linesize;
    const int uvstride= s->uvlinesize;
    uint8_t *src_data[3]= {
        s->new_picture.data[0] + 16*(s->mb_x + stride*s->mb_y),
        s->new_picture.data[1] + 8*(s->mb_x + uvstride*s->mb_y),
        s->new_picture.data[2] + 8*(s->mb_x + uvstride*s->mb_y)
    };
    uint8_t *ref_data[6]= {
        s->last_picture.data[0] + 16*(s->mb_x + stride*s->mb_y),
        s->last_picture.data[1] + 8*(s->mb_x + uvstride*s->mb_y),
        s->last_picture.data[2] + 8*(s->mb_x + uvstride*s->mb_y),
        s->next_picture.data[0] + 16*(s->mb_x + stride*s->mb_y),
        s->next_picture.data[1] + 8*(s->mb_x + uvstride*s->mb_y),
        s->next_picture.data[2] + 8*(s->mb_x + uvstride*s->mb_y)
    };
1670
    
1671 1672
    s->me.skip=0;
    if (s->codec_id == CODEC_ID_MPEG4)
1673
        dmin= direct_search(s, src_data, ref_data, stride, uvstride, mb_x, mb_y);
1674 1675
    else
        dmin= INT_MAX;
1676
//FIXME penalty stuff for non mpeg4
1677
    s->me.skip=0;
1678 1679
    fmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, src_data, 
                               ref_data, stride, uvstride, s->f_code) + 3*penalty_factor;
1680 1681
    
    s->me.skip=0;
1682 1683
    bmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, src_data, 
                               ref_data+3, stride, uvstride, s->b_code) + 2*penalty_factor;
1684
//printf(" %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
1685

1686
    s->me.skip=0;
1687
    fbmin= bidir_refine(s, src_data, ref_data, stride, uvstride, mb_x, mb_y) + penalty_factor;
1688
//printf("%d %d %d %d\n", dmin, fmin, bmin, fbmin);
1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703
    
    if(s->flags & CODEC_FLAG_INTERLACED_ME){
        const int xy = mb_y*s->mb_stride + mb_x;

//FIXME mb type penalty
        s->me.skip=0;
        fimin= interlaced_search(s, src_data, ref_data  , 
                                 s->b_field_mv_table[0], s->b_field_select_table[0], s->f_code,
                                 s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
        bimin= interlaced_search(s, src_data, ref_data+3, 
                                 s->b_field_mv_table[1], s->b_field_select_table[1], s->b_code,
                                 s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1]);
    }else
        fimin= bimin= INT_MAX;

1704
    {
1705
        int score= fmin;
1706
        type = CANDIDATE_MB_TYPE_FORWARD;
1707
        
1708
        if (dmin <= score){
1709
            score = dmin;
1710
            type = CANDIDATE_MB_TYPE_DIRECT;
1711 1712 1713
        }
        if(bmin<score){
            score=bmin;
1714
            type= CANDIDATE_MB_TYPE_BACKWARD; 
1715 1716 1717
        }
        if(fbmin<score){
            score=fbmin;
1718 1719 1720 1721 1722 1723 1724 1725 1726
            type= CANDIDATE_MB_TYPE_BIDIR;
        }
        if(fimin<score){
            score=fimin;
            type= CANDIDATE_MB_TYPE_FORWARD_I;
        }
        if(bimin<score){
            score=bimin;
            type= CANDIDATE_MB_TYPE_BACKWARD_I;
1727
        }
1728
        
1729
        score= ((unsigned)(score*score + 128*256))>>16;
Michael Niedermayer's avatar
Michael Niedermayer committed
1730
        s->current_picture.mc_mb_var_sum += score;
1731
        s->current_picture.mc_mb_var[mb_y*s->mb_stride + mb_x] = score; //FIXME use SSE
1732
    }
1733

1734
    if(s->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
1735 1736 1737 1738 1739 1740 1741 1742 1743 1744
        type= CANDIDATE_MB_TYPE_FORWARD | CANDIDATE_MB_TYPE_BACKWARD | CANDIDATE_MB_TYPE_BIDIR | CANDIDATE_MB_TYPE_DIRECT;
        if(fimin < INT_MAX)
            type |= CANDIDATE_MB_TYPE_FORWARD_I;
        if(bimin < INT_MAX)
            type |= CANDIDATE_MB_TYPE_BACKWARD_I;
        if(fimin < INT_MAX && bimin < INT_MAX){
            type |= CANDIDATE_MB_TYPE_BIDIR_I;
        }
         //FIXME something smarter
        if(dmin>256*256*16) type&= ~CANDIDATE_MB_TYPE_DIRECT; //dont try direct mode if its invalid for this MB
1745 1746 1747 1748
#if 0        
        if(s->out_format == FMT_MPEG1)
            type |= CANDIDATE_MB_TYPE_INTRA;
#endif
1749 1750
    }

1751
    s->mb_type[mb_y*s->mb_stride + mb_x]= type;
1752 1753 1754 1755 1756 1757
}

/* find best f_code for ME which do unlimited searches */
int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type)
{
    if(s->me_method>=ME_EPZS){
1758
        int score[8];
1759
        int i, y;
1760
        uint8_t * fcode_tab= s->fcode_tab;
1761 1762
        int best_fcode=-1;
        int best_score=-10000000;
1763

Michael Niedermayer's avatar
Michael Niedermayer committed
1764
        for(i=0; i<8; i++) score[i]= s->mb_num*(8-i);
1765 1766 1767

        for(y=0; y<s->mb_height; y++){
            int x;
1768
            int xy= y*s->mb_stride;
1769
            for(x=0; x<s->mb_width; x++){
Michael Niedermayer's avatar
Michael Niedermayer committed
1770
                if(s->mb_type[xy] & type){
1771 1772
                    int fcode= FFMAX(fcode_tab[mv_table[xy][0] + MAX_MV],
                                     fcode_tab[mv_table[xy][1] + MAX_MV]);
1773 1774 1775
                    int j;
                    
                    for(j=0; j<fcode && j<8; j++){
1776
                        if(s->pict_type==B_TYPE || s->current_picture.mc_mb_var[xy] < s->current_picture.mb_var[xy])
1777 1778
                            score[j]-= 170;
                    }
1779 1780 1781 1782
                }
                xy++;
            }
        }
1783 1784 1785 1786 1787 1788 1789
        
        for(i=1; i<8; i++){
            if(score[i] > best_score){
                best_score= score[i];
                best_fcode= i;
            }
//            printf("%d %d\n", i, score[i]);
1790
        }
1791

1792
//    printf("fcode: %d type: %d\n", i, s->pict_type);
1793
        return best_fcode;
1794 1795 1796 1797 1798 1799
/*        for(i=0; i<=MAX_FCODE; i++){
            printf("%d ", mv_num[i]);
        }
        printf("\n");*/
    }else{
        return 1;
Fabrice Bellard's avatar
Fabrice Bellard committed
1800 1801 1802
    }
}

1803 1804 1805
void ff_fix_long_p_mvs(MpegEncContext * s)
{
    const int f_code= s->f_code;
1806
    int y, range;
Michael Niedermayer's avatar
Michael Niedermayer committed
1807
    assert(s->pict_type==P_TYPE);
1808

Michael Niedermayer's avatar
Michael Niedermayer committed
1809
    range = (((s->out_format == FMT_MPEG1) ? 8 : 16) << f_code);
1810 1811 1812 1813 1814
    
    if(s->msmpeg4_version) range= 16;
    
    if(s->avctx->me_range && range > s->avctx->me_range) range= s->avctx->me_range;
    
1815
//printf("%d no:%d %d//\n", clip, noclip, f_code);
1816 1817 1818 1819 1820 1821
    if(s->flags&CODEC_FLAG_4MV){
        const int wrap= 2+ s->mb_width*2;

        /* clip / convert to intra 8x8 type MVs */
        for(y=0; y<s->mb_height; y++){
            int xy= (y*2 + 1)*wrap + 1;
1822
            int i= y*s->mb_stride;
1823 1824 1825
            int x;

            for(x=0; x<s->mb_width; x++){
1826
                if(s->mb_type[i]&CANDIDATE_MB_TYPE_INTER4V){
1827 1828 1829
                    int block;
                    for(block=0; block<4; block++){
                        int off= (block& 1) + (block>>1)*wrap;
1830 1831
                        int mx= s->current_picture.motion_val[0][ xy + off ][0];
                        int my= s->current_picture.motion_val[0][ xy + off ][1];
1832

1833 1834
                        if(   mx >=range || mx <-range
                           || my >=range || my <-range){
1835 1836 1837
                            s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V;
                            s->mb_type[i] |= CANDIDATE_MB_TYPE_INTRA;
                            s->current_picture.mb_type[i]= CANDIDATE_MB_TYPE_INTRA;
1838 1839 1840
                        }
                    }
                }
Michael Niedermayer's avatar
Michael Niedermayer committed
1841 1842
                xy+=2;
                i++;
1843 1844 1845 1846 1847
            }
        }
    }
}

1848 1849 1850 1851 1852 1853
/**
 *
 * @param truncate 1 for truncation, 0 for using intra
 */
void ff_fix_long_mvs(MpegEncContext * s, uint8_t *field_select_table, int field_select, 
                     int16_t (*mv_table)[2], int f_code, int type, int truncate)
1854
{
1855
    int y, h_range, v_range;
1856

1857
    // RAL: 8 in MPEG-1, 16 in MPEG-4
Michael Niedermayer's avatar
Michael Niedermayer committed
1858
    int range = (((s->out_format == FMT_MPEG1) ? 8 : 16) << f_code);
1859 1860

    if(s->msmpeg4_version) range= 16;
1861
    if(s->avctx->me_range && range > s->avctx->me_range) range= s->avctx->me_range;
1862

1863 1864 1865
    h_range= range;
    v_range= field_select_table ? range>>1 : range;

1866 1867 1868
    /* clip / convert to intra 16x16 type MVs */
    for(y=0; y<s->mb_height; y++){
        int x;
1869
        int xy= y*s->mb_stride;
1870
        for(x=0; x<s->mb_width; x++){
1871
            if (s->mb_type[xy] & type){    // RAL: "type" test added...
1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886
                if(field_select_table==NULL || field_select_table[xy] == field_select){
                    if(   mv_table[xy][0] >=h_range || mv_table[xy][0] <-h_range
                       || mv_table[xy][1] >=v_range || mv_table[xy][1] <-v_range){

                        if(truncate){
                            if     (mv_table[xy][0] > h_range-1) mv_table[xy][0]=  h_range-1;
                            else if(mv_table[xy][0] < -h_range ) mv_table[xy][0]= -h_range;
                            if     (mv_table[xy][1] > v_range-1) mv_table[xy][1]=  v_range-1;
                            else if(mv_table[xy][1] < -v_range ) mv_table[xy][1]= -v_range;
                        }else{
                            s->mb_type[xy] &= ~type;
                            s->mb_type[xy] |= CANDIDATE_MB_TYPE_INTRA;
                            mv_table[xy][0]=
                            mv_table[xy][1]= 0;
                        }
1887
                    }
1888
                }
1889 1890 1891 1892 1893
            }
            xy++;
        }
    }
}