motion_est.c 67.1 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
5
 *
6
 * new motion estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>
Fabrice Bellard's avatar
Fabrice Bellard committed
7
 *
8 9 10
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
11 12
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
13
 * version 2.1 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
Fabrice Bellard committed
14
 *
15
 * FFmpeg is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Fabrice Bellard's avatar
Fabrice Bellard committed
19
 *
20
 * You should have received a copy of the GNU Lesser General Public
21
 * License along with FFmpeg; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Fabrice Bellard's avatar
Fabrice Bellard committed
23
 */
24

Michael Niedermayer's avatar
Michael Niedermayer committed
25
/**
26
 * @file
Michael Niedermayer's avatar
Michael Niedermayer committed
27 28
 * Motion estimation.
 */
29

Fabrice Bellard's avatar
Fabrice Bellard committed
30 31
#include <stdlib.h>
#include <stdio.h>
32
#include <limits.h>
33

Fabrice Bellard's avatar
Fabrice Bellard committed
34
#include "avcodec.h"
35
#include "internal.h"
36
#include "mathops.h"
37
#include "motion_est.h"
38
#include "mpegutils.h"
Fabrice Bellard's avatar
Fabrice Bellard committed
39 40
#include "mpegvideo.h"

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]

47 48 49
#define ME_MAP_SHIFT 3
#define ME_MAP_MV_BITS 11

50
static int sad_hpel_motion_search(MpegEncContext * s,
51
                                  int *mx_ptr, int *my_ptr, int dmin,
52 53
                                  int src_index, int ref_index,
                                  int size, int h);
Michael Niedermayer's avatar
Michael Niedermayer committed
54

55
static inline unsigned update_map_generation(MotionEstContext *c)
Michael Niedermayer's avatar
Michael Niedermayer committed
56
{
57 58 59 60
    c->map_generation+= 1<<(ME_MAP_MV_BITS*2);
    if(c->map_generation==0){
        c->map_generation= 1<<(ME_MAP_MV_BITS*2);
        memset(c->map, 0, sizeof(uint32_t)*ME_MAP_SIZE);
Michael Niedermayer's avatar
Michael Niedermayer committed
61
    }
62
    return c->map_generation;
Michael Niedermayer's avatar
Michael Niedermayer committed
63 64
}

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

72
static int minima_cmp(const void *a, const void *b){
73 74
    const Minima *da = (const Minima *) a;
    const Minima *db = (const Minima *) b;
75

76 77
    return da->height - db->height;
}
Michael Niedermayer's avatar
Michael Niedermayer committed
78

79 80 81
#define FLAG_QPEL   1 //must be 1
#define FLAG_CHROMA 2
#define FLAG_DIRECT 4
Michael Niedermayer's avatar
Michael Niedermayer committed
82

83
static inline void init_ref(MotionEstContext *c, uint8_t *src[3], uint8_t *ref[3], uint8_t *ref2[3], int x, int y, int ref_index){
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    const int offset[3]= {
          y*c->  stride + x,
        ((y*c->uvstride + x)>>1),
        ((y*c->uvstride + x)>>1),
    };
    int i;
    for(i=0; i<3; i++){
        c->src[0][i]= src [i] + offset[i];
        c->ref[0][i]= ref [i] + offset[i];
    }
    if(ref_index){
        for(i=0; i<3; i++){
            c->ref[ref_index][i]= ref2[i] + offset[i];
        }
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
99 100
}

101
static int get_flags(MotionEstContext *c, int direct, int chroma){
102
    return   ((c->avctx->flags&AV_CODEC_FLAG_QPEL) ? FLAG_QPEL : 0)
103
           + (direct ? FLAG_DIRECT : 0)
104
           + (chroma ? FLAG_CHROMA : 0);
Michael Niedermayer's avatar
Michael Niedermayer committed
105 106
}

107
static av_always_inline int cmp_direct_inline(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
108
                      const int size, const int h, int ref_index, int src_index,
109
                      me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel){
110 111 112 113 114 115 116 117
    MotionEstContext * const c= &s->me;
    const int stride= c->stride;
    const int hx= subx + (x<<(1+qpel));
    const int hy= suby + (y<<(1+qpel));
    uint8_t * const * const ref= c->ref[ref_index];
    uint8_t * const * const src= c->src[src_index];
    int d;
    //FIXME check chroma 4mv, (no crashes ...)
118
        av_assert2(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1));
119 120 121 122 123 124 125 126 127 128 129 130 131
        if(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1)){
            const int time_pp= s->pp_time;
            const int time_pb= s->pb_time;
            const int mask= 2*qpel+1;
            if(s->mv_type==MV_TYPE_8X8){
                int i;
                for(i=0; i<4; i++){
                    int fx = c->direct_basis_mv[i][0] + hx;
                    int fy = c->direct_basis_mv[i][1] + hy;
                    int bx = hx ? fx - c->co_located_mv[i][0] : c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(qpel+4));
                    int by = hy ? fy - c->co_located_mv[i][1] : c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(qpel+4));
                    int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));
                    int bxy= (bx&mask) + ((by&mask)<<(qpel+1));
132

133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
                    uint8_t *dst= c->temp + 8*(i&1) + 8*stride*(i>>1);
                    if(qpel){
                        c->qpel_put[1][fxy](dst, ref[0] + (fx>>2) + (fy>>2)*stride, stride);
                        c->qpel_avg[1][bxy](dst, ref[8] + (bx>>2) + (by>>2)*stride, stride);
                    }else{
                        c->hpel_put[1][fxy](dst, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 8);
                        c->hpel_avg[1][bxy](dst, ref[8] + (bx>>1) + (by>>1)*stride, stride, 8);
                    }
                }
            }else{
                int fx = c->direct_basis_mv[0][0] + hx;
                int fy = c->direct_basis_mv[0][1] + hy;
                int bx = hx ? fx - c->co_located_mv[0][0] : (c->co_located_mv[0][0]*(time_pb - time_pp)/time_pp);
                int by = hy ? fy - c->co_located_mv[0][1] : (c->co_located_mv[0][1]*(time_pb - time_pp)/time_pp);
                int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));
                int bxy= (bx&mask) + ((by&mask)<<(qpel+1));
149

150 151 152 153 154 155 156 157 158
                if(qpel){
                    c->qpel_put[1][fxy](c->temp               , ref[0] + (fx>>2) + (fy>>2)*stride               , stride);
                    c->qpel_put[1][fxy](c->temp + 8           , ref[0] + (fx>>2) + (fy>>2)*stride + 8           , stride);
                    c->qpel_put[1][fxy](c->temp     + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride     + 8*stride, stride);
                    c->qpel_put[1][fxy](c->temp + 8 + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8 + 8*stride, stride);
                    c->qpel_avg[1][bxy](c->temp               , ref[8] + (bx>>2) + (by>>2)*stride               , stride);
                    c->qpel_avg[1][bxy](c->temp + 8           , ref[8] + (bx>>2) + (by>>2)*stride + 8           , stride);
                    c->qpel_avg[1][bxy](c->temp     + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride     + 8*stride, stride);
                    c->qpel_avg[1][bxy](c->temp + 8 + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8 + 8*stride, stride);
159
                }else{
160 161 162 163 164 165 166 167
                    av_assert2((fx>>1) + 16*s->mb_x >= -16);
                    av_assert2((fy>>1) + 16*s->mb_y >= -16);
                    av_assert2((fx>>1) + 16*s->mb_x <= s->width);
                    av_assert2((fy>>1) + 16*s->mb_y <= s->height);
                    av_assert2((bx>>1) + 16*s->mb_x >= -16);
                    av_assert2((by>>1) + 16*s->mb_y >= -16);
                    av_assert2((bx>>1) + 16*s->mb_x <= s->width);
                    av_assert2((by>>1) + 16*s->mb_y <= s->height);
168 169 170 171 172 173 174 175

                    c->hpel_put[0][fxy](c->temp, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 16);
                    c->hpel_avg[0][bxy](c->temp, ref[8] + (bx>>1) + (by>>1)*stride, stride, 16);
                }
            }
            d = cmp_func(s, c->temp, src[0], stride, 16);
        }else
            d= 256*256*256*32;
176 177 178 179 180 181 182 183 184 185
    return d;
}

static av_always_inline int cmp_inline(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
                      const int size, const int h, int ref_index, int src_index,
                      me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel, int chroma){
    MotionEstContext * const c= &s->me;
    const int stride= c->stride;
    const int uvstride= c->uvstride;
    const int dxy= subx + (suby<<(1+qpel)); //FIXME log2_subpel?
186 187
    const int hx= subx + x*(1<<(1+qpel));
    const int hy= suby + y*(1<<(1+qpel));
188 189 190 191
    uint8_t * const * const ref= c->ref[ref_index];
    uint8_t * const * const src= c->src[src_index];
    int d;
    //FIXME check chroma 4mv, (no crashes ...)
192
        int uvdxy;              /* no, it might not be used uninitialized */
193 194
        if(dxy){
            if(qpel){
195 196 197 198 199 200 201
                if (h << size == 16) {
                    c->qpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride); //FIXME prototype (add h)
                } else if (size == 0 && h == 8) {
                    c->qpel_put[1][dxy](c->temp    , ref[0] + x + y*stride    , stride);
                    c->qpel_put[1][dxy](c->temp + 8, ref[0] + x + y*stride + 8, stride);
                } else
                    av_assert2(0);
202 203 204 205 206 207
                if(chroma){
                    int cx= hx/2;
                    int cy= hy/2;
                    cx= (cx>>1)|(cx&1);
                    cy= (cy>>1)|(cy&1);
                    uvdxy= (cx&1) + 2*(cy&1);
208
                    // FIXME x/y wrong, but MPEG-4 qpel is sick anyway, we should drop as much of it as possible in favor for H.264
209 210 211 212 213 214
                }
            }else{
                c->hpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride, h);
                if(chroma)
                    uvdxy= dxy | (x&1) | (2*(y&1));
            }
215
            d = cmp_func(s, c->temp, src[0], stride, h);
216
        }else{
217
            d = cmp_func(s, src[0], ref[0] + x + y*stride, stride, h);
218 219 220 221 222 223 224
            if(chroma)
                uvdxy= (x&1) + 2*(y&1);
        }
        if(chroma){
            uint8_t * const uvtemp= c->temp + 16*stride;
            c->hpel_put[size+1][uvdxy](uvtemp  , ref[1] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);
            c->hpel_put[size+1][uvdxy](uvtemp+8, ref[2] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);
225 226
            d += chroma_cmp_func(s, uvtemp  , src[1], uvstride, h>>1);
            d += chroma_cmp_func(s, uvtemp+8, src[2], uvstride, h>>1);
227
        }
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
    return d;
}

static int cmp_simple(MpegEncContext *s, const int x, const int y,
                      int ref_index, int src_index,
                      me_cmp_func cmp_func, me_cmp_func chroma_cmp_func){
    return cmp_inline(s,x,y,0,0,0,16,ref_index,src_index, cmp_func, chroma_cmp_func, 0, 0);
}

static int cmp_fpel_internal(MpegEncContext *s, const int x, const int y,
                      const int size, const int h, int ref_index, int src_index,
                      me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
    if(flags&FLAG_DIRECT){
        return cmp_direct_inline(s,x,y,0,0,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags&FLAG_QPEL);
    }else{
        return cmp_inline(s,x,y,0,0,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0, flags&FLAG_CHROMA);
244
    }
245 246 247 248 249 250 251 252 253
}

static int cmp_internal(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
                      const int size, const int h, int ref_index, int src_index,
                      me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
    if(flags&FLAG_DIRECT){
        return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags&FLAG_QPEL);
    }else{
        return cmp_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags&FLAG_QPEL, flags&FLAG_CHROMA);
254
    }
255
}
256

257
/** @brief compares a block (either a full macroblock or a partition thereof)
258 259
    against a proposed motion-compensated prediction of that block
 */
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
static av_always_inline int cmp(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
                      const int size, const int h, int ref_index, int src_index,
                      me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
    if(av_builtin_constant_p(flags) && av_builtin_constant_p(h) && av_builtin_constant_p(size)
       && av_builtin_constant_p(subx) && av_builtin_constant_p(suby)
       && flags==0 && h==16 && size==0 && subx==0 && suby==0){
        return cmp_simple(s,x,y,ref_index,src_index, cmp_func, chroma_cmp_func);
    }else if(av_builtin_constant_p(subx) && av_builtin_constant_p(suby)
       && subx==0 && suby==0){
        return cmp_fpel_internal(s,x,y,size,h,ref_index,src_index, cmp_func, chroma_cmp_func,flags);
    }else{
        return cmp_internal(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags);
    }
}

static int cmp_hpel(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
                      const int size, const int h, int ref_index, int src_index,
                      me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
    if(flags&FLAG_DIRECT){
        return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0);
    }else{
        return cmp_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0, flags&FLAG_CHROMA);
    }
}

static int cmp_qpel(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
                      const int size, const int h, int ref_index, int src_index,
                      me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
    if(flags&FLAG_DIRECT){
        return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 1);
    }else{
        return cmp_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 1, flags&FLAG_CHROMA);
    }
293
}
Michael Niedermayer's avatar
Michael Niedermayer committed
294 295 296

#include "motion_est_template.c"

297
static int zero_cmp(MpegEncContext *s, uint8_t *a, uint8_t *b,
298
                    ptrdiff_t stride, int h)
299
{
Michael Niedermayer's avatar
Michael Niedermayer committed
300 301 302
    return 0;
}

303
static void zero_hpel(uint8_t *a, const uint8_t *b, ptrdiff_t stride, int h){
Michael Niedermayer's avatar
Michael Niedermayer committed
304 305
}

306
int ff_init_me(MpegEncContext *s){
307
    MotionEstContext * const c= &s->me;
308 309
    int cache_size= FFMIN(ME_MAP_SIZE>>ME_MAP_SHIFT, 1<<ME_MAP_SHIFT);
    int dia_size= FFMAX(FFABS(s->avctx->dia_size)&255, FFABS(s->avctx->pre_dia_size)&255);
310

311
    if(FFMIN(s->avctx->dia_size, s->avctx->pre_dia_size) < -FFMIN(ME_MAP_SIZE, MAX_SAB_SIZE)){
312 313 314
        av_log(s->avctx, AV_LOG_ERROR, "ME_MAP size is too small for SAB diamond\n");
        return -1;
    }
315

Michael Niedermayer's avatar
Michael Niedermayer committed
316
    c->avctx= s->avctx;
317

318 319 320
    if(s->codec_id == AV_CODEC_ID_H261)
        c->avctx->me_sub_cmp = c->avctx->me_cmp;

321 322 323
    if(cache_size < 2*dia_size && !c->stride){
        av_log(s->avctx, AV_LOG_INFO, "ME_MAP size may be a little small for the selected diamond size\n");
    }
324

325 326 327 328
    ff_set_cmp(&s->mecc, s->mecc.me_pre_cmp, c->avctx->me_pre_cmp);
    ff_set_cmp(&s->mecc, s->mecc.me_cmp,     c->avctx->me_cmp);
    ff_set_cmp(&s->mecc, s->mecc.me_sub_cmp, c->avctx->me_sub_cmp);
    ff_set_cmp(&s->mecc, s->mecc.mb_cmp,     c->avctx->mb_cmp);
329

330 331 332
    c->flags    = get_flags(c, 0, c->avctx->me_cmp    &FF_CMP_CHROMA);
    c->sub_flags= get_flags(c, 0, c->avctx->me_sub_cmp&FF_CMP_CHROMA);
    c->mb_flags = get_flags(c, 0, c->avctx->mb_cmp    &FF_CMP_CHROMA);
Fabrice Bellard's avatar
Fabrice Bellard committed
333

334
/*FIXME s->no_rounding b_type*/
335
    if (s->avctx->flags & AV_CODEC_FLAG_QPEL) {
336
        c->sub_motion_search= qpel_motion_search;
337 338 339 340 341
        c->qpel_avg = s->qdsp.avg_qpel_pixels_tab;
        if (s->no_rounding)
            c->qpel_put = s->qdsp.put_no_rnd_qpel_pixels_tab;
        else
            c->qpel_put = s->qdsp.put_qpel_pixels_tab;
Michael Niedermayer's avatar
Michael Niedermayer committed
342
    }else{
343
        if(c->avctx->me_sub_cmp&FF_CMP_CHROMA)
344
            c->sub_motion_search= hpel_motion_search;
345 346
        else if(   c->avctx->me_sub_cmp == FF_CMP_SAD
                && c->avctx->    me_cmp == FF_CMP_SAD
347
                && c->avctx->    mb_cmp == FF_CMP_SAD)
348
            c->sub_motion_search= sad_hpel_motion_search; // 2050 vs. 2450 cycles
Michael Niedermayer's avatar
Michael Niedermayer committed
349
        else
350
            c->sub_motion_search= hpel_motion_search;
Michael Niedermayer's avatar
Michael Niedermayer committed
351
    }
352 353 354 355 356
    c->hpel_avg = s->hdsp.avg_pixels_tab;
    if (s->no_rounding)
        c->hpel_put = s->hdsp.put_no_rnd_pixels_tab;
    else
        c->hpel_put = s->hdsp.put_pixels_tab;
Michael Niedermayer's avatar
Michael Niedermayer committed
357

358
    if(s->linesize){
359
        c->stride  = s->linesize;
360
        c->uvstride= s->uvlinesize;
361
    }else{
362 363
        c->stride  = 16*s->mb_width + 32;
        c->uvstride=  8*s->mb_width + 16;
364
    }
365

Diego Biurrun's avatar
Diego Biurrun committed
366 367 368
    /* 8x8 fullpel search would need a 4x4 chroma compare, which we do
     * not have yet, and even if we had, the motion estimation code
     * does not expect it. */
369 370 371 372 373
    if (s->codec_id != AV_CODEC_ID_SNOW) {
        if ((c->avctx->me_cmp & FF_CMP_CHROMA) /* && !s->mecc.me_cmp[2] */)
            s->mecc.me_cmp[2] = zero_cmp;
        if ((c->avctx->me_sub_cmp & FF_CMP_CHROMA) && !s->mecc.me_sub_cmp[2])
            s->mecc.me_sub_cmp[2] = zero_cmp;
374 375
        c->hpel_put[2][0]= c->hpel_put[2][1]=
        c->hpel_put[2][2]= c->hpel_put[2][3]= zero_hpel;
Michael Niedermayer's avatar
Michael Niedermayer committed
376 377
    }

378
    if(s->codec_id == AV_CODEC_ID_H261){
379 380 381
        c->sub_motion_search= no_sub_motion_search;
    }

382
    return 0;
Michael Niedermayer's avatar
Michael Niedermayer committed
383
}
384

Michael Niedermayer's avatar
Michael Niedermayer committed
385
#define CHECK_SAD_HALF_MV(suffix, x, y) \
386
{\
387
    d  = s->mecc.pix_abs[size][(x ? 1 : 0) + (y ? 2 : 0)](NULL, pix, ptr + ((x) >> 1), stride, h); \
Michael Niedermayer's avatar
Michael Niedermayer committed
388
    d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*penalty_factor;\
389 390
    COPY3_IF_LT(dminh, d, dx, x, dy, y)\
}
391

392
static int sad_hpel_motion_search(MpegEncContext * s,
393
                                  int *mx_ptr, int *my_ptr, int dmin,
394 395
                                  int src_index, int ref_index,
                                  int size, int h)
Fabrice Bellard's avatar
Fabrice Bellard committed
396
{
397 398
    MotionEstContext * const c= &s->me;
    const int penalty_factor= c->sub_penalty_factor;
399
    int mx, my, dminh;
400
    uint8_t *pix, *ptr;
401
    int stride= c->stride;
402
    LOAD_COMMON
403

404
    av_assert2(c->sub_flags == 0);
Fabrice Bellard's avatar
Fabrice Bellard committed
405

406
    if(c->skip){
407 408 409 410
        *mx_ptr = 0;
        *my_ptr = 0;
        return dmin;
    }
411

412
    pix = c->src[src_index][0];
413

414 415
    mx = *mx_ptr;
    my = *my_ptr;
416
    ptr = c->ref[ref_index][0] + (my * stride) + mx;
417

418 419
    dminh = dmin;

420
    if (mx > xmin && mx < xmax &&
421
        my > ymin && my < ymax) {
422
        int dx=0, dy=0;
423
        int d, pen_x, pen_y;
424
        const int index= my*(1<<ME_MAP_SHIFT) + mx;
425 426 427 428
        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)];
429 430
        mx += mx;
        my += my;
431

432

433 434 435
        pen_x= pred_x + mx;
        pen_y= pred_y + my;

436
        ptr-= stride;
437
        if(t<=b){
Michael Niedermayer's avatar
Michael Niedermayer committed
438
            CHECK_SAD_HALF_MV(y2 , 0, -1)
439
            if(l<=r){
Michael Niedermayer's avatar
Michael Niedermayer committed
440
                CHECK_SAD_HALF_MV(xy2, -1, -1)
441
                if(t+r<=b+l){
Michael Niedermayer's avatar
Michael Niedermayer committed
442
                    CHECK_SAD_HALF_MV(xy2, +1, -1)
443
                    ptr+= stride;
444
                }else{
445
                    ptr+= stride;
Michael Niedermayer's avatar
Michael Niedermayer committed
446
                    CHECK_SAD_HALF_MV(xy2, -1, +1)
447
                }
Michael Niedermayer's avatar
Michael Niedermayer committed
448
                CHECK_SAD_HALF_MV(x2 , -1,  0)
449
            }else{
Michael Niedermayer's avatar
Michael Niedermayer committed
450
                CHECK_SAD_HALF_MV(xy2, +1, -1)
451
                if(t+l<=b+r){
Michael Niedermayer's avatar
Michael Niedermayer committed
452
                    CHECK_SAD_HALF_MV(xy2, -1, -1)
453
                    ptr+= stride;
454
                }else{
455
                    ptr+= stride;
Michael Niedermayer's avatar
Michael Niedermayer committed
456
                    CHECK_SAD_HALF_MV(xy2, +1, +1)
457
                }
Michael Niedermayer's avatar
Michael Niedermayer committed
458
                CHECK_SAD_HALF_MV(x2 , +1,  0)
459 460 461 462
            }
        }else{
            if(l<=r){
                if(t+l<=b+r){
Michael Niedermayer's avatar
Michael Niedermayer committed
463
                    CHECK_SAD_HALF_MV(xy2, -1, -1)
464
                    ptr+= stride;
465
                }else{
466
                    ptr+= stride;
Michael Niedermayer's avatar
Michael Niedermayer committed
467
                    CHECK_SAD_HALF_MV(xy2, +1, +1)
468
                }
Michael Niedermayer's avatar
Michael Niedermayer committed
469 470
                CHECK_SAD_HALF_MV(x2 , -1,  0)
                CHECK_SAD_HALF_MV(xy2, -1, +1)
471 472
            }else{
                if(t+r<=b+l){
Michael Niedermayer's avatar
Michael Niedermayer committed
473
                    CHECK_SAD_HALF_MV(xy2, +1, -1)
474
                    ptr+= stride;
475
                }else{
476
                    ptr+= stride;
Michael Niedermayer's avatar
Michael Niedermayer committed
477
                    CHECK_SAD_HALF_MV(xy2, -1, +1)
478
                }
Michael Niedermayer's avatar
Michael Niedermayer committed
479 480
                CHECK_SAD_HALF_MV(x2 , +1,  0)
                CHECK_SAD_HALF_MV(xy2, +1, +1)
481
            }
Michael Niedermayer's avatar
Michael Niedermayer committed
482
            CHECK_SAD_HALF_MV(y2 ,  0, +1)
483 484 485
        }
        mx+=dx;
        my+=dy;
486 487

    }else{
488 489
        mx += mx;
        my += my;
490 491 492 493
    }

    *mx_ptr = mx;
    *my_ptr = my;
494
    return dminh;
495 496
}

497
static inline void set_p_mv_tables(MpegEncContext * s, int mx, int my, int mv4)
498
{
499
    const int xy= s->mb_x + s->mb_y*s->mb_stride;
500

501 502
    s->p_mv_table[xy][0] = mx;
    s->p_mv_table[xy][1] = my;
503

Diego Biurrun's avatar
Diego Biurrun committed
504
    /* has already been set to the 4 MV if 4MV is done */
505
    if(mv4){
506 507
        int mot_xy= s->block_index[0];

508 509 510 511
        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;
512

513
        mot_xy += s->b8_stride;
514 515 516 517
        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;
518 519 520
    }
}

521 522 523
/**
 * get fullpel ME search limits.
 */
524
static inline void get_limits(MpegEncContext *s, int x, int y)
Fabrice Bellard's avatar
Fabrice Bellard committed
525
{
526
    MotionEstContext * const c= &s->me;
527
    int range= c->avctx->me_range >> (1 + !!(c->flags&FLAG_QPEL));
528
    int max_range = MAX_MV >> (1 + !!(c->flags&FLAG_QPEL));
529
/*
530
    if(c->avctx->me_range) c->range= c->avctx->me_range >> 1;
531
    else                   c->range= 16;
532
*/
Fabrice Bellard's avatar
Fabrice Bellard committed
533
    if (s->unrestricted_mv) {
534 535
        c->xmin = - x - 16;
        c->ymin = - y - 16;
536 537
        c->xmax = - x + s->width;
        c->ymax = - y + s->height;
538
    } else if (s->out_format == FMT_H261){
539
        // Search range of H.261 is different from other codec standards
540 541
        c->xmin = (x > 15) ? - 15 : 0;
        c->ymin = (y > 15) ? - 15 : 0;
542
        c->xmax = (x < s->mb_width * 16 - 16) ? 15 : 0;
543
        c->ymax = (y < s->mb_height * 16 - 16) ? 15 : 0;
Fabrice Bellard's avatar
Fabrice Bellard committed
544
    } else {
545 546 547 548
        c->xmin = - x;
        c->ymin = - y;
        c->xmax = - x + s->mb_width *16 - 16;
        c->ymax = - y + s->mb_height*16 - 16;
Fabrice Bellard's avatar
Fabrice Bellard committed
549
    }
550 551
    if(!range || range > max_range)
        range = max_range;
552 553 554 555 556 557
    if(range){
        c->xmin = FFMAX(c->xmin,-range);
        c->xmax = FFMIN(c->xmax, range);
        c->ymin = FFMAX(c->ymin,-range);
        c->ymax = FFMIN(c->ymax, range);
    }
558 559
}

560 561
static inline void init_mv4_ref(MotionEstContext *c){
    const int stride= c->stride;
562 563 564 565 566 567 568 569 570

    c->ref[1][0] = c->ref[0][0] + 8;
    c->ref[2][0] = c->ref[0][0] + 8*stride;
    c->ref[3][0] = c->ref[2][0] + 8;
    c->src[1][0] = c->src[0][0] + 8;
    c->src[2][0] = c->src[0][0] + 8*stride;
    c->src[3][0] = c->src[2][0] + 8;
}

571
static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift)
572
{
573
    MotionEstContext * const c= &s->me;
574 575
    const int size= 1;
    const int h=8;
576 577
    int block;
    int P[10][2];
578
    int dmin_sum=0, mx4_sum=0, my4_sum=0, i;
579
    int same=1;
580
    const int stride= c->stride;
581
    uint8_t *mv_penalty= c->current_mv_penalty;
582
    int safety_clipping= s->unrestricted_mv && (s->width&15) && (s->height&15);
583

584
    init_mv4_ref(c);
585

586 587 588 589 590
    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};
591
        const int mot_stride = s->b8_stride;
592
        const int mot_xy = s->block_index[block];
593

594
        if(safety_clipping){
595 596 597 598
            c->xmax = - 16*s->mb_x + s->width  - 8*(block &1);
            c->ymax = - 16*s->mb_y + s->height - 8*(block>>1);
        }

599 600
        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];
601

602
        if(P_LEFT[0]       > (c->xmax<<shift)) P_LEFT[0]       = (c->xmax<<shift);
603 604

        /* special case for first line */
605
        if (s->first_slice_line && block<2) {
606 607
            c->pred_x= pred_x4= P_LEFT[0];
            c->pred_y= pred_y4= P_LEFT[1];
608
        } else {
609 610 611 612
            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];
613 614 615 616
            if(P_TOP[1]      > (c->ymax<<shift)) P_TOP[1]     = (c->ymax<<shift);
            if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
            if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
            if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
617

618 619 620
            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]);

621 622
            c->pred_x= pred_x4 = P_MEDIAN[0];
            c->pred_y= pred_y4 = P_MEDIAN[1];
623 624 625
        }
        P_MV1[0]= mx;
        P_MV1[1]= my;
626
        if(safety_clipping)
627 628 629 630 631
            for(i=1; i<10; i++){
                if (s->first_slice_line && block<2 && i>1 && i<9)
                    continue;
                if (i>4 && i<9)
                    continue;
632 633 634
                if(P[i][0] > (c->xmax<<shift)) P[i][0]= (c->xmax<<shift);
                if(P[i][1] > (c->ymax<<shift)) P[i][1]= (c->ymax<<shift);
            }
635

636
        dmin4 = epzs_motion_search4(s, &mx4, &my4, P, block, block, s->p_mv_table, (1<<16)>>shift);
637

638
        dmin4= c->sub_motion_search(s, &mx4, &my4, dmin4, block, block, size, h);
639

640
        if (s->mecc.me_sub_cmp[0] != s->mecc.mb_cmp[0]) {
641
            int dxy;
642
            const int offset= ((block&1) + (block>>1)*stride)*8;
643
            uint8_t *dest_y = c->scratchpad + offset;
644
            if(s->quarter_sample){
645
                uint8_t *ref= c->ref[block][0] + (mx4>>2) + (my4>>2)*stride;
646 647 648
                dxy = ((my4 & 3) << 2) | (mx4 & 3);

                if(s->no_rounding)
649
                    s->qdsp.put_no_rnd_qpel_pixels_tab[1][dxy](dest_y, ref, stride);
650
                else
651
                    s->qdsp.put_qpel_pixels_tab[1][dxy](dest_y, ref, stride);
652
            }else{
653
                uint8_t *ref= c->ref[block][0] + (mx4>>1) + (my4>>1)*stride;
654 655 656
                dxy = ((my4 & 1) << 1) | (mx4 & 1);

                if(s->no_rounding)
657
                    s->hdsp.put_no_rnd_pixels_tab[1][dxy](dest_y    , ref    , stride, h);
658
                else
659
                    s->hdsp.put_pixels_tab       [1][dxy](dest_y    , ref    , stride, h);
660
            }
661
            dmin_sum+= (mv_penalty[mx4-pred_x4] + mv_penalty[my4-pred_y4])*c->mb_penalty_factor;
662 663 664 665 666 667 668 669 670 671
        }else
            dmin_sum+= dmin4;

        if(s->quarter_sample){
            mx4_sum+= mx4/2;
            my4_sum+= my4/2;
        }else{
            mx4_sum+= mx4;
            my4_sum+= my4;
        }
672

673 674
        s->current_picture.motion_val[0][s->block_index[block]][0] = mx4;
        s->current_picture.motion_val[0][s->block_index[block]][1] = my4;
675 676

        if(mx4 != mx || my4 != my) same=0;
677
    }
678

679 680
    if(same)
        return INT_MAX;
681

682 683 684 685 686
    if (s->mecc.me_sub_cmp[0] != s->mecc.mb_cmp[0]) {
        dmin_sum += s->mecc.mb_cmp[0](s,
                                      s->new_picture.f->data[0] +
                                      s->mb_x * 16 + s->mb_y * 16 * stride,
                                      c->scratchpad, stride, 16);
687
    }
688

689
    if(c->avctx->mb_cmp&FF_CMP_CHROMA){
690 691 692 693 694 695 696
        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);
697

698
        offset= (s->mb_x*8 + (mx>>1)) + (s->mb_y*8 + (my>>1))*s->uvlinesize;
699

700
        if(s->no_rounding){
701 702
            s->hdsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad    , s->last_picture.f->data[1] + offset, s->uvlinesize, 8);
            s->hdsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad + 8, s->last_picture.f->data[2] + offset, s->uvlinesize, 8);
703
        }else{
704 705
            s->hdsp.put_pixels_tab       [1][dxy](c->scratchpad    , s->last_picture.f->data[1] + offset, s->uvlinesize, 8);
            s->hdsp.put_pixels_tab       [1][dxy](c->scratchpad + 8, s->last_picture.f->data[2] + offset, s->uvlinesize, 8);
706 707
        }

708 709
        dmin_sum += s->mecc.mb_cmp[1](s, s->new_picture.f->data[1] + s->mb_x * 8 + s->mb_y * 8 * s->uvlinesize, c->scratchpad,     s->uvlinesize, 8);
        dmin_sum += s->mecc.mb_cmp[1](s, s->new_picture.f->data[2] + s->mb_x * 8 + s->mb_y * 8 * s->uvlinesize, c->scratchpad + 8, s->uvlinesize, 8);
710
    }
711

712 713
    c->pred_x= mx;
    c->pred_y= my;
714

715
    switch(c->avctx->mb_cmp&0xFF){
716 717 718 719 720
    /*case FF_CMP_SSE:
        return dmin_sum+ 32*s->qscale*s->qscale;*/
    case FF_CMP_RD:
        return dmin_sum;
    default:
721
        return dmin_sum+ 11*c->mb_penalty_factor;
722
    }
723 724
}

725 726 727 728 729 730 731 732 733 734 735 736 737
static inline void init_interlaced_ref(MpegEncContext *s, int ref_index){
    MotionEstContext * const c= &s->me;

    c->ref[1+ref_index][0] = c->ref[0+ref_index][0] + s->linesize;
    c->src[1][0] = c->src[0][0] + s->linesize;
    if(c->flags & FLAG_CHROMA){
        c->ref[1+ref_index][1] = c->ref[0+ref_index][1] + s->uvlinesize;
        c->ref[1+ref_index][2] = c->ref[0+ref_index][2] + s->uvlinesize;
        c->src[1][1] = c->src[0][1] + s->uvlinesize;
        c->src[1][2] = c->src[0][2] + s->uvlinesize;
    }
}

738
static int interlaced_search(MpegEncContext *s, int ref_index,
739
                             int16_t (*mv_tables[2][2])[2], uint8_t *field_select_tables[2], int mx, int my, int user_field_select)
740
{
741
    MotionEstContext * const c= &s->me;
742 743 744 745
    const int size=0;
    const int h=8;
    int block;
    int P[10][2];
746
    uint8_t * const mv_penalty= c->current_mv_penalty;
747 748 749 750 751
    int same=1;
    const int stride= 2*s->linesize;
    int dmin_sum= 0;
    const int mot_stride= s->mb_stride;
    const int xy= s->mb_x + s->mb_y*mot_stride;
752

753 754 755 756
    c->ymin>>=1;
    c->ymax>>=1;
    c->stride<<=1;
    c->uvstride<<=1;
757
    init_interlaced_ref(s, ref_index);
758

759 760 761 762 763 764
    for(block=0; block<2; block++){
        int field_select;
        int best_dmin= INT_MAX;
        int best_field= -1;

        for(field_select=0; field_select<2; field_select++){
765
            int dmin, mx_i, my_i;
766
            int16_t (*mv_table)[2]= mv_tables[block][field_select];
767

768
            if(user_field_select){
769 770
                av_assert1(field_select==0 || field_select==1);
                av_assert1(field_select_tables[block][xy]==0 || field_select_tables[block][xy]==1);
771 772 773
                if(field_select_tables[block][xy] != field_select)
                    continue;
            }
774

775 776
            P_LEFT[0] = mv_table[xy - 1][0];
            P_LEFT[1] = mv_table[xy - 1][1];
777
            if(P_LEFT[0]       > (c->xmax<<1)) P_LEFT[0]       = (c->xmax<<1);
778

779 780
            c->pred_x= P_LEFT[0];
            c->pred_y= P_LEFT[1];
781

782
            if(!s->first_slice_line){
783 784 785 786
                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];
787 788 789 790
                if(P_TOP[1]      > (c->ymax<<1)) P_TOP[1]     = (c->ymax<<1);
                if(P_TOPRIGHT[0] < (c->xmin<<1)) P_TOPRIGHT[0]= (c->xmin<<1);
                if(P_TOPRIGHT[0] > (c->xmax<<1)) P_TOPRIGHT[0]= (c->xmax<<1);
                if(P_TOPRIGHT[1] > (c->ymax<<1)) P_TOPRIGHT[1]= (c->ymax<<1);
791

792 793 794 795 796
                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;
797

798
            dmin = epzs_motion_search2(s, &mx_i, &my_i, P, block, field_select+ref_index, mv_table, (1<<16)>>1);
799

800
            dmin= c->sub_motion_search(s, &mx_i, &my_i, dmin, block, field_select+ref_index, size, h);
801

802 803
            mv_table[xy][0]= mx_i;
            mv_table[xy][1]= my_i;
804

805
            if (s->mecc.me_sub_cmp[0] != s->mecc.mb_cmp[0]) {
806 807 808
                int dxy;

                //FIXME chroma ME
809
                uint8_t *ref= c->ref[field_select+ref_index][0] + (mx_i>>1) + (my_i>>1)*stride;
810 811 812
                dxy = ((my_i & 1) << 1) | (mx_i & 1);

                if(s->no_rounding){
813
                    s->hdsp.put_no_rnd_pixels_tab[size][dxy](c->scratchpad, ref    , stride, h);
814
                }else{
815
                    s->hdsp.put_pixels_tab       [size][dxy](c->scratchpad, ref    , stride, h);
816
                }
817
                dmin = s->mecc.mb_cmp[size](s, c->src[block][0], c->scratchpad, stride, h);
818
                dmin+= (mv_penalty[mx_i-c->pred_x] + mv_penalty[my_i-c->pred_y] + 1)*c->mb_penalty_factor;
819
            }else
820
                dmin+= c->mb_penalty_factor; //field_select bits
821

822
            dmin += field_select != block; //slightly prefer same field
823

824 825 826 827 828 829 830 831 832 833
            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;
834
            if(mv_table[xy][1]*2 != my) same=0;
835 836 837 838 839 840
            if(best_field != block) same=0;
        }

        field_select_tables[block][xy]= best_field;
        dmin_sum += best_dmin;
    }
841

842 843 844 845
    c->ymin<<=1;
    c->ymax<<=1;
    c->stride>>=1;
    c->uvstride>>=1;
846 847 848

    if(same)
        return INT_MAX;
849

850
    switch(c->avctx->mb_cmp&0xFF){
851 852 853 854 855
    /*case FF_CMP_SSE:
        return dmin_sum+ 32*s->qscale*s->qscale;*/
    case FF_CMP_RD:
        return dmin_sum;
    default:
856
        return dmin_sum+ 11*c->mb_penalty_factor;
857 858 859
    }
}

860 861 862 863 864 865 866
static inline int get_penalty_factor(int lambda, int lambda2, int type){
    switch(type&0xFF){
    default:
    case FF_CMP_SAD:
        return lambda>>FF_LAMBDA_SHIFT;
    case FF_CMP_DCT:
        return (3*lambda)>>(FF_LAMBDA_SHIFT+1);
867 868 869 870
    case FF_CMP_W53:
        return (4*lambda)>>(FF_LAMBDA_SHIFT);
    case FF_CMP_W97:
        return (2*lambda)>>(FF_LAMBDA_SHIFT);
871 872 873 874 875 876 877 878 879
    case FF_CMP_SATD:
    case FF_CMP_DCT264:
        return (2*lambda)>>FF_LAMBDA_SHIFT;
    case FF_CMP_RD:
    case FF_CMP_PSNR:
    case FF_CMP_SSE:
    case FF_CMP_NSSE:
        return lambda2>>FF_LAMBDA_SHIFT;
    case FF_CMP_BIT:
880
    case FF_CMP_MEDIAN_SAD:
881 882 883 884
        return 1;
    }
}

885 886 887
void ff_estimate_p_frame_motion(MpegEncContext * s,
                                int mb_x, int mb_y)
{
888
    MotionEstContext * const c= &s->me;
889
    uint8_t *pix, *ppix;
890
    int sum, mx = 0, my = 0, dmin = 0;
891 892
    int varc;            ///< the variance of the block (sum of squared (p[y][x]-average))
    int vard;            ///< sum of squared differences with the estimated motion vector
893
    int P[10][2];
894 895
    const int shift= 1+s->quarter_sample;
    int mb_type=0;
Michael Niedermayer's avatar
Michael Niedermayer committed
896
    Picture * const pic= &s->current_picture;
897

898
    init_ref(c, s->new_picture.f->data, s->last_picture.f->data, NULL, 16*mb_x, 16*mb_y, 0);
899

900 901 902
    av_assert0(s->quarter_sample==0 || s->quarter_sample==1);
    av_assert0(s->linesize == c->stride);
    av_assert0(s->uvlinesize == c->uvstride);
Michael Niedermayer's avatar
Michael Niedermayer committed
903

904 905 906
    c->penalty_factor    = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
    c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
    c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
907
    c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_DMV;
908

909
    get_limits(s, 16*mb_x, 16*mb_y);
910
    c->skip=0;
911

912 913
    /* intra / predictive decision */
    pix = c->src[0][0];
914 915 916
    sum  = s->mpvencdsp.pix_sum(pix, s->linesize);
    varc = s->mpvencdsp.pix_norm1(pix, s->linesize) -
           (((unsigned) sum * sum) >> 8) + 500;
917 918

    pic->mb_mean[s->mb_stride * mb_y + mb_x] = (sum+128)>>8;
919 920
    pic->mb_var [s->mb_stride * mb_y + mb_x] = (varc+128)>>8;
    c->mb_var_sum_temp += (varc+128)>>8;
921

922 923 924
    if (s->motion_est != FF_ME_ZERO) {
        const int mot_stride = s->b8_stride;
        const int mot_xy = s->block_index[0];
925

926 927
        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];
928

929 930
        if (P_LEFT[0] > (c->xmax << shift))
            P_LEFT[0] =  c->xmax << shift;
931

932 933 934 935 936 937 938
        if (!s->first_slice_line) {
            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];
            if (P_TOP[1] > (c->ymax << shift))
                P_TOP[1] =  c->ymax << shift;
939 940 941 942
            if (P_TOPRIGHT[0] < (c->xmin * (1 << shift)))
                P_TOPRIGHT[0] =  c->xmin * (1 << shift);
            if (P_TOPRIGHT[1] > (c->ymax * (1 << shift)))
                P_TOPRIGHT[1] =  c->ymax * (1 << shift);
943 944 945 946 947 948 949

            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) {
                c->pred_x = P_MEDIAN[0];
                c->pred_y = P_MEDIAN[1];
950
            } else { /* MPEG-1 at least */
951 952 953 954 955 956
                c->pred_x = P_LEFT[0];
                c->pred_y = P_LEFT[1];
            }
        } else {
            c->pred_x = P_LEFT[0];
            c->pred_y = P_LEFT[1];
957
        }
958
        dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
Fabrice Bellard's avatar
Fabrice Bellard committed
959 960
    }

961
    /* At this point (mx,my) are full-pell and the relative displacement */
962
    ppix = c->ref[0][0] + (my * s->linesize) + mx;
963

964
    vard = s->mecc.sse[0](NULL, pix, ppix, s->linesize, 16);
965

966 967
    pic->mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8;
    c->mc_mb_var_sum_temp += (vard+128)>>8;
968

969
    if (c->avctx->mb_decision > FF_MB_DECISION_SIMPLE) {
970 971 972
        int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
        int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
        c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
973

974
        if (vard*2 + 200*256 > varc)
975
            mb_type|= CANDIDATE_MB_TYPE_INTRA;
976 977
        if (varc*2 + 200*256 > vard || s->qscale > 24){
//        if (varc*2 + 200*256 + 50*(s->lambda2>>FF_LAMBDA_SHIFT) > vard){
978
            mb_type|= CANDIDATE_MB_TYPE_INTER;
979
            c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
980
            if (s->mpv_flags & FF_MPV_FLAG_MV0)
981
                if(mx || my)
982
                    mb_type |= CANDIDATE_MB_TYPE_SKIPPED; //FIXME check difference
983
        }else{
Michael Niedermayer's avatar
Michael Niedermayer committed
984 985
            mx <<=shift;
            my <<=shift;
Fabrice Bellard's avatar
Fabrice Bellard committed
986
        }
987
        if ((s->avctx->flags & AV_CODEC_FLAG_4MV)
988
           && !c->skip && varc>50<<8 && vard>10<<8){
989 990
            if(h263_mv4_search(s, mx, my, shift) < INT_MAX)
                mb_type|=CANDIDATE_MB_TYPE_INTER4V;
991 992 993 994

            set_p_mv_tables(s, mx, my, 0);
        }else
            set_p_mv_tables(s, mx, my, 1);
995
        if ((s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)
996
           && !c->skip){ //FIXME varc/d checks
997
            if(interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 0) < INT_MAX)
998 999
                mb_type |= CANDIDATE_MB_TYPE_INTER_I;
        }
1000
    }else{
1001
        int intra_score, i;
1002
        mb_type= CANDIDATE_MB_TYPE_INTER;
1003

1004
        dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
1005
        if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
1006
            dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
1007

1008
        if ((s->avctx->flags & AV_CODEC_FLAG_4MV)
1009
           && !c->skip && varc>50<<8 && vard>10<<8){
1010
            int dmin4= h263_mv4_search(s, mx, my, shift);
1011
            if(dmin4 < dmin){
1012
                mb_type= CANDIDATE_MB_TYPE_INTER4V;
1013
                dmin=dmin4;
1014
            }
1015
        }
1016
        if ((s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)
1017
           && !c->skip){ //FIXME varc/d checks
1018
            int dmin_i= interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 0);
1019 1020 1021 1022 1023
            if(dmin_i < dmin){
                mb_type = CANDIDATE_MB_TYPE_INTER_I;
                dmin= dmin_i;
            }
        }
1024

1025
        set_p_mv_tables(s, mx, my, mb_type!=CANDIDATE_MB_TYPE_INTER4V);
1026 1027

        /* get intra luma score */
1028
        if((c->avctx->mb_cmp&0xFF)==FF_CMP_SSE){
1029
            intra_score= varc - 500;
1030
        }else{
1031
            unsigned mean = (sum+128)>>8;
1032
            mean*= 0x01010101;
1033

1034
            for(i=0; i<16; i++){
1035 1036 1037 1038
                *(uint32_t*)(&c->scratchpad[i*s->linesize+ 0]) = mean;
                *(uint32_t*)(&c->scratchpad[i*s->linesize+ 4]) = mean;
                *(uint32_t*)(&c->scratchpad[i*s->linesize+ 8]) = mean;
                *(uint32_t*)(&c->scratchpad[i*s->linesize+12]) = mean;
1039 1040
            }

1041
            intra_score= s->mecc.mb_cmp[0](s, c->scratchpad, pix, s->linesize, 16);
1042
        }
1043
        intra_score += c->mb_penalty_factor*16;
1044

1045
        if(intra_score < dmin){
1046
            mb_type= CANDIDATE_MB_TYPE_INTRA;
1047
            s->current_picture.mb_type[mb_y*s->mb_stride + mb_x] = CANDIDATE_MB_TYPE_INTRA; //FIXME cleanup
1048
        }else
1049
            s->current_picture.mb_type[mb_y*s->mb_stride + mb_x] = 0;
1050

1051 1052 1053 1054
        {
            int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
            int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
            c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
1055
        }
Fabrice Bellard's avatar
Fabrice Bellard committed
1056
    }
1057

1058
    s->mb_type[mb_y*s->mb_stride + mb_x]= mb_type;
1059 1060
}

1061 1062 1063
int ff_pre_estimate_p_frame_motion(MpegEncContext * s,
                                    int mb_x, int mb_y)
{
1064
    MotionEstContext * const c= &s->me;
1065
    int mx, my, dmin;
1066 1067
    int P[10][2];
    const int shift= 1+s->quarter_sample;
1068
    const int xy= mb_x + mb_y*s->mb_stride;
1069
    init_ref(c, s->new_picture.f->data, s->last_picture.f->data, NULL, 16*mb_x, 16*mb_y, 0);
1070

1071
    av_assert0(s->quarter_sample==0 || s->quarter_sample==1);
1072

1073
    c->pre_penalty_factor    = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_pre_cmp);
1074
    c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_DMV;
1075

1076
    get_limits(s, 16*mb_x, 16*mb_y);
1077
    c->skip=0;
1078 1079 1080 1081

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

1082
    if(P_LEFT[0]       < (c->xmin<<shift)) P_LEFT[0]       = (c->xmin<<shift);
1083 1084

    /* special case for first line */
1085
    if (s->first_slice_line) {
1086 1087
        c->pred_x= P_LEFT[0];
        c->pred_y= P_LEFT[1];
1088
        P_TOP[0]= P_TOPRIGHT[0]= P_MEDIAN[0]=
1089
        P_TOP[1]= P_TOPRIGHT[1]= P_MEDIAN[1]= 0; //FIXME
1090
    } else {
1091 1092 1093 1094
        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];
1095 1096 1097
        if(P_TOP[1]      < (c->ymin<<shift)) P_TOP[1]     = (c->ymin<<shift);
        if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
        if(P_TOPRIGHT[1] < (c->ymin<<shift)) P_TOPRIGHT[1]= (c->ymin<<shift);
1098

1099 1100 1101
        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]);

1102 1103
        c->pred_x = P_MEDIAN[0];
        c->pred_y = P_MEDIAN[1];
1104
    }
1105

1106
    dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
1107

1108 1109
    s->p_mv_table[xy][0] = mx<<shift;
    s->p_mv_table[xy][1] = my<<shift;
1110

1111 1112 1113
    return dmin;
}

1114 1115
static int estimate_motion_b(MpegEncContext *s, int mb_x, int mb_y,
                             int16_t (*mv_table)[2], int ref_index, int f_code)
1116
{
1117
    MotionEstContext * const c= &s->me;
1118
    int mx = 0, my = 0, dmin = 0;
1119
    int P[10][2];
1120
    const int shift= 1+s->quarter_sample;
1121 1122
    const int mot_stride = s->mb_stride;
    const int mot_xy = mb_y*mot_stride + mb_x;
1123
    uint8_t * const mv_penalty= c->mv_penalty[f_code] + MAX_DMV;
1124
    int mv_scale;
1125

1126 1127 1128
    c->penalty_factor    = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
    c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
    c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
1129
    c->current_mv_penalty= mv_penalty;
Michael Niedermayer's avatar
Michael Niedermayer committed
1130

1131
    get_limits(s, 16*mb_x, 16*mb_y);
1132

1133
    if (s->motion_est != FF_ME_ZERO) {
1134 1135
        P_LEFT[0] = mv_table[mot_xy - 1][0];
        P_LEFT[1] = mv_table[mot_xy - 1][1];
1136

1137
        if (P_LEFT[0] > (c->xmax << shift)) P_LEFT[0] = (c->xmax << shift);
1138

1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
        /* special case for first line */
        if (!s->first_slice_line) {
            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];
            if (P_TOP[1] > (c->ymax << shift)) P_TOP[1] = (c->ymax << shift);
            if (P_TOPRIGHT[0] < (c->xmin << shift)) P_TOPRIGHT[0] = (c->xmin << shift);
            if (P_TOPRIGHT[1] > (c->ymax << shift)) P_TOPRIGHT[1] = (c->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]);
1151
        }
1152 1153
        c->pred_x = P_LEFT[0];
        c->pred_y = P_LEFT[1];
1154

1155 1156 1157 1158 1159
        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);
        }
1160

1161
        dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, ref_index, s->p_mv_table, mv_scale, 0, 16);
1162
    }
1163

1164
    dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, ref_index, 0, 16);
1165

1166
    if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
1167
        dmin= get_mb_score(s, mx, my, 0, ref_index, 0, 16, 1);
1168

1169 1170 1171
//    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
1172

1173
    return dmin;
Fabrice Bellard's avatar
Fabrice Bellard committed
1174 1175
}

1176
static inline int check_bidir_mv(MpegEncContext * s,
1177 1178 1179
                   int motion_fx, int motion_fy,
                   int motion_bx, int motion_by,
                   int pred_fx, int pred_fy,
1180 1181
                   int pred_bx, int pred_by,
                   int size, int h)
Fabrice Bellard's avatar
Fabrice Bellard committed
1182
{
1183
    //FIXME optimize?
Michael Niedermayer's avatar
Michael Niedermayer committed
1184
    //FIXME better f_code prediction (max mv & distance)
1185
    //FIXME pointers
1186
    MotionEstContext * const c= &s->me;
1187 1188
    uint8_t * const mv_penalty_f= c->mv_penalty[s->f_code] + MAX_DMV; // f_code of the prev frame
    uint8_t * const mv_penalty_b= c->mv_penalty[s->b_code] + MAX_DMV; // f_code of the prev frame
1189 1190
    int stride= c->stride;
    uint8_t *dest_y = c->scratchpad;
1191 1192 1193 1194
    uint8_t *ptr;
    int dxy;
    int src_x, src_y;
    int fbmin;
1195 1196 1197
    uint8_t **src_data= c->src[0];
    uint8_t **ref_data= c->ref[0];
    uint8_t **ref2_data= c->ref[2];
1198

Michael Niedermayer's avatar
Michael Niedermayer committed
1199 1200
    if(s->quarter_sample){
        dxy = ((motion_fy & 3) << 2) | (motion_fx & 3);
1201 1202
        src_x = motion_fx >> 2;
        src_y = motion_fy >> 2;
Michael Niedermayer's avatar
Michael Niedermayer committed
1203

1204
        ptr = ref_data[0] + (src_y * stride) + src_x;
1205
        s->qdsp.put_qpel_pixels_tab[0][dxy](dest_y, ptr, stride);
Michael Niedermayer's avatar
Michael Niedermayer committed
1206 1207

        dxy = ((motion_by & 3) << 2) | (motion_bx & 3);
1208 1209
        src_x = motion_bx >> 2;
        src_y = motion_by >> 2;
1210

1211
        ptr = ref2_data[0] + (src_y * stride) + src_x;
1212
        s->qdsp.avg_qpel_pixels_tab[size][dxy](dest_y, ptr, stride);
Michael Niedermayer's avatar
Michael Niedermayer committed
1213 1214
    }else{
        dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
1215 1216
        src_x = motion_fx >> 1;
        src_y = motion_fy >> 1;
Michael Niedermayer's avatar
Michael Niedermayer committed
1217

1218
        ptr = ref_data[0] + (src_y * stride) + src_x;
1219
        s->hdsp.put_pixels_tab[size][dxy](dest_y    , ptr    , stride, h);
Michael Niedermayer's avatar
Michael Niedermayer committed
1220 1221

        dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
1222 1223
        src_x = motion_bx >> 1;
        src_y = motion_by >> 1;
1224

1225
        ptr = ref2_data[0] + (src_y * stride) + src_x;
1226
        s->hdsp.avg_pixels_tab[size][dxy](dest_y    , ptr    , stride, h);
Michael Niedermayer's avatar
Michael Niedermayer committed
1227 1228
    }

Michael Niedermayer's avatar
Michael Niedermayer committed
1229 1230
    fbmin = (mv_penalty_f[motion_fx-pred_fx] + mv_penalty_f[motion_fy-pred_fy])*c->mb_penalty_factor
           +(mv_penalty_b[motion_bx-pred_bx] + mv_penalty_b[motion_by-pred_by])*c->mb_penalty_factor
1231
           + s->mecc.mb_cmp[size](s, src_data[0], dest_y, stride, h); // FIXME new_pic
1232

1233
    if(c->avctx->mb_cmp&FF_CMP_CHROMA){
1234 1235
    }
    //FIXME CHROMA !!!
1236

1237 1238
    return fbmin;
}
1239

1240
/* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
1241
static inline int bidir_refine(MpegEncContext * s, int mb_x, int mb_y)
1242
{
1243
    MotionEstContext * const c= &s->me;
1244 1245
    const int mot_stride = s->mb_stride;
    const int xy = mb_y *mot_stride + mb_x;
1246 1247 1248 1249 1250 1251 1252 1253 1254
    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];
1255 1256 1257 1258 1259 1260 1261
    const int flags= c->sub_flags;
    const int qpel= flags&FLAG_QPEL;
    const int shift= 1+qpel;
    const int xmin= c->xmin<<shift;
    const int ymin= c->ymin<<shift;
    const int xmax= c->xmax<<shift;
    const int ymax= c->ymax<<shift;
1262
#define HASH(fx,fy,bx,by) ((fx)+17*(fy)+63*(bx)+117*(by))
1263
#define HASH8(fx,fy,bx,by) ((uint8_t)HASH(fx,fy,bx,by))
1264
    int hashidx= HASH(motion_fx,motion_fy, motion_bx, motion_by);
1265
    uint8_t map[256] = { 0 };
1266

1267
    map[hashidx&255] = 1;
1268

1269
    fbmin= check_bidir_mv(s, motion_fx, motion_fy,
1270 1271
                          motion_bx, motion_by,
                          pred_fx, pred_fy,
1272 1273
                          pred_bx, pred_by,
                          0, 16);
1274

1275
    if(s->avctx->bidir_refine){
1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296
        int end;
        static const uint8_t limittab[5]={0,8,32,64,80};
        const int limit= limittab[s->avctx->bidir_refine];
        static const int8_t vect[][4]={
{ 0, 0, 0, 1}, { 0, 0, 0,-1}, { 0, 0, 1, 0}, { 0, 0,-1, 0}, { 0, 1, 0, 0}, { 0,-1, 0, 0}, { 1, 0, 0, 0}, {-1, 0, 0, 0},

{ 0, 0, 1, 1}, { 0, 0,-1,-1}, { 0, 1, 1, 0}, { 0,-1,-1, 0}, { 1, 1, 0, 0}, {-1,-1, 0, 0}, { 1, 0, 0, 1}, {-1, 0, 0,-1},
{ 0, 1, 0, 1}, { 0,-1, 0,-1}, { 1, 0, 1, 0}, {-1, 0,-1, 0},
{ 0, 0,-1, 1}, { 0, 0, 1,-1}, { 0,-1, 1, 0}, { 0, 1,-1, 0}, {-1, 1, 0, 0}, { 1,-1, 0, 0}, { 1, 0, 0,-1}, {-1, 0, 0, 1},
{ 0,-1, 0, 1}, { 0, 1, 0,-1}, {-1, 0, 1, 0}, { 1, 0,-1, 0},

{ 0, 1, 1, 1}, { 0,-1,-1,-1}, { 1, 1, 1, 0}, {-1,-1,-1, 0}, { 1, 1, 0, 1}, {-1,-1, 0,-1}, { 1, 0, 1, 1}, {-1, 0,-1,-1},
{ 0,-1, 1, 1}, { 0, 1,-1,-1}, {-1, 1, 1, 0}, { 1,-1,-1, 0}, { 1, 1, 0,-1}, {-1,-1, 0, 1}, { 1, 0,-1, 1}, {-1, 0, 1,-1},
{ 0, 1,-1, 1}, { 0,-1, 1,-1}, { 1,-1, 1, 0}, {-1, 1,-1, 0}, {-1, 1, 0, 1}, { 1,-1, 0,-1}, { 1, 0, 1,-1}, {-1, 0,-1, 1},
{ 0, 1, 1,-1}, { 0,-1,-1, 1}, { 1, 1,-1, 0}, {-1,-1, 1, 0}, { 1,-1, 0, 1}, {-1, 1, 0,-1}, {-1, 0, 1, 1}, { 1, 0,-1,-1},

{ 1, 1, 1, 1}, {-1,-1,-1,-1},
{ 1, 1, 1,-1}, {-1,-1,-1, 1}, { 1, 1,-1, 1}, {-1,-1, 1,-1}, { 1,-1, 1, 1}, {-1, 1,-1,-1}, {-1, 1, 1, 1}, { 1,-1,-1,-1},
{ 1, 1,-1,-1}, {-1,-1, 1, 1}, { 1,-1,-1, 1}, {-1, 1, 1,-1}, { 1,-1, 1,-1}, {-1, 1,-1, 1},
        };
        static const uint8_t hash[]={
1297
HASH8( 0, 0, 0, 1), HASH8( 0, 0, 0,-1), HASH8( 0, 0, 1, 0), HASH8( 0, 0,-1, 0), HASH8( 0, 1, 0, 0), HASH8( 0,-1, 0, 0), HASH8( 1, 0, 0, 0), HASH8(-1, 0, 0, 0),
1298

1299 1300 1301 1302
HASH8( 0, 0, 1, 1), HASH8( 0, 0,-1,-1), HASH8( 0, 1, 1, 0), HASH8( 0,-1,-1, 0), HASH8( 1, 1, 0, 0), HASH8(-1,-1, 0, 0), HASH8( 1, 0, 0, 1), HASH8(-1, 0, 0,-1),
HASH8( 0, 1, 0, 1), HASH8( 0,-1, 0,-1), HASH8( 1, 0, 1, 0), HASH8(-1, 0,-1, 0),
HASH8( 0, 0,-1, 1), HASH8( 0, 0, 1,-1), HASH8( 0,-1, 1, 0), HASH8( 0, 1,-1, 0), HASH8(-1, 1, 0, 0), HASH8( 1,-1, 0, 0), HASH8( 1, 0, 0,-1), HASH8(-1, 0, 0, 1),
HASH8( 0,-1, 0, 1), HASH8( 0, 1, 0,-1), HASH8(-1, 0, 1, 0), HASH8( 1, 0,-1, 0),
1303

1304 1305 1306 1307
HASH8( 0, 1, 1, 1), HASH8( 0,-1,-1,-1), HASH8( 1, 1, 1, 0), HASH8(-1,-1,-1, 0), HASH8( 1, 1, 0, 1), HASH8(-1,-1, 0,-1), HASH8( 1, 0, 1, 1), HASH8(-1, 0,-1,-1),
HASH8( 0,-1, 1, 1), HASH8( 0, 1,-1,-1), HASH8(-1, 1, 1, 0), HASH8( 1,-1,-1, 0), HASH8( 1, 1, 0,-1), HASH8(-1,-1, 0, 1), HASH8( 1, 0,-1, 1), HASH8(-1, 0, 1,-1),
HASH8( 0, 1,-1, 1), HASH8( 0,-1, 1,-1), HASH8( 1,-1, 1, 0), HASH8(-1, 1,-1, 0), HASH8(-1, 1, 0, 1), HASH8( 1,-1, 0,-1), HASH8( 1, 0, 1,-1), HASH8(-1, 0,-1, 1),
HASH8( 0, 1, 1,-1), HASH8( 0,-1,-1, 1), HASH8( 1, 1,-1, 0), HASH8(-1,-1, 1, 0), HASH8( 1,-1, 0, 1), HASH8(-1, 1, 0,-1), HASH8(-1, 0, 1, 1), HASH8( 1, 0,-1,-1),
1308

1309 1310 1311
HASH8( 1, 1, 1, 1), HASH8(-1,-1,-1,-1),
HASH8( 1, 1, 1,-1), HASH8(-1,-1,-1, 1), HASH8( 1, 1,-1, 1), HASH8(-1,-1, 1,-1), HASH8( 1,-1, 1, 1), HASH8(-1, 1,-1,-1), HASH8(-1, 1, 1, 1), HASH8( 1,-1,-1,-1),
HASH8( 1, 1,-1,-1), HASH8(-1,-1, 1, 1), HASH8( 1,-1,-1, 1), HASH8(-1, 1, 1,-1), HASH8( 1,-1, 1,-1), HASH8(-1, 1,-1, 1),
1312 1313
};

1314
#define CHECK_BIDIR(fx,fy,bx,by)\
1315
    if( !map[(hashidx+HASH(fx,fy,bx,by))&255]\
1316
       &&(fx<=0 || motion_fx+fx<=xmax) && (fy<=0 || motion_fy+fy<=ymax) && (bx<=0 || motion_bx+bx<=xmax) && (by<=0 || motion_by+by<=ymax)\
Michael Niedermayer's avatar
Michael Niedermayer committed
1317
       &&(fx>=0 || motion_fx+fx>=xmin) && (fy>=0 || motion_fy+fy>=ymin) && (bx>=0 || motion_bx+bx>=xmin) && (by>=0 || motion_by+by>=ymin)){\
1318
        int score;\
1319
        map[(hashidx+HASH(fx,fy,bx,by))&255] = 1;\
Michael Niedermayer's avatar
Michael Niedermayer committed
1320 1321
        score= check_bidir_mv(s, motion_fx+fx, motion_fy+fy, motion_bx+bx, motion_by+by, pred_fx, pred_fy, pred_bx, pred_by, 0, 16);\
        if(score < fbmin){\
1322
            hashidx += HASH(fx,fy,bx,by);\
Michael Niedermayer's avatar
Michael Niedermayer committed
1323 1324 1325 1326 1327 1328 1329
            fbmin= score;\
            motion_fx+=fx;\
            motion_fy+=fy;\
            motion_bx+=bx;\
            motion_by+=by;\
            end=0;\
        }\
1330 1331 1332
    }
#define CHECK_BIDIR2(a,b,c,d)\
CHECK_BIDIR(a,b,c,d)\
1333
CHECK_BIDIR(-(a),-(b),-(c),-(d))
1334 1335

        do{
1336 1337
            int i;
            int borderdist=0;
1338 1339
            end=1;

1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373
            CHECK_BIDIR2(0,0,0,1)
            CHECK_BIDIR2(0,0,1,0)
            CHECK_BIDIR2(0,1,0,0)
            CHECK_BIDIR2(1,0,0,0)

            for(i=8; i<limit; i++){
                int fx= motion_fx+vect[i][0];
                int fy= motion_fy+vect[i][1];
                int bx= motion_bx+vect[i][2];
                int by= motion_by+vect[i][3];
                if(borderdist<=0){
                    int a= (xmax - FFMAX(fx,bx))|(FFMIN(fx,bx) - xmin);
                    int b= (ymax - FFMAX(fy,by))|(FFMIN(fy,by) - ymin);
                    if((a|b) < 0)
                        map[(hashidx+hash[i])&255] = 1;
                }
                if(!map[(hashidx+hash[i])&255]){
                    int score;
                    map[(hashidx+hash[i])&255] = 1;
                    score= check_bidir_mv(s, fx, fy, bx, by, pred_fx, pred_fy, pred_bx, pred_by, 0, 16);
                    if(score < fbmin){
                        hashidx += hash[i];
                        fbmin= score;
                        motion_fx=fx;
                        motion_fy=fy;
                        motion_bx=bx;
                        motion_by=by;
                        end=0;
                        borderdist--;
                        if(borderdist<=0){
                            int a= FFMIN(xmax - FFMAX(fx,bx), FFMIN(fx,bx) - xmin);
                            int b= FFMIN(ymax - FFMAX(fy,by), FFMIN(fy,by) - ymin);
                            borderdist= FFMIN(a,b);
                        }
1374 1375 1376 1377 1378 1379
                    }
                }
            }
        }while(!end);
    }

1380 1381 1382 1383 1384
    s->b_bidir_forw_mv_table[xy][0]= motion_fx;
    s->b_bidir_forw_mv_table[xy][1]= motion_fy;
    s->b_bidir_back_mv_table[xy][0]= motion_bx;
    s->b_bidir_back_mv_table[xy][1]= motion_by;

1385
    return fbmin;
1386 1387
}

1388
static inline int direct_search(MpegEncContext * s, int mb_x, int mb_y)
1389
{
1390
    MotionEstContext * const c= &s->me;
1391
    int P[10][2];
1392 1393
    const int mot_stride = s->mb_stride;
    const int mot_xy = mb_y*mot_stride + mb_x;
Michael Niedermayer's avatar
Michael Niedermayer committed
1394 1395
    const int shift= 1+s->quarter_sample;
    int dmin, i;
1396
    const int time_pp= s->pp_time;
1397
    const int time_pb= s->pb_time;
Michael Niedermayer's avatar
Michael Niedermayer committed
1398
    int mx, my, xmin, xmax, ymin, ymax;
1399
    int16_t (*mv_table)[2]= s->b_direct_mv_table;
1400

1401
    c->current_mv_penalty= c->mv_penalty[1] + MAX_DMV;
Michael Niedermayer's avatar
Michael Niedermayer committed
1402 1403 1404
    ymin= xmin=(-32)>>shift;
    ymax= xmax=   31>>shift;

1405
    if (IS_8X8(s->next_picture.mb_type[mot_xy])) {
Michael Niedermayer's avatar
Michael Niedermayer committed
1406 1407 1408
        s->mv_type= MV_TYPE_8X8;
    }else{
        s->mv_type= MV_TYPE_16X16;
1409
    }
Michael Niedermayer's avatar
Michael Niedermayer committed
1410 1411 1412 1413

    for(i=0; i<4; i++){
        int index= s->block_index[i];
        int min, max;
1414

1415 1416
        c->co_located_mv[i][0] = s->next_picture.motion_val[0][index][0];
        c->co_located_mv[i][1] = s->next_picture.motion_val[0][index][1];
1417 1418 1419 1420 1421 1422 1423
        c->direct_basis_mv[i][0]= c->co_located_mv[i][0]*time_pb/time_pp + ((i& 1)<<(shift+3));
        c->direct_basis_mv[i][1]= c->co_located_mv[i][1]*time_pb/time_pp + ((i>>1)<<(shift+3));
//        c->direct_basis_mv[1][i][0]= c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(shift+3);
//        c->direct_basis_mv[1][i][1]= c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(shift+3);

        max= FFMAX(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
        min= FFMIN(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
1424 1425
        max+= 16*mb_x + 1; // +-1 is for the simpler rounding
        min+= 16*mb_x - 1;
1426 1427
        xmax= FFMIN(xmax, s->width - max);
        xmin= FFMAX(xmin, - 16     - min);
Michael Niedermayer's avatar
Michael Niedermayer committed
1428

1429 1430
        max= FFMAX(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
        min= FFMIN(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
1431 1432
        max+= 16*mb_y + 1; // +-1 is for the simpler rounding
        min+= 16*mb_y - 1;
1433 1434
        ymax= FFMIN(ymax, s->height - max);
        ymin= FFMAX(ymin, - 16      - min);
1435

Michael Niedermayer's avatar
Michael Niedermayer committed
1436
        if(s->mv_type == MV_TYPE_16X16) break;
1437
    }
1438

1439
    av_assert2(xmax <= 15 && ymax <= 15 && xmin >= -16 && ymin >= -16);
1440

Michael Niedermayer's avatar
Michael Niedermayer committed
1441 1442 1443 1444 1445 1446
    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;
    }
1447

1448 1449 1450 1451 1452 1453 1454 1455
    c->xmin= xmin;
    c->ymin= ymin;
    c->xmax= xmax;
    c->ymax= ymax;
    c->flags     |= FLAG_DIRECT;
    c->sub_flags |= FLAG_DIRECT;
    c->pred_x=0;
    c->pred_y=0;
Michael Niedermayer's avatar
Michael Niedermayer committed
1456

1457 1458
    P_LEFT[0]        = av_clip(mv_table[mot_xy - 1][0], xmin<<shift, xmax<<shift);
    P_LEFT[1]        = av_clip(mv_table[mot_xy - 1][1], ymin<<shift, ymax<<shift);
Michael Niedermayer's avatar
Michael Niedermayer committed
1459 1460

    /* special case for first line */
Diego Biurrun's avatar
Diego Biurrun committed
1461
    if (!s->first_slice_line) { //FIXME maybe allow this over thread boundary as it is clipped
1462 1463 1464 1465
        P_TOP[0]      = av_clip(mv_table[mot_xy - mot_stride             ][0], xmin<<shift, xmax<<shift);
        P_TOP[1]      = av_clip(mv_table[mot_xy - mot_stride             ][1], ymin<<shift, ymax<<shift);
        P_TOPRIGHT[0] = av_clip(mv_table[mot_xy - mot_stride + 1         ][0], xmin<<shift, xmax<<shift);
        P_TOPRIGHT[1] = av_clip(mv_table[mot_xy - mot_stride + 1         ][1], ymin<<shift, ymax<<shift);
1466

Michael Niedermayer's avatar
Michael Niedermayer committed
1467 1468 1469
        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]);
    }
1470

1471
    dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, mv_table, 1<<(16-shift), 0, 16);
1472
    if(c->sub_flags&FLAG_QPEL)
1473 1474 1475
        dmin = qpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
    else
        dmin = hpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
1476

1477
    if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
1478
        dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
1479

1480
    get_limits(s, 16*mb_x, 16*mb_y); //restore c->?min/max, maybe not needed
1481

Michael Niedermayer's avatar
Michael Niedermayer committed
1482 1483
    mv_table[mot_xy][0]= mx;
    mv_table[mot_xy][1]= my;
1484 1485
    c->flags     &= ~FLAG_DIRECT;
    c->sub_flags &= ~FLAG_DIRECT;
1486

1487
    return dmin;
1488 1489 1490 1491 1492
}

void ff_estimate_b_frame_motion(MpegEncContext * s,
                             int mb_x, int mb_y)
{
1493 1494
    MotionEstContext * const c= &s->me;
    const int penalty_factor= c->mb_penalty_factor;
1495
    int fmin, bmin, dmin, fbmin, bimin, fimin;
1496
    int type=0;
1497
    const int xy = mb_y*s->mb_stride + mb_x;
1498 1499
    init_ref(c, s->new_picture.f->data, s->last_picture.f->data,
             s->next_picture.f->data, 16 * mb_x, 16 * mb_y, 2);
1500

1501
    get_limits(s, 16*mb_x, 16*mb_y);
1502

1503
    c->skip=0;
1504

1505
    if (s->codec_id == AV_CODEC_ID_MPEG4 && s->next_picture.mbskip_table[xy]) {
1506 1507 1508 1509 1510 1511 1512 1513 1514 1515
        int score= direct_search(s, mb_x, mb_y); //FIXME just check 0,0

        score= ((unsigned)(score*score + 128*256))>>16;
        c->mc_mb_var_sum_temp += score;
        s->current_picture.mc_mb_var[mb_y*s->mb_stride + mb_x] = score; //FIXME use SSE
        s->mb_type[mb_y*s->mb_stride + mb_x]= CANDIDATE_MB_TYPE_DIRECT0;

        return;
    }

1516
    if (s->codec_id == AV_CODEC_ID_MPEG4)
1517
        dmin= direct_search(s, mb_x, mb_y);
1518 1519
    else
        dmin= INT_MAX;
1520
// FIXME penalty stuff for non-MPEG-4
1521
    c->skip=0;
1522 1523
    fmin = estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code) +
           3 * penalty_factor;
1524

1525
    c->skip=0;
1526 1527
    bmin = estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code) +
           2 * penalty_factor;
1528
    ff_dlog(s, " %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
1529

1530
    c->skip=0;
1531
    fbmin= bidir_refine(s, mb_x, mb_y) + penalty_factor;
1532
    ff_dlog(s, "%d %d %d %d\n", dmin, fmin, bmin, fbmin);
1533

1534
    if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME) {
1535
//FIXME mb type penalty
1536
        c->skip=0;
1537
        c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_DMV;
1538 1539
        fimin= interlaced_search(s, 0,
                                 s->b_field_mv_table[0], s->b_field_select_table[0],
1540
                                 s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1], 0);
1541
        c->current_mv_penalty= c->mv_penalty[s->b_code] + MAX_DMV;
1542 1543
        bimin= interlaced_search(s, 2,
                                 s->b_field_mv_table[1], s->b_field_select_table[1],
1544
                                 s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1], 0);
1545 1546 1547
    }else
        fimin= bimin= INT_MAX;

1548
    {
1549
        int score= fmin;
1550
        type = CANDIDATE_MB_TYPE_FORWARD;
1551

1552
        if (dmin <= score){
1553
            score = dmin;
1554
            type = CANDIDATE_MB_TYPE_DIRECT;
1555 1556 1557
        }
        if(bmin<score){
            score=bmin;
1558
            type= CANDIDATE_MB_TYPE_BACKWARD;
1559 1560 1561
        }
        if(fbmin<score){
            score=fbmin;
1562 1563 1564 1565 1566 1567 1568 1569 1570
            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;
1571
        }
1572

1573
        score= ((unsigned)(score*score + 128*256))>>16;
1574
        c->mc_mb_var_sum_temp += score;
1575
        s->current_picture.mc_mb_var[mb_y*s->mb_stride + mb_x] = score; //FIXME use SSE
1576
    }
1577

1578
    if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
1579 1580 1581 1582 1583 1584 1585 1586 1587
        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
Diego Biurrun's avatar
Diego Biurrun committed
1588
        if(dmin>256*256*16) type&= ~CANDIDATE_MB_TYPE_DIRECT; //do not try direct mode if it is invalid for this MB
1589 1590
        if (s->codec_id == AV_CODEC_ID_MPEG4 && type&CANDIDATE_MB_TYPE_DIRECT &&
            s->mpv_flags & FF_MPV_FLAG_MV0 && *(uint32_t*)s->b_direct_mv_table[xy])
1591
            type |= CANDIDATE_MB_TYPE_DIRECT0;
1592 1593
    }

1594
    s->mb_type[mb_y*s->mb_stride + mb_x]= type;
1595 1596 1597 1598 1599
}

/* find best f_code for ME which do unlimited searches */
int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type)
{
1600
    if (s->motion_est != FF_ME_ZERO) {
1601
        int score[8];
1602
        int i, y, range= s->avctx->me_range ? s->avctx->me_range : (INT_MAX/2);
1603
        uint8_t * fcode_tab= s->fcode_tab;
1604 1605
        int best_fcode=-1;
        int best_score=-10000000;
1606

1607
        if(s->msmpeg4_version)
1608
            range= FFMIN(range, 16);
1609
        else if(s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL)
1610 1611
            range= FFMIN(range, 256);

Michael Niedermayer's avatar
Michael Niedermayer committed
1612
        for(i=0; i<8; i++) score[i]= s->mb_num*(8-i);
1613 1614 1615

        for(y=0; y<s->mb_height; y++){
            int x;
1616
            int xy= y*s->mb_stride;
1617
            for(x=0; x<s->mb_width; x++){
Michael Niedermayer's avatar
Michael Niedermayer committed
1618
                if(s->mb_type[xy] & type){
1619 1620 1621 1622
                    int mx= mv_table[xy][0];
                    int my= mv_table[xy][1];
                    int fcode= FFMAX(fcode_tab[mx + MAX_MV],
                                     fcode_tab[my + MAX_MV]);
1623
                    int j;
1624 1625

                        if(mx >= range || mx < -range ||
1626 1627
                           my >= range || my < -range)
                            continue;
1628

1629
                    for(j=0; j<fcode && j<8; j++){
1630
                        if(s->pict_type==AV_PICTURE_TYPE_B || s->current_picture.mc_mb_var[xy] < s->current_picture.mb_var[xy])
1631 1632
                            score[j]-= 170;
                    }
1633 1634 1635 1636
                }
                xy++;
            }
        }
1637

1638 1639 1640 1641 1642
        for(i=1; i<8; i++){
            if(score[i] > best_score){
                best_score= score[i];
                best_fcode= i;
            }
1643
        }
1644 1645

        return best_fcode;
1646 1647
    }else{
        return 1;
Fabrice Bellard's avatar
Fabrice Bellard committed
1648 1649 1650
    }
}

1651 1652
void ff_fix_long_p_mvs(MpegEncContext * s)
{
1653
    MotionEstContext * const c= &s->me;
1654
    const int f_code= s->f_code;
1655
    int y, range;
1656
    av_assert0(s->pict_type==AV_PICTURE_TYPE_P);
1657

1658 1659
    range = (((s->out_format == FMT_MPEG1 || s->msmpeg4_version) ? 8 : 16) << f_code);

1660 1661
    av_assert0(range <= 16 || !s->msmpeg4_version);
    av_assert0(range <=256 || !(s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL));
1662

1663
    if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
1664

1665
    if (s->avctx->flags & AV_CODEC_FLAG_4MV) {
1666
        const int wrap= s->b8_stride;
1667 1668 1669

        /* clip / convert to intra 8x8 type MVs */
        for(y=0; y<s->mb_height; y++){
1670
            int xy= y*2*wrap;
1671
            int i= y*s->mb_stride;
1672 1673 1674
            int x;

            for(x=0; x<s->mb_width; x++){
1675
                if(s->mb_type[i]&CANDIDATE_MB_TYPE_INTER4V){
1676 1677 1678
                    int block;
                    for(block=0; block<4; block++){
                        int off= (block& 1) + (block>>1)*wrap;
1679 1680
                        int mx = s->current_picture.motion_val[0][ xy + off ][0];
                        int my = s->current_picture.motion_val[0][ xy + off ][1];
1681

1682 1683
                        if(   mx >=range || mx <-range
                           || my >=range || my <-range){
1684 1685
                            s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V;
                            s->mb_type[i] |= CANDIDATE_MB_TYPE_INTRA;
1686
                            s->current_picture.mb_type[i] = CANDIDATE_MB_TYPE_INTRA;
1687 1688 1689
                        }
                    }
                }
Michael Niedermayer's avatar
Michael Niedermayer committed
1690 1691
                xy+=2;
                i++;
1692 1693 1694 1695 1696
            }
        }
    }
}

1697 1698 1699
/**
 * @param truncate 1 for truncation, 0 for using intra
 */
1700
void ff_fix_long_mvs(MpegEncContext * s, uint8_t *field_select_table, int field_select,
1701
                     int16_t (*mv_table)[2], int f_code, int type, int truncate)
1702
{
1703
    MotionEstContext * const c= &s->me;
1704
    int y, h_range, v_range;
1705

1706
    // RAL: 8 in MPEG-1, 16 in MPEG-4
1707
    int range = (((s->out_format == FMT_MPEG1 || s->msmpeg4_version) ? 8 : 16) << f_code);
1708

1709
    if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
1710

1711 1712 1713
    h_range= range;
    v_range= field_select_table ? range>>1 : range;

1714 1715 1716
    /* clip / convert to intra 16x16 type MVs */
    for(y=0; y<s->mb_height; y++){
        int x;
1717
        int xy= y*s->mb_stride;
1718
        for(x=0; x<s->mb_width; x++){
1719
            if (s->mb_type[xy] & type){    // RAL: "type" test added...
1720
                if (!field_select_table || field_select_table[xy] == field_select) {
1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734
                    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;
                        }
1735
                    }
1736
                }
1737 1738 1739 1740 1741
            }
            xy++;
        }
    }
}