Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Motion estimation
  3.  * Copyright (c) 2000,2001 Fabrice Bellard
  4.  * Copyright (c) 2002-2004 Michael Niedermayer
  5.  *
  6.  * new motion estimation (X1/EPZS) by Michael Niedermayer <michaelni@gmx.at>
  7.  *
  8.  * This file is part of FFmpeg.
  9.  *
  10.  * FFmpeg is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU Lesser General Public
  12.  * License as published by the Free Software Foundation; either
  13.  * version 2.1 of the License, or (at your option) any later version.
  14.  *
  15.  * FFmpeg is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18.  * Lesser General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU Lesser General Public
  21.  * License along with FFmpeg; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23.  */
  24.  
  25. /**
  26.  * @file
  27.  * Motion estimation.
  28.  */
  29.  
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <limits.h>
  33.  
  34. #include "avcodec.h"
  35. #include "mathops.h"
  36. #include "mpegvideo.h"
  37.  
  38. #undef NDEBUG
  39. #include <assert.h>
  40.  
  41. #define P_LEFT P[1]
  42. #define P_TOP P[2]
  43. #define P_TOPRIGHT P[3]
  44. #define P_MEDIAN P[4]
  45. #define P_MV1 P[9]
  46.  
  47. static int sad_hpel_motion_search(MpegEncContext * s,
  48.                                   int *mx_ptr, int *my_ptr, int dmin,
  49.                                   int src_index, int ref_index,
  50.                                   int size, int h);
  51.  
  52. static inline unsigned update_map_generation(MotionEstContext *c)
  53. {
  54.     c->map_generation+= 1<<(ME_MAP_MV_BITS*2);
  55.     if(c->map_generation==0){
  56.         c->map_generation= 1<<(ME_MAP_MV_BITS*2);
  57.         memset(c->map, 0, sizeof(uint32_t)*ME_MAP_SIZE);
  58.     }
  59.     return c->map_generation;
  60. }
  61.  
  62. /* shape adaptive search stuff */
  63. typedef struct Minima{
  64.     int height;
  65.     int x, y;
  66.     int checked;
  67. }Minima;
  68.  
  69. static int minima_cmp(const void *a, const void *b){
  70.     const Minima *da = (const Minima *) a;
  71.     const Minima *db = (const Minima *) b;
  72.  
  73.     return da->height - db->height;
  74. }
  75.  
  76. #define FLAG_QPEL   1 //must be 1
  77. #define FLAG_CHROMA 2
  78. #define FLAG_DIRECT 4
  79.  
  80. 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){
  81.     const int offset[3]= {
  82.           y*c->  stride + x,
  83.         ((y*c->uvstride + x)>>1),
  84.         ((y*c->uvstride + x)>>1),
  85.     };
  86.     int i;
  87.     for(i=0; i<3; i++){
  88.         c->src[0][i]= src [i] + offset[i];
  89.         c->ref[0][i]= ref [i] + offset[i];
  90.     }
  91.     if(ref_index){
  92.         for(i=0; i<3; i++){
  93.             c->ref[ref_index][i]= ref2[i] + offset[i];
  94.         }
  95.     }
  96. }
  97.  
  98. static int get_flags(MotionEstContext *c, int direct, int chroma){
  99.     return   ((c->avctx->flags&CODEC_FLAG_QPEL) ? FLAG_QPEL : 0)
  100.            + (direct ? FLAG_DIRECT : 0)
  101.            + (chroma ? FLAG_CHROMA : 0);
  102. }
  103.  
  104. static av_always_inline int cmp_direct_inline(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
  105.                       const int size, const int h, int ref_index, int src_index,
  106.                       me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel){
  107.     MotionEstContext * const c= &s->me;
  108.     const int stride= c->stride;
  109.     const int hx= subx + (x<<(1+qpel));
  110.     const int hy= suby + (y<<(1+qpel));
  111.     uint8_t * const * const ref= c->ref[ref_index];
  112.     uint8_t * const * const src= c->src[src_index];
  113.     int d;
  114.     //FIXME check chroma 4mv, (no crashes ...)
  115.         av_assert2(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1));
  116.         if(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1)){
  117.             const int time_pp= s->pp_time;
  118.             const int time_pb= s->pb_time;
  119.             const int mask= 2*qpel+1;
  120.             if(s->mv_type==MV_TYPE_8X8){
  121.                 int i;
  122.                 for(i=0; i<4; i++){
  123.                     int fx = c->direct_basis_mv[i][0] + hx;
  124.                     int fy = c->direct_basis_mv[i][1] + hy;
  125.                     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));
  126.                     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));
  127.                     int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));
  128.                     int bxy= (bx&mask) + ((by&mask)<<(qpel+1));
  129.  
  130.                     uint8_t *dst= c->temp + 8*(i&1) + 8*stride*(i>>1);
  131.                     if(qpel){
  132.                         c->qpel_put[1][fxy](dst, ref[0] + (fx>>2) + (fy>>2)*stride, stride);
  133.                         c->qpel_avg[1][bxy](dst, ref[8] + (bx>>2) + (by>>2)*stride, stride);
  134.                     }else{
  135.                         c->hpel_put[1][fxy](dst, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 8);
  136.                         c->hpel_avg[1][bxy](dst, ref[8] + (bx>>1) + (by>>1)*stride, stride, 8);
  137.                     }
  138.                 }
  139.             }else{
  140.                 int fx = c->direct_basis_mv[0][0] + hx;
  141.                 int fy = c->direct_basis_mv[0][1] + hy;
  142.                 int bx = hx ? fx - c->co_located_mv[0][0] : (c->co_located_mv[0][0]*(time_pb - time_pp)/time_pp);
  143.                 int by = hy ? fy - c->co_located_mv[0][1] : (c->co_located_mv[0][1]*(time_pb - time_pp)/time_pp);
  144.                 int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));
  145.                 int bxy= (bx&mask) + ((by&mask)<<(qpel+1));
  146.  
  147.                 if(qpel){
  148.                     c->qpel_put[1][fxy](c->temp               , ref[0] + (fx>>2) + (fy>>2)*stride               , stride);
  149.                     c->qpel_put[1][fxy](c->temp + 8           , ref[0] + (fx>>2) + (fy>>2)*stride + 8           , stride);
  150.                     c->qpel_put[1][fxy](c->temp     + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride     + 8*stride, stride);
  151.                     c->qpel_put[1][fxy](c->temp + 8 + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8 + 8*stride, stride);
  152.                     c->qpel_avg[1][bxy](c->temp               , ref[8] + (bx>>2) + (by>>2)*stride               , stride);
  153.                     c->qpel_avg[1][bxy](c->temp + 8           , ref[8] + (bx>>2) + (by>>2)*stride + 8           , stride);
  154.                     c->qpel_avg[1][bxy](c->temp     + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride     + 8*stride, stride);
  155.                     c->qpel_avg[1][bxy](c->temp + 8 + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8 + 8*stride, stride);
  156.                 }else{
  157.                     av_assert2((fx>>1) + 16*s->mb_x >= -16);
  158.                     av_assert2((fy>>1) + 16*s->mb_y >= -16);
  159.                     av_assert2((fx>>1) + 16*s->mb_x <= s->width);
  160.                     av_assert2((fy>>1) + 16*s->mb_y <= s->height);
  161.                     av_assert2((bx>>1) + 16*s->mb_x >= -16);
  162.                     av_assert2((by>>1) + 16*s->mb_y >= -16);
  163.                     av_assert2((bx>>1) + 16*s->mb_x <= s->width);
  164.                     av_assert2((by>>1) + 16*s->mb_y <= s->height);
  165.  
  166.                     c->hpel_put[0][fxy](c->temp, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 16);
  167.                     c->hpel_avg[0][bxy](c->temp, ref[8] + (bx>>1) + (by>>1)*stride, stride, 16);
  168.                 }
  169.             }
  170.             d = cmp_func(s, c->temp, src[0], stride, 16);
  171.         }else
  172.             d= 256*256*256*32;
  173.     return d;
  174. }
  175.  
  176. static av_always_inline int cmp_inline(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
  177.                       const int size, const int h, int ref_index, int src_index,
  178.                       me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, int qpel, int chroma){
  179.     MotionEstContext * const c= &s->me;
  180.     const int stride= c->stride;
  181.     const int uvstride= c->uvstride;
  182.     const int dxy= subx + (suby<<(1+qpel)); //FIXME log2_subpel?
  183.     const int hx= subx + (x<<(1+qpel));
  184.     const int hy= suby + (y<<(1+qpel));
  185.     uint8_t * const * const ref= c->ref[ref_index];
  186.     uint8_t * const * const src= c->src[src_index];
  187.     int d;
  188.     //FIXME check chroma 4mv, (no crashes ...)
  189.         int uvdxy;              /* no, it might not be used uninitialized */
  190.         if(dxy){
  191.             if(qpel){
  192.                 c->qpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride); //FIXME prototype (add h)
  193.                 if(chroma){
  194.                     int cx= hx/2;
  195.                     int cy= hy/2;
  196.                     cx= (cx>>1)|(cx&1);
  197.                     cy= (cy>>1)|(cy&1);
  198.                     uvdxy= (cx&1) + 2*(cy&1);
  199.                     //FIXME x/y wrong, but mpeg4 qpel is sick anyway, we should drop as much of it as possible in favor for h264
  200.                 }
  201.             }else{
  202.                 c->hpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride, h);
  203.                 if(chroma)
  204.                     uvdxy= dxy | (x&1) | (2*(y&1));
  205.             }
  206.             d = cmp_func(s, c->temp, src[0], stride, h);
  207.         }else{
  208.             d = cmp_func(s, src[0], ref[0] + x + y*stride, stride, h);
  209.             if(chroma)
  210.                 uvdxy= (x&1) + 2*(y&1);
  211.         }
  212.         if(chroma){
  213.             uint8_t * const uvtemp= c->temp + 16*stride;
  214.             c->hpel_put[size+1][uvdxy](uvtemp  , ref[1] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);
  215.             c->hpel_put[size+1][uvdxy](uvtemp+8, ref[2] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);
  216.             d += chroma_cmp_func(s, uvtemp  , src[1], uvstride, h>>1);
  217.             d += chroma_cmp_func(s, uvtemp+8, src[2], uvstride, h>>1);
  218.         }
  219.     return d;
  220. }
  221.  
  222. static int cmp_simple(MpegEncContext *s, const int x, const int y,
  223.                       int ref_index, int src_index,
  224.                       me_cmp_func cmp_func, me_cmp_func chroma_cmp_func){
  225.     return cmp_inline(s,x,y,0,0,0,16,ref_index,src_index, cmp_func, chroma_cmp_func, 0, 0);
  226. }
  227.  
  228. static int cmp_fpel_internal(MpegEncContext *s, const int x, const int y,
  229.                       const int size, const int h, int ref_index, int src_index,
  230.                       me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
  231.     if(flags&FLAG_DIRECT){
  232.         return cmp_direct_inline(s,x,y,0,0,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags&FLAG_QPEL);
  233.     }else{
  234.         return cmp_inline(s,x,y,0,0,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0, flags&FLAG_CHROMA);
  235.     }
  236. }
  237.  
  238. static int cmp_internal(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
  239.                       const int size, const int h, int ref_index, int src_index,
  240.                       me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
  241.     if(flags&FLAG_DIRECT){
  242.         return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags&FLAG_QPEL);
  243.     }else{
  244.         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);
  245.     }
  246. }
  247.  
  248. /** @brief compares a block (either a full macroblock or a partition thereof)
  249.     against a proposed motion-compensated prediction of that block
  250.  */
  251. static av_always_inline int cmp(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
  252.                       const int size, const int h, int ref_index, int src_index,
  253.                       me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
  254.     if(av_builtin_constant_p(flags) && av_builtin_constant_p(h) && av_builtin_constant_p(size)
  255.        && av_builtin_constant_p(subx) && av_builtin_constant_p(suby)
  256.        && flags==0 && h==16 && size==0 && subx==0 && suby==0){
  257.         return cmp_simple(s,x,y,ref_index,src_index, cmp_func, chroma_cmp_func);
  258.     }else if(av_builtin_constant_p(subx) && av_builtin_constant_p(suby)
  259.        && subx==0 && suby==0){
  260.         return cmp_fpel_internal(s,x,y,size,h,ref_index,src_index, cmp_func, chroma_cmp_func,flags);
  261.     }else{
  262.         return cmp_internal(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, flags);
  263.     }
  264. }
  265.  
  266. static int cmp_hpel(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
  267.                       const int size, const int h, int ref_index, int src_index,
  268.                       me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
  269.     if(flags&FLAG_DIRECT){
  270.         return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0);
  271.     }else{
  272.         return cmp_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 0, flags&FLAG_CHROMA);
  273.     }
  274. }
  275.  
  276. static int cmp_qpel(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
  277.                       const int size, const int h, int ref_index, int src_index,
  278.                       me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
  279.     if(flags&FLAG_DIRECT){
  280.         return cmp_direct_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 1);
  281.     }else{
  282.         return cmp_inline(s,x,y,subx,suby,size,h,ref_index,src_index, cmp_func, chroma_cmp_func, 1, flags&FLAG_CHROMA);
  283.     }
  284. }
  285.  
  286. #include "motion_est_template.c"
  287.  
  288. static int zero_cmp(void *s, uint8_t *a, uint8_t *b, int stride, int h){
  289.     return 0;
  290. }
  291.  
  292. static void zero_hpel(uint8_t *a, const uint8_t *b, ptrdiff_t stride, int h){
  293. }
  294.  
  295. int ff_init_me(MpegEncContext *s){
  296.     MotionEstContext * const c= &s->me;
  297.     int cache_size= FFMIN(ME_MAP_SIZE>>ME_MAP_SHIFT, 1<<ME_MAP_SHIFT);
  298.     int dia_size= FFMAX(FFABS(s->avctx->dia_size)&255, FFABS(s->avctx->pre_dia_size)&255);
  299.  
  300.     if(FFMIN(s->avctx->dia_size, s->avctx->pre_dia_size) < -FFMIN(ME_MAP_SIZE, MAX_SAB_SIZE)){
  301.         av_log(s->avctx, AV_LOG_ERROR, "ME_MAP size is too small for SAB diamond\n");
  302.         return -1;
  303.     }
  304.     //special case of snow is needed because snow uses its own iterative ME code
  305.     if(s->me_method!=ME_ZERO && s->me_method!=ME_EPZS && s->me_method!=ME_X1 && s->avctx->codec_id != AV_CODEC_ID_SNOW){
  306.         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");
  307.         return -1;
  308.     }
  309.  
  310.     c->avctx= s->avctx;
  311.  
  312.     if(cache_size < 2*dia_size && !c->stride){
  313.         av_log(s->avctx, AV_LOG_INFO, "ME_MAP size may be a little small for the selected diamond size\n");
  314.     }
  315.  
  316.     ff_set_cmp(&s->dsp, s->dsp.me_pre_cmp, c->avctx->me_pre_cmp);
  317.     ff_set_cmp(&s->dsp, s->dsp.me_cmp, c->avctx->me_cmp);
  318.     ff_set_cmp(&s->dsp, s->dsp.me_sub_cmp, c->avctx->me_sub_cmp);
  319.     ff_set_cmp(&s->dsp, s->dsp.mb_cmp, c->avctx->mb_cmp);
  320.  
  321.     c->flags    = get_flags(c, 0, c->avctx->me_cmp    &FF_CMP_CHROMA);
  322.     c->sub_flags= get_flags(c, 0, c->avctx->me_sub_cmp&FF_CMP_CHROMA);
  323.     c->mb_flags = get_flags(c, 0, c->avctx->mb_cmp    &FF_CMP_CHROMA);
  324.  
  325. /*FIXME s->no_rounding b_type*/
  326.     if(s->flags&CODEC_FLAG_QPEL){
  327.         c->sub_motion_search= qpel_motion_search;
  328.         c->qpel_avg= s->dsp.avg_qpel_pixels_tab;
  329.         if(s->no_rounding) c->qpel_put= s->dsp.put_no_rnd_qpel_pixels_tab;
  330.         else               c->qpel_put= s->dsp.put_qpel_pixels_tab;
  331.     }else{
  332.         if(c->avctx->me_sub_cmp&FF_CMP_CHROMA)
  333.             c->sub_motion_search= hpel_motion_search;
  334.         else if(   c->avctx->me_sub_cmp == FF_CMP_SAD
  335.                 && c->avctx->    me_cmp == FF_CMP_SAD
  336.                 && c->avctx->    mb_cmp == FF_CMP_SAD)
  337.             c->sub_motion_search= sad_hpel_motion_search; // 2050 vs. 2450 cycles
  338.         else
  339.             c->sub_motion_search= hpel_motion_search;
  340.     }
  341.     c->hpel_avg = s->hdsp.avg_pixels_tab;
  342.     if (s->no_rounding)
  343.         c->hpel_put = s->hdsp.put_no_rnd_pixels_tab;
  344.     else
  345.         c->hpel_put = s->hdsp.put_pixels_tab;
  346.  
  347.     if(s->linesize){
  348.         c->stride  = s->linesize;
  349.         c->uvstride= s->uvlinesize;
  350.     }else{
  351.         c->stride  = 16*s->mb_width + 32;
  352.         c->uvstride=  8*s->mb_width + 16;
  353.     }
  354.  
  355.     /* 8x8 fullpel search would need a 4x4 chroma compare, which we do
  356.      * not have yet, and even if we had, the motion estimation code
  357.      * does not expect it. */
  358.     if(s->codec_id != AV_CODEC_ID_SNOW){
  359.         if((c->avctx->me_cmp&FF_CMP_CHROMA)/* && !s->dsp.me_cmp[2]*/){
  360.             s->dsp.me_cmp[2]= zero_cmp;
  361.         }
  362.         if((c->avctx->me_sub_cmp&FF_CMP_CHROMA) && !s->dsp.me_sub_cmp[2]){
  363.             s->dsp.me_sub_cmp[2]= zero_cmp;
  364.         }
  365.         c->hpel_put[2][0]= c->hpel_put[2][1]=
  366.         c->hpel_put[2][2]= c->hpel_put[2][3]= zero_hpel;
  367.     }
  368.  
  369.     if(s->codec_id == AV_CODEC_ID_H261){
  370.         c->sub_motion_search= no_sub_motion_search;
  371.     }
  372.  
  373.     return 0;
  374. }
  375.  
  376. #define CHECK_SAD_HALF_MV(suffix, x, y) \
  377. {\
  378.     d= s->dsp.pix_abs[size][(x?1:0)+(y?2:0)](NULL, pix, ptr+((x)>>1), stride, h);\
  379.     d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*penalty_factor;\
  380.     COPY3_IF_LT(dminh, d, dx, x, dy, y)\
  381. }
  382.  
  383. static int sad_hpel_motion_search(MpegEncContext * s,
  384.                                   int *mx_ptr, int *my_ptr, int dmin,
  385.                                   int src_index, int ref_index,
  386.                                   int size, int h)
  387. {
  388.     MotionEstContext * const c= &s->me;
  389.     const int penalty_factor= c->sub_penalty_factor;
  390.     int mx, my, dminh;
  391.     uint8_t *pix, *ptr;
  392.     int stride= c->stride;
  393.     const int flags= c->sub_flags;
  394.     LOAD_COMMON
  395.  
  396.     av_assert2(flags == 0);
  397.  
  398.     if(c->skip){
  399.         *mx_ptr = 0;
  400.         *my_ptr = 0;
  401.         return dmin;
  402.     }
  403.  
  404.     pix = c->src[src_index][0];
  405.  
  406.     mx = *mx_ptr;
  407.     my = *my_ptr;
  408.     ptr = c->ref[ref_index][0] + (my * stride) + mx;
  409.  
  410.     dminh = dmin;
  411.  
  412.     if (mx > xmin && mx < xmax &&
  413.         my > ymin && my < ymax) {
  414.         int dx=0, dy=0;
  415.         int d, pen_x, pen_y;
  416.         const int index= (my<<ME_MAP_SHIFT) + mx;
  417.         const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
  418.         const int l= score_map[(index- 1               )&(ME_MAP_SIZE-1)];
  419.         const int r= score_map[(index+ 1               )&(ME_MAP_SIZE-1)];
  420.         const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
  421.         mx<<=1;
  422.         my<<=1;
  423.  
  424.  
  425.         pen_x= pred_x + mx;
  426.         pen_y= pred_y + my;
  427.  
  428.         ptr-= stride;
  429.         if(t<=b){
  430.             CHECK_SAD_HALF_MV(y2 , 0, -1)
  431.             if(l<=r){
  432.                 CHECK_SAD_HALF_MV(xy2, -1, -1)
  433.                 if(t+r<=b+l){
  434.                     CHECK_SAD_HALF_MV(xy2, +1, -1)
  435.                     ptr+= stride;
  436.                 }else{
  437.                     ptr+= stride;
  438.                     CHECK_SAD_HALF_MV(xy2, -1, +1)
  439.                 }
  440.                 CHECK_SAD_HALF_MV(x2 , -1,  0)
  441.             }else{
  442.                 CHECK_SAD_HALF_MV(xy2, +1, -1)
  443.                 if(t+l<=b+r){
  444.                     CHECK_SAD_HALF_MV(xy2, -1, -1)
  445.                     ptr+= stride;
  446.                 }else{
  447.                     ptr+= stride;
  448.                     CHECK_SAD_HALF_MV(xy2, +1, +1)
  449.                 }
  450.                 CHECK_SAD_HALF_MV(x2 , +1,  0)
  451.             }
  452.         }else{
  453.             if(l<=r){
  454.                 if(t+l<=b+r){
  455.                     CHECK_SAD_HALF_MV(xy2, -1, -1)
  456.                     ptr+= stride;
  457.                 }else{
  458.                     ptr+= stride;
  459.                     CHECK_SAD_HALF_MV(xy2, +1, +1)
  460.                 }
  461.                 CHECK_SAD_HALF_MV(x2 , -1,  0)
  462.                 CHECK_SAD_HALF_MV(xy2, -1, +1)
  463.             }else{
  464.                 if(t+r<=b+l){
  465.                     CHECK_SAD_HALF_MV(xy2, +1, -1)
  466.                     ptr+= stride;
  467.                 }else{
  468.                     ptr+= stride;
  469.                     CHECK_SAD_HALF_MV(xy2, -1, +1)
  470.                 }
  471.                 CHECK_SAD_HALF_MV(x2 , +1,  0)
  472.                 CHECK_SAD_HALF_MV(xy2, +1, +1)
  473.             }
  474.             CHECK_SAD_HALF_MV(y2 ,  0, +1)
  475.         }
  476.         mx+=dx;
  477.         my+=dy;
  478.  
  479.     }else{
  480.         mx<<=1;
  481.         my<<=1;
  482.     }
  483.  
  484.     *mx_ptr = mx;
  485.     *my_ptr = my;
  486.     return dminh;
  487. }
  488.  
  489. static inline void set_p_mv_tables(MpegEncContext * s, int mx, int my, int mv4)
  490. {
  491.     const int xy= s->mb_x + s->mb_y*s->mb_stride;
  492.  
  493.     s->p_mv_table[xy][0] = mx;
  494.     s->p_mv_table[xy][1] = my;
  495.  
  496.     /* has already been set to the 4 MV if 4MV is done */
  497.     if(mv4){
  498.         int mot_xy= s->block_index[0];
  499.  
  500.         s->current_picture.motion_val[0][mot_xy    ][0] = mx;
  501.         s->current_picture.motion_val[0][mot_xy    ][1] = my;
  502.         s->current_picture.motion_val[0][mot_xy + 1][0] = mx;
  503.         s->current_picture.motion_val[0][mot_xy + 1][1] = my;
  504.  
  505.         mot_xy += s->b8_stride;
  506.         s->current_picture.motion_val[0][mot_xy    ][0] = mx;
  507.         s->current_picture.motion_val[0][mot_xy    ][1] = my;
  508.         s->current_picture.motion_val[0][mot_xy + 1][0] = mx;
  509.         s->current_picture.motion_val[0][mot_xy + 1][1] = my;
  510.     }
  511. }
  512.  
  513. /**
  514.  * get fullpel ME search limits.
  515.  */
  516. static inline void get_limits(MpegEncContext *s, int x, int y)
  517. {
  518.     MotionEstContext * const c= &s->me;
  519.     int range= c->avctx->me_range >> (1 + !!(c->flags&FLAG_QPEL));
  520.     int max_range = MAX_MV >> (1 + !!(c->flags&FLAG_QPEL));
  521. /*
  522.     if(c->avctx->me_range) c->range= c->avctx->me_range >> 1;
  523.     else                   c->range= 16;
  524. */
  525.     if (s->unrestricted_mv) {
  526.         c->xmin = - x - 16;
  527.         c->ymin = - y - 16;
  528.         c->xmax = - x + s->width;
  529.         c->ymax = - y + s->height;
  530.     } else if (s->out_format == FMT_H261){
  531.         // Search range of H261 is different from other codec standards
  532.         c->xmin = (x > 15) ? - 15 : 0;
  533.         c->ymin = (y > 15) ? - 15 : 0;
  534.         c->xmax = (x < s->mb_width * 16 - 16) ? 15 : 0;
  535.         c->ymax = (y < s->mb_height * 16 - 16) ? 15 : 0;
  536.     } else {
  537.         c->xmin = - x;
  538.         c->ymin = - y;
  539.         c->xmax = - x + s->mb_width *16 - 16;
  540.         c->ymax = - y + s->mb_height*16 - 16;
  541.     }
  542.     if(!range || range > max_range)
  543.         range = max_range;
  544.     if(range){
  545.         c->xmin = FFMAX(c->xmin,-range);
  546.         c->xmax = FFMIN(c->xmax, range);
  547.         c->ymin = FFMAX(c->ymin,-range);
  548.         c->ymax = FFMIN(c->ymax, range);
  549.     }
  550. }
  551.  
  552. static inline void init_mv4_ref(MotionEstContext *c){
  553.     const int stride= c->stride;
  554.  
  555.     c->ref[1][0] = c->ref[0][0] + 8;
  556.     c->ref[2][0] = c->ref[0][0] + 8*stride;
  557.     c->ref[3][0] = c->ref[2][0] + 8;
  558.     c->src[1][0] = c->src[0][0] + 8;
  559.     c->src[2][0] = c->src[0][0] + 8*stride;
  560.     c->src[3][0] = c->src[2][0] + 8;
  561. }
  562.  
  563. static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift)
  564. {
  565.     MotionEstContext * const c= &s->me;
  566.     const int size= 1;
  567.     const int h=8;
  568.     int block;
  569.     int P[10][2];
  570.     int dmin_sum=0, mx4_sum=0, my4_sum=0, i;
  571.     int same=1;
  572.     const int stride= c->stride;
  573.     uint8_t *mv_penalty= c->current_mv_penalty;
  574.     int saftey_cliping= s->unrestricted_mv && (s->width&15) && (s->height&15);
  575.  
  576.     init_mv4_ref(c);
  577.  
  578.     for(block=0; block<4; block++){
  579.         int mx4, my4;
  580.         int pred_x4, pred_y4;
  581.         int dmin4;
  582.         static const int off[4]= {2, 1, 1, -1};
  583.         const int mot_stride = s->b8_stride;
  584.         const int mot_xy = s->block_index[block];
  585.  
  586.         if(saftey_cliping){
  587.             c->xmax = - 16*s->mb_x + s->width  - 8*(block &1);
  588.             c->ymax = - 16*s->mb_y + s->height - 8*(block>>1);
  589.         }
  590.  
  591.         P_LEFT[0] = s->current_picture.motion_val[0][mot_xy - 1][0];
  592.         P_LEFT[1] = s->current_picture.motion_val[0][mot_xy - 1][1];
  593.  
  594.         if(P_LEFT[0]       > (c->xmax<<shift)) P_LEFT[0]       = (c->xmax<<shift);
  595.  
  596.         /* special case for first line */
  597.         if (s->first_slice_line && block<2) {
  598.             c->pred_x= pred_x4= P_LEFT[0];
  599.             c->pred_y= pred_y4= P_LEFT[1];
  600.         } else {
  601.             P_TOP[0]      = s->current_picture.motion_val[0][mot_xy - mot_stride             ][0];
  602.             P_TOP[1]      = s->current_picture.motion_val[0][mot_xy - mot_stride             ][1];
  603.             P_TOPRIGHT[0] = s->current_picture.motion_val[0][mot_xy - mot_stride + off[block]][0];
  604.             P_TOPRIGHT[1] = s->current_picture.motion_val[0][mot_xy - mot_stride + off[block]][1];
  605.             if(P_TOP[1]      > (c->ymax<<shift)) P_TOP[1]     = (c->ymax<<shift);
  606.             if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
  607.             if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
  608.             if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
  609.  
  610.             P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
  611.             P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
  612.  
  613.             c->pred_x= pred_x4 = P_MEDIAN[0];
  614.             c->pred_y= pred_y4 = P_MEDIAN[1];
  615.         }
  616.         P_MV1[0]= mx;
  617.         P_MV1[1]= my;
  618.         if(saftey_cliping)
  619.             for(i=0; i<10; i++){
  620.                 if(P[i][0] > (c->xmax<<shift)) P[i][0]= (c->xmax<<shift);
  621.                 if(P[i][1] > (c->ymax<<shift)) P[i][1]= (c->ymax<<shift);
  622.             }
  623.  
  624.         dmin4 = epzs_motion_search4(s, &mx4, &my4, P, block, block, s->p_mv_table, (1<<16)>>shift);
  625.  
  626.         dmin4= c->sub_motion_search(s, &mx4, &my4, dmin4, block, block, size, h);
  627.  
  628.         if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){
  629.             int dxy;
  630.             const int offset= ((block&1) + (block>>1)*stride)*8;
  631.             uint8_t *dest_y = c->scratchpad + offset;
  632.             if(s->quarter_sample){
  633.                 uint8_t *ref= c->ref[block][0] + (mx4>>2) + (my4>>2)*stride;
  634.                 dxy = ((my4 & 3) << 2) | (mx4 & 3);
  635.  
  636.                 if(s->no_rounding)
  637.                     s->dsp.put_no_rnd_qpel_pixels_tab[1][dxy](dest_y   , ref    , stride);
  638.                 else
  639.                     s->dsp.put_qpel_pixels_tab       [1][dxy](dest_y   , ref    , stride);
  640.             }else{
  641.                 uint8_t *ref= c->ref[block][0] + (mx4>>1) + (my4>>1)*stride;
  642.                 dxy = ((my4 & 1) << 1) | (mx4 & 1);
  643.  
  644.                 if(s->no_rounding)
  645.                     s->hdsp.put_no_rnd_pixels_tab[1][dxy](dest_y    , ref    , stride, h);
  646.                 else
  647.                     s->hdsp.put_pixels_tab       [1][dxy](dest_y    , ref    , stride, h);
  648.             }
  649.             dmin_sum+= (mv_penalty[mx4-pred_x4] + mv_penalty[my4-pred_y4])*c->mb_penalty_factor;
  650.         }else
  651.             dmin_sum+= dmin4;
  652.  
  653.         if(s->quarter_sample){
  654.             mx4_sum+= mx4/2;
  655.             my4_sum+= my4/2;
  656.         }else{
  657.             mx4_sum+= mx4;
  658.             my4_sum+= my4;
  659.         }
  660.  
  661.         s->current_picture.motion_val[0][s->block_index[block]][0] = mx4;
  662.         s->current_picture.motion_val[0][s->block_index[block]][1] = my4;
  663.  
  664.         if(mx4 != mx || my4 != my) same=0;
  665.     }
  666.  
  667.     if(same)
  668.         return INT_MAX;
  669.  
  670.     if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){
  671.         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);
  672.     }
  673.  
  674.     if(c->avctx->mb_cmp&FF_CMP_CHROMA){
  675.         int dxy;
  676.         int mx, my;
  677.         int offset;
  678.  
  679.         mx= ff_h263_round_chroma(mx4_sum);
  680.         my= ff_h263_round_chroma(my4_sum);
  681.         dxy = ((my & 1) << 1) | (mx & 1);
  682.  
  683.         offset= (s->mb_x*8 + (mx>>1)) + (s->mb_y*8 + (my>>1))*s->uvlinesize;
  684.  
  685.         if(s->no_rounding){
  686.             s->hdsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad    , s->last_picture.f.data[1] + offset, s->uvlinesize, 8);
  687.             s->hdsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad + 8, s->last_picture.f.data[2] + offset, s->uvlinesize, 8);
  688.         }else{
  689.             s->hdsp.put_pixels_tab       [1][dxy](c->scratchpad    , s->last_picture.f.data[1] + offset, s->uvlinesize, 8);
  690.             s->hdsp.put_pixels_tab       [1][dxy](c->scratchpad + 8, s->last_picture.f.data[2] + offset, s->uvlinesize, 8);
  691.         }
  692.  
  693.         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);
  694.         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);
  695.     }
  696.  
  697.     c->pred_x= mx;
  698.     c->pred_y= my;
  699.  
  700.     switch(c->avctx->mb_cmp&0xFF){
  701.     /*case FF_CMP_SSE:
  702.         return dmin_sum+ 32*s->qscale*s->qscale;*/
  703.     case FF_CMP_RD:
  704.         return dmin_sum;
  705.     default:
  706.         return dmin_sum+ 11*c->mb_penalty_factor;
  707.     }
  708. }
  709.  
  710. static inline void init_interlaced_ref(MpegEncContext *s, int ref_index){
  711.     MotionEstContext * const c= &s->me;
  712.  
  713.     c->ref[1+ref_index][0] = c->ref[0+ref_index][0] + s->linesize;
  714.     c->src[1][0] = c->src[0][0] + s->linesize;
  715.     if(c->flags & FLAG_CHROMA){
  716.         c->ref[1+ref_index][1] = c->ref[0+ref_index][1] + s->uvlinesize;
  717.         c->ref[1+ref_index][2] = c->ref[0+ref_index][2] + s->uvlinesize;
  718.         c->src[1][1] = c->src[0][1] + s->uvlinesize;
  719.         c->src[1][2] = c->src[0][2] + s->uvlinesize;
  720.     }
  721. }
  722.  
  723. static int interlaced_search(MpegEncContext *s, int ref_index,
  724.                              int16_t (*mv_tables[2][2])[2], uint8_t *field_select_tables[2], int mx, int my, int user_field_select)
  725. {
  726.     MotionEstContext * const c= &s->me;
  727.     const int size=0;
  728.     const int h=8;
  729.     int block;
  730.     int P[10][2];
  731.     uint8_t * const mv_penalty= c->current_mv_penalty;
  732.     int same=1;
  733.     const int stride= 2*s->linesize;
  734.     int dmin_sum= 0;
  735.     const int mot_stride= s->mb_stride;
  736.     const int xy= s->mb_x + s->mb_y*mot_stride;
  737.  
  738.     c->ymin>>=1;
  739.     c->ymax>>=1;
  740.     c->stride<<=1;
  741.     c->uvstride<<=1;
  742.     init_interlaced_ref(s, ref_index);
  743.  
  744.     for(block=0; block<2; block++){
  745.         int field_select;
  746.         int best_dmin= INT_MAX;
  747.         int best_field= -1;
  748.  
  749.         for(field_select=0; field_select<2; field_select++){
  750.             int dmin, mx_i, my_i;
  751.             int16_t (*mv_table)[2]= mv_tables[block][field_select];
  752.  
  753.             if(user_field_select){
  754.                 av_assert1(field_select==0 || field_select==1);
  755.                 av_assert1(field_select_tables[block][xy]==0 || field_select_tables[block][xy]==1);
  756.                 if(field_select_tables[block][xy] != field_select)
  757.                     continue;
  758.             }
  759.  
  760.             P_LEFT[0] = mv_table[xy - 1][0];
  761.             P_LEFT[1] = mv_table[xy - 1][1];
  762.             if(P_LEFT[0]       > (c->xmax<<1)) P_LEFT[0]       = (c->xmax<<1);
  763.  
  764.             c->pred_x= P_LEFT[0];
  765.             c->pred_y= P_LEFT[1];
  766.  
  767.             if(!s->first_slice_line){
  768.                 P_TOP[0]      = mv_table[xy - mot_stride][0];
  769.                 P_TOP[1]      = mv_table[xy - mot_stride][1];
  770.                 P_TOPRIGHT[0] = mv_table[xy - mot_stride + 1][0];
  771.                 P_TOPRIGHT[1] = mv_table[xy - mot_stride + 1][1];
  772.                 if(P_TOP[1]      > (c->ymax<<1)) P_TOP[1]     = (c->ymax<<1);
  773.                 if(P_TOPRIGHT[0] < (c->xmin<<1)) P_TOPRIGHT[0]= (c->xmin<<1);
  774.                 if(P_TOPRIGHT[0] > (c->xmax<<1)) P_TOPRIGHT[0]= (c->xmax<<1);
  775.                 if(P_TOPRIGHT[1] > (c->ymax<<1)) P_TOPRIGHT[1]= (c->ymax<<1);
  776.  
  777.                 P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
  778.                 P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
  779.             }
  780.             P_MV1[0]= mx; //FIXME not correct if block != field_select
  781.             P_MV1[1]= my / 2;
  782.  
  783.             dmin = epzs_motion_search2(s, &mx_i, &my_i, P, block, field_select+ref_index, mv_table, (1<<16)>>1);
  784.  
  785.             dmin= c->sub_motion_search(s, &mx_i, &my_i, dmin, block, field_select+ref_index, size, h);
  786.  
  787.             mv_table[xy][0]= mx_i;
  788.             mv_table[xy][1]= my_i;
  789.  
  790.             if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){
  791.                 int dxy;
  792.  
  793.                 //FIXME chroma ME
  794.                 uint8_t *ref= c->ref[field_select+ref_index][0] + (mx_i>>1) + (my_i>>1)*stride;
  795.                 dxy = ((my_i & 1) << 1) | (mx_i & 1);
  796.  
  797.                 if(s->no_rounding){
  798.                     s->hdsp.put_no_rnd_pixels_tab[size][dxy](c->scratchpad, ref    , stride, h);
  799.                 }else{
  800.                     s->hdsp.put_pixels_tab       [size][dxy](c->scratchpad, ref    , stride, h);
  801.                 }
  802.                 dmin= s->dsp.mb_cmp[size](s, c->src[block][0], c->scratchpad, stride, h);
  803.                 dmin+= (mv_penalty[mx_i-c->pred_x] + mv_penalty[my_i-c->pred_y] + 1)*c->mb_penalty_factor;
  804.             }else
  805.                 dmin+= c->mb_penalty_factor; //field_select bits
  806.  
  807.             dmin += field_select != block; //slightly prefer same field
  808.  
  809.             if(dmin < best_dmin){
  810.                 best_dmin= dmin;
  811.                 best_field= field_select;
  812.             }
  813.         }
  814.         {
  815.             int16_t (*mv_table)[2]= mv_tables[block][best_field];
  816.  
  817.             if(mv_table[xy][0] != mx) same=0; //FIXME check if these checks work and are any good at all
  818.             if(mv_table[xy][1]&1) same=0;
  819.             if(mv_table[xy][1]*2 != my) same=0;
  820.             if(best_field != block) same=0;
  821.         }
  822.  
  823.         field_select_tables[block][xy]= best_field;
  824.         dmin_sum += best_dmin;
  825.     }
  826.  
  827.     c->ymin<<=1;
  828.     c->ymax<<=1;
  829.     c->stride>>=1;
  830.     c->uvstride>>=1;
  831.  
  832.     if(same)
  833.         return INT_MAX;
  834.  
  835.     switch(c->avctx->mb_cmp&0xFF){
  836.     /*case FF_CMP_SSE:
  837.         return dmin_sum+ 32*s->qscale*s->qscale;*/
  838.     case FF_CMP_RD:
  839.         return dmin_sum;
  840.     default:
  841.         return dmin_sum+ 11*c->mb_penalty_factor;
  842.     }
  843. }
  844.  
  845. static inline int get_penalty_factor(int lambda, int lambda2, int type){
  846.     switch(type&0xFF){
  847.     default:
  848.     case FF_CMP_SAD:
  849.         return lambda>>FF_LAMBDA_SHIFT;
  850.     case FF_CMP_DCT:
  851.         return (3*lambda)>>(FF_LAMBDA_SHIFT+1);
  852.     case FF_CMP_W53:
  853.         return (4*lambda)>>(FF_LAMBDA_SHIFT);
  854.     case FF_CMP_W97:
  855.         return (2*lambda)>>(FF_LAMBDA_SHIFT);
  856.     case FF_CMP_SATD:
  857.     case FF_CMP_DCT264:
  858.         return (2*lambda)>>FF_LAMBDA_SHIFT;
  859.     case FF_CMP_RD:
  860.     case FF_CMP_PSNR:
  861.     case FF_CMP_SSE:
  862.     case FF_CMP_NSSE:
  863.         return lambda2>>FF_LAMBDA_SHIFT;
  864.     case FF_CMP_BIT:
  865.         return 1;
  866.     }
  867. }
  868.  
  869. void ff_estimate_p_frame_motion(MpegEncContext * s,
  870.                                 int mb_x, int mb_y)
  871. {
  872.     MotionEstContext * const c= &s->me;
  873.     uint8_t *pix, *ppix;
  874.     int sum, mx, my, dmin;
  875.     int varc;            ///< the variance of the block (sum of squared (p[y][x]-average))
  876.     int vard;            ///< sum of squared differences with the estimated motion vector
  877.     int P[10][2];
  878.     const int shift= 1+s->quarter_sample;
  879.     int mb_type=0;
  880.     Picture * const pic= &s->current_picture;
  881.  
  882.     init_ref(c, s->new_picture.f.data, s->last_picture.f.data, NULL, 16*mb_x, 16*mb_y, 0);
  883.  
  884.     av_assert0(s->quarter_sample==0 || s->quarter_sample==1);
  885.     av_assert0(s->linesize == c->stride);
  886.     av_assert0(s->uvlinesize == c->uvstride);
  887.  
  888.     c->penalty_factor    = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
  889.     c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
  890.     c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
  891.     c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV;
  892.  
  893.     get_limits(s, 16*mb_x, 16*mb_y);
  894.     c->skip=0;
  895.  
  896.     /* intra / predictive decision */
  897.     pix = c->src[0][0];
  898.     sum = s->dsp.pix_sum(pix, s->linesize);
  899.     varc = s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)sum*sum)>>8) + 500;
  900.  
  901.     pic->mb_mean[s->mb_stride * mb_y + mb_x] = (sum+128)>>8;
  902.     pic->mb_var [s->mb_stride * mb_y + mb_x] = (varc+128)>>8;
  903.     c->mb_var_sum_temp += (varc+128)>>8;
  904.  
  905.     switch(s->me_method) {
  906.     case ME_ZERO:
  907.     default:
  908.         mx   = 0;
  909.         my   = 0;
  910.         dmin = 0;
  911.         break;
  912.     case ME_X1:
  913.     case ME_EPZS:
  914.        {
  915.             const int mot_stride = s->b8_stride;
  916.             const int mot_xy = s->block_index[0];
  917.  
  918.             P_LEFT[0] = s->current_picture.motion_val[0][mot_xy - 1][0];
  919.             P_LEFT[1] = s->current_picture.motion_val[0][mot_xy - 1][1];
  920.  
  921.             if(P_LEFT[0]       > (c->xmax<<shift)) P_LEFT[0]       = (c->xmax<<shift);
  922.  
  923.             if(!s->first_slice_line) {
  924.                 P_TOP[0]      = s->current_picture.motion_val[0][mot_xy - mot_stride    ][0];
  925.                 P_TOP[1]      = s->current_picture.motion_val[0][mot_xy - mot_stride    ][1];
  926.                 P_TOPRIGHT[0] = s->current_picture.motion_val[0][mot_xy - mot_stride + 2][0];
  927.                 P_TOPRIGHT[1] = s->current_picture.motion_val[0][mot_xy - mot_stride + 2][1];
  928.                 if(P_TOP[1]      > (c->ymax<<shift)) P_TOP[1]     = (c->ymax<<shift);
  929.                 if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
  930.                 if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
  931.  
  932.                 P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
  933.                 P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
  934.  
  935.                 if(s->out_format == FMT_H263){
  936.                     c->pred_x = P_MEDIAN[0];
  937.                     c->pred_y = P_MEDIAN[1];
  938.                 }else { /* mpeg1 at least */
  939.                     c->pred_x= P_LEFT[0];
  940.                     c->pred_y= P_LEFT[1];
  941.                 }
  942.             }else{
  943.                 c->pred_x= P_LEFT[0];
  944.                 c->pred_y= P_LEFT[1];
  945.             }
  946.  
  947.         }
  948.         dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
  949.  
  950.         break;
  951.     }
  952.  
  953.     /* At this point (mx,my) are full-pell and the relative displacement */
  954.     ppix = c->ref[0][0] + (my * s->linesize) + mx;
  955.  
  956.     vard = s->dsp.sse[0](NULL, pix, ppix, s->linesize, 16);
  957.  
  958.     pic->mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8;
  959.     c->mc_mb_var_sum_temp += (vard+128)>>8;
  960.  
  961.     if(mb_type){
  962.         int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
  963.         int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
  964.         c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
  965.  
  966.         if(mb_type == CANDIDATE_MB_TYPE_INTER){
  967.             c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
  968.             set_p_mv_tables(s, mx, my, 1);
  969.         }else{
  970.             mx <<=shift;
  971.             my <<=shift;
  972.         }
  973.         if(mb_type == CANDIDATE_MB_TYPE_INTER4V){
  974.             h263_mv4_search(s, mx, my, shift);
  975.  
  976.             set_p_mv_tables(s, mx, my, 0);
  977.         }
  978.         if(mb_type == CANDIDATE_MB_TYPE_INTER_I){
  979.             interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 1);
  980.         }
  981.     }else if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
  982.         int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
  983.         int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
  984.         c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
  985.  
  986.         if (vard*2 + 200*256 > varc)
  987.             mb_type|= CANDIDATE_MB_TYPE_INTRA;
  988.         if (varc*2 + 200*256 > vard || s->qscale > 24){
  989. //        if (varc*2 + 200*256 + 50*(s->lambda2>>FF_LAMBDA_SHIFT) > vard){
  990.             mb_type|= CANDIDATE_MB_TYPE_INTER;
  991.             c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
  992.             if(s->flags&CODEC_FLAG_MV0)
  993.                 if(mx || my)
  994.                     mb_type |= CANDIDATE_MB_TYPE_SKIPPED; //FIXME check difference
  995.         }else{
  996.             mx <<=shift;
  997.             my <<=shift;
  998.         }
  999.         if((s->flags&CODEC_FLAG_4MV)
  1000.            && !c->skip && varc>50<<8 && vard>10<<8){
  1001.             if(h263_mv4_search(s, mx, my, shift) < INT_MAX)
  1002.                 mb_type|=CANDIDATE_MB_TYPE_INTER4V;
  1003.  
  1004.             set_p_mv_tables(s, mx, my, 0);
  1005.         }else
  1006.             set_p_mv_tables(s, mx, my, 1);
  1007.         if((s->flags&CODEC_FLAG_INTERLACED_ME)
  1008.            && !c->skip){ //FIXME varc/d checks
  1009.             if(interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 0) < INT_MAX)
  1010.                 mb_type |= CANDIDATE_MB_TYPE_INTER_I;
  1011.         }
  1012.     }else{
  1013.         int intra_score, i;
  1014.         mb_type= CANDIDATE_MB_TYPE_INTER;
  1015.  
  1016.         dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
  1017.         if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
  1018.             dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
  1019.  
  1020.         if((s->flags&CODEC_FLAG_4MV)
  1021.            && !c->skip && varc>50<<8 && vard>10<<8){
  1022.             int dmin4= h263_mv4_search(s, mx, my, shift);
  1023.             if(dmin4 < dmin){
  1024.                 mb_type= CANDIDATE_MB_TYPE_INTER4V;
  1025.                 dmin=dmin4;
  1026.             }
  1027.         }
  1028.         if((s->flags&CODEC_FLAG_INTERLACED_ME)
  1029.            && !c->skip){ //FIXME varc/d checks
  1030.             int dmin_i= interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 0);
  1031.             if(dmin_i < dmin){
  1032.                 mb_type = CANDIDATE_MB_TYPE_INTER_I;
  1033.                 dmin= dmin_i;
  1034.             }
  1035.         }
  1036.  
  1037.         set_p_mv_tables(s, mx, my, mb_type!=CANDIDATE_MB_TYPE_INTER4V);
  1038.  
  1039.         /* get intra luma score */
  1040.         if((c->avctx->mb_cmp&0xFF)==FF_CMP_SSE){
  1041.             intra_score= varc - 500;
  1042.         }else{
  1043.             unsigned mean = (sum+128)>>8;
  1044.             mean*= 0x01010101;
  1045.  
  1046.             for(i=0; i<16; i++){
  1047.                 *(uint32_t*)(&c->scratchpad[i*s->linesize+ 0]) = mean;
  1048.                 *(uint32_t*)(&c->scratchpad[i*s->linesize+ 4]) = mean;
  1049.                 *(uint32_t*)(&c->scratchpad[i*s->linesize+ 8]) = mean;
  1050.                 *(uint32_t*)(&c->scratchpad[i*s->linesize+12]) = mean;
  1051.             }
  1052.  
  1053.             intra_score= s->dsp.mb_cmp[0](s, c->scratchpad, pix, s->linesize, 16);
  1054.         }
  1055.         intra_score += c->mb_penalty_factor*16;
  1056.  
  1057.         if(intra_score < dmin){
  1058.             mb_type= CANDIDATE_MB_TYPE_INTRA;
  1059.             s->current_picture.mb_type[mb_y*s->mb_stride + mb_x] = CANDIDATE_MB_TYPE_INTRA; //FIXME cleanup
  1060.         }else
  1061.             s->current_picture.mb_type[mb_y*s->mb_stride + mb_x] = 0;
  1062.  
  1063.         {
  1064.             int p_score= FFMIN(vard, varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*100);
  1065.             int i_score= varc-500+(s->lambda2>>FF_LAMBDA_SHIFT)*20;
  1066.             c->scene_change_score+= ff_sqrt(p_score) - ff_sqrt(i_score);
  1067.         }
  1068.     }
  1069.  
  1070.     s->mb_type[mb_y*s->mb_stride + mb_x]= mb_type;
  1071. }
  1072.  
  1073. int ff_pre_estimate_p_frame_motion(MpegEncContext * s,
  1074.                                     int mb_x, int mb_y)
  1075. {
  1076.     MotionEstContext * const c= &s->me;
  1077.     int mx, my, dmin;
  1078.     int P[10][2];
  1079.     const int shift= 1+s->quarter_sample;
  1080.     const int xy= mb_x + mb_y*s->mb_stride;
  1081.     init_ref(c, s->new_picture.f.data, s->last_picture.f.data, NULL, 16*mb_x, 16*mb_y, 0);
  1082.  
  1083.     av_assert0(s->quarter_sample==0 || s->quarter_sample==1);
  1084.  
  1085.     c->pre_penalty_factor    = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_pre_cmp);
  1086.     c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV;
  1087.  
  1088.     get_limits(s, 16*mb_x, 16*mb_y);
  1089.     c->skip=0;
  1090.  
  1091.     P_LEFT[0]       = s->p_mv_table[xy + 1][0];
  1092.     P_LEFT[1]       = s->p_mv_table[xy + 1][1];
  1093.  
  1094.     if(P_LEFT[0]       < (c->xmin<<shift)) P_LEFT[0]       = (c->xmin<<shift);
  1095.  
  1096.     /* special case for first line */
  1097.     if (s->first_slice_line) {
  1098.         c->pred_x= P_LEFT[0];
  1099.         c->pred_y= P_LEFT[1];
  1100.         P_TOP[0]= P_TOPRIGHT[0]= P_MEDIAN[0]=
  1101.         P_TOP[1]= P_TOPRIGHT[1]= P_MEDIAN[1]= 0; //FIXME
  1102.     } else {
  1103.         P_TOP[0]      = s->p_mv_table[xy + s->mb_stride    ][0];
  1104.         P_TOP[1]      = s->p_mv_table[xy + s->mb_stride    ][1];
  1105.         P_TOPRIGHT[0] = s->p_mv_table[xy + s->mb_stride - 1][0];
  1106.         P_TOPRIGHT[1] = s->p_mv_table[xy + s->mb_stride - 1][1];
  1107.         if(P_TOP[1]      < (c->ymin<<shift)) P_TOP[1]     = (c->ymin<<shift);
  1108.         if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
  1109.         if(P_TOPRIGHT[1] < (c->ymin<<shift)) P_TOPRIGHT[1]= (c->ymin<<shift);
  1110.  
  1111.         P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
  1112.         P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
  1113.  
  1114.         c->pred_x = P_MEDIAN[0];
  1115.         c->pred_y = P_MEDIAN[1];
  1116.     }
  1117.  
  1118.     dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
  1119.  
  1120.     s->p_mv_table[xy][0] = mx<<shift;
  1121.     s->p_mv_table[xy][1] = my<<shift;
  1122.  
  1123.     return dmin;
  1124. }
  1125.  
  1126. static int estimate_motion_b(MpegEncContext *s, int mb_x, int mb_y,
  1127.                              int16_t (*mv_table)[2], int ref_index, int f_code)
  1128. {
  1129.     MotionEstContext * const c= &s->me;
  1130.     int mx, my, dmin;
  1131.     int P[10][2];
  1132.     const int shift= 1+s->quarter_sample;
  1133.     const int mot_stride = s->mb_stride;
  1134.     const int mot_xy = mb_y*mot_stride + mb_x;
  1135.     uint8_t * const mv_penalty= c->mv_penalty[f_code] + MAX_MV;
  1136.     int mv_scale;
  1137.  
  1138.     c->penalty_factor    = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
  1139.     c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
  1140.     c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
  1141.     c->current_mv_penalty= mv_penalty;
  1142.  
  1143.     get_limits(s, 16*mb_x, 16*mb_y);
  1144.  
  1145.     switch(s->me_method) {
  1146.     case ME_ZERO:
  1147.     default:
  1148.         mx   = 0;
  1149.         my   = 0;
  1150.         dmin = 0;
  1151.         break;
  1152.     case ME_X1:
  1153.     case ME_EPZS:
  1154.         P_LEFT[0] = mv_table[mot_xy - 1][0];
  1155.         P_LEFT[1] = mv_table[mot_xy - 1][1];
  1156.  
  1157.         if (P_LEFT[0] > (c->xmax << shift)) P_LEFT[0] = (c->xmax << shift);
  1158.  
  1159.         /* special case for first line */
  1160.         if (!s->first_slice_line) {
  1161.             P_TOP[0]      = mv_table[mot_xy - mot_stride    ][0];
  1162.             P_TOP[1]      = mv_table[mot_xy - mot_stride    ][1];
  1163.             P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1][0];
  1164.             P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1][1];
  1165.             if (P_TOP[1] > (c->ymax << shift)) P_TOP[1] = (c->ymax << shift);
  1166.             if (P_TOPRIGHT[0] < (c->xmin << shift)) P_TOPRIGHT[0] = (c->xmin << shift);
  1167.             if (P_TOPRIGHT[1] > (c->ymax << shift)) P_TOPRIGHT[1] = (c->ymax << shift);
  1168.  
  1169.             P_MEDIAN[0] = mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
  1170.             P_MEDIAN[1] = mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
  1171.         }
  1172.         c->pred_x = P_LEFT[0];
  1173.         c->pred_y = P_LEFT[1];
  1174.  
  1175.         if(mv_table == s->b_forw_mv_table){
  1176.             mv_scale= (s->pb_time<<16) / (s->pp_time<<shift);
  1177.         }else{
  1178.             mv_scale= ((s->pb_time - s->pp_time)<<16) / (s->pp_time<<shift);
  1179.         }
  1180.  
  1181.         dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, ref_index, s->p_mv_table, mv_scale, 0, 16);
  1182.  
  1183.         break;
  1184.     }
  1185.  
  1186.     dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, ref_index, 0, 16);
  1187.  
  1188.     if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
  1189.         dmin= get_mb_score(s, mx, my, 0, ref_index, 0, 16, 1);
  1190.  
  1191. //    s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
  1192.     mv_table[mot_xy][0]= mx;
  1193.     mv_table[mot_xy][1]= my;
  1194.  
  1195.     return dmin;
  1196. }
  1197.  
  1198. static inline int check_bidir_mv(MpegEncContext * s,
  1199.                    int motion_fx, int motion_fy,
  1200.                    int motion_bx, int motion_by,
  1201.                    int pred_fx, int pred_fy,
  1202.                    int pred_bx, int pred_by,
  1203.                    int size, int h)
  1204. {
  1205.     //FIXME optimize?
  1206.     //FIXME better f_code prediction (max mv & distance)
  1207.     //FIXME pointers
  1208.     MotionEstContext * const c= &s->me;
  1209.     uint8_t * const mv_penalty_f= c->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
  1210.     uint8_t * const mv_penalty_b= c->mv_penalty[s->b_code] + MAX_MV; // f_code of the prev frame
  1211.     int stride= c->stride;
  1212.     uint8_t *dest_y = c->scratchpad;
  1213.     uint8_t *ptr;
  1214.     int dxy;
  1215.     int src_x, src_y;
  1216.     int fbmin;
  1217.     uint8_t **src_data= c->src[0];
  1218.     uint8_t **ref_data= c->ref[0];
  1219.     uint8_t **ref2_data= c->ref[2];
  1220.  
  1221.     if(s->quarter_sample){
  1222.         dxy = ((motion_fy & 3) << 2) | (motion_fx & 3);
  1223.         src_x = motion_fx >> 2;
  1224.         src_y = motion_fy >> 2;
  1225.  
  1226.         ptr = ref_data[0] + (src_y * stride) + src_x;
  1227.         s->dsp.put_qpel_pixels_tab[0][dxy](dest_y    , ptr    , stride);
  1228.  
  1229.         dxy = ((motion_by & 3) << 2) | (motion_bx & 3);
  1230.         src_x = motion_bx >> 2;
  1231.         src_y = motion_by >> 2;
  1232.  
  1233.         ptr = ref2_data[0] + (src_y * stride) + src_x;
  1234.         s->dsp.avg_qpel_pixels_tab[size][dxy](dest_y    , ptr    , stride);
  1235.     }else{
  1236.         dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
  1237.         src_x = motion_fx >> 1;
  1238.         src_y = motion_fy >> 1;
  1239.  
  1240.         ptr = ref_data[0] + (src_y * stride) + src_x;
  1241.         s->hdsp.put_pixels_tab[size][dxy](dest_y    , ptr    , stride, h);
  1242.  
  1243.         dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
  1244.         src_x = motion_bx >> 1;
  1245.         src_y = motion_by >> 1;
  1246.  
  1247.         ptr = ref2_data[0] + (src_y * stride) + src_x;
  1248.         s->hdsp.avg_pixels_tab[size][dxy](dest_y    , ptr    , stride, h);
  1249.     }
  1250.  
  1251.     fbmin = (mv_penalty_f[motion_fx-pred_fx] + mv_penalty_f[motion_fy-pred_fy])*c->mb_penalty_factor
  1252.            +(mv_penalty_b[motion_bx-pred_bx] + mv_penalty_b[motion_by-pred_by])*c->mb_penalty_factor
  1253.            + s->dsp.mb_cmp[size](s, src_data[0], dest_y, stride, h); //FIXME new_pic
  1254.  
  1255.     if(c->avctx->mb_cmp&FF_CMP_CHROMA){
  1256.     }
  1257.     //FIXME CHROMA !!!
  1258.  
  1259.     return fbmin;
  1260. }
  1261.  
  1262. /* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
  1263. static inline int bidir_refine(MpegEncContext * s, int mb_x, int mb_y)
  1264. {
  1265.     MotionEstContext * const c= &s->me;
  1266.     const int mot_stride = s->mb_stride;
  1267.     const int xy = mb_y *mot_stride + mb_x;
  1268.     int fbmin;
  1269.     int pred_fx= s->b_bidir_forw_mv_table[xy-1][0];
  1270.     int pred_fy= s->b_bidir_forw_mv_table[xy-1][1];
  1271.     int pred_bx= s->b_bidir_back_mv_table[xy-1][0];
  1272.     int pred_by= s->b_bidir_back_mv_table[xy-1][1];
  1273.     int motion_fx= s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0];
  1274.     int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1];
  1275.     int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0];
  1276.     int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1];
  1277.     const int flags= c->sub_flags;
  1278.     const int qpel= flags&FLAG_QPEL;
  1279.     const int shift= 1+qpel;
  1280.     const int xmin= c->xmin<<shift;
  1281.     const int ymin= c->ymin<<shift;
  1282.     const int xmax= c->xmax<<shift;
  1283.     const int ymax= c->ymax<<shift;
  1284. #define HASH(fx,fy,bx,by) ((fx)+17*(fy)+63*(bx)+117*(by))
  1285. #define HASH8(fx,fy,bx,by) ((uint8_t)HASH(fx,fy,bx,by))
  1286.     int hashidx= HASH(motion_fx,motion_fy, motion_bx, motion_by);
  1287.     uint8_t map[256] = { 0 };
  1288.  
  1289.     map[hashidx&255] = 1;
  1290.  
  1291.     fbmin= check_bidir_mv(s, motion_fx, motion_fy,
  1292.                           motion_bx, motion_by,
  1293.                           pred_fx, pred_fy,
  1294.                           pred_bx, pred_by,
  1295.                           0, 16);
  1296.  
  1297.     if(s->avctx->bidir_refine){
  1298.         int end;
  1299.         static const uint8_t limittab[5]={0,8,32,64,80};
  1300.         const int limit= limittab[s->avctx->bidir_refine];
  1301.         static const int8_t vect[][4]={
  1302. { 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},
  1303.  
  1304. { 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},
  1305. { 0, 1, 0, 1}, { 0,-1, 0,-1}, { 1, 0, 1, 0}, {-1, 0,-1, 0},
  1306. { 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},
  1307. { 0,-1, 0, 1}, { 0, 1, 0,-1}, {-1, 0, 1, 0}, { 1, 0,-1, 0},
  1308.  
  1309. { 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},
  1310. { 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},
  1311. { 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},
  1312. { 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},
  1313.  
  1314. { 1, 1, 1, 1}, {-1,-1,-1,-1},
  1315. { 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},
  1316. { 1, 1,-1,-1}, {-1,-1, 1, 1}, { 1,-1,-1, 1}, {-1, 1, 1,-1}, { 1,-1, 1,-1}, {-1, 1,-1, 1},
  1317.         };
  1318.         static const uint8_t hash[]={
  1319. 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),
  1320.  
  1321. 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),
  1322. HASH8( 0, 1, 0, 1), HASH8( 0,-1, 0,-1), HASH8( 1, 0, 1, 0), HASH8(-1, 0,-1, 0),
  1323. 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),
  1324. HASH8( 0,-1, 0, 1), HASH8( 0, 1, 0,-1), HASH8(-1, 0, 1, 0), HASH8( 1, 0,-1, 0),
  1325.  
  1326. 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),
  1327. 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),
  1328. 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),
  1329. 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),
  1330.  
  1331. HASH8( 1, 1, 1, 1), HASH8(-1,-1,-1,-1),
  1332. 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),
  1333. 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),
  1334. };
  1335.  
  1336. #define CHECK_BIDIR(fx,fy,bx,by)\
  1337.     if( !map[(hashidx+HASH(fx,fy,bx,by))&255]\
  1338.        &&(fx<=0 || motion_fx+fx<=xmax) && (fy<=0 || motion_fy+fy<=ymax) && (bx<=0 || motion_bx+bx<=xmax) && (by<=0 || motion_by+by<=ymax)\
  1339.        &&(fx>=0 || motion_fx+fx>=xmin) && (fy>=0 || motion_fy+fy>=ymin) && (bx>=0 || motion_bx+bx>=xmin) && (by>=0 || motion_by+by>=ymin)){\
  1340.         int score;\
  1341.         map[(hashidx+HASH(fx,fy,bx,by))&255] = 1;\
  1342.         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);\
  1343.         if(score < fbmin){\
  1344.             hashidx += HASH(fx,fy,bx,by);\
  1345.             fbmin= score;\
  1346.             motion_fx+=fx;\
  1347.             motion_fy+=fy;\
  1348.             motion_bx+=bx;\
  1349.             motion_by+=by;\
  1350.             end=0;\
  1351.         }\
  1352.     }
  1353. #define CHECK_BIDIR2(a,b,c,d)\
  1354. CHECK_BIDIR(a,b,c,d)\
  1355. CHECK_BIDIR(-(a),-(b),-(c),-(d))
  1356.  
  1357.         do{
  1358.             int i;
  1359.             int borderdist=0;
  1360.             end=1;
  1361.  
  1362.             CHECK_BIDIR2(0,0,0,1)
  1363.             CHECK_BIDIR2(0,0,1,0)
  1364.             CHECK_BIDIR2(0,1,0,0)
  1365.             CHECK_BIDIR2(1,0,0,0)
  1366.  
  1367.             for(i=8; i<limit; i++){
  1368.                 int fx= motion_fx+vect[i][0];
  1369.                 int fy= motion_fy+vect[i][1];
  1370.                 int bx= motion_bx+vect[i][2];
  1371.                 int by= motion_by+vect[i][3];
  1372.                 if(borderdist<=0){
  1373.                     int a= (xmax - FFMAX(fx,bx))|(FFMIN(fx,bx) - xmin);
  1374.                     int b= (ymax - FFMAX(fy,by))|(FFMIN(fy,by) - ymin);
  1375.                     if((a|b) < 0)
  1376.                         map[(hashidx+hash[i])&255] = 1;
  1377.                 }
  1378.                 if(!map[(hashidx+hash[i])&255]){
  1379.                     int score;
  1380.                     map[(hashidx+hash[i])&255] = 1;
  1381.                     score= check_bidir_mv(s, fx, fy, bx, by, pred_fx, pred_fy, pred_bx, pred_by, 0, 16);
  1382.                     if(score < fbmin){
  1383.                         hashidx += hash[i];
  1384.                         fbmin= score;
  1385.                         motion_fx=fx;
  1386.                         motion_fy=fy;
  1387.                         motion_bx=bx;
  1388.                         motion_by=by;
  1389.                         end=0;
  1390.                         borderdist--;
  1391.                         if(borderdist<=0){
  1392.                             int a= FFMIN(xmax - FFMAX(fx,bx), FFMIN(fx,bx) - xmin);
  1393.                             int b= FFMIN(ymax - FFMAX(fy,by), FFMIN(fy,by) - ymin);
  1394.                             borderdist= FFMIN(a,b);
  1395.                         }
  1396.                     }
  1397.                 }
  1398.             }
  1399.         }while(!end);
  1400.     }
  1401.  
  1402.     s->b_bidir_forw_mv_table[xy][0]= motion_fx;
  1403.     s->b_bidir_forw_mv_table[xy][1]= motion_fy;
  1404.     s->b_bidir_back_mv_table[xy][0]= motion_bx;
  1405.     s->b_bidir_back_mv_table[xy][1]= motion_by;
  1406.  
  1407.     return fbmin;
  1408. }
  1409.  
  1410. static inline int direct_search(MpegEncContext * s, int mb_x, int mb_y)
  1411. {
  1412.     MotionEstContext * const c= &s->me;
  1413.     int P[10][2];
  1414.     const int mot_stride = s->mb_stride;
  1415.     const int mot_xy = mb_y*mot_stride + mb_x;
  1416.     const int shift= 1+s->quarter_sample;
  1417.     int dmin, i;
  1418.     const int time_pp= s->pp_time;
  1419.     const int time_pb= s->pb_time;
  1420.     int mx, my, xmin, xmax, ymin, ymax;
  1421.     int16_t (*mv_table)[2]= s->b_direct_mv_table;
  1422.  
  1423.     c->current_mv_penalty= c->mv_penalty[1] + MAX_MV;
  1424.     ymin= xmin=(-32)>>shift;
  1425.     ymax= xmax=   31>>shift;
  1426.  
  1427.     if (IS_8X8(s->next_picture.mb_type[mot_xy])) {
  1428.         s->mv_type= MV_TYPE_8X8;
  1429.     }else{
  1430.         s->mv_type= MV_TYPE_16X16;
  1431.     }
  1432.  
  1433.     for(i=0; i<4; i++){
  1434.         int index= s->block_index[i];
  1435.         int min, max;
  1436.  
  1437.         c->co_located_mv[i][0] = s->next_picture.motion_val[0][index][0];
  1438.         c->co_located_mv[i][1] = s->next_picture.motion_val[0][index][1];
  1439.         c->direct_basis_mv[i][0]= c->co_located_mv[i][0]*time_pb/time_pp + ((i& 1)<<(shift+3));
  1440.         c->direct_basis_mv[i][1]= c->co_located_mv[i][1]*time_pb/time_pp + ((i>>1)<<(shift+3));
  1441. //        c->direct_basis_mv[1][i][0]= c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(shift+3);
  1442. //        c->direct_basis_mv[1][i][1]= c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(shift+3);
  1443.  
  1444.         max= FFMAX(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
  1445.         min= FFMIN(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
  1446.         max+= 16*mb_x + 1; // +-1 is for the simpler rounding
  1447.         min+= 16*mb_x - 1;
  1448.         xmax= FFMIN(xmax, s->width - max);
  1449.         xmin= FFMAX(xmin, - 16     - min);
  1450.  
  1451.         max= FFMAX(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
  1452.         min= FFMIN(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
  1453.         max+= 16*mb_y + 1; // +-1 is for the simpler rounding
  1454.         min+= 16*mb_y - 1;
  1455.         ymax= FFMIN(ymax, s->height - max);
  1456.         ymin= FFMAX(ymin, - 16      - min);
  1457.  
  1458.         if(s->mv_type == MV_TYPE_16X16) break;
  1459.     }
  1460.  
  1461.     av_assert2(xmax <= 15 && ymax <= 15 && xmin >= -16 && ymin >= -16);
  1462.  
  1463.     if(xmax < 0 || xmin >0 || ymax < 0 || ymin > 0){
  1464.         s->b_direct_mv_table[mot_xy][0]= 0;
  1465.         s->b_direct_mv_table[mot_xy][1]= 0;
  1466.  
  1467.         return 256*256*256*64;
  1468.     }
  1469.  
  1470.     c->xmin= xmin;
  1471.     c->ymin= ymin;
  1472.     c->xmax= xmax;
  1473.     c->ymax= ymax;
  1474.     c->flags     |= FLAG_DIRECT;
  1475.     c->sub_flags |= FLAG_DIRECT;
  1476.     c->pred_x=0;
  1477.     c->pred_y=0;
  1478.  
  1479.     P_LEFT[0]        = av_clip(mv_table[mot_xy - 1][0], xmin<<shift, xmax<<shift);
  1480.     P_LEFT[1]        = av_clip(mv_table[mot_xy - 1][1], ymin<<shift, ymax<<shift);
  1481.  
  1482.     /* special case for first line */
  1483.     if (!s->first_slice_line) { //FIXME maybe allow this over thread boundary as it is clipped
  1484.         P_TOP[0]      = av_clip(mv_table[mot_xy - mot_stride             ][0], xmin<<shift, xmax<<shift);
  1485.         P_TOP[1]      = av_clip(mv_table[mot_xy - mot_stride             ][1], ymin<<shift, ymax<<shift);
  1486.         P_TOPRIGHT[0] = av_clip(mv_table[mot_xy - mot_stride + 1         ][0], xmin<<shift, xmax<<shift);
  1487.         P_TOPRIGHT[1] = av_clip(mv_table[mot_xy - mot_stride + 1         ][1], ymin<<shift, ymax<<shift);
  1488.  
  1489.         P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
  1490.         P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
  1491.     }
  1492.  
  1493.     dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, mv_table, 1<<(16-shift), 0, 16);
  1494.     if(c->sub_flags&FLAG_QPEL)
  1495.         dmin = qpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
  1496.     else
  1497.         dmin = hpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
  1498.  
  1499.     if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
  1500.         dmin= get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
  1501.  
  1502.     get_limits(s, 16*mb_x, 16*mb_y); //restore c->?min/max, maybe not needed
  1503.  
  1504.     mv_table[mot_xy][0]= mx;
  1505.     mv_table[mot_xy][1]= my;
  1506.     c->flags     &= ~FLAG_DIRECT;
  1507.     c->sub_flags &= ~FLAG_DIRECT;
  1508.  
  1509.     return dmin;
  1510. }
  1511.  
  1512. void ff_estimate_b_frame_motion(MpegEncContext * s,
  1513.                              int mb_x, int mb_y)
  1514. {
  1515.     MotionEstContext * const c= &s->me;
  1516.     const int penalty_factor= c->mb_penalty_factor;
  1517.     int fmin, bmin, dmin, fbmin, bimin, fimin;
  1518.     int type=0;
  1519.     const int xy = mb_y*s->mb_stride + mb_x;
  1520.     init_ref(c, s->new_picture.f.data, s->last_picture.f.data,
  1521.              s->next_picture.f.data, 16 * mb_x, 16 * mb_y, 2);
  1522.  
  1523.     get_limits(s, 16*mb_x, 16*mb_y);
  1524.  
  1525.     c->skip=0;
  1526.  
  1527.     if (s->codec_id == AV_CODEC_ID_MPEG4 && s->next_picture.mbskip_table[xy]) {
  1528.         int score= direct_search(s, mb_x, mb_y); //FIXME just check 0,0
  1529.  
  1530.         score= ((unsigned)(score*score + 128*256))>>16;
  1531.         c->mc_mb_var_sum_temp += score;
  1532.         s->current_picture.mc_mb_var[mb_y*s->mb_stride + mb_x] = score; //FIXME use SSE
  1533.         s->mb_type[mb_y*s->mb_stride + mb_x]= CANDIDATE_MB_TYPE_DIRECT0;
  1534.  
  1535.         return;
  1536.     }
  1537.  
  1538.     if (s->codec_id == AV_CODEC_ID_MPEG4)
  1539.         dmin= direct_search(s, mb_x, mb_y);
  1540.     else
  1541.         dmin= INT_MAX;
  1542. //FIXME penalty stuff for non mpeg4
  1543.     c->skip=0;
  1544.     fmin = estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code) +
  1545.            3 * penalty_factor;
  1546.  
  1547.     c->skip=0;
  1548.     bmin = estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code) +
  1549.            2 * penalty_factor;
  1550.     av_dlog(s, " %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
  1551.  
  1552.     c->skip=0;
  1553.     fbmin= bidir_refine(s, mb_x, mb_y) + penalty_factor;
  1554.     av_dlog(s, "%d %d %d %d\n", dmin, fmin, bmin, fbmin);
  1555.  
  1556.     if(s->flags & CODEC_FLAG_INTERLACED_ME){
  1557. //FIXME mb type penalty
  1558.         c->skip=0;
  1559.         c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV;
  1560.         fimin= interlaced_search(s, 0,
  1561.                                  s->b_field_mv_table[0], s->b_field_select_table[0],
  1562.                                  s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1], 0);
  1563.         c->current_mv_penalty= c->mv_penalty[s->b_code] + MAX_MV;
  1564.         bimin= interlaced_search(s, 2,
  1565.                                  s->b_field_mv_table[1], s->b_field_select_table[1],
  1566.                                  s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1], 0);
  1567.     }else
  1568.         fimin= bimin= INT_MAX;
  1569.  
  1570.     {
  1571.         int score= fmin;
  1572.         type = CANDIDATE_MB_TYPE_FORWARD;
  1573.  
  1574.         if (dmin <= score){
  1575.             score = dmin;
  1576.             type = CANDIDATE_MB_TYPE_DIRECT;
  1577.         }
  1578.         if(bmin<score){
  1579.             score=bmin;
  1580.             type= CANDIDATE_MB_TYPE_BACKWARD;
  1581.         }
  1582.         if(fbmin<score){
  1583.             score=fbmin;
  1584.             type= CANDIDATE_MB_TYPE_BIDIR;
  1585.         }
  1586.         if(fimin<score){
  1587.             score=fimin;
  1588.             type= CANDIDATE_MB_TYPE_FORWARD_I;
  1589.         }
  1590.         if(bimin<score){
  1591.             score=bimin;
  1592.             type= CANDIDATE_MB_TYPE_BACKWARD_I;
  1593.         }
  1594.  
  1595.         score= ((unsigned)(score*score + 128*256))>>16;
  1596.         c->mc_mb_var_sum_temp += score;
  1597.         s->current_picture.mc_mb_var[mb_y*s->mb_stride + mb_x] = score; //FIXME use SSE
  1598.     }
  1599.  
  1600.     if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
  1601.         type= CANDIDATE_MB_TYPE_FORWARD | CANDIDATE_MB_TYPE_BACKWARD | CANDIDATE_MB_TYPE_BIDIR | CANDIDATE_MB_TYPE_DIRECT;
  1602.         if(fimin < INT_MAX)
  1603.             type |= CANDIDATE_MB_TYPE_FORWARD_I;
  1604.         if(bimin < INT_MAX)
  1605.             type |= CANDIDATE_MB_TYPE_BACKWARD_I;
  1606.         if(fimin < INT_MAX && bimin < INT_MAX){
  1607.             type |= CANDIDATE_MB_TYPE_BIDIR_I;
  1608.         }
  1609.          //FIXME something smarter
  1610.         if(dmin>256*256*16) type&= ~CANDIDATE_MB_TYPE_DIRECT; //do not try direct mode if it is invalid for this MB
  1611.         if(s->codec_id == AV_CODEC_ID_MPEG4 && type&CANDIDATE_MB_TYPE_DIRECT && s->flags&CODEC_FLAG_MV0 && *(uint32_t*)s->b_direct_mv_table[xy])
  1612.             type |= CANDIDATE_MB_TYPE_DIRECT0;
  1613.     }
  1614.  
  1615.     s->mb_type[mb_y*s->mb_stride + mb_x]= type;
  1616. }
  1617.  
  1618. /* find best f_code for ME which do unlimited searches */
  1619. int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type)
  1620. {
  1621.     if(s->me_method>=ME_EPZS){
  1622.         int score[8];
  1623.         int i, y, range= s->avctx->me_range ? s->avctx->me_range : (INT_MAX/2);
  1624.         uint8_t * fcode_tab= s->fcode_tab;
  1625.         int best_fcode=-1;
  1626.         int best_score=-10000000;
  1627.  
  1628.         if(s->msmpeg4_version)
  1629.             range= FFMIN(range, 16);
  1630.         else if(s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL)
  1631.             range= FFMIN(range, 256);
  1632.  
  1633.         for(i=0; i<8; i++) score[i]= s->mb_num*(8-i);
  1634.  
  1635.         for(y=0; y<s->mb_height; y++){
  1636.             int x;
  1637.             int xy= y*s->mb_stride;
  1638.             for(x=0; x<s->mb_width; x++){
  1639.                 if(s->mb_type[xy] & type){
  1640.                     int mx= mv_table[xy][0];
  1641.                     int my= mv_table[xy][1];
  1642.                     int fcode= FFMAX(fcode_tab[mx + MAX_MV],
  1643.                                      fcode_tab[my + MAX_MV]);
  1644.                     int j;
  1645.  
  1646.                         if(mx >= range || mx < -range ||
  1647.                            my >= range || my < -range)
  1648.                             continue;
  1649.  
  1650.                     for(j=0; j<fcode && j<8; j++){
  1651.                         if(s->pict_type==AV_PICTURE_TYPE_B || s->current_picture.mc_mb_var[xy] < s->current_picture.mb_var[xy])
  1652.                             score[j]-= 170;
  1653.                     }
  1654.                 }
  1655.                 xy++;
  1656.             }
  1657.         }
  1658.  
  1659.         for(i=1; i<8; i++){
  1660.             if(score[i] > best_score){
  1661.                 best_score= score[i];
  1662.                 best_fcode= i;
  1663.             }
  1664.         }
  1665.  
  1666.         return best_fcode;
  1667.     }else{
  1668.         return 1;
  1669.     }
  1670. }
  1671.  
  1672. void ff_fix_long_p_mvs(MpegEncContext * s)
  1673. {
  1674.     MotionEstContext * const c= &s->me;
  1675.     const int f_code= s->f_code;
  1676.     int y, range;
  1677.     av_assert0(s->pict_type==AV_PICTURE_TYPE_P);
  1678.  
  1679.     range = (((s->out_format == FMT_MPEG1 || s->msmpeg4_version) ? 8 : 16) << f_code);
  1680.  
  1681.     av_assert0(range <= 16 || !s->msmpeg4_version);
  1682.     av_assert0(range <=256 || !(s->codec_id == AV_CODEC_ID_MPEG2VIDEO && s->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL));
  1683.  
  1684.     if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
  1685.  
  1686.     if(s->flags&CODEC_FLAG_4MV){
  1687.         const int wrap= s->b8_stride;
  1688.  
  1689.         /* clip / convert to intra 8x8 type MVs */
  1690.         for(y=0; y<s->mb_height; y++){
  1691.             int xy= y*2*wrap;
  1692.             int i= y*s->mb_stride;
  1693.             int x;
  1694.  
  1695.             for(x=0; x<s->mb_width; x++){
  1696.                 if(s->mb_type[i]&CANDIDATE_MB_TYPE_INTER4V){
  1697.                     int block;
  1698.                     for(block=0; block<4; block++){
  1699.                         int off= (block& 1) + (block>>1)*wrap;
  1700.                         int mx = s->current_picture.motion_val[0][ xy + off ][0];
  1701.                         int my = s->current_picture.motion_val[0][ xy + off ][1];
  1702.  
  1703.                         if(   mx >=range || mx <-range
  1704.                            || my >=range || my <-range){
  1705.                             s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V;
  1706.                             s->mb_type[i] |= CANDIDATE_MB_TYPE_INTRA;
  1707.                             s->current_picture.mb_type[i] = CANDIDATE_MB_TYPE_INTRA;
  1708.                         }
  1709.                     }
  1710.                 }
  1711.                 xy+=2;
  1712.                 i++;
  1713.             }
  1714.         }
  1715.     }
  1716. }
  1717.  
  1718. /**
  1719.  *
  1720.  * @param truncate 1 for truncation, 0 for using intra
  1721.  */
  1722. void ff_fix_long_mvs(MpegEncContext * s, uint8_t *field_select_table, int field_select,
  1723.                      int16_t (*mv_table)[2], int f_code, int type, int truncate)
  1724. {
  1725.     MotionEstContext * const c= &s->me;
  1726.     int y, h_range, v_range;
  1727.  
  1728.     // RAL: 8 in MPEG-1, 16 in MPEG-4
  1729.     int range = (((s->out_format == FMT_MPEG1 || s->msmpeg4_version) ? 8 : 16) << f_code);
  1730.  
  1731.     if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
  1732.  
  1733.     h_range= range;
  1734.     v_range= field_select_table ? range>>1 : range;
  1735.  
  1736.     /* clip / convert to intra 16x16 type MVs */
  1737.     for(y=0; y<s->mb_height; y++){
  1738.         int x;
  1739.         int xy= y*s->mb_stride;
  1740.         for(x=0; x<s->mb_width; x++){
  1741.             if (s->mb_type[xy] & type){    // RAL: "type" test added...
  1742.                 if(field_select_table==NULL || field_select_table[xy] == field_select){
  1743.                     if(   mv_table[xy][0] >=h_range || mv_table[xy][0] <-h_range
  1744.                        || mv_table[xy][1] >=v_range || mv_table[xy][1] <-v_range){
  1745.  
  1746.                         if(truncate){
  1747.                             if     (mv_table[xy][0] > h_range-1) mv_table[xy][0]=  h_range-1;
  1748.                             else if(mv_table[xy][0] < -h_range ) mv_table[xy][0]= -h_range;
  1749.                             if     (mv_table[xy][1] > v_range-1) mv_table[xy][1]=  v_range-1;
  1750.                             else if(mv_table[xy][1] < -v_range ) mv_table[xy][1]= -v_range;
  1751.                         }else{
  1752.                             s->mb_type[xy] &= ~type;
  1753.                             s->mb_type[xy] |= CANDIDATE_MB_TYPE_INTRA;
  1754.                             mv_table[xy][0]=
  1755.                             mv_table[xy][1]= 0;
  1756.                         }
  1757.                     }
  1758.                 }
  1759.             }
  1760.             xy++;
  1761.         }
  1762.     }
  1763. }
  1764.