annotate ffmpeg/libavcodec/motion_est_template.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Motion estimation
yading@10 3 * Copyright (c) 2002-2004 Michael Niedermayer
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 /**
yading@10 23 * @file
yading@10 24 * Motion estimation template.
yading@10 25 */
yading@10 26
yading@10 27 //Let us hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...)
yading@10 28 #define LOAD_COMMON\
yading@10 29 uint32_t av_unused * const score_map= c->score_map;\
yading@10 30 const int av_unused xmin= c->xmin;\
yading@10 31 const int av_unused ymin= c->ymin;\
yading@10 32 const int av_unused xmax= c->xmax;\
yading@10 33 const int av_unused ymax= c->ymax;\
yading@10 34 uint8_t *mv_penalty= c->current_mv_penalty;\
yading@10 35 const int pred_x= c->pred_x;\
yading@10 36 const int pred_y= c->pred_y;\
yading@10 37
yading@10 38 #define CHECK_HALF_MV(dx, dy, x, y)\
yading@10 39 {\
yading@10 40 const int hx= 2*(x)+(dx);\
yading@10 41 const int hy= 2*(y)+(dy);\
yading@10 42 d= cmp_hpel(s, x, y, dx, dy, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);\
yading@10 43 d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
yading@10 44 COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
yading@10 45 }
yading@10 46
yading@10 47 static int hpel_motion_search(MpegEncContext * s,
yading@10 48 int *mx_ptr, int *my_ptr, int dmin,
yading@10 49 int src_index, int ref_index,
yading@10 50 int size, int h)
yading@10 51 {
yading@10 52 MotionEstContext * const c= &s->me;
yading@10 53 const int mx = *mx_ptr;
yading@10 54 const int my = *my_ptr;
yading@10 55 const int penalty_factor= c->sub_penalty_factor;
yading@10 56 me_cmp_func cmp_sub, chroma_cmp_sub;
yading@10 57 int bx=2*mx, by=2*my;
yading@10 58
yading@10 59 LOAD_COMMON
yading@10 60 int flags= c->sub_flags;
yading@10 61
yading@10 62 //FIXME factorize
yading@10 63
yading@10 64 cmp_sub= s->dsp.me_sub_cmp[size];
yading@10 65 chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];
yading@10 66
yading@10 67 if(c->skip){ //FIXME move out of hpel?
yading@10 68 *mx_ptr = 0;
yading@10 69 *my_ptr = 0;
yading@10 70 return dmin;
yading@10 71 }
yading@10 72
yading@10 73 if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
yading@10 74 dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
yading@10 75 if(mx || my || size>0)
yading@10 76 dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor;
yading@10 77 }
yading@10 78
yading@10 79 if (mx > xmin && mx < xmax &&
yading@10 80 my > ymin && my < ymax) {
yading@10 81 int d= dmin;
yading@10 82 const int index= (my<<ME_MAP_SHIFT) + mx;
yading@10 83 const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
yading@10 84 + (mv_penalty[bx - pred_x] + mv_penalty[by-2 - pred_y])*c->penalty_factor;
yading@10 85 const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)]
yading@10 86 + (mv_penalty[bx-2 - pred_x] + mv_penalty[by - pred_y])*c->penalty_factor;
yading@10 87 const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)]
yading@10 88 + (mv_penalty[bx+2 - pred_x] + mv_penalty[by - pred_y])*c->penalty_factor;
yading@10 89 const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)]
yading@10 90 + (mv_penalty[bx - pred_x] + mv_penalty[by+2 - pred_y])*c->penalty_factor;
yading@10 91
yading@10 92 #if defined(ASSERT_LEVEL) && ASSERT_LEVEL > 1
yading@10 93 unsigned key;
yading@10 94 unsigned map_generation= c->map_generation;
yading@10 95 key= ((my-1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
yading@10 96 av_assert2(c->map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
yading@10 97 key= ((my+1)<<ME_MAP_MV_BITS) + (mx) + map_generation;
yading@10 98 av_assert2(c->map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key);
yading@10 99 key= ((my)<<ME_MAP_MV_BITS) + (mx+1) + map_generation;
yading@10 100 av_assert2(c->map[(index+1)&(ME_MAP_SIZE-1)] == key);
yading@10 101 key= ((my)<<ME_MAP_MV_BITS) + (mx-1) + map_generation;
yading@10 102 av_assert2(c->map[(index-1)&(ME_MAP_SIZE-1)] == key);
yading@10 103 #endif
yading@10 104 if(t<=b){
yading@10 105 CHECK_HALF_MV(0, 1, mx ,my-1)
yading@10 106 if(l<=r){
yading@10 107 CHECK_HALF_MV(1, 1, mx-1, my-1)
yading@10 108 if(t+r<=b+l){
yading@10 109 CHECK_HALF_MV(1, 1, mx , my-1)
yading@10 110 }else{
yading@10 111 CHECK_HALF_MV(1, 1, mx-1, my )
yading@10 112 }
yading@10 113 CHECK_HALF_MV(1, 0, mx-1, my )
yading@10 114 }else{
yading@10 115 CHECK_HALF_MV(1, 1, mx , my-1)
yading@10 116 if(t+l<=b+r){
yading@10 117 CHECK_HALF_MV(1, 1, mx-1, my-1)
yading@10 118 }else{
yading@10 119 CHECK_HALF_MV(1, 1, mx , my )
yading@10 120 }
yading@10 121 CHECK_HALF_MV(1, 0, mx , my )
yading@10 122 }
yading@10 123 }else{
yading@10 124 if(l<=r){
yading@10 125 if(t+l<=b+r){
yading@10 126 CHECK_HALF_MV(1, 1, mx-1, my-1)
yading@10 127 }else{
yading@10 128 CHECK_HALF_MV(1, 1, mx , my )
yading@10 129 }
yading@10 130 CHECK_HALF_MV(1, 0, mx-1, my)
yading@10 131 CHECK_HALF_MV(1, 1, mx-1, my)
yading@10 132 }else{
yading@10 133 if(t+r<=b+l){
yading@10 134 CHECK_HALF_MV(1, 1, mx , my-1)
yading@10 135 }else{
yading@10 136 CHECK_HALF_MV(1, 1, mx-1, my)
yading@10 137 }
yading@10 138 CHECK_HALF_MV(1, 0, mx , my)
yading@10 139 CHECK_HALF_MV(1, 1, mx , my)
yading@10 140 }
yading@10 141 CHECK_HALF_MV(0, 1, mx , my)
yading@10 142 }
yading@10 143 av_assert2(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2);
yading@10 144 }
yading@10 145
yading@10 146 *mx_ptr = bx;
yading@10 147 *my_ptr = by;
yading@10 148
yading@10 149 return dmin;
yading@10 150 }
yading@10 151
yading@10 152 static int no_sub_motion_search(MpegEncContext * s,
yading@10 153 int *mx_ptr, int *my_ptr, int dmin,
yading@10 154 int src_index, int ref_index,
yading@10 155 int size, int h)
yading@10 156 {
yading@10 157 (*mx_ptr)<<=1;
yading@10 158 (*my_ptr)<<=1;
yading@10 159 return dmin;
yading@10 160 }
yading@10 161
yading@10 162 static inline int get_mb_score(MpegEncContext *s, int mx, int my,
yading@10 163 int src_index, int ref_index, int size,
yading@10 164 int h, int add_rate)
yading@10 165 {
yading@10 166 // const int check_luma= s->dsp.me_sub_cmp != s->dsp.mb_cmp;
yading@10 167 MotionEstContext * const c= &s->me;
yading@10 168 const int penalty_factor= c->mb_penalty_factor;
yading@10 169 const int flags= c->mb_flags;
yading@10 170 const int qpel= flags & FLAG_QPEL;
yading@10 171 const int mask= 1+2*qpel;
yading@10 172 me_cmp_func cmp_sub, chroma_cmp_sub;
yading@10 173 int d;
yading@10 174
yading@10 175 LOAD_COMMON
yading@10 176
yading@10 177 //FIXME factorize
yading@10 178
yading@10 179 cmp_sub= s->dsp.mb_cmp[size];
yading@10 180 chroma_cmp_sub= s->dsp.mb_cmp[size+1];
yading@10 181
yading@10 182 d= cmp(s, mx>>(qpel+1), my>>(qpel+1), mx&mask, my&mask, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
yading@10 183 //FIXME check cbp before adding penalty for (0,0) vector
yading@10 184 if(add_rate && (mx || my || size>0))
yading@10 185 d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor;
yading@10 186
yading@10 187 return d;
yading@10 188 }
yading@10 189
yading@10 190 int ff_get_mb_score(MpegEncContext *s, int mx, int my, int src_index,
yading@10 191 int ref_index, int size, int h, int add_rate)
yading@10 192 {
yading@10 193 return get_mb_score(s, mx, my, src_index, ref_index, size, h, add_rate);
yading@10 194 }
yading@10 195
yading@10 196 #define CHECK_QUARTER_MV(dx, dy, x, y)\
yading@10 197 {\
yading@10 198 const int hx= 4*(x)+(dx);\
yading@10 199 const int hy= 4*(y)+(dy);\
yading@10 200 d= cmp_qpel(s, x, y, dx, dy, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
yading@10 201 d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\
yading@10 202 COPY3_IF_LT(dmin, d, bx, hx, by, hy)\
yading@10 203 }
yading@10 204
yading@10 205 static int qpel_motion_search(MpegEncContext * s,
yading@10 206 int *mx_ptr, int *my_ptr, int dmin,
yading@10 207 int src_index, int ref_index,
yading@10 208 int size, int h)
yading@10 209 {
yading@10 210 MotionEstContext * const c= &s->me;
yading@10 211 const int mx = *mx_ptr;
yading@10 212 const int my = *my_ptr;
yading@10 213 const int penalty_factor= c->sub_penalty_factor;
yading@10 214 const unsigned map_generation = c->map_generation;
yading@10 215 const int subpel_quality= c->avctx->me_subpel_quality;
yading@10 216 uint32_t *map= c->map;
yading@10 217 me_cmp_func cmpf, chroma_cmpf;
yading@10 218 me_cmp_func cmp_sub, chroma_cmp_sub;
yading@10 219
yading@10 220 LOAD_COMMON
yading@10 221 int flags= c->sub_flags;
yading@10 222
yading@10 223 cmpf= s->dsp.me_cmp[size];
yading@10 224 chroma_cmpf= s->dsp.me_cmp[size+1]; //factorize FIXME
yading@10 225 //FIXME factorize
yading@10 226
yading@10 227 cmp_sub= s->dsp.me_sub_cmp[size];
yading@10 228 chroma_cmp_sub= s->dsp.me_sub_cmp[size+1];
yading@10 229
yading@10 230 if(c->skip){ //FIXME somehow move up (benchmark)
yading@10 231 *mx_ptr = 0;
yading@10 232 *my_ptr = 0;
yading@10 233 return dmin;
yading@10 234 }
yading@10 235
yading@10 236 if(c->avctx->me_cmp != c->avctx->me_sub_cmp){
yading@10 237 dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);
yading@10 238 if(mx || my || size>0)
yading@10 239 dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor;
yading@10 240 }
yading@10 241
yading@10 242 if (mx > xmin && mx < xmax &&
yading@10 243 my > ymin && my < ymax) {
yading@10 244 int bx=4*mx, by=4*my;
yading@10 245 int d= dmin;
yading@10 246 int i, nx, ny;
yading@10 247 const int index= (my<<ME_MAP_SHIFT) + mx;
yading@10 248 const int t= score_map[(index-(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)];
yading@10 249 const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)];
yading@10 250 const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)];
yading@10 251 const int b= score_map[(index+(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)];
yading@10 252 const int c= score_map[(index )&(ME_MAP_SIZE-1)];
yading@10 253 int best[8];
yading@10 254 int best_pos[8][2];
yading@10 255
yading@10 256 memset(best, 64, sizeof(int)*8);
yading@10 257 if(s->me.dia_size>=2){
yading@10 258 const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
yading@10 259 const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
yading@10 260 const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
yading@10 261 const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)];
yading@10 262
yading@10 263 for(ny= -3; ny <= 3; ny++){
yading@10 264 for(nx= -3; nx <= 3; nx++){
yading@10 265 //FIXME this could overflow (unlikely though)
yading@10 266 const int64_t t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t;
yading@10 267 const int64_t c2= nx*nx*( r + l - 2*c) + 4*nx*( r- l) + 32*c;
yading@10 268 const int64_t b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b;
yading@10 269 int score= (ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2 + 512)>>10;
yading@10 270 int i;
yading@10 271
yading@10 272 if((nx&3)==0 && (ny&3)==0) continue;
yading@10 273
yading@10 274 score += (mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
yading@10 275
yading@10 276 // if(nx&1) score-=1024*c->penalty_factor;
yading@10 277 // if(ny&1) score-=1024*c->penalty_factor;
yading@10 278
yading@10 279 for(i=0; i<8; i++){
yading@10 280 if(score < best[i]){
yading@10 281 memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
yading@10 282 memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
yading@10 283 best[i]= score;
yading@10 284 best_pos[i][0]= nx + 4*mx;
yading@10 285 best_pos[i][1]= ny + 4*my;
yading@10 286 break;
yading@10 287 }
yading@10 288 }
yading@10 289 }
yading@10 290 }
yading@10 291 }else{
yading@10 292 int tl;
yading@10 293 //FIXME this could overflow (unlikely though)
yading@10 294 const int cx = 4*(r - l);
yading@10 295 const int cx2= r + l - 2*c;
yading@10 296 const int cy = 4*(b - t);
yading@10 297 const int cy2= b + t - 2*c;
yading@10 298 int cxy;
yading@10 299
yading@10 300 if(map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == (my<<ME_MAP_MV_BITS) + mx + map_generation && 0){ //FIXME
yading@10 301 tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)];
yading@10 302 }else{
yading@10 303 tl= cmp(s, mx-1, my-1, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);//FIXME wrong if chroma me is different
yading@10 304 }
yading@10 305
yading@10 306 cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c;
yading@10 307
yading@10 308 av_assert2(16*cx2 + 4*cx + 32*c == 32*r);
yading@10 309 av_assert2(16*cx2 - 4*cx + 32*c == 32*l);
yading@10 310 av_assert2(16*cy2 + 4*cy + 32*c == 32*b);
yading@10 311 av_assert2(16*cy2 - 4*cy + 32*c == 32*t);
yading@10 312 av_assert2(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl);
yading@10 313
yading@10 314 for(ny= -3; ny <= 3; ny++){
yading@10 315 for(nx= -3; nx <= 3; nx++){
yading@10 316 //FIXME this could overflow (unlikely though)
yading@10 317 int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor
yading@10 318 int i;
yading@10 319
yading@10 320 if((nx&3)==0 && (ny&3)==0) continue;
yading@10 321
yading@10 322 score += 32*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor;
yading@10 323 // if(nx&1) score-=32*c->penalty_factor;
yading@10 324 // if(ny&1) score-=32*c->penalty_factor;
yading@10 325
yading@10 326 for(i=0; i<8; i++){
yading@10 327 if(score < best[i]){
yading@10 328 memmove(&best[i+1], &best[i], sizeof(int)*(7-i));
yading@10 329 memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i));
yading@10 330 best[i]= score;
yading@10 331 best_pos[i][0]= nx + 4*mx;
yading@10 332 best_pos[i][1]= ny + 4*my;
yading@10 333 break;
yading@10 334 }
yading@10 335 }
yading@10 336 }
yading@10 337 }
yading@10 338 }
yading@10 339 for(i=0; i<subpel_quality; i++){
yading@10 340 nx= best_pos[i][0];
yading@10 341 ny= best_pos[i][1];
yading@10 342 CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2)
yading@10 343 }
yading@10 344
yading@10 345 av_assert2(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4);
yading@10 346
yading@10 347 *mx_ptr = bx;
yading@10 348 *my_ptr = by;
yading@10 349 }else{
yading@10 350 *mx_ptr =4*mx;
yading@10 351 *my_ptr =4*my;
yading@10 352 }
yading@10 353
yading@10 354 return dmin;
yading@10 355 }
yading@10 356
yading@10 357
yading@10 358 #define CHECK_MV(x,y)\
yading@10 359 {\
yading@10 360 const unsigned key = ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
yading@10 361 const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
yading@10 362 av_assert2((x) >= xmin);\
yading@10 363 av_assert2((x) <= xmax);\
yading@10 364 av_assert2((y) >= ymin);\
yading@10 365 av_assert2((y) <= ymax);\
yading@10 366 if(map[index]!=key){\
yading@10 367 d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
yading@10 368 map[index]= key;\
yading@10 369 score_map[index]= d;\
yading@10 370 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
yading@10 371 COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\
yading@10 372 }\
yading@10 373 }
yading@10 374
yading@10 375 #define CHECK_CLIPPED_MV(ax,ay)\
yading@10 376 {\
yading@10 377 const int Lx= ax;\
yading@10 378 const int Ly= ay;\
yading@10 379 const int Lx2= FFMAX(xmin, FFMIN(Lx, xmax));\
yading@10 380 const int Ly2= FFMAX(ymin, FFMIN(Ly, ymax));\
yading@10 381 CHECK_MV(Lx2, Ly2)\
yading@10 382 }
yading@10 383
yading@10 384 #define CHECK_MV_DIR(x,y,new_dir)\
yading@10 385 {\
yading@10 386 const unsigned key = ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\
yading@10 387 const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\
yading@10 388 if(map[index]!=key){\
yading@10 389 d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
yading@10 390 map[index]= key;\
yading@10 391 score_map[index]= d;\
yading@10 392 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\
yading@10 393 if(d<dmin){\
yading@10 394 best[0]=x;\
yading@10 395 best[1]=y;\
yading@10 396 dmin=d;\
yading@10 397 next_dir= new_dir;\
yading@10 398 }\
yading@10 399 }\
yading@10 400 }
yading@10 401
yading@10 402 #define check(x,y,S,v)\
yading@10 403 if( (x)<(xmin<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\
yading@10 404 if( (x)>(xmax<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\
yading@10 405 if( (y)<(ymin<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\
yading@10 406 if( (y)>(ymax<<(S)) ) av_log(NULL, AV_LOG_ERROR, "%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\
yading@10 407
yading@10 408 #define LOAD_COMMON2\
yading@10 409 uint32_t *map= c->map;\
yading@10 410 const int qpel= flags&FLAG_QPEL;\
yading@10 411 const int shift= 1+qpel;\
yading@10 412
yading@10 413 static av_always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin,
yading@10 414 int src_index, int ref_index, int const penalty_factor,
yading@10 415 int size, int h, int flags)
yading@10 416 {
yading@10 417 MotionEstContext * const c= &s->me;
yading@10 418 me_cmp_func cmpf, chroma_cmpf;
yading@10 419 int next_dir=-1;
yading@10 420 LOAD_COMMON
yading@10 421 LOAD_COMMON2
yading@10 422 unsigned map_generation = c->map_generation;
yading@10 423
yading@10 424 cmpf= s->dsp.me_cmp[size];
yading@10 425 chroma_cmpf= s->dsp.me_cmp[size+1];
yading@10 426
yading@10 427 { /* ensure that the best point is in the MAP as h/qpel refinement needs it */
yading@10 428 const unsigned key = (best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation;
yading@10 429 const int index= ((best[1]<<ME_MAP_SHIFT) + best[0])&(ME_MAP_SIZE-1);
yading@10 430 if(map[index]!=key){ //this will be executed only very rarey
yading@10 431 score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
yading@10 432 map[index]= key;
yading@10 433 }
yading@10 434 }
yading@10 435
yading@10 436 for(;;){
yading@10 437 int d;
yading@10 438 const int dir= next_dir;
yading@10 439 const int x= best[0];
yading@10 440 const int y= best[1];
yading@10 441 next_dir=-1;
yading@10 442
yading@10 443 if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0)
yading@10 444 if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1)
yading@10 445 if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2)
yading@10 446 if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3)
yading@10 447
yading@10 448 if(next_dir==-1){
yading@10 449 return dmin;
yading@10 450 }
yading@10 451 }
yading@10 452 }
yading@10 453
yading@10 454 static int funny_diamond_search(MpegEncContext * s, int *best, int dmin,
yading@10 455 int src_index, int ref_index, int const penalty_factor,
yading@10 456 int size, int h, int flags)
yading@10 457 {
yading@10 458 MotionEstContext * const c= &s->me;
yading@10 459 me_cmp_func cmpf, chroma_cmpf;
yading@10 460 int dia_size;
yading@10 461 LOAD_COMMON
yading@10 462 LOAD_COMMON2
yading@10 463 unsigned map_generation = c->map_generation;
yading@10 464
yading@10 465 cmpf= s->dsp.me_cmp[size];
yading@10 466 chroma_cmpf= s->dsp.me_cmp[size+1];
yading@10 467
yading@10 468 for(dia_size=1; dia_size<=4; dia_size++){
yading@10 469 int dir;
yading@10 470 const int x= best[0];
yading@10 471 const int y= best[1];
yading@10 472
yading@10 473 if(dia_size&(dia_size-1)) continue;
yading@10 474
yading@10 475 if( x + dia_size > xmax
yading@10 476 || x - dia_size < xmin
yading@10 477 || y + dia_size > ymax
yading@10 478 || y - dia_size < ymin)
yading@10 479 continue;
yading@10 480
yading@10 481 for(dir= 0; dir<dia_size; dir+=2){
yading@10 482 int d;
yading@10 483
yading@10 484 CHECK_MV(x + dir , y + dia_size - dir);
yading@10 485 CHECK_MV(x + dia_size - dir, y - dir );
yading@10 486 CHECK_MV(x - dir , y - dia_size + dir);
yading@10 487 CHECK_MV(x - dia_size + dir, y + dir );
yading@10 488 }
yading@10 489
yading@10 490 if(x!=best[0] || y!=best[1])
yading@10 491 dia_size=0;
yading@10 492 }
yading@10 493 return dmin;
yading@10 494 }
yading@10 495
yading@10 496 static int hex_search(MpegEncContext * s, int *best, int dmin,
yading@10 497 int src_index, int ref_index, int const penalty_factor,
yading@10 498 int size, int h, int flags, int dia_size)
yading@10 499 {
yading@10 500 MotionEstContext * const c= &s->me;
yading@10 501 me_cmp_func cmpf, chroma_cmpf;
yading@10 502 LOAD_COMMON
yading@10 503 LOAD_COMMON2
yading@10 504 unsigned map_generation = c->map_generation;
yading@10 505 int x,y,d;
yading@10 506 const int dec= dia_size & (dia_size-1);
yading@10 507
yading@10 508 cmpf= s->dsp.me_cmp[size];
yading@10 509 chroma_cmpf= s->dsp.me_cmp[size+1];
yading@10 510
yading@10 511 for(;dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
yading@10 512 do{
yading@10 513 x= best[0];
yading@10 514 y= best[1];
yading@10 515
yading@10 516 CHECK_CLIPPED_MV(x -dia_size , y);
yading@10 517 CHECK_CLIPPED_MV(x+ dia_size , y);
yading@10 518 CHECK_CLIPPED_MV(x+( dia_size>>1), y+dia_size);
yading@10 519 CHECK_CLIPPED_MV(x+( dia_size>>1), y-dia_size);
yading@10 520 if(dia_size>1){
yading@10 521 CHECK_CLIPPED_MV(x+(-dia_size>>1), y+dia_size);
yading@10 522 CHECK_CLIPPED_MV(x+(-dia_size>>1), y-dia_size);
yading@10 523 }
yading@10 524 }while(best[0] != x || best[1] != y);
yading@10 525 }
yading@10 526
yading@10 527 return dmin;
yading@10 528 }
yading@10 529
yading@10 530 static int l2s_dia_search(MpegEncContext * s, int *best, int dmin,
yading@10 531 int src_index, int ref_index, int const penalty_factor,
yading@10 532 int size, int h, int flags)
yading@10 533 {
yading@10 534 MotionEstContext * const c= &s->me;
yading@10 535 me_cmp_func cmpf, chroma_cmpf;
yading@10 536 LOAD_COMMON
yading@10 537 LOAD_COMMON2
yading@10 538 unsigned map_generation = c->map_generation;
yading@10 539 int x,y,i,d;
yading@10 540 int dia_size= c->dia_size&0xFF;
yading@10 541 const int dec= dia_size & (dia_size-1);
yading@10 542 static const int hex[8][2]={{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1},
yading@10 543 { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}};
yading@10 544
yading@10 545 cmpf= s->dsp.me_cmp[size];
yading@10 546 chroma_cmpf= s->dsp.me_cmp[size+1];
yading@10 547
yading@10 548 for(; dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){
yading@10 549 do{
yading@10 550 x= best[0];
yading@10 551 y= best[1];
yading@10 552 for(i=0; i<8; i++){
yading@10 553 CHECK_CLIPPED_MV(x+hex[i][0]*dia_size, y+hex[i][1]*dia_size);
yading@10 554 }
yading@10 555 }while(best[0] != x || best[1] != y);
yading@10 556 }
yading@10 557
yading@10 558 x= best[0];
yading@10 559 y= best[1];
yading@10 560 CHECK_CLIPPED_MV(x+1, y);
yading@10 561 CHECK_CLIPPED_MV(x, y+1);
yading@10 562 CHECK_CLIPPED_MV(x-1, y);
yading@10 563 CHECK_CLIPPED_MV(x, y-1);
yading@10 564
yading@10 565 return dmin;
yading@10 566 }
yading@10 567
yading@10 568 static int umh_search(MpegEncContext * s, int *best, int dmin,
yading@10 569 int src_index, int ref_index, int const penalty_factor,
yading@10 570 int size, int h, int flags)
yading@10 571 {
yading@10 572 MotionEstContext * const c= &s->me;
yading@10 573 me_cmp_func cmpf, chroma_cmpf;
yading@10 574 LOAD_COMMON
yading@10 575 LOAD_COMMON2
yading@10 576 unsigned map_generation = c->map_generation;
yading@10 577 int x,y,x2,y2, i, j, d;
yading@10 578 const int dia_size= c->dia_size&0xFE;
yading@10 579 static const int hex[16][2]={{-4,-2}, {-4,-1}, {-4, 0}, {-4, 1}, {-4, 2},
yading@10 580 { 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2},
yading@10 581 {-2, 3}, { 0, 4}, { 2, 3},
yading@10 582 {-2,-3}, { 0,-4}, { 2,-3},};
yading@10 583
yading@10 584 cmpf= s->dsp.me_cmp[size];
yading@10 585 chroma_cmpf= s->dsp.me_cmp[size+1];
yading@10 586
yading@10 587 x= best[0];
yading@10 588 y= best[1];
yading@10 589 for(x2=FFMAX(x-dia_size+1, xmin); x2<=FFMIN(x+dia_size-1,xmax); x2+=2){
yading@10 590 CHECK_MV(x2, y);
yading@10 591 }
yading@10 592 for(y2=FFMAX(y-dia_size/2+1, ymin); y2<=FFMIN(y+dia_size/2-1,ymax); y2+=2){
yading@10 593 CHECK_MV(x, y2);
yading@10 594 }
yading@10 595
yading@10 596 x= best[0];
yading@10 597 y= best[1];
yading@10 598 for(y2=FFMAX(y-2, ymin); y2<=FFMIN(y+2,ymax); y2++){
yading@10 599 for(x2=FFMAX(x-2, xmin); x2<=FFMIN(x+2,xmax); x2++){
yading@10 600 CHECK_MV(x2, y2);
yading@10 601 }
yading@10 602 }
yading@10 603
yading@10 604 //FIXME prevent the CLIP stuff
yading@10 605
yading@10 606 for(j=1; j<=dia_size/4; j++){
yading@10 607 for(i=0; i<16; i++){
yading@10 608 CHECK_CLIPPED_MV(x+hex[i][0]*j, y+hex[i][1]*j);
yading@10 609 }
yading@10 610 }
yading@10 611
yading@10 612 return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, 2);
yading@10 613 }
yading@10 614
yading@10 615 static int full_search(MpegEncContext * s, int *best, int dmin,
yading@10 616 int src_index, int ref_index, int const penalty_factor,
yading@10 617 int size, int h, int flags)
yading@10 618 {
yading@10 619 MotionEstContext * const c= &s->me;
yading@10 620 me_cmp_func cmpf, chroma_cmpf;
yading@10 621 LOAD_COMMON
yading@10 622 LOAD_COMMON2
yading@10 623 unsigned map_generation = c->map_generation;
yading@10 624 int x,y, d;
yading@10 625 const int dia_size= c->dia_size&0xFF;
yading@10 626
yading@10 627 cmpf= s->dsp.me_cmp[size];
yading@10 628 chroma_cmpf= s->dsp.me_cmp[size+1];
yading@10 629
yading@10 630 for(y=FFMAX(-dia_size, ymin); y<=FFMIN(dia_size,ymax); y++){
yading@10 631 for(x=FFMAX(-dia_size, xmin); x<=FFMIN(dia_size,xmax); x++){
yading@10 632 CHECK_MV(x, y);
yading@10 633 }
yading@10 634 }
yading@10 635
yading@10 636 x= best[0];
yading@10 637 y= best[1];
yading@10 638 d= dmin;
yading@10 639 CHECK_CLIPPED_MV(x , y);
yading@10 640 CHECK_CLIPPED_MV(x+1, y);
yading@10 641 CHECK_CLIPPED_MV(x, y+1);
yading@10 642 CHECK_CLIPPED_MV(x-1, y);
yading@10 643 CHECK_CLIPPED_MV(x, y-1);
yading@10 644 best[0]= x;
yading@10 645 best[1]= y;
yading@10 646
yading@10 647 return d;
yading@10 648 }
yading@10 649
yading@10 650 #define SAB_CHECK_MV(ax,ay)\
yading@10 651 {\
yading@10 652 const unsigned key = ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\
yading@10 653 const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\
yading@10 654 if(map[index]!=key){\
yading@10 655 d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\
yading@10 656 map[index]= key;\
yading@10 657 score_map[index]= d;\
yading@10 658 d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\
yading@10 659 if(d < minima[minima_count-1].height){\
yading@10 660 int j=0;\
yading@10 661 \
yading@10 662 while(d >= minima[j].height) j++;\
yading@10 663 \
yading@10 664 memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\
yading@10 665 \
yading@10 666 minima[j].checked= 0;\
yading@10 667 minima[j].height= d;\
yading@10 668 minima[j].x= ax;\
yading@10 669 minima[j].y= ay;\
yading@10 670 \
yading@10 671 i=-1;\
yading@10 672 continue;\
yading@10 673 }\
yading@10 674 }\
yading@10 675 }
yading@10 676
yading@10 677 #define MAX_SAB_SIZE ME_MAP_SIZE
yading@10 678 static int sab_diamond_search(MpegEncContext * s, int *best, int dmin,
yading@10 679 int src_index, int ref_index, int const penalty_factor,
yading@10 680 int size, int h, int flags)
yading@10 681 {
yading@10 682 MotionEstContext * const c= &s->me;
yading@10 683 me_cmp_func cmpf, chroma_cmpf;
yading@10 684 Minima minima[MAX_SAB_SIZE];
yading@10 685 const int minima_count= FFABS(c->dia_size);
yading@10 686 int i, j;
yading@10 687 LOAD_COMMON
yading@10 688 LOAD_COMMON2
yading@10 689 unsigned map_generation = c->map_generation;
yading@10 690
yading@10 691 av_assert1(minima_count <= MAX_SAB_SIZE);
yading@10 692
yading@10 693 cmpf= s->dsp.me_cmp[size];
yading@10 694 chroma_cmpf= s->dsp.me_cmp[size+1];
yading@10 695
yading@10 696 /*Note j<MAX_SAB_SIZE is needed if MAX_SAB_SIZE < ME_MAP_SIZE as j can
yading@10 697 become larger due to MVs overflowing their ME_MAP_MV_BITS bits space in map
yading@10 698 */
yading@10 699 for(j=i=0; i<ME_MAP_SIZE && j<MAX_SAB_SIZE; i++){
yading@10 700 uint32_t key= map[i];
yading@10 701
yading@10 702 key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1));
yading@10 703
yading@10 704 if((key&((-1)<<(2*ME_MAP_MV_BITS))) != map_generation) continue;
yading@10 705
yading@10 706 minima[j].height= score_map[i];
yading@10 707 minima[j].x= key & ((1<<ME_MAP_MV_BITS)-1); key>>=ME_MAP_MV_BITS;
yading@10 708 minima[j].y= key & ((1<<ME_MAP_MV_BITS)-1);
yading@10 709 minima[j].x-= (1<<(ME_MAP_MV_BITS-1));
yading@10 710 minima[j].y-= (1<<(ME_MAP_MV_BITS-1));
yading@10 711
yading@10 712 // all entries in map should be in range except if the mv overflows their ME_MAP_MV_BITS bits space
yading@10 713 if( minima[j].x > xmax || minima[j].x < xmin
yading@10 714 || minima[j].y > ymax || minima[j].y < ymin)
yading@10 715 continue;
yading@10 716
yading@10 717 minima[j].checked=0;
yading@10 718 if(minima[j].x || minima[j].y)
yading@10 719 minima[j].height+= (mv_penalty[((minima[j].x)<<shift)-pred_x] + mv_penalty[((minima[j].y)<<shift)-pred_y])*penalty_factor;
yading@10 720
yading@10 721 j++;
yading@10 722 }
yading@10 723
yading@10 724 qsort(minima, j, sizeof(Minima), minima_cmp);
yading@10 725
yading@10 726 for(; j<minima_count; j++){
yading@10 727 minima[j].height=256*256*256*64;
yading@10 728 minima[j].checked=0;
yading@10 729 minima[j].x= minima[j].y=0;
yading@10 730 }
yading@10 731
yading@10 732 for(i=0; i<minima_count; i++){
yading@10 733 const int x= minima[i].x;
yading@10 734 const int y= minima[i].y;
yading@10 735 int d;
yading@10 736
yading@10 737 if(minima[i].checked) continue;
yading@10 738
yading@10 739 if( x >= xmax || x <= xmin
yading@10 740 || y >= ymax || y <= ymin)
yading@10 741 continue;
yading@10 742
yading@10 743 SAB_CHECK_MV(x-1, y)
yading@10 744 SAB_CHECK_MV(x+1, y)
yading@10 745 SAB_CHECK_MV(x , y-1)
yading@10 746 SAB_CHECK_MV(x , y+1)
yading@10 747
yading@10 748 minima[i].checked= 1;
yading@10 749 }
yading@10 750
yading@10 751 best[0]= minima[0].x;
yading@10 752 best[1]= minima[0].y;
yading@10 753 dmin= minima[0].height;
yading@10 754
yading@10 755 if( best[0] < xmax && best[0] > xmin
yading@10 756 && best[1] < ymax && best[1] > ymin){
yading@10 757 int d;
yading@10 758 //ensure that the refernece samples for hpel refinement are in the map
yading@10 759 CHECK_MV(best[0]-1, best[1])
yading@10 760 CHECK_MV(best[0]+1, best[1])
yading@10 761 CHECK_MV(best[0], best[1]-1)
yading@10 762 CHECK_MV(best[0], best[1]+1)
yading@10 763 }
yading@10 764 return dmin;
yading@10 765 }
yading@10 766
yading@10 767 static int var_diamond_search(MpegEncContext * s, int *best, int dmin,
yading@10 768 int src_index, int ref_index, int const penalty_factor,
yading@10 769 int size, int h, int flags)
yading@10 770 {
yading@10 771 MotionEstContext * const c= &s->me;
yading@10 772 me_cmp_func cmpf, chroma_cmpf;
yading@10 773 int dia_size;
yading@10 774 LOAD_COMMON
yading@10 775 LOAD_COMMON2
yading@10 776 unsigned map_generation = c->map_generation;
yading@10 777
yading@10 778 cmpf= s->dsp.me_cmp[size];
yading@10 779 chroma_cmpf= s->dsp.me_cmp[size+1];
yading@10 780
yading@10 781 for(dia_size=1; dia_size<=c->dia_size; dia_size++){
yading@10 782 int dir, start, end;
yading@10 783 const int x= best[0];
yading@10 784 const int y= best[1];
yading@10 785
yading@10 786 start= FFMAX(0, y + dia_size - ymax);
yading@10 787 end = FFMIN(dia_size, xmax - x + 1);
yading@10 788 for(dir= start; dir<end; dir++){
yading@10 789 int d;
yading@10 790
yading@10 791 //check(x + dir,y + dia_size - dir,0, a0)
yading@10 792 CHECK_MV(x + dir , y + dia_size - dir);
yading@10 793 }
yading@10 794
yading@10 795 start= FFMAX(0, x + dia_size - xmax);
yading@10 796 end = FFMIN(dia_size, y - ymin + 1);
yading@10 797 for(dir= start; dir<end; dir++){
yading@10 798 int d;
yading@10 799
yading@10 800 //check(x + dia_size - dir, y - dir,0, a1)
yading@10 801 CHECK_MV(x + dia_size - dir, y - dir );
yading@10 802 }
yading@10 803
yading@10 804 start= FFMAX(0, -y + dia_size + ymin );
yading@10 805 end = FFMIN(dia_size, x - xmin + 1);
yading@10 806 for(dir= start; dir<end; dir++){
yading@10 807 int d;
yading@10 808
yading@10 809 //check(x - dir,y - dia_size + dir,0, a2)
yading@10 810 CHECK_MV(x - dir , y - dia_size + dir);
yading@10 811 }
yading@10 812
yading@10 813 start= FFMAX(0, -x + dia_size + xmin );
yading@10 814 end = FFMIN(dia_size, ymax - y + 1);
yading@10 815 for(dir= start; dir<end; dir++){
yading@10 816 int d;
yading@10 817
yading@10 818 //check(x - dia_size + dir, y + dir,0, a3)
yading@10 819 CHECK_MV(x - dia_size + dir, y + dir );
yading@10 820 }
yading@10 821
yading@10 822 if(x!=best[0] || y!=best[1])
yading@10 823 dia_size=0;
yading@10 824 }
yading@10 825 return dmin;
yading@10 826 }
yading@10 827
yading@10 828 static av_always_inline int diamond_search(MpegEncContext * s, int *best, int dmin,
yading@10 829 int src_index, int ref_index, int const penalty_factor,
yading@10 830 int size, int h, int flags){
yading@10 831 MotionEstContext * const c= &s->me;
yading@10 832 if(c->dia_size==-1)
yading@10 833 return funny_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
yading@10 834 else if(c->dia_size<-1)
yading@10 835 return sab_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
yading@10 836 else if(c->dia_size<2)
yading@10 837 return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
yading@10 838 else if(c->dia_size>1024)
yading@10 839 return full_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
yading@10 840 else if(c->dia_size>768)
yading@10 841 return umh_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
yading@10 842 else if(c->dia_size>512)
yading@10 843 return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, c->dia_size&0xFF);
yading@10 844 else if(c->dia_size>256)
yading@10 845 return l2s_dia_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
yading@10 846 else
yading@10 847 return var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
yading@10 848 }
yading@10 849
yading@10 850 /**
yading@10 851 @param P a list of candidate mvs to check before starting the
yading@10 852 iterative search. If one of the candidates is close to the optimal mv, then
yading@10 853 it takes fewer iterations. And it increases the chance that we find the
yading@10 854 optimal mv.
yading@10 855 */
yading@10 856 static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int *mx_ptr, int *my_ptr,
yading@10 857 int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2],
yading@10 858 int ref_mv_scale, int flags, int size, int h)
yading@10 859 {
yading@10 860 MotionEstContext * const c= &s->me;
yading@10 861 int best[2]={0, 0}; /**< x and y coordinates of the best motion vector.
yading@10 862 i.e. the difference between the position of the
yading@10 863 block currently being encoded and the position of
yading@10 864 the block chosen to predict it from. */
yading@10 865 int d; ///< the score (cmp + penalty) of any given mv
yading@10 866 int dmin; /**< the best value of d, i.e. the score
yading@10 867 corresponding to the mv stored in best[]. */
yading@10 868 unsigned map_generation;
yading@10 869 int penalty_factor;
yading@10 870 const int ref_mv_stride= s->mb_stride; //pass as arg FIXME
yading@10 871 const int ref_mv_xy= s->mb_x + s->mb_y*ref_mv_stride; //add to last_mv beforepassing FIXME
yading@10 872 me_cmp_func cmpf, chroma_cmpf;
yading@10 873
yading@10 874 LOAD_COMMON
yading@10 875 LOAD_COMMON2
yading@10 876
yading@10 877 if(c->pre_pass){
yading@10 878 penalty_factor= c->pre_penalty_factor;
yading@10 879 cmpf= s->dsp.me_pre_cmp[size];
yading@10 880 chroma_cmpf= s->dsp.me_pre_cmp[size+1];
yading@10 881 }else{
yading@10 882 penalty_factor= c->penalty_factor;
yading@10 883 cmpf= s->dsp.me_cmp[size];
yading@10 884 chroma_cmpf= s->dsp.me_cmp[size+1];
yading@10 885 }
yading@10 886
yading@10 887 map_generation= update_map_generation(c);
yading@10 888
yading@10 889 av_assert2(cmpf);
yading@10 890 dmin= cmp(s, 0, 0, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);
yading@10 891 map[0]= map_generation;
yading@10 892 score_map[0]= dmin;
yading@10 893
yading@10 894 //FIXME precalc first term below?
yading@10 895 if((s->pict_type == AV_PICTURE_TYPE_B && !(c->flags & FLAG_DIRECT)) || s->flags&CODEC_FLAG_MV0)
yading@10 896 dmin += (mv_penalty[pred_x] + mv_penalty[pred_y])*penalty_factor;
yading@10 897
yading@10 898 /* first line */
yading@10 899 if (s->first_slice_line) {
yading@10 900 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
yading@10 901 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
yading@10 902 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
yading@10 903 }else{
yading@10 904 if(dmin<((h*h*s->avctx->mv0_threshold)>>8)
yading@10 905 && ( P_LEFT[0] |P_LEFT[1]
yading@10 906 |P_TOP[0] |P_TOP[1]
yading@10 907 |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){
yading@10 908 *mx_ptr= 0;
yading@10 909 *my_ptr= 0;
yading@10 910 c->skip=1;
yading@10 911 return dmin;
yading@10 912 }
yading@10 913 CHECK_MV( P_MEDIAN[0] >>shift , P_MEDIAN[1] >>shift)
yading@10 914 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)-1)
yading@10 915 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)+1)
yading@10 916 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)-1, (P_MEDIAN[1]>>shift) )
yading@10 917 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)+1, (P_MEDIAN[1]>>shift) )
yading@10 918 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
yading@10 919 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
yading@10 920 CHECK_MV(P_LEFT[0] >>shift, P_LEFT[1] >>shift)
yading@10 921 CHECK_MV(P_TOP[0] >>shift, P_TOP[1] >>shift)
yading@10 922 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
yading@10 923 }
yading@10 924 if(dmin>h*h*4){
yading@10 925 if(c->pre_pass){
yading@10 926 CHECK_CLIPPED_MV((last_mv[ref_mv_xy-1][0]*ref_mv_scale + (1<<15))>>16,
yading@10 927 (last_mv[ref_mv_xy-1][1]*ref_mv_scale + (1<<15))>>16)
yading@10 928 if(!s->first_slice_line)
yading@10 929 CHECK_CLIPPED_MV((last_mv[ref_mv_xy-ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
yading@10 930 (last_mv[ref_mv_xy-ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
yading@10 931 }else{
yading@10 932 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
yading@10 933 (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
yading@10 934 if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line
yading@10 935 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
yading@10 936 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
yading@10 937 }
yading@10 938 }
yading@10 939
yading@10 940 if(c->avctx->last_predictor_count){
yading@10 941 const int count= c->avctx->last_predictor_count;
yading@10 942 const int xstart= FFMAX(0, s->mb_x - count);
yading@10 943 const int ystart= FFMAX(0, s->mb_y - count);
yading@10 944 const int xend= FFMIN(s->mb_width , s->mb_x + count + 1);
yading@10 945 const int yend= FFMIN(s->mb_height, s->mb_y + count + 1);
yading@10 946 int mb_y;
yading@10 947
yading@10 948 for(mb_y=ystart; mb_y<yend; mb_y++){
yading@10 949 int mb_x;
yading@10 950 for(mb_x=xstart; mb_x<xend; mb_x++){
yading@10 951 const int xy= mb_x + 1 + (mb_y + 1)*ref_mv_stride;
yading@10 952 int mx= (last_mv[xy][0]*ref_mv_scale + (1<<15))>>16;
yading@10 953 int my= (last_mv[xy][1]*ref_mv_scale + (1<<15))>>16;
yading@10 954
yading@10 955 if(mx>xmax || mx<xmin || my>ymax || my<ymin) continue;
yading@10 956 CHECK_MV(mx,my)
yading@10 957 }
yading@10 958 }
yading@10 959 }
yading@10 960
yading@10 961 //check(best[0],best[1],0, b0)
yading@10 962 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
yading@10 963
yading@10 964 //check(best[0],best[1],0, b1)
yading@10 965 *mx_ptr= best[0];
yading@10 966 *my_ptr= best[1];
yading@10 967
yading@10 968 return dmin;
yading@10 969 }
yading@10 970
yading@10 971 //this function is dedicated to the braindamaged gcc
yading@10 972 int ff_epzs_motion_search(MpegEncContext *s, int *mx_ptr, int *my_ptr,
yading@10 973 int P[10][2], int src_index, int ref_index,
yading@10 974 int16_t (*last_mv)[2], int ref_mv_scale,
yading@10 975 int size, int h)
yading@10 976 {
yading@10 977 MotionEstContext * const c= &s->me;
yading@10 978 //FIXME convert other functions in the same way if faster
yading@10 979 if(c->flags==0 && h==16 && size==0){
yading@10 980 return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, 0, 0, 16);
yading@10 981 // case FLAG_QPEL:
yading@10 982 // return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, FLAG_QPEL);
yading@10 983 }else{
yading@10 984 return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, c->flags, size, h);
yading@10 985 }
yading@10 986 }
yading@10 987
yading@10 988 static int epzs_motion_search4(MpegEncContext * s,
yading@10 989 int *mx_ptr, int *my_ptr, int P[10][2],
yading@10 990 int src_index, int ref_index, int16_t (*last_mv)[2],
yading@10 991 int ref_mv_scale)
yading@10 992 {
yading@10 993 MotionEstContext * const c= &s->me;
yading@10 994 int best[2]={0, 0};
yading@10 995 int d, dmin;
yading@10 996 unsigned map_generation;
yading@10 997 const int penalty_factor= c->penalty_factor;
yading@10 998 const int size=1;
yading@10 999 const int h=8;
yading@10 1000 const int ref_mv_stride= s->mb_stride;
yading@10 1001 const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
yading@10 1002 me_cmp_func cmpf, chroma_cmpf;
yading@10 1003 LOAD_COMMON
yading@10 1004 int flags= c->flags;
yading@10 1005 LOAD_COMMON2
yading@10 1006
yading@10 1007 cmpf= s->dsp.me_cmp[size];
yading@10 1008 chroma_cmpf= s->dsp.me_cmp[size+1];
yading@10 1009
yading@10 1010 map_generation= update_map_generation(c);
yading@10 1011
yading@10 1012 dmin = 1000000;
yading@10 1013
yading@10 1014 /* first line */
yading@10 1015 if (s->first_slice_line) {
yading@10 1016 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
yading@10 1017 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
yading@10 1018 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
yading@10 1019 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
yading@10 1020 }else{
yading@10 1021 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
yading@10 1022 //FIXME try some early stop
yading@10 1023 CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
yading@10 1024 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
yading@10 1025 CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
yading@10 1026 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
yading@10 1027 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
yading@10 1028 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
yading@10 1029 }
yading@10 1030 if(dmin>64*4){
yading@10 1031 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
yading@10 1032 (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
yading@10 1033 if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line
yading@10 1034 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
yading@10 1035 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
yading@10 1036 }
yading@10 1037
yading@10 1038 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
yading@10 1039
yading@10 1040 *mx_ptr= best[0];
yading@10 1041 *my_ptr= best[1];
yading@10 1042
yading@10 1043 return dmin;
yading@10 1044 }
yading@10 1045
yading@10 1046 //try to merge with above FIXME (needs PSNR test)
yading@10 1047 static int epzs_motion_search2(MpegEncContext * s,
yading@10 1048 int *mx_ptr, int *my_ptr, int P[10][2],
yading@10 1049 int src_index, int ref_index, int16_t (*last_mv)[2],
yading@10 1050 int ref_mv_scale)
yading@10 1051 {
yading@10 1052 MotionEstContext * const c= &s->me;
yading@10 1053 int best[2]={0, 0};
yading@10 1054 int d, dmin;
yading@10 1055 unsigned map_generation;
yading@10 1056 const int penalty_factor= c->penalty_factor;
yading@10 1057 const int size=0; //FIXME pass as arg
yading@10 1058 const int h=8;
yading@10 1059 const int ref_mv_stride= s->mb_stride;
yading@10 1060 const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride;
yading@10 1061 me_cmp_func cmpf, chroma_cmpf;
yading@10 1062 LOAD_COMMON
yading@10 1063 int flags= c->flags;
yading@10 1064 LOAD_COMMON2
yading@10 1065
yading@10 1066 cmpf= s->dsp.me_cmp[size];
yading@10 1067 chroma_cmpf= s->dsp.me_cmp[size+1];
yading@10 1068
yading@10 1069 map_generation= update_map_generation(c);
yading@10 1070
yading@10 1071 dmin = 1000000;
yading@10 1072
yading@10 1073 /* first line */
yading@10 1074 if (s->first_slice_line) {
yading@10 1075 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
yading@10 1076 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
yading@10 1077 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
yading@10 1078 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
yading@10 1079 }else{
yading@10 1080 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift)
yading@10 1081 //FIXME try some early stop
yading@10 1082 CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift)
yading@10 1083 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift)
yading@10 1084 CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift)
yading@10 1085 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift)
yading@10 1086 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16,
yading@10 1087 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16)
yading@10 1088 }
yading@10 1089 if(dmin>64*4){
yading@10 1090 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16,
yading@10 1091 (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16)
yading@10 1092 if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line
yading@10 1093 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16,
yading@10 1094 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16)
yading@10 1095 }
yading@10 1096
yading@10 1097 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags);
yading@10 1098
yading@10 1099 *mx_ptr= best[0];
yading@10 1100 *my_ptr= best[1];
yading@10 1101
yading@10 1102 return dmin;
yading@10 1103 }