00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 #include <limits.h>
00033 #include "libavutil/intmath.h"
00034 #include "avcodec.h"
00035 #include "dsputil.h"
00036 #include "mathops.h"
00037 #include "mpegvideo.h"
00038
00039 #undef NDEBUG
00040 #include <assert.h>
00041
00042 #define SQ(a) ((a)*(a))
00043
00044 #define P_LEFT P[1]
00045 #define P_TOP P[2]
00046 #define P_TOPRIGHT P[3]
00047 #define P_MEDIAN P[4]
00048 #define P_MV1 P[9]
00049
00050 static inline int sad_hpel_motion_search(MpegEncContext * s,
00051 int *mx_ptr, int *my_ptr, int dmin,
00052 int src_index, int ref_index,
00053 int size, int h);
00054
00055 static inline unsigned update_map_generation(MotionEstContext *c)
00056 {
00057 c->map_generation+= 1<<(ME_MAP_MV_BITS*2);
00058 if(c->map_generation==0){
00059 c->map_generation= 1<<(ME_MAP_MV_BITS*2);
00060 memset(c->map, 0, sizeof(uint32_t)*ME_MAP_SIZE);
00061 }
00062 return c->map_generation;
00063 }
00064
00065
00066 typedef struct Minima{
00067 int height;
00068 int x, y;
00069 int checked;
00070 }Minima;
00071
00072 static int minima_cmp(const void *a, const void *b){
00073 const Minima *da = (const Minima *) a;
00074 const Minima *db = (const Minima *) b;
00075
00076 return da->height - db->height;
00077 }
00078
00079 #define FLAG_QPEL 1 //must be 1
00080 #define FLAG_CHROMA 2
00081 #define FLAG_DIRECT 4
00082
00083 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){
00084 const int offset[3]= {
00085 y*c-> stride + x,
00086 ((y*c->uvstride + x)>>1),
00087 ((y*c->uvstride + x)>>1),
00088 };
00089 int i;
00090 for(i=0; i<3; i++){
00091 c->src[0][i]= src [i] + offset[i];
00092 c->ref[0][i]= ref [i] + offset[i];
00093 }
00094 if(ref_index){
00095 for(i=0; i<3; i++){
00096 c->ref[ref_index][i]= ref2[i] + offset[i];
00097 }
00098 }
00099 }
00100
00101 static int get_flags(MotionEstContext *c, int direct, int chroma){
00102 return ((c->avctx->flags&CODEC_FLAG_QPEL) ? FLAG_QPEL : 0)
00103 + (direct ? FLAG_DIRECT : 0)
00104 + (chroma ? FLAG_CHROMA : 0);
00105 }
00106
00107 static av_always_inline int cmp_direct_inline(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
00108 const int size, const int h, int ref_index, int src_index,
00109 me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel){
00110 MotionEstContext * const c= &s->me;
00111 const int stride= c->stride;
00112 const int hx= subx + (x<<(1+qpel));
00113 const int hy= suby + (y<<(1+qpel));
00114 uint8_t * const * const ref= c->ref[ref_index];
00115 uint8_t * const * const src= c->src[src_index];
00116 int d;
00117
00118 assert(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1));
00119 if(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1)){
00120 const int time_pp= s->pp_time;
00121 const int time_pb= s->pb_time;
00122 const int mask= 2*qpel+1;
00123 if(s->mv_type==MV_TYPE_8X8){
00124 int i;
00125 for(i=0; i<4; i++){
00126 int fx = c->direct_basis_mv[i][0] + hx;
00127 int fy = c->direct_basis_mv[i][1] + hy;
00128 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));
00129 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));
00130 int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));
00131 int bxy= (bx&mask) + ((by&mask)<<(qpel+1));
00132
00133 uint8_t *dst= c->temp + 8*(i&1) + 8*stride*(i>>1);
00134 if(qpel){
00135 c->qpel_put[1][fxy](dst, ref[0] + (fx>>2) + (fy>>2)*stride, stride);
00136 c->qpel_avg[1][bxy](dst, ref[8] + (bx>>2) + (by>>2)*stride, stride);
00137 }else{
00138 c->hpel_put[1][fxy](dst, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 8);
00139 c->hpel_avg[1][bxy](dst, ref[8] + (bx>>1) + (by>>1)*stride, stride, 8);
00140 }
00141 }
00142 }else{
00143 int fx = c->direct_basis_mv[0][0] + hx;
00144 int fy = c->direct_basis_mv[0][1] + hy;
00145 int bx = hx ? fx - c->co_located_mv[0][0] : (c->co_located_mv[0][0]*(time_pb - time_pp)/time_pp);
00146 int by = hy ? fy - c->co_located_mv[0][1] : (c->co_located_mv[0][1]*(time_pb - time_pp)/time_pp);
00147 int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));
00148 int bxy= (bx&mask) + ((by&mask)<<(qpel+1));
00149
00150 if(qpel){
00151 c->qpel_put[1][fxy](c->temp , ref[0] + (fx>>2) + (fy>>2)*stride , stride);
00152 c->qpel_put[1][fxy](c->temp + 8 , ref[0] + (fx>>2) + (fy>>2)*stride + 8 , stride);
00153 c->qpel_put[1][fxy](c->temp + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8*stride, stride);
00154 c->qpel_put[1][fxy](c->temp + 8 + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8 + 8*stride, stride);
00155 c->qpel_avg[1][bxy](c->temp , ref[8] + (bx>>2) + (by>>2)*stride , stride);
00156 c->qpel_avg[1][bxy](c->temp + 8 , ref[8] + (bx>>2) + (by>>2)*stride + 8 , stride);
00157 c->qpel_avg[1][bxy](c->temp + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8*stride, stride);
00158 c->qpel_avg[1][bxy](c->temp + 8 + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8 + 8*stride, stride);
00159 }else{
00160 assert((fx>>1) + 16*s->mb_x >= -16);
00161 assert((fy>>1) + 16*s->mb_y >= -16);
00162 assert((fx>>1) + 16*s->mb_x <= s->width);
00163 assert((fy>>1) + 16*s->mb_y <= s->height);
00164 assert((bx>>1) + 16*s->mb_x >= -16);
00165 assert((by>>1) + 16*s->mb_y >= -16);
00166 assert((bx>>1) + 16*s->mb_x <= s->width);
00167 assert((by>>1) + 16*s->mb_y <= s->height);
00168
00169 c->hpel_put[0][fxy](c->temp, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 16);
00170 c->hpel_avg[0][bxy](c->temp, ref[8] + (bx>>1) + (by>>1)*stride, stride, 16);
00171 }
00172 }
00173 d = cmp_func(s, c->temp, src[0], stride, 16);
00174 }else
00175 d= 256*256*256*32;
00176 return d;
00177 }
00178
00179 static av_always_inline int cmp_inline(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
00180 const int size, const int h, int ref_index, int src_index,
00181 me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel, int chroma){
00182 MotionEstContext * const c= &s->me;
00183 const int stride= c->stride;
00184 const int uvstride= c->uvstride;
00185 const int dxy= subx + (suby<<(1+qpel));
00186 const int hx= subx + (x<<(1+qpel));
00187 const int hy= suby + (y<<(1+qpel));
00188 uint8_t * const * const ref= c->ref[ref_index];
00189 uint8_t * const * const src= c->src[src_index];
00190 int d;
00191
00192 int uvdxy;
00193 if(dxy){
00194 if(qpel){
00195 c->qpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride);
00196 if(chroma){
00197 int cx= hx/2;
00198 int cy= hy/2;
00199 cx= (cx>>1)|(cx&1);
00200 cy= (cy>>1)|(cy&1);
00201 uvdxy= (cx&1) + 2*(cy&1);
00202
00203 }
00204 }else{
00205 c->hpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride, h);
00206 if(chroma)
00207 uvdxy= dxy | (x&1) | (2*(y&1));
00208 }
00209 d = cmp_func(s, c->temp, src[0], stride, h);
00210 }else{
00211 d = cmp_func(s, src[0], ref[0] + x + y*stride, stride, h);
00212 if(chroma)
00213 uvdxy= (x&1) + 2*(y&1);
00214 }
00215 if(chroma){
00216 uint8_t * const uvtemp= c->temp + 16*stride;
00217 c->hpel_put[size+1][uvdxy](uvtemp , ref[1] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);
00218 c->hpel_put[size+1][uvdxy](uvtemp+8, ref[2] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);
00219 d += chroma_cmp_func(s, uvtemp , src[1], uvstride, h>>1);
00220 d += chroma_cmp_func(s, uvtemp+8, src[2], uvstride, h>>1);
00221 }
00222 return d;
00223 }
00224
00225 static int cmp_simple(MpegEncContext *s, const int x, const int y,
00226 int ref_index, int src_index,
00227 me_cmp_func cmp_func, me_cmp_func chroma_cmp_func){
00228 return cmp_inline(s,x,y,0,0,0,16,ref_index,src_index, cmp_func, chroma_cmp_func, 0, 0);
00229 }
00230
00231 static int cmp_fpel_internal(MpegEncContext *s, const int x, const int y,
00232 const int size, const int h, int ref_index, int src_index,
00233 me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
00234 if(flags&FLAG_DIRECT){
00235 return cmp_direct_inline(s,x,y,0,0,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags&FLAG_QPEL);
00236 }else{
00237 return cmp_inline(s,x,y,0,0,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0, flags&FLAG_CHROMA);
00238 }
00239 }
00240
00241 static int cmp_internal(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
00242 const int size, const int h, int ref_index, int src_index,
00243 me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
00244 if(flags&FLAG_DIRECT){
00245 return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags&FLAG_QPEL);
00246 }else{
00247 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);
00248 }
00249 }
00250
00254 static av_always_inline int cmp(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
00255 const int size, const int h, int ref_index, int src_index,
00256 me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
00257 if(av_builtin_constant_p(flags) && av_builtin_constant_p(h) && av_builtin_constant_p(size)
00258 && av_builtin_constant_p(subx) && av_builtin_constant_p(suby)
00259 && flags==0 && h==16 && size==0 && subx==0 && suby==0){
00260 return cmp_simple(s,x,y,ref_index,src_index, cmp_func, chroma_cmp_func);
00261 }else if(av_builtin_constant_p(subx) && av_builtin_constant_p(suby)
00262 && subx==0 && suby==0){
00263 return cmp_fpel_internal(s,x,y,size,h,ref_index,src_index, cmp_func, chroma_cmp_func,flags);
00264 }else{
00265 return cmp_internal(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags);
00266 }
00267 }
00268
00269 static int cmp_hpel(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
00270 const int size, const int h, int ref_index, int src_index,
00271 me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
00272 if(flags&FLAG_DIRECT){
00273 return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0);
00274 }else{
00275 return cmp_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0, flags&FLAG_CHROMA);
00276 }
00277 }
00278
00279 static int cmp_qpel(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
00280 const int size, const int h, int ref_index, int src_index,
00281 me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
00282 if(flags&FLAG_DIRECT){
00283 return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 1);
00284 }else{
00285 return cmp_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 1, flags&FLAG_CHROMA);
00286 }
00287 }
00288
00289 #include "motion_est_template.c"
00290
00291 static int zero_cmp(void *s, uint8_t *a, uint8_t *b, int stride, int h){
00292 return 0;
00293 }
00294
00295 static void zero_hpel(uint8_t *a, const uint8_t *b, int stride, int h){
00296 }
00297
00298 int ff_init_me(MpegEncContext *s){
00299 MotionEstContext * const c= &s->me;
00300 int cache_size= FFMIN(ME_MAP_SIZE>>ME_MAP_SHIFT, 1<<ME_MAP_SHIFT);
00301 int dia_size= FFMAX(FFABS(s->avctx->dia_size)&255, FFABS(s->avctx->pre_dia_size)&255);
00302
00303 if(FFMIN(s->avctx->dia_size, s->avctx->pre_dia_size) < -ME_MAP_SIZE){
00304 av_log(s->avctx, AV_LOG_ERROR, "ME_MAP size is too small for SAB diamond\n");
00305 return -1;
00306 }
00307
00308 if(s->me_method!=ME_ZERO && s->me_method!=ME_EPZS && s->me_method!=ME_X1 && s->avctx->codec_id != CODEC_ID_SNOW){
00309 av_log(s->avctx, AV_LOG_ERROR, "me_method is only allowed to be set to zero and epzs; for hex,umh,full and others see dia_size\n");
00310 return -1;
00311 }
00312
00313 c->avctx= s->avctx;
00314
00315 if(cache_size < 2*dia_size && !c->stride){
00316 av_log(s->avctx, AV_LOG_INFO, "ME_MAP size may be a little small for the selected diamond size\n");
00317 }
00318
00319 ff_set_cmp(&s->dsp, s->dsp.me_pre_cmp, c->avctx->me_pre_cmp);
00320 ff_set_cmp(&s->dsp, s->dsp.me_cmp, c->avctx->me_cmp);
00321 ff_set_cmp(&s->dsp, s->dsp.me_sub_cmp, c->avctx->me_sub_cmp);
00322 ff_set_cmp(&s->dsp, s->dsp.mb_cmp, c->avctx->mb_cmp);
00323
00324 c->flags = get_flags(c, 0, c->avctx->me_cmp &FF_CMP_CHROMA);
00325 c->sub_flags= get_flags(c, 0, c->avctx->me_sub_cmp&FF_CMP_CHROMA);
00326 c->mb_flags = get_flags(c, 0, c->avctx->mb_cmp &FF_CMP_CHROMA);
00327
00328
00329 if(s->flags&CODEC_FLAG_QPEL){
00330 c->sub_motion_search= qpel_motion_search;
00331 c->qpel_avg= s->dsp.avg_qpel_pixels_tab;
00332 if(s->no_rounding) c->qpel_put= s->dsp.put_no_rnd_qpel_pixels_tab;
00333 else c->qpel_put= s->dsp.put_qpel_pixels_tab;
00334 }else{
00335 if(c->avctx->me_sub_cmp&FF_CMP_CHROMA)
00336 c->sub_motion_search= hpel_motion_search;
00337 else if( c->avctx->me_sub_cmp == FF_CMP_SAD
00338 && c->avctx-> me_cmp == FF_CMP_SAD
00339 && c->avctx-> mb_cmp == FF_CMP_SAD)
00340 c->sub_motion_search= sad_hpel_motion_search;
00341 else
00342 c->sub_motion_search= hpel_motion_search;
00343 }
00344 c->hpel_avg= s->dsp.avg_pixels_tab;
00345 if(s->no_rounding) c->hpel_put= s->dsp.put_no_rnd_pixels_tab;
00346 else c->hpel_put= s->dsp.put_pixels_tab;
00347
00348 if(s->linesize){
00349 c->stride = s->linesize;
00350 c->uvstride= s->uvlinesize;
00351 }else{
00352 c->stride = 16*s->mb_width + 32;
00353 c->uvstride= 8*s->mb_width + 16;
00354 }
00355
00356
00357
00358
00359 if(s->codec_id != CODEC_ID_SNOW){
00360 if((c->avctx->me_cmp&FF_CMP_CHROMA)){
00361 s->dsp.me_cmp[2]= zero_cmp;
00362 }
00363 if((c->avctx->me_sub_cmp&FF_CMP_CHROMA) && !s->dsp.me_sub_cmp[2]){
00364 s->dsp.me_sub_cmp[2]= zero_cmp;
00365 }
00366 c->hpel_put[2][0]= c->hpel_put[2][1]=
00367 c->hpel_put[2][2]= c->hpel_put[2][3]= zero_hpel;
00368 }
00369
00370 if(s->codec_id == CODEC_ID_H261){
00371 c->sub_motion_search= no_sub_motion_search;
00372 }
00373
00374 return 0;
00375 }
00376
00377 static inline void no_motion_search(MpegEncContext * s,
00378 int *mx_ptr, int *my_ptr)
00379 {
00380 *mx_ptr = 16 * s->mb_x;
00381 *my_ptr = 16 * s->mb_y;
00382 }
00383
00384 #define Z_THRESHOLD 256
00385
00386 #define CHECK_SAD_HALF_MV(suffix, x, y) \
00387 {\
00388 d= s->dsp.pix_abs[size][(x?1:0)+(y?2:0)](NULL, pix, ptr+((x)>>1), stride, h);\
00389 d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*penalty_factor;\
00390 COPY3_IF_LT(dminh, d, dx, x, dy, y)\
00391 }
00392
00393 static inline int sad_hpel_motion_search(MpegEncContext * s,
00394 int *mx_ptr, int *my_ptr, int dmin,
00395 int src_index, int ref_index,
00396 int size, int h)
00397 {
00398 MotionEstContext * const c= &s->me;
00399 const int penalty_factor= c->sub_penalty_factor;
00400 int mx, my, dminh;
00401 uint8_t *pix, *ptr;
00402 int stride= c->stride;
00403 const int flags= c->sub_flags;
00404 LOAD_COMMON
00405
00406 assert(flags == 0);
00407
00408 if(c->skip){
00409
00410 *mx_ptr = 0;
00411 *my_ptr = 0;
00412 return dmin;
00413 }
00414
00415
00416 pix = c->src[src_index][0];
00417
00418 mx = *mx_ptr;
00419 my = *my_ptr;
00420 ptr = c->ref[ref_index][0] + (my * stride) + mx;
00421
00422 dminh = dmin;
00423
00424 if (mx > xmin && mx < xmax &&
00425 my > ymin && my < ymax) {
00426 int dx=0, dy=0;
00427 int d, pen_x, pen_y;
00428 const int index= (my<<ME_MAP_SHIFT) + mx;
00429 const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
00430 const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)];
00431 const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)];
00432 const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
00433 mx<<=1;
00434 my<<=1;
00435
00436
00437 pen_x= pred_x + mx;
00438 pen_y= pred_y + my;
00439
00440 ptr-= stride;
00441 if(t<=b){
00442 CHECK_SAD_HALF_MV(y2 , 0, -1)
00443 if(l<=r){
00444 CHECK_SAD_HALF_MV(xy2, -1, -1)
00445 if(t+r<=b+l){
00446 CHECK_SAD_HALF_MV(xy2, +1, -1)
00447 ptr+= stride;
00448 }else{
00449 ptr+= stride;
00450 CHECK_SAD_HALF_MV(xy2, -1, +1)
00451 }
00452 CHECK_SAD_HALF_MV(x2 , -1, 0)
00453 }else{
00454 CHECK_SAD_HALF_MV(xy2, +1, -1)
00455 if(t+l<=b+r){
00456 CHECK_SAD_HALF_MV(xy2, -1, -1)
00457 ptr+= stride;
00458 }else{
00459 ptr+= stride;
00460 CHECK_SAD_HALF_MV(xy2, +1, +1)
00461 }
00462 CHECK_SAD_HALF_MV(x2 , +1, 0)
00463 }
00464 }else{
00465 if(l<=r){
00466 if(t+l<=b+r){
00467 CHECK_SAD_HALF_MV(xy2, -1, -1)
00468 ptr+= stride;
00469 }else{
00470 ptr+= stride;
00471 CHECK_SAD_HALF_MV(xy2, +1, +1)
00472 }
00473 CHECK_SAD_HALF_MV(x2 , -1, 0)
00474 CHECK_SAD_HALF_MV(xy2, -1, +1)
00475 }else{
00476 if(t+r<=b+l){
00477 CHECK_SAD_HALF_MV(xy2, +1, -1)
00478 ptr+= stride;
00479 }else{
00480 ptr+= stride;
00481 CHECK_SAD_HALF_MV(xy2, -1, +1)
00482 }
00483 CHECK_SAD_HALF_MV(x2 , +1, 0)
00484 CHECK_SAD_HALF_MV(xy2, +1, +1)
00485 }
00486 CHECK_SAD_HALF_MV(y2 , 0, +1)
00487 }
00488 mx+=dx;
00489 my+=dy;
00490
00491 }else{
00492 mx<<=1;
00493 my<<=1;
00494 }
00495
00496 *mx_ptr = mx;
00497 *my_ptr = my;
00498 return dminh;
00499 }
00500
00501 static inline void set_p_mv_tables(MpegEncContext * s, int mx, int my, int mv4)
00502 {
00503 const int xy= s->mb_x + s->mb_y*s->mb_stride;
00504
00505 s->p_mv_table[xy][0] = mx;
00506 s->p_mv_table[xy][1] = my;
00507
00508
00509 if(mv4){
00510 int mot_xy= s->block_index[0];
00511
00512 s->current_picture.f.motion_val[0][mot_xy ][0] = mx;
00513 s->current_picture.f.motion_val[0][mot_xy ][1] = my;
00514 s->current_picture.f.motion_val[0][mot_xy + 1][0] = mx;
00515 s->current_picture.f.motion_val[0][mot_xy + 1][1] = my;
00516
00517 mot_xy += s->b8_stride;
00518 s->current_picture.f.motion_val[0][mot_xy ][0] = mx;
00519 s->current_picture.f.motion_val[0][mot_xy ][1] = my;
00520 s->current_picture.f.motion_val[0][mot_xy + 1][0] = mx;
00521 s->current_picture.f.motion_val[0][mot_xy + 1][1] = my;
00522 }
00523 }
00524
00528 static inline void get_limits(MpegEncContext *s, int x, int y)
00529 {
00530 MotionEstContext * const c= &s->me;
00531 int range= c->avctx->me_range >> (1 + !!(c->flags&FLAG_QPEL));
00532
00533
00534
00535
00536 if (s->unrestricted_mv) {
00537 c->xmin = - x - 16;
00538 c->ymin = - y - 16;
00539 c->xmax = - x + s->mb_width *16;
00540 c->ymax = - y + s->mb_height*16;
00541 } else if (s->out_format == FMT_H261){
00542
00543 c->xmin = (x > 15) ? - 15 : 0;
00544 c->ymin = (y > 15) ? - 15 : 0;
00545 c->xmax = (x < s->mb_width * 16 - 16) ? 15 : 0;
00546 c->ymax = (y < s->mb_height * 16 - 16) ? 15 : 0;
00547 } else {
00548 c->xmin = - x;
00549 c->ymin = - y;
00550 c->xmax = - x + s->mb_width *16 - 16;
00551 c->ymax = - y + s->mb_height*16 - 16;
00552 }
00553 if(range){
00554 c->xmin = FFMAX(c->xmin,-range);
00555 c->xmax = FFMIN(c->xmax, range);
00556 c->ymin = FFMAX(c->ymin,-range);
00557 c->ymax = FFMIN(c->ymax, range);
00558 }
00559 }
00560
00561 static inline void init_mv4_ref(MotionEstContext *c){
00562 const int stride= c->stride;
00563
00564 c->ref[1][0] = c->ref[0][0] + 8;
00565 c->ref[2][0] = c->ref[0][0] + 8*stride;
00566 c->ref[3][0] = c->ref[2][0] + 8;
00567 c->src[1][0] = c->src[0][0] + 8;
00568 c->src[2][0] = c->src[0][0] + 8*stride;
00569 c->src[3][0] = c->src[2][0] + 8;
00570 }
00571
00572 static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift)
00573 {
00574 MotionEstContext * const c= &s->me;
00575 const int size= 1;
00576 const int h=8;
00577 int block;
00578 int P[10][2];
00579 int dmin_sum=0, mx4_sum=0, my4_sum=0;
00580 int same=1;
00581 const int stride= c->stride;
00582 uint8_t *mv_penalty= c->current_mv_penalty;
00583
00584 init_mv4_ref(c);
00585
00586 for(block=0; block<4; block++){
00587 int mx4, my4;
00588 int pred_x4, pred_y4;
00589 int dmin4;
00590 static const int off[4]= {2, 1, 1, -1};
00591 const int mot_stride = s->b8_stride;
00592 const int mot_xy = s->block_index[block];
00593
00594 P_LEFT[0] = s->current_picture.f.motion_val[0][mot_xy - 1][0];
00595 P_LEFT[1] = s->current_picture.f.motion_val[0][mot_xy - 1][1];
00596
00597 if(P_LEFT[0] > (c->xmax<<shift)) P_LEFT[0] = (c->xmax<<shift);
00598
00599
00600 if (s->first_slice_line && block<2) {
00601 c->pred_x= pred_x4= P_LEFT[0];
00602 c->pred_y= pred_y4= P_LEFT[1];
00603 } else {
00604 P_TOP[0] = s->current_picture.f.motion_val[0][mot_xy - mot_stride ][0];
00605 P_TOP[1] = s->current_picture.f.motion_val[0][mot_xy - mot_stride ][1];
00606 P_TOPRIGHT[0] = s->current_picture.f.motion_val[0][mot_xy - mot_stride + off[block]][0];
00607 P_TOPRIGHT[1] = s->current_picture.f.motion_val[0][mot_xy - mot_stride + off[block]][1];
00608 if(P_TOP[1] > (c->ymax<<shift)) P_TOP[1] = (c->ymax<<shift);
00609 if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
00610 if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
00611 if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
00612
00613 P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
00614 P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
00615
00616 c->pred_x= pred_x4 = P_MEDIAN[0];
00617 c->pred_y= pred_y4 = P_MEDIAN[1];
00618 }
00619 P_MV1[0]= mx;
00620 P_MV1[1]= my;
00621
00622 dmin4 = epzs_motion_search4(s, &mx4, &my4, P, block, block, s->p_mv_table, (1<<16)>>shift);
00623
00624 dmin4= c->sub_motion_search(s, &mx4, &my4, dmin4, block, block, size, h);
00625
00626 if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){
00627 int dxy;
00628 const int offset= ((block&1) + (block>>1)*stride)*8;
00629 uint8_t *dest_y = c->scratchpad + offset;
00630 if(s->quarter_sample){
00631 uint8_t *ref= c->ref[block][0] + (mx4>>2) + (my4>>2)*stride;
00632 dxy = ((my4 & 3) << 2) | (mx4 & 3);
00633
00634 if(s->no_rounding)
00635 s->dsp.put_no_rnd_qpel_pixels_tab[1][dxy](dest_y , ref , stride);
00636 else
00637 s->dsp.put_qpel_pixels_tab [1][dxy](dest_y , ref , stride);
00638 }else{
00639 uint8_t *ref= c->ref[block][0] + (mx4>>1) + (my4>>1)*stride;
00640 dxy = ((my4 & 1) << 1) | (mx4 & 1);
00641
00642 if(s->no_rounding)
00643 s->dsp.put_no_rnd_pixels_tab[1][dxy](dest_y , ref , stride, h);
00644 else
00645 s->dsp.put_pixels_tab [1][dxy](dest_y , ref , stride, h);
00646 }
00647 dmin_sum+= (mv_penalty[mx4-pred_x4] + mv_penalty[my4-pred_y4])*c->mb_penalty_factor;
00648 }else
00649 dmin_sum+= dmin4;
00650
00651 if(s->quarter_sample){
00652 mx4_sum+= mx4/2;
00653 my4_sum+= my4/2;
00654 }else{
00655 mx4_sum+= mx4;
00656 my4_sum+= my4;
00657 }
00658
00659 s->current_picture.f.motion_val[0][s->block_index[block]][0] = mx4;
00660 s->current_picture.f.motion_val[0][s->block_index[block]][1] = my4;
00661
00662 if(mx4 != mx || my4 != my) same=0;
00663 }
00664
00665 if(same)
00666 return INT_MAX;
00667
00668 if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){
00669 dmin_sum += s->dsp.mb_cmp[0](s, s->new_picture.f.data[0] + s->mb_x*16 + s->mb_y*16*stride, c->scratchpad, stride, 16);
00670 }
00671
00672 if(c->avctx->mb_cmp&FF_CMP_CHROMA){
00673 int dxy;
00674 int mx, my;
00675 int offset;
00676
00677 mx= ff_h263_round_chroma(mx4_sum);
00678 my= ff_h263_round_chroma(my4_sum);
00679 dxy = ((my & 1) << 1) | (mx & 1);
00680
00681 offset= (s->mb_x*8 + (mx>>1)) + (s->mb_y*8 + (my>>1))*s->uvlinesize;
00682
00683 if(s->no_rounding){
00684 s->dsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad , s->last_picture.f.data[1] + offset, s->uvlinesize, 8);
00685 s->dsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad + 8, s->last_picture.f.data[2] + offset, s->uvlinesize, 8);
00686 }else{
00687 s->dsp.put_pixels_tab [1][dxy](c->scratchpad , s->last_picture.f.data[1] + offset, s->uvlinesize, 8);
00688 s->dsp.put_pixels_tab [1][dxy](c->scratchpad + 8, s->last_picture.f.data[2] + offset, s->uvlinesize, 8);
00689 }
00690
00691 dmin_sum += s->dsp.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);
00692 dmin_sum += s->dsp.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);
00693 }
00694
00695 c->pred_x= mx;
00696 c->pred_y= my;
00697
00698 switch(c->avctx->mb_cmp&0xFF){
00699
00700
00701 case FF_CMP_RD:
00702 return dmin_sum;
00703 default:
00704 return dmin_sum+ 11*c->mb_penalty_factor;
00705 }
00706 }
00707
00708 static inline void init_interlaced_ref(MpegEncContext *s, int ref_index){
00709 MotionEstContext * const c= &s->me;
00710
00711 c->ref[1+ref_index][0] = c->ref[0+ref_index][0] + s->linesize;
00712 c->src[1][0] = c->src[0][0] + s->linesize;
00713 if(c->flags & FLAG_CHROMA){
00714 c->ref[1+ref_index][1] = c->ref[0+ref_index][1] + s->uvlinesize;
00715 c->ref[1+ref_index][2] = c->ref[0+ref_index][2] + s->uvlinesize;
00716 c->src[1][1] = c->src[0][1] + s->uvlinesize;
00717 c->src[1][2] = c->src[0][2] + s->uvlinesize;
00718 }
00719 }
00720
00721 static int interlaced_search(MpegEncContext *s, int ref_index,
00722 int16_t (*mv_tables[2][2])[2], uint8_t *field_select_tables[2], int mx, int my, int user_field_select)
00723 {
00724 MotionEstContext * const c= &s->me;
00725 const int size=0;
00726 const int h=8;
00727 int block;
00728 int P[10][2];
00729 uint8_t * const mv_penalty= c->current_mv_penalty;
00730 int same=1;
00731 const int stride= 2*s->linesize;
00732 int dmin_sum= 0;
00733 const int mot_stride= s->mb_stride;
00734 const int xy= s->mb_x + s->mb_y*mot_stride;
00735
00736 c->ymin>>=1;
00737 c->ymax>>=1;
00738 c->stride<<=1;
00739 c->uvstride<<=1;
00740 init_interlaced_ref(s, ref_index);
00741
00742 for(block=0; block<2; block++){
00743 int field_select;
00744 int best_dmin= INT_MAX;
00745 int best_field= -1;
00746
00747 for(field_select=0; field_select<2; field_select++){
00748 int dmin, mx_i, my_i;
00749 int16_t (*mv_table)[2]= mv_tables[block][field_select];
00750
00751 if(user_field_select){
00752 assert(field_select==0 || field_select==1);
00753 assert(field_select_tables[block][xy]==0 || field_select_tables[block][xy]==1);
00754 if(field_select_tables[block][xy] != field_select)
00755 continue;
00756 }
00757
00758 P_LEFT[0] = mv_table[xy - 1][0];
00759 P_LEFT[1] = mv_table[xy - 1][1];
00760 if(P_LEFT[0] > (c->xmax<<1)) P_LEFT[0] = (c->xmax<<1);
00761
00762 c->pred_x= P_LEFT[0];
00763 c->pred_y= P_LEFT[1];
00764
00765 if(!s->first_slice_line){
00766 P_TOP[0] = mv_table[xy - mot_stride][0];
00767 P_TOP[1] = mv_table[xy - mot_stride][1];
00768 P_TOPRIGHT[0] = mv_table[xy - mot_stride + 1][0];
00769 P_TOPRIGHT[1] = mv_table[xy - mot_stride + 1][1];
00770 if(P_TOP[1] > (c->ymax<<1)) P_TOP[1] = (c->ymax<<1);
00771 if(P_TOPRIGHT[0] < (c->xmin<<1)) P_TOPRIGHT[0]= (c->xmin<<1);
00772 if(P_TOPRIGHT[0] > (c->xmax<<1)) P_TOPRIGHT[0]= (c->xmax<<1);
00773 if(P_TOPRIGHT[1] > (c->ymax<<1)) P_TOPRIGHT[1]= (c->ymax<<1);
00774
00775 P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
00776 P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
00777 }
00778 P_MV1[0]= mx;
00779 P_MV1[1]= my / 2;
00780
00781 dmin = epzs_motion_search2(s, &mx_i, &my_i, P, block, field_select+ref_index, mv_table, (1<<16)>>1);
00782
00783 dmin= c->sub_motion_search(s, &mx_i, &my_i, dmin, block, field_select+ref_index, size, h);
00784
00785 mv_table[xy][0]= mx_i;
00786 mv_table[xy][1]= my_i;
00787
00788 if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){
00789 int dxy;
00790
00791
00792 uint8_t *ref= c->ref[field_select+ref_index][0] + (mx_i>>1) + (my_i>>1)*stride;
00793 dxy = ((my_i & 1) << 1) | (mx_i & 1);
00794
00795 if(s->no_rounding){
00796 s->dsp.put_no_rnd_pixels_tab[size][dxy](c->scratchpad, ref , stride, h);
00797 }else{
00798 s->dsp.put_pixels_tab [size][dxy](c->scratchpad, ref , stride, h);
00799 }
00800 dmin= s->dsp.mb_cmp[size](s, c->src[block][0], c->scratchpad, stride, h);
00801 dmin+= (mv_penalty[mx_i-c->pred_x] + mv_penalty[my_i-c->pred_y] + 1)*c->mb_penalty_factor;
00802 }else
00803 dmin+= c->mb_penalty_factor;
00804
00805 dmin += field_select != block;
00806
00807 if(dmin < best_dmin){
00808 best_dmin= dmin;
00809 best_field= field_select;
00810 }
00811 }
00812 {
00813 int16_t (*mv_table)[2]= mv_tables[block][best_field];
00814
00815 if(mv_table[xy][0] != mx) same=0;
00816 if(mv_table[xy][1]&1) same=0;
00817 if(mv_table[xy][1]*2 != my) same=0;
00818 if(best_field != block) same=0;
00819 }
00820
00821 field_select_tables[block][xy]= best_field;
00822 dmin_sum += best_dmin;
00823 }
00824
00825 c->ymin<<=1;
00826 c->ymax<<=1;
00827 c->stride>>=1;
00828 c->uvstride>>=1;
00829
00830 if(same)
00831 return INT_MAX;
00832
00833 switch(c->avctx->mb_cmp&0xFF){
00834
00835
00836 case FF_CMP_RD:
00837 return dmin_sum;
00838 default:
00839 return dmin_sum+ 11*c->mb_penalty_factor;
00840 }
00841 }
00842
00843 static void clip_input_mv(MpegEncContext * s, int16_t *mv, int interlaced){
00844 int ymax= s->me.ymax>>interlaced;
00845 int ymin= s->me.ymin>>interlaced;
00846
00847 if(mv[0] < s->me.xmin) mv[0] = s->me.xmin;
00848 if(mv[0] > s->me.xmax) mv[0] = s->me.xmax;
00849 if(mv[1] < ymin) mv[1] = ymin;
00850 if(mv[1] > ymax) mv[1] = ymax;
00851 }
00852
00853 static inline int check_input_motion(MpegEncContext * s, int mb_x, int mb_y, int p_type){
00854 MotionEstContext * const c= &s->me;
00855 Picture *p= s->current_picture_ptr;
00856 int mb_xy= mb_x + mb_y*s->mb_stride;
00857 int xy= 2*mb_x + 2*mb_y*s->b8_stride;
00858 int mb_type= s->current_picture.f.mb_type[mb_xy];
00859 int flags= c->flags;
00860 int shift= (flags&FLAG_QPEL) + 1;
00861 int mask= (1<<shift)-1;
00862 int x, y, i;
00863 int d=0;
00864 me_cmp_func cmpf= s->dsp.sse[0];
00865 me_cmp_func chroma_cmpf= s->dsp.sse[1];
00866
00867 if(p_type && USES_LIST(mb_type, 1)){
00868 av_log(c->avctx, AV_LOG_ERROR, "backward motion vector in P frame\n");
00869 return INT_MAX/2;
00870 }
00871 assert(IS_INTRA(mb_type) || USES_LIST(mb_type,0) || USES_LIST(mb_type,1));
00872
00873 for(i=0; i<4; i++){
00874 int xy= s->block_index[i];
00875 clip_input_mv(s, p->f.motion_val[0][xy], !!IS_INTERLACED(mb_type));
00876 clip_input_mv(s, p->f.motion_val[1][xy], !!IS_INTERLACED(mb_type));
00877 }
00878
00879 if(IS_INTERLACED(mb_type)){
00880 int xy2= xy + s->b8_stride;
00881 s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTRA;
00882 c->stride<<=1;
00883 c->uvstride<<=1;
00884
00885 if(!(s->flags & CODEC_FLAG_INTERLACED_ME)){
00886 av_log(c->avctx, AV_LOG_ERROR, "Interlaced macroblock selected but interlaced motion estimation disabled\n");
00887 return INT_MAX/2;
00888 }
00889
00890 if(USES_LIST(mb_type, 0)){
00891 int field_select0= p->f.ref_index[0][4*mb_xy ];
00892 int field_select1= p->f.ref_index[0][4*mb_xy+2];
00893 assert(field_select0==0 ||field_select0==1);
00894 assert(field_select1==0 ||field_select1==1);
00895 init_interlaced_ref(s, 0);
00896
00897 if(p_type){
00898 s->p_field_select_table[0][mb_xy]= field_select0;
00899 s->p_field_select_table[1][mb_xy]= field_select1;
00900 *(uint32_t*)s->p_field_mv_table[0][field_select0][mb_xy] = *(uint32_t*)p->f.motion_val[0][xy ];
00901 *(uint32_t*)s->p_field_mv_table[1][field_select1][mb_xy] = *(uint32_t*)p->f.motion_val[0][xy2];
00902 s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER_I;
00903 }else{
00904 s->b_field_select_table[0][0][mb_xy]= field_select0;
00905 s->b_field_select_table[0][1][mb_xy]= field_select1;
00906 *(uint32_t*)s->b_field_mv_table[0][0][field_select0][mb_xy] = *(uint32_t*)p->f.motion_val[0][xy ];
00907 *(uint32_t*)s->b_field_mv_table[0][1][field_select1][mb_xy] = *(uint32_t*)p->f.motion_val[0][xy2];
00908 s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_FORWARD_I;
00909 }
00910
00911 x = p->f.motion_val[0][xy ][0];
00912 y = p->f.motion_val[0][xy ][1];
00913 d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select0, 0, cmpf, chroma_cmpf, flags);
00914 x = p->f.motion_val[0][xy2][0];
00915 y = p->f.motion_val[0][xy2][1];
00916 d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select1, 1, cmpf, chroma_cmpf, flags);
00917 }
00918 if(USES_LIST(mb_type, 1)){
00919 int field_select0 = p->f.ref_index[1][4 * mb_xy ];
00920 int field_select1 = p->f.ref_index[1][4 * mb_xy + 2];
00921 assert(field_select0==0 ||field_select0==1);
00922 assert(field_select1==0 ||field_select1==1);
00923 init_interlaced_ref(s, 2);
00924
00925 s->b_field_select_table[1][0][mb_xy]= field_select0;
00926 s->b_field_select_table[1][1][mb_xy]= field_select1;
00927 *(uint32_t*)s->b_field_mv_table[1][0][field_select0][mb_xy] = *(uint32_t*)p->f.motion_val[1][xy ];
00928 *(uint32_t*)s->b_field_mv_table[1][1][field_select1][mb_xy] = *(uint32_t*)p->f.motion_val[1][xy2];
00929 if(USES_LIST(mb_type, 0)){
00930 s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_BIDIR_I;
00931 }else{
00932 s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_BACKWARD_I;
00933 }
00934
00935 x = p->f.motion_val[1][xy ][0];
00936 y = p->f.motion_val[1][xy ][1];
00937 d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select0+2, 0, cmpf, chroma_cmpf, flags);
00938 x = p->f.motion_val[1][xy2][0];
00939 y = p->f.motion_val[1][xy2][1];
00940 d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select1+2, 1, cmpf, chroma_cmpf, flags);
00941
00942 }
00943 c->stride>>=1;
00944 c->uvstride>>=1;
00945 }else if(IS_8X8(mb_type)){
00946 if(!(s->flags & CODEC_FLAG_4MV)){
00947 av_log(c->avctx, AV_LOG_ERROR, "4MV macroblock selected but 4MV encoding disabled\n");
00948 return INT_MAX/2;
00949 }
00950 cmpf= s->dsp.sse[1];
00951 chroma_cmpf= s->dsp.sse[1];
00952 init_mv4_ref(c);
00953 for(i=0; i<4; i++){
00954 xy= s->block_index[i];
00955 x= p->f.motion_val[0][xy][0];
00956 y= p->f.motion_val[0][xy][1];
00957 d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 1, 8, i, i, cmpf, chroma_cmpf, flags);
00958 }
00959 s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER4V;
00960 }else{
00961 if(USES_LIST(mb_type, 0)){
00962 if(p_type){
00963 *(uint32_t*)s->p_mv_table[mb_xy] = *(uint32_t*)p->f.motion_val[0][xy];
00964 s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER;
00965 }else if(USES_LIST(mb_type, 1)){
00966 *(uint32_t*)s->b_bidir_forw_mv_table[mb_xy] = *(uint32_t*)p->f.motion_val[0][xy];
00967 *(uint32_t*)s->b_bidir_back_mv_table[mb_xy] = *(uint32_t*)p->f.motion_val[1][xy];
00968 s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_BIDIR;
00969 }else{
00970 *(uint32_t*)s->b_forw_mv_table[mb_xy] = *(uint32_t*)p->f.motion_val[0][xy];
00971 s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_FORWARD;
00972 }
00973 x = p->f.motion_val[0][xy][0];
00974 y = p->f.motion_val[0][xy][1];
00975 d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 16, 0, 0, cmpf, chroma_cmpf, flags);
00976 }else if(USES_LIST(mb_type, 1)){
00977 *(uint32_t*)s->b_back_mv_table[mb_xy] = *(uint32_t*)p->f.motion_val[1][xy];
00978 s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_BACKWARD;
00979
00980 x = p->f.motion_val[1][xy][0];
00981 y = p->f.motion_val[1][xy][1];
00982 d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 16, 2, 0, cmpf, chroma_cmpf, flags);
00983 }else
00984 s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTRA;
00985 }
00986 return d;
00987 }
00988
00989 void ff_estimate_p_frame_motion(MpegEncContext * s,
00990 int mb_x, int mb_y)
00991 {
00992 MotionEstContext * const c= &s->me;
00993 uint8_t *pix, *ppix;
00994 int sum, mx, my, dmin;
00995 int varc;
00996 int vard;
00997 int P[10][2];
00998 const int shift= 1+s->quarter_sample;
00999 int mb_type=0;
01000 Picture * const pic= &s->current_picture;
01001
01002 init_ref(c, s->new_picture.f.data, s->last_picture.f.data, NULL, 16*mb_x, 16*mb_y, 0);
01003
01004 assert(s->quarter_sample==0 || s->quarter_sample==1);
01005 assert(s->linesize == c->stride);
01006 assert(s->uvlinesize == c->uvstride);
01007
01008 c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
01009 c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
01010 c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
01011 c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV;
01012
01013 get_limits(s, 16*mb_x, 16*mb_y);
01014 c->skip=0;
01015
01016
01017 pix = c->src[0][0];
01018 sum = s->dsp.pix_sum(pix, s->linesize);
01019 varc = s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)sum*sum)>>8) + 500;
01020
01021 pic->mb_mean[s->mb_stride * mb_y + mb_x] = (sum+128)>>8;
01022 pic->mb_var [s->mb_stride * mb_y + mb_x] = (varc+128)>>8;
01023 c->mb_var_sum_temp += (varc+128)>>8;
01024
01025 if(c->avctx->me_threshold){
01026 vard= check_input_motion(s, mb_x, mb_y, 1);
01027
01028 if((vard+128)>>8 < c->avctx->me_threshold){
01029 int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
01030 int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
01031 pic->mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8;
01032 c->mc_mb_var_sum_temp += (vard+128)>>8;
01033 c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
01034 return;
01035 }
01036 if((vard+128)>>8 < c->avctx->mb_threshold)
01037 mb_type= s->mb_type[mb_x + mb_y*s->mb_stride];
01038 }
01039
01040 switch(s->me_method) {
01041 case ME_ZERO:
01042 default:
01043 no_motion_search(s, &mx, &my);
01044 mx-= mb_x*16;
01045 my-= mb_y*16;
01046 dmin = 0;
01047 break;
01048 case ME_X1:
01049 case ME_EPZS:
01050 {
01051 const int mot_stride = s->b8_stride;
01052 const int mot_xy = s->block_index[0];
01053
01054 P_LEFT[0] = s->current_picture.f.motion_val[0][mot_xy - 1][0];
01055 P_LEFT[1] = s->current_picture.f.motion_val[0][mot_xy - 1][1];
01056
01057 if(P_LEFT[0] > (c->xmax<<shift)) P_LEFT[0] = (c->xmax<<shift);
01058
01059 if(!s->first_slice_line) {
01060 P_TOP[0] = s->current_picture.f.motion_val[0][mot_xy - mot_stride ][0];
01061 P_TOP[1] = s->current_picture.f.motion_val[0][mot_xy - mot_stride ][1];
01062 P_TOPRIGHT[0] = s->current_picture.f.motion_val[0][mot_xy - mot_stride + 2][0];
01063 P_TOPRIGHT[1] = s->current_picture.f.motion_val[0][mot_xy - mot_stride + 2][1];
01064 if(P_TOP[1] > (c->ymax<<shift)) P_TOP[1] = (c->ymax<<shift);
01065 if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
01066 if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
01067
01068 P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
01069 P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
01070
01071 if(s->out_format == FMT_H263){
01072 c->pred_x = P_MEDIAN[0];
01073 c->pred_y = P_MEDIAN[1];
01074 }else {
01075 c->pred_x= P_LEFT[0];
01076 c->pred_y= P_LEFT[1];
01077 }
01078 }else{
01079 c->pred_x= P_LEFT[0];
01080 c->pred_y= P_LEFT[1];
01081 }
01082
01083 }
01084 dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
01085
01086 break;
01087 }
01088
01089
01090 ppix = c->ref[0][0] + (my * s->linesize) + mx;
01091
01092 vard = s->dsp.sse[0](NULL, pix, ppix, s->linesize, 16);
01093
01094 pic->mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8;
01095
01096 c->mc_mb_var_sum_temp += (vard+128)>>8;
01097
01098 if(mb_type){
01099 int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
01100 int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
01101 c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
01102
01103 if(mb_type == CANDIDATE_MB_TYPE_INTER){
01104 c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
01105 set_p_mv_tables(s, mx, my, 1);
01106 }else{
01107 mx <<=shift;
01108 my <<=shift;
01109 }
01110 if(mb_type == CANDIDATE_MB_TYPE_INTER4V){
01111 h263_mv4_search(s, mx, my, shift);
01112
01113 set_p_mv_tables(s, mx, my, 0);
01114 }
01115 if(mb_type == CANDIDATE_MB_TYPE_INTER_I){
01116 interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 1);
01117 }
01118 }else if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
01119 int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
01120 int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
01121 c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
01122
01123 if (vard*2 + 200*256 > varc)
01124 mb_type|= CANDIDATE_MB_TYPE_INTRA;
01125 if (varc*2 + 200*256 > vard || s->qscale > 24){
01126
01127 mb_type|= CANDIDATE_MB_TYPE_INTER;
01128 c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
01129 if(s->flags&CODEC_FLAG_MV0)
01130 if(mx || my)
01131 mb_type |= CANDIDATE_MB_TYPE_SKIPPED;
01132 }else{
01133 mx <<=shift;
01134 my <<=shift;
01135 }
01136 if((s->flags&CODEC_FLAG_4MV)
01137 && !c->skip && varc>50<<8 && vard>10<<8){
01138 if(h263_mv4_search(s, mx, my, shift) < INT_MAX)
01139 mb_type|=CANDIDATE_MB_TYPE_INTER4V;
01140
01141 set_p_mv_tables(s, mx, my, 0);
01142 }else
01143 set_p_mv_tables(s, mx, my, 1);
01144 if((s->flags&CODEC_FLAG_INTERLACED_ME)
01145 && !c->skip){
01146 if(interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 0) < INT_MAX)
01147 mb_type |= CANDIDATE_MB_TYPE_INTER_I;
01148 }
01149 }else{
01150 int intra_score, i;
01151 mb_type= CANDIDATE_MB_TYPE_INTER;
01152
01153 dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
01154 if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
01155 dmin= ff_get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
01156
01157 if((s->flags&CODEC_FLAG_4MV)
01158 && !c->skip && varc>50<<8 && vard>10<<8){
01159 int dmin4= h263_mv4_search(s, mx, my, shift);
01160 if(dmin4 < dmin){
01161 mb_type= CANDIDATE_MB_TYPE_INTER4V;
01162 dmin=dmin4;
01163 }
01164 }
01165 if((s->flags&CODEC_FLAG_INTERLACED_ME)
01166 && !c->skip){
01167 int dmin_i= interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 0);
01168 if(dmin_i < dmin){
01169 mb_type = CANDIDATE_MB_TYPE_INTER_I;
01170 dmin= dmin_i;
01171 }
01172 }
01173
01174
01175 set_p_mv_tables(s, mx, my, mb_type!=CANDIDATE_MB_TYPE_INTER4V);
01176
01177
01178 if((c->avctx->mb_cmp&0xFF)==FF_CMP_SSE){
01179 intra_score= varc - 500;
01180 }else{
01181 unsigned mean = (sum+128)>>8;
01182 mean*= 0x01010101;
01183
01184 for(i=0; i<16; i++){
01185 *(uint32_t*)(&c->scratchpad[i*s->linesize+ 0]) = mean;
01186 *(uint32_t*)(&c->scratchpad[i*s->linesize+ 4]) = mean;
01187 *(uint32_t*)(&c->scratchpad[i*s->linesize+ 8]) = mean;
01188 *(uint32_t*)(&c->scratchpad[i*s->linesize+12]) = mean;
01189 }
01190
01191 intra_score= s->dsp.mb_cmp[0](s, c->scratchpad, pix, s->linesize, 16);
01192 }
01193 intra_score += c->mb_penalty_factor*16;
01194
01195 if(intra_score < dmin){
01196 mb_type= CANDIDATE_MB_TYPE_INTRA;
01197 s->current_picture.f.mb_type[mb_y*s->mb_stride + mb_x] = CANDIDATE_MB_TYPE_INTRA;
01198 }else
01199 s->current_picture.f.mb_type[mb_y*s->mb_stride + mb_x] = 0;
01200
01201 {
01202 int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
01203 int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
01204 c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
01205 }
01206 }
01207
01208 s->mb_type[mb_y*s->mb_stride + mb_x]= mb_type;
01209 }
01210
01211 int ff_pre_estimate_p_frame_motion(MpegEncContext * s,
01212 int mb_x, int mb_y)
01213 {
01214 MotionEstContext * const c= &s->me;
01215 int mx, my, dmin;
01216 int P[10][2];
01217 const int shift= 1+s->quarter_sample;
01218 const int xy= mb_x + mb_y*s->mb_stride;
01219 init_ref(c, s->new_picture.f.data, s->last_picture.f.data, NULL, 16*mb_x, 16*mb_y, 0);
01220
01221 assert(s->quarter_sample==0 || s->quarter_sample==1);
01222
01223 c->pre_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_pre_cmp);
01224 c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV;
01225
01226 get_limits(s, 16*mb_x, 16*mb_y);
01227 c->skip=0;
01228
01229 P_LEFT[0] = s->p_mv_table[xy + 1][0];
01230 P_LEFT[1] = s->p_mv_table[xy + 1][1];
01231
01232 if(P_LEFT[0] < (c->xmin<<shift)) P_LEFT[0] = (c->xmin<<shift);
01233
01234
01235 if (s->first_slice_line) {
01236 c->pred_x= P_LEFT[0];
01237 c->pred_y= P_LEFT[1];
01238 P_TOP[0]= P_TOPRIGHT[0]= P_MEDIAN[0]=
01239 P_TOP[1]= P_TOPRIGHT[1]= P_MEDIAN[1]= 0;
01240 } else {
01241 P_TOP[0] = s->p_mv_table[xy + s->mb_stride ][0];
01242 P_TOP[1] = s->p_mv_table[xy + s->mb_stride ][1];
01243 P_TOPRIGHT[0] = s->p_mv_table[xy + s->mb_stride - 1][0];
01244 P_TOPRIGHT[1] = s->p_mv_table[xy + s->mb_stride - 1][1];
01245 if(P_TOP[1] < (c->ymin<<shift)) P_TOP[1] = (c->ymin<<shift);
01246 if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
01247 if(P_TOPRIGHT[1] < (c->ymin<<shift)) P_TOPRIGHT[1]= (c->ymin<<shift);
01248
01249 P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
01250 P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
01251
01252 c->pred_x = P_MEDIAN[0];
01253 c->pred_y = P_MEDIAN[1];
01254 }
01255
01256 dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
01257
01258 s->p_mv_table[xy][0] = mx<<shift;
01259 s->p_mv_table[xy][1] = my<<shift;
01260
01261 return dmin;
01262 }
01263
01264 static int ff_estimate_motion_b(MpegEncContext * s,
01265 int mb_x, int mb_y, int16_t (*mv_table)[2], int ref_index, int f_code)
01266 {
01267 MotionEstContext * const c= &s->me;
01268 int mx, my, dmin;
01269 int P[10][2];
01270 const int shift= 1+s->quarter_sample;
01271 const int mot_stride = s->mb_stride;
01272 const int mot_xy = mb_y*mot_stride + mb_x;
01273 uint8_t * const mv_penalty= c->mv_penalty[f_code] + MAX_MV;
01274 int mv_scale;
01275
01276 c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
01277 c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
01278 c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
01279 c->current_mv_penalty= mv_penalty;
01280
01281 get_limits(s, 16*mb_x, 16*mb_y);
01282
01283 switch(s->me_method) {
01284 case ME_ZERO:
01285 default:
01286 no_motion_search(s, &mx, &my);
01287 dmin = 0;
01288 mx-= mb_x*16;
01289 my-= mb_y*16;
01290 break;
01291 case ME_X1:
01292 case ME_EPZS:
01293 {
01294 P_LEFT[0] = mv_table[mot_xy - 1][0];
01295 P_LEFT[1] = mv_table[mot_xy - 1][1];
01296
01297 if(P_LEFT[0] > (c->xmax<<shift)) P_LEFT[0] = (c->xmax<<shift);
01298
01299
01300 if (!s->first_slice_line) {
01301 P_TOP[0] = mv_table[mot_xy - mot_stride ][0];
01302 P_TOP[1] = mv_table[mot_xy - mot_stride ][1];
01303 P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1 ][0];
01304 P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1 ][1];
01305 if(P_TOP[1] > (c->ymax<<shift)) P_TOP[1]= (c->ymax<<shift);
01306 if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
01307 if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
01308
01309 P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
01310 P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
01311 }
01312 c->pred_x= P_LEFT[0];
01313 c->pred_y= P_LEFT[1];
01314 }
01315
01316 if(mv_table == s->b_forw_mv_table){
01317 mv_scale= (s->pb_time<<16) / (s->pp_time<<shift);
01318 }else{
01319 mv_scale= ((s->pb_time - s->pp_time)<<16) / (s->pp_time<<shift);
01320 }
01321
01322 dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, ref_index, s->p_mv_table, mv_scale, 0, 16);
01323
01324 break;
01325 }
01326
01327 dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, ref_index, 0, 16);
01328
01329 if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
01330 dmin= ff_get_mb_score(s, mx, my, 0, ref_index, 0, 16, 1);
01331
01332
01333
01334 mv_table[mot_xy][0]= mx;
01335 mv_table[mot_xy][1]= my;
01336
01337 return dmin;
01338 }
01339
01340 static inline int check_bidir_mv(MpegEncContext * s,
01341 int motion_fx, int motion_fy,
01342 int motion_bx, int motion_by,
01343 int pred_fx, int pred_fy,
01344 int pred_bx, int pred_by,
01345 int size, int h)
01346 {
01347
01348
01349
01350 MotionEstContext * const c= &s->me;
01351 uint8_t * const mv_penalty_f= c->mv_penalty[s->f_code] + MAX_MV;
01352 uint8_t * const mv_penalty_b= c->mv_penalty[s->b_code] + MAX_MV;
01353 int stride= c->stride;
01354 uint8_t *dest_y = c->scratchpad;
01355 uint8_t *ptr;
01356 int dxy;
01357 int src_x, src_y;
01358 int fbmin;
01359 uint8_t **src_data= c->src[0];
01360 uint8_t **ref_data= c->ref[0];
01361 uint8_t **ref2_data= c->ref[2];
01362
01363 if(s->quarter_sample){
01364 dxy = ((motion_fy & 3) << 2) | (motion_fx & 3);
01365 src_x = motion_fx >> 2;
01366 src_y = motion_fy >> 2;
01367
01368 ptr = ref_data[0] + (src_y * stride) + src_x;
01369 s->dsp.put_qpel_pixels_tab[0][dxy](dest_y , ptr , stride);
01370
01371 dxy = ((motion_by & 3) << 2) | (motion_bx & 3);
01372 src_x = motion_bx >> 2;
01373 src_y = motion_by >> 2;
01374
01375 ptr = ref2_data[0] + (src_y * stride) + src_x;
01376 s->dsp.avg_qpel_pixels_tab[size][dxy](dest_y , ptr , stride);
01377 }else{
01378 dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
01379 src_x = motion_fx >> 1;
01380 src_y = motion_fy >> 1;
01381
01382 ptr = ref_data[0] + (src_y * stride) + src_x;
01383 s->dsp.put_pixels_tab[size][dxy](dest_y , ptr , stride, h);
01384
01385 dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
01386 src_x = motion_bx >> 1;
01387 src_y = motion_by >> 1;
01388
01389 ptr = ref2_data[0] + (src_y * stride) + src_x;
01390 s->dsp.avg_pixels_tab[size][dxy](dest_y , ptr , stride, h);
01391 }
01392
01393 fbmin = (mv_penalty_f[motion_fx-pred_fx] + mv_penalty_f[motion_fy-pred_fy])*c->mb_penalty_factor
01394 +(mv_penalty_b[motion_bx-pred_bx] + mv_penalty_b[motion_by-pred_by])*c->mb_penalty_factor
01395 + s->dsp.mb_cmp[size](s, src_data[0], dest_y, stride, h);
01396
01397 if(c->avctx->mb_cmp&FF_CMP_CHROMA){
01398 }
01399
01400
01401 return fbmin;
01402 }
01403
01404
01405 static inline int bidir_refine(MpegEncContext * s, int mb_x, int mb_y)
01406 {
01407 MotionEstContext * const c= &s->me;
01408 const int mot_stride = s->mb_stride;
01409 const int xy = mb_y *mot_stride + mb_x;
01410 int fbmin;
01411 int pred_fx= s->b_bidir_forw_mv_table[xy-1][0];
01412 int pred_fy= s->b_bidir_forw_mv_table[xy-1][1];
01413 int pred_bx= s->b_bidir_back_mv_table[xy-1][0];
01414 int pred_by= s->b_bidir_back_mv_table[xy-1][1];
01415 int motion_fx= s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0];
01416 int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1];
01417 int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0];
01418 int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1];
01419 const int flags= c->sub_flags;
01420 const int qpel= flags&FLAG_QPEL;
01421 const int shift= 1+qpel;
01422 const int xmin= c->xmin<<shift;
01423 const int ymin= c->ymin<<shift;
01424 const int xmax= c->xmax<<shift;
01425 const int ymax= c->ymax<<shift;
01426 #define HASH(fx,fy,bx,by) ((fx)+17*(fy)+63*(bx)+117*(by))
01427 #define HASH8(fx,fy,bx,by) ((uint8_t)HASH(fx,fy,bx,by))
01428 int hashidx= HASH(motion_fx,motion_fy, motion_bx, motion_by);
01429 uint8_t map[256];
01430
01431 memset(map,0,sizeof(map));
01432 map[hashidx&255] = 1;
01433
01434 fbmin= check_bidir_mv(s, motion_fx, motion_fy,
01435 motion_bx, motion_by,
01436 pred_fx, pred_fy,
01437 pred_bx, pred_by,
01438 0, 16);
01439
01440 if(s->avctx->bidir_refine){
01441 int end;
01442 static const uint8_t limittab[5]={0,8,32,64,80};
01443 const int limit= limittab[s->avctx->bidir_refine];
01444 static const int8_t vect[][4]={
01445 { 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},
01446
01447 { 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},
01448 { 0, 1, 0, 1}, { 0,-1, 0,-1}, { 1, 0, 1, 0}, {-1, 0,-1, 0},
01449 { 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},
01450 { 0,-1, 0, 1}, { 0, 1, 0,-1}, {-1, 0, 1, 0}, { 1, 0,-1, 0},
01451
01452 { 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},
01453 { 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},
01454 { 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},
01455 { 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},
01456
01457 { 1, 1, 1, 1}, {-1,-1,-1,-1},
01458 { 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},
01459 { 1, 1,-1,-1}, {-1,-1, 1, 1}, { 1,-1,-1, 1}, {-1, 1, 1,-1}, { 1,-1, 1,-1}, {-1, 1,-1, 1},
01460 };
01461 static const uint8_t hash[]={
01462 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),
01463
01464 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),
01465 HASH8( 0, 1, 0, 1), HASH8( 0,-1, 0,-1), HASH8( 1, 0, 1, 0), HASH8(-1, 0,-1, 0),
01466 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),
01467 HASH8( 0,-1, 0, 1), HASH8( 0, 1, 0,-1), HASH8(-1, 0, 1, 0), HASH8( 1, 0,-1, 0),
01468
01469 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),
01470 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),
01471 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),
01472 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),
01473
01474 HASH8( 1, 1, 1, 1), HASH8(-1,-1,-1,-1),
01475 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),
01476 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),
01477 };
01478
01479 #define CHECK_BIDIR(fx,fy,bx,by)\
01480 if( !map[(hashidx+HASH(fx,fy,bx,by))&255]\
01481 &&(fx<=0 || motion_fx+fx<=xmax) && (fy<=0 || motion_fy+fy<=ymax) && (bx<=0 || motion_bx+bx<=xmax) && (by<=0 || motion_by+by<=ymax)\
01482 &&(fx>=0 || motion_fx+fx>=xmin) && (fy>=0 || motion_fy+fy>=ymin) && (bx>=0 || motion_bx+bx>=xmin) && (by>=0 || motion_by+by>=ymin)){\
01483 int score;\
01484 map[(hashidx+HASH(fx,fy,bx,by))&255] = 1;\
01485 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);\
01486 if(score < fbmin){\
01487 hashidx += HASH(fx,fy,bx,by);\
01488 fbmin= score;\
01489 motion_fx+=fx;\
01490 motion_fy+=fy;\
01491 motion_bx+=bx;\
01492 motion_by+=by;\
01493 end=0;\
01494 }\
01495 }
01496 #define CHECK_BIDIR2(a,b,c,d)\
01497 CHECK_BIDIR(a,b,c,d)\
01498 CHECK_BIDIR(-(a),-(b),-(c),-(d))
01499
01500 do{
01501 int i;
01502 int borderdist=0;
01503 end=1;
01504
01505 CHECK_BIDIR2(0,0,0,1)
01506 CHECK_BIDIR2(0,0,1,0)
01507 CHECK_BIDIR2(0,1,0,0)
01508 CHECK_BIDIR2(1,0,0,0)
01509
01510 for(i=8; i<limit; i++){
01511 int fx= motion_fx+vect[i][0];
01512 int fy= motion_fy+vect[i][1];
01513 int bx= motion_bx+vect[i][2];
01514 int by= motion_by+vect[i][3];
01515 if(borderdist<=0){
01516 int a= (xmax - FFMAX(fx,bx))|(FFMIN(fx,bx) - xmin);
01517 int b= (ymax - FFMAX(fy,by))|(FFMIN(fy,by) - ymin);
01518 if((a|b) < 0)
01519 map[(hashidx+hash[i])&255] = 1;
01520 }
01521 if(!map[(hashidx+hash[i])&255]){
01522 int score;
01523 map[(hashidx+hash[i])&255] = 1;
01524 score= check_bidir_mv(s, fx, fy, bx, by, pred_fx, pred_fy, pred_bx, pred_by, 0, 16);
01525 if(score < fbmin){
01526 hashidx += hash[i];
01527 fbmin= score;
01528 motion_fx=fx;
01529 motion_fy=fy;
01530 motion_bx=bx;
01531 motion_by=by;
01532 end=0;
01533 borderdist--;
01534 if(borderdist<=0){
01535 int a= FFMIN(xmax - FFMAX(fx,bx), FFMIN(fx,bx) - xmin);
01536 int b= FFMIN(ymax - FFMAX(fy,by), FFMIN(fy,by) - ymin);
01537 borderdist= FFMIN(a,b);
01538 }
01539 }
01540 }
01541 }
01542 }while(!end);
01543 }
01544
01545 s->b_bidir_forw_mv_table[xy][0]= motion_fx;
01546 s->b_bidir_forw_mv_table[xy][1]= motion_fy;
01547 s->b_bidir_back_mv_table[xy][0]= motion_bx;
01548 s->b_bidir_back_mv_table[xy][1]= motion_by;
01549
01550 return fbmin;
01551 }
01552
01553 static inline int direct_search(MpegEncContext * s, int mb_x, int mb_y)
01554 {
01555 MotionEstContext * const c= &s->me;
01556 int P[10][2];
01557 const int mot_stride = s->mb_stride;
01558 const int mot_xy = mb_y*mot_stride + mb_x;
01559 const int shift= 1+s->quarter_sample;
01560 int dmin, i;
01561 const int time_pp= s->pp_time;
01562 const int time_pb= s->pb_time;
01563 int mx, my, xmin, xmax, ymin, ymax;
01564 int16_t (*mv_table)[2]= s->b_direct_mv_table;
01565
01566 c->current_mv_penalty= c->mv_penalty[1] + MAX_MV;
01567 ymin= xmin=(-32)>>shift;
01568 ymax= xmax= 31>>shift;
01569
01570 if (IS_8X8(s->next_picture.f.mb_type[mot_xy])) {
01571 s->mv_type= MV_TYPE_8X8;
01572 }else{
01573 s->mv_type= MV_TYPE_16X16;
01574 }
01575
01576 for(i=0; i<4; i++){
01577 int index= s->block_index[i];
01578 int min, max;
01579
01580 c->co_located_mv[i][0] = s->next_picture.f.motion_val[0][index][0];
01581 c->co_located_mv[i][1] = s->next_picture.f.motion_val[0][index][1];
01582 c->direct_basis_mv[i][0]= c->co_located_mv[i][0]*time_pb/time_pp + ((i& 1)<<(shift+3));
01583 c->direct_basis_mv[i][1]= c->co_located_mv[i][1]*time_pb/time_pp + ((i>>1)<<(shift+3));
01584
01585
01586
01587 max= FFMAX(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
01588 min= FFMIN(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
01589 max+= 16*mb_x + 1;
01590 min+= 16*mb_x - 1;
01591 xmax= FFMIN(xmax, s->width - max);
01592 xmin= FFMAX(xmin, - 16 - min);
01593
01594 max= FFMAX(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
01595 min= FFMIN(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
01596 max+= 16*mb_y + 1;
01597 min+= 16*mb_y - 1;
01598 ymax= FFMIN(ymax, s->height - max);
01599 ymin= FFMAX(ymin, - 16 - min);
01600
01601 if(s->mv_type == MV_TYPE_16X16) break;
01602 }
01603
01604 assert(xmax <= 15 && ymax <= 15 && xmin >= -16 && ymin >= -16);
01605
01606 if(xmax < 0 || xmin >0 || ymax < 0 || ymin > 0){
01607 s->b_direct_mv_table[mot_xy][0]= 0;
01608 s->b_direct_mv_table[mot_xy][1]= 0;
01609
01610 return 256*256*256*64;
01611 }
01612
01613 c->xmin= xmin;
01614 c->ymin= ymin;
01615 c->xmax= xmax;
01616 c->ymax= ymax;
01617 c->flags |= FLAG_DIRECT;
01618 c->sub_flags |= FLAG_DIRECT;
01619 c->pred_x=0;
01620 c->pred_y=0;
01621
01622 P_LEFT[0] = av_clip(mv_table[mot_xy - 1][0], xmin<<shift, xmax<<shift);
01623 P_LEFT[1] = av_clip(mv_table[mot_xy - 1][1], ymin<<shift, ymax<<shift);
01624
01625
01626 if (!s->first_slice_line) {
01627 P_TOP[0] = av_clip(mv_table[mot_xy - mot_stride ][0], xmin<<shift, xmax<<shift);
01628 P_TOP[1] = av_clip(mv_table[mot_xy - mot_stride ][1], ymin<<shift, ymax<<shift);
01629 P_TOPRIGHT[0] = av_clip(mv_table[mot_xy - mot_stride + 1 ][0], xmin<<shift, xmax<<shift);
01630 P_TOPRIGHT[1] = av_clip(mv_table[mot_xy - mot_stride + 1 ][1], ymin<<shift, ymax<<shift);
01631
01632 P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
01633 P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
01634 }
01635
01636 dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, mv_table, 1<<(16-shift), 0, 16);
01637 if(c->sub_flags&FLAG_QPEL)
01638 dmin = qpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
01639 else
01640 dmin = hpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
01641
01642 if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
01643 dmin= ff_get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
01644
01645 get_limits(s, 16*mb_x, 16*mb_y);
01646
01647 mv_table[mot_xy][0]= mx;
01648 mv_table[mot_xy][1]= my;
01649 c->flags &= ~FLAG_DIRECT;
01650 c->sub_flags &= ~FLAG_DIRECT;
01651
01652 return dmin;
01653 }
01654
01655 void ff_estimate_b_frame_motion(MpegEncContext * s,
01656 int mb_x, int mb_y)
01657 {
01658 MotionEstContext * const c= &s->me;
01659 const int penalty_factor= c->mb_penalty_factor;
01660 int fmin, bmin, dmin, fbmin, bimin, fimin;
01661 int type=0;
01662 const int xy = mb_y*s->mb_stride + mb_x;
01663 init_ref(c, s->new_picture.f.data, s->last_picture.f.data,
01664 s->next_picture.f.data, 16 * mb_x, 16 * mb_y, 2);
01665
01666 get_limits(s, 16*mb_x, 16*mb_y);
01667
01668 c->skip=0;
01669
01670 if (s->codec_id == CODEC_ID_MPEG4 && s->next_picture.f.mbskip_table[xy]) {
01671 int score= direct_search(s, mb_x, mb_y);
01672
01673 score= ((unsigned)(score*score + 128*256))>>16;
01674 c->mc_mb_var_sum_temp += score;
01675 s->current_picture.mc_mb_var[mb_y*s->mb_stride + mb_x] = score;
01676 s->mb_type[mb_y*s->mb_stride + mb_x]= CANDIDATE_MB_TYPE_DIRECT0;
01677
01678 return;
01679 }
01680
01681 if(c->avctx->me_threshold){
01682 int vard= check_input_motion(s, mb_x, mb_y, 0);
01683
01684 if((vard+128)>>8 < c->avctx->me_threshold){
01685
01686
01687
01688
01689
01690 s->current_picture.mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8;
01691
01692
01693 c->mc_mb_var_sum_temp += (vard+128)>>8;
01694
01695
01696
01697
01698
01699 return;
01700 }
01701 if((vard+128)>>8 < c->avctx->mb_threshold){
01702 type= s->mb_type[mb_y*s->mb_stride + mb_x];
01703 if(type == CANDIDATE_MB_TYPE_DIRECT){
01704 direct_search(s, mb_x, mb_y);
01705 }
01706 if(type == CANDIDATE_MB_TYPE_FORWARD || type == CANDIDATE_MB_TYPE_BIDIR){
01707 c->skip=0;
01708 ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code);
01709 }
01710 if(type == CANDIDATE_MB_TYPE_BACKWARD || type == CANDIDATE_MB_TYPE_BIDIR){
01711 c->skip=0;
01712 ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code);
01713 }
01714 if(type == CANDIDATE_MB_TYPE_FORWARD_I || type == CANDIDATE_MB_TYPE_BIDIR_I){
01715 c->skip=0;
01716 c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV;
01717 interlaced_search(s, 0,
01718 s->b_field_mv_table[0], s->b_field_select_table[0],
01719 s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1], 1);
01720 }
01721 if(type == CANDIDATE_MB_TYPE_BACKWARD_I || type == CANDIDATE_MB_TYPE_BIDIR_I){
01722 c->skip=0;
01723 c->current_mv_penalty= c->mv_penalty[s->b_code] + MAX_MV;
01724 interlaced_search(s, 2,
01725 s->b_field_mv_table[1], s->b_field_select_table[1],
01726 s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1], 1);
01727 }
01728 return;
01729 }
01730 }
01731
01732 if (s->codec_id == CODEC_ID_MPEG4)
01733 dmin= direct_search(s, mb_x, mb_y);
01734 else
01735 dmin= INT_MAX;
01736
01737 c->skip=0;
01738 fmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code) + 3*penalty_factor;
01739
01740 c->skip=0;
01741 bmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code) + 2*penalty_factor;
01742
01743
01744 c->skip=0;
01745 fbmin= bidir_refine(s, mb_x, mb_y) + penalty_factor;
01746
01747
01748 if(s->flags & CODEC_FLAG_INTERLACED_ME){
01749
01750 c->skip=0;
01751 c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV;
01752 fimin= interlaced_search(s, 0,
01753 s->b_field_mv_table[0], s->b_field_select_table[0],
01754 s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1], 0);
01755 c->current_mv_penalty= c->mv_penalty[s->b_code] + MAX_MV;
01756 bimin= interlaced_search(s, 2,
01757 s->b_field_mv_table[1], s->b_field_select_table[1],
01758 s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1], 0);
01759 }else
01760 fimin= bimin= INT_MAX;
01761
01762 {
01763 int score= fmin;
01764 type = CANDIDATE_MB_TYPE_FORWARD;
01765
01766 if (dmin <= score){
01767 score = dmin;
01768 type = CANDIDATE_MB_TYPE_DIRECT;
01769 }
01770 if(bmin<score){
01771 score=bmin;
01772 type= CANDIDATE_MB_TYPE_BACKWARD;
01773 }
01774 if(fbmin<score){
01775 score=fbmin;
01776 type= CANDIDATE_MB_TYPE_BIDIR;
01777 }
01778 if(fimin<score){
01779 score=fimin;
01780 type= CANDIDATE_MB_TYPE_FORWARD_I;
01781 }
01782 if(bimin<score){
01783 score=bimin;
01784 type= CANDIDATE_MB_TYPE_BACKWARD_I;
01785 }
01786
01787 score= ((unsigned)(score*score + 128*256))>>16;
01788 c->mc_mb_var_sum_temp += score;
01789 s->current_picture.mc_mb_var[mb_y*s->mb_stride + mb_x] = score;
01790 }
01791
01792 if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
01793 type= CANDIDATE_MB_TYPE_FORWARD | CANDIDATE_MB_TYPE_BACKWARD | CANDIDATE_MB_TYPE_BIDIR | CANDIDATE_MB_TYPE_DIRECT;
01794 if(fimin < INT_MAX)
01795 type |= CANDIDATE_MB_TYPE_FORWARD_I;
01796 if(bimin < INT_MAX)
01797 type |= CANDIDATE_MB_TYPE_BACKWARD_I;
01798 if(fimin < INT_MAX && bimin < INT_MAX){
01799 type |= CANDIDATE_MB_TYPE_BIDIR_I;
01800 }
01801
01802 if(dmin>256*256*16) type&= ~CANDIDATE_MB_TYPE_DIRECT;
01803 if(s->codec_id == CODEC_ID_MPEG4 && type&CANDIDATE_MB_TYPE_DIRECT && s->flags&CODEC_FLAG_MV0 && *(uint32_t*)s->b_direct_mv_table[xy])
01804 type |= CANDIDATE_MB_TYPE_DIRECT0;
01805 }
01806
01807 s->mb_type[mb_y*s->mb_stride + mb_x]= type;
01808 }
01809
01810
01811 int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type)
01812 {
01813 if(s->me_method>=ME_EPZS){
01814 int score[8];
01815 int i, y, range= s->avctx->me_range ? s->avctx->me_range : (INT_MAX/2);
01816 uint8_t * fcode_tab= s->fcode_tab;
01817 int best_fcode=-1;
01818 int best_score=-10000000;
01819
01820 if(s->msmpeg4_version)
01821 range= FFMIN(range, 16);
01822 else if(s->codec_id == CODEC_ID_MPEG2VIDEO && s->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL)
01823 range= FFMIN(range, 256);
01824
01825 for(i=0; i<8; i++) score[i]= s->mb_num*(8-i);
01826
01827 for(y=0; y<s->mb_height; y++){
01828 int x;
01829 int xy= y*s->mb_stride;
01830 for(x=0; x<s->mb_width; x++){
01831 if(s->mb_type[xy] & type){
01832 int mx= mv_table[xy][0];
01833 int my= mv_table[xy][1];
01834 int fcode= FFMAX(fcode_tab[mx + MAX_MV],
01835 fcode_tab[my + MAX_MV]);
01836 int j;
01837
01838 if(mx >= range || mx < -range ||
01839 my >= range || my < -range)
01840 continue;
01841
01842 for(j=0; j<fcode && j<8; j++){
01843 if(s->pict_type==AV_PICTURE_TYPE_B || s->current_picture.mc_mb_var[xy] < s->current_picture.mb_var[xy])
01844 score[j]-= 170;
01845 }
01846 }
01847 xy++;
01848 }
01849 }
01850
01851 for(i=1; i<8; i++){
01852 if(score[i] > best_score){
01853 best_score= score[i];
01854 best_fcode= i;
01855 }
01856
01857 }
01858
01859
01860 return best_fcode;
01861
01862
01863
01864
01865 }else{
01866 return 1;
01867 }
01868 }
01869
01870 void ff_fix_long_p_mvs(MpegEncContext * s)
01871 {
01872 MotionEstContext * const c= &s->me;
01873 const int f_code= s->f_code;
01874 int y, range;
01875 assert(s->pict_type==AV_PICTURE_TYPE_P);
01876
01877 range = (((s->out_format == FMT_MPEG1 || s->msmpeg4_version) ? 8 : 16) << f_code);
01878
01879 assert(range <= 16 || !s->msmpeg4_version);
01880 assert(range <=256 || !(s->codec_id == CODEC_ID_MPEG2VIDEO && s->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL));
01881
01882 if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
01883
01884
01885 if(s->flags&CODEC_FLAG_4MV){
01886 const int wrap= s->b8_stride;
01887
01888
01889 for(y=0; y<s->mb_height; y++){
01890 int xy= y*2*wrap;
01891 int i= y*s->mb_stride;
01892 int x;
01893
01894 for(x=0; x<s->mb_width; x++){
01895 if(s->mb_type[i]&CANDIDATE_MB_TYPE_INTER4V){
01896 int block;
01897 for(block=0; block<4; block++){
01898 int off= (block& 1) + (block>>1)*wrap;
01899 int mx = s->current_picture.f.motion_val[0][ xy + off ][0];
01900 int my = s->current_picture.f.motion_val[0][ xy + off ][1];
01901
01902 if( mx >=range || mx <-range
01903 || my >=range || my <-range){
01904 s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V;
01905 s->mb_type[i] |= CANDIDATE_MB_TYPE_INTRA;
01906 s->current_picture.f.mb_type[i] = CANDIDATE_MB_TYPE_INTRA;
01907 }
01908 }
01909 }
01910 xy+=2;
01911 i++;
01912 }
01913 }
01914 }
01915 }
01916
01921 void ff_fix_long_mvs(MpegEncContext * s, uint8_t *field_select_table, int field_select,
01922 int16_t (*mv_table)[2], int f_code, int type, int truncate)
01923 {
01924 MotionEstContext * const c= &s->me;
01925 int y, h_range, v_range;
01926
01927
01928 int range = (((s->out_format == FMT_MPEG1 || s->msmpeg4_version) ? 8 : 16) << f_code);
01929
01930 if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
01931
01932 h_range= range;
01933 v_range= field_select_table ? range>>1 : range;
01934
01935
01936 for(y=0; y<s->mb_height; y++){
01937 int x;
01938 int xy= y*s->mb_stride;
01939 for(x=0; x<s->mb_width; x++){
01940 if (s->mb_type[xy] & type){
01941 if(field_select_table==NULL || field_select_table[xy] == field_select){
01942 if( mv_table[xy][0] >=h_range || mv_table[xy][0] <-h_range
01943 || mv_table[xy][1] >=v_range || mv_table[xy][1] <-v_range){
01944
01945 if(truncate){
01946 if (mv_table[xy][0] > h_range-1) mv_table[xy][0]= h_range-1;
01947 else if(mv_table[xy][0] < -h_range ) mv_table[xy][0]= -h_range;
01948 if (mv_table[xy][1] > v_range-1) mv_table[xy][1]= v_range-1;
01949 else if(mv_table[xy][1] < -v_range ) mv_table[xy][1]= -v_range;
01950 }else{
01951 s->mb_type[xy] &= ~type;
01952 s->mb_type[xy] |= CANDIDATE_MB_TYPE_INTRA;
01953 mv_table[xy][0]=
01954 mv_table[xy][1]= 0;
01955 }
01956 }
01957 }
01958 }
01959 xy++;
01960 }
01961 }
01962 }