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