static av_always_inline int cmp(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
                      const int size, const int h, int ref_index, int src_index,
                      me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
    MotionEstContext * const c= &s->me;
    const int stride= c->stride;
    const int uvstride= c->uvstride;
    const int qpel= flags&FLAG_QPEL;
    const int chroma= flags&FLAG_CHROMA;
    const int dxy= subx + (suby<<(1+qpel));
    const int hx= subx + (x<<(1+qpel));
    const int hy= suby + (y<<(1+qpel));
    uint8_t * const * const ref= c->ref[ref_index];
    uint8_t * const * const src= c->src[src_index];
    int d;
    if(flags&FLAG_DIRECT){
        assert(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1));
        if(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1)){
            const int time_pp= s->pp_time;
            const int time_pb= s->pb_time;
            const int mask= 2*qpel+1;
            if(s->mv_type==MV_TYPE_8X8){
                int i;
                for(i=0; i<4; i++){
                    int fx = c->direct_basis_mv[i][0] + hx;
                    int fy = c->direct_basis_mv[i][1] + hy;
                    int bx = hx ? fx - c->co_located_mv[i][0] : c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(qpel+4));
                    int by = hy ? fy - c->co_located_mv[i][1] : c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(qpel+4));
                    int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));
                    int bxy= (bx&mask) + ((by&mask)<<(qpel+1));
                    uint8_t *dst= c->temp + 8*(i&1) + 8*stride*(i>>1);
                    if(qpel){
                        c->qpel_put[1][fxy](dst, ref[0] + (fx>>2) + (fy>>2)*stride, stride);
                        c->qpel_avg[1][bxy](dst, ref[8] + (bx>>2) + (by>>2)*stride, stride);
                    }else{
                        c->hpel_put[1][fxy](dst, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 8);
                        c->hpel_avg[1][bxy](dst, ref[8] + (bx>>1) + (by>>1)*stride, stride, 8);
                    }
                }
            }else{
                int fx = c->direct_basis_mv[0][0] + hx;
                int fy = c->direct_basis_mv[0][1] + hy;
                int bx = hx ? fx - c->co_located_mv[0][0] : (c->co_located_mv[0][0]*(time_pb - time_pp)/time_pp);
                int by = hy ? fy - c->co_located_mv[0][1] : (c->co_located_mv[0][1]*(time_pb - time_pp)/time_pp);
                int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));
                int bxy= (bx&mask) + ((by&mask)<<(qpel+1));
                if(qpel){
                    c->qpel_put[1][fxy](c->temp               , ref[0] + (fx>>2) + (fy>>2)*stride               , stride);
                    c->qpel_put[1][fxy](c->temp + 8           , ref[0] + (fx>>2) + (fy>>2)*stride + 8           , stride);
                    c->qpel_put[1][fxy](c->temp     + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride     + 8*stride, stride);
                    c->qpel_put[1][fxy](c->temp + 8 + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8 + 8*stride, stride);
                    c->qpel_avg[1][bxy](c->temp               , ref[8] + (bx>>2) + (by>>2)*stride               , stride);
                    c->qpel_avg[1][bxy](c->temp + 8           , ref[8] + (bx>>2) + (by>>2)*stride + 8           , stride);
                    c->qpel_avg[1][bxy](c->temp     + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride     + 8*stride, stride);
                    c->qpel_avg[1][bxy](c->temp + 8 + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8 + 8*stride, stride);
                }else{
                    assert((fx>>1) + 16*s->mb_x >= -16);
                    assert((fy>>1) + 16*s->mb_y >= -16);
                    assert((fx>>1) + 16*s->mb_x <= s->width);
                    assert((fy>>1) + 16*s->mb_y <= s->height);
                    assert((bx>>1) + 16*s->mb_x >= -16);
                    assert((by>>1) + 16*s->mb_y >= -16);
                    assert((bx>>1) + 16*s->mb_x <= s->width);
                    assert((by>>1) + 16*s->mb_y <= s->height);
                    c->hpel_put[0][fxy](c->temp, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 16);
                    c->hpel_avg[0][bxy](c->temp, ref[8] + (bx>>1) + (by>>1)*stride, stride, 16);
                }
            }
            d = cmp_func(s, c->temp, src[0], stride, 16);
        }else
            d= 256*256*256*32;
    }else{
        int uvdxy;
        if(dxy){
            if(qpel){
                c->qpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride);
                if(chroma){
                    int cx= hx/2;
                    int cy= hy/2;
                    cx= (cx>>1)|(cx&1);
                    cy= (cy>>1)|(cy&1);
                    uvdxy= (cx&1) + 2*(cy&1);
                }
            }else{
                c->hpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride, h);
                if(chroma)
                    uvdxy= dxy | (x&1) | (2*(y&1));
            }
            d = cmp_func(s, c->temp, src[0], stride, h);
        }else{
            d = cmp_func(s, src[0], ref[0] + x + y*stride, stride, h);
            if(chroma)
                uvdxy= (x&1) + 2*(y&1);
        }
        if(chroma){
            uint8_t * const uvtemp= c->temp + 16*stride;
            c->hpel_put[size+1][uvdxy](uvtemp  , ref[1] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);
            c->hpel_put[size+1][uvdxy](uvtemp+8, ref[2] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);
            d += chroma_cmp_func(s, uvtemp  , src[1], uvstride, h>>1);
            d += chroma_cmp_func(s, uvtemp+8, src[2], uvstride, h>>1);
        }
    }
#if 0
    if(full_pel){
        const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);
        score_map[index]= d;
    }
    d += (c->mv_penalty[hx - c->pred_x] + c->mv_penalty[hy - c->pred_y])*c->penalty_factor;
#endif
    return d;
}
['static inline int check_input_motion(MpegEncContext * s, int mb_x, int mb_y, int p_type){\n    MotionEstContext * const c= &s->me;\n    Picture *p= s->current_picture_ptr;\n    int mb_xy= mb_x + mb_y*s->mb_stride;\n    int xy= 2*mb_x + 2*mb_y*s->b8_stride;\n    int mb_type= s->current_picture.mb_type[mb_xy];\n    int flags= c->flags;\n    int shift= (flags&FLAG_QPEL) + 1;\n    int mask= (1<<shift)-1;\n    int x, y, i;\n    int d=0;\n    me_cmp_func cmpf= s->dsp.sse[0];\n    me_cmp_func chroma_cmpf= s->dsp.sse[1];\n    if(p_type && USES_LIST(mb_type, 1)){\n        av_log(c->avctx, AV_LOG_ERROR, "backward motion vector in P frame\\n");\n        return INT_MAX/2;\n    }\n    assert(IS_INTRA(mb_type) || USES_LIST(mb_type,0) || USES_LIST(mb_type,1));\n    for(i=0; i<4; i++){\n        int xy= s->block_index[i];\n        clip_input_mv(s, p->motion_val[0][xy], !!IS_INTERLACED(mb_type));\n        clip_input_mv(s, p->motion_val[1][xy], !!IS_INTERLACED(mb_type));\n    }\n    if(IS_INTERLACED(mb_type)){\n        int xy2= xy  + s->b8_stride;\n        s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTRA;\n        c->stride<<=1;\n        c->uvstride<<=1;\n        if(!(s->flags & CODEC_FLAG_INTERLACED_ME)){\n            av_log(c->avctx, AV_LOG_ERROR, "Interlaced macroblock selected but interlaced motion estimation disabled\\n");\n            return INT_MAX/2;\n        }\n        if(USES_LIST(mb_type, 0)){\n            int field_select0= p->ref_index[0][xy ];\n            int field_select1= p->ref_index[0][xy2];\n            assert(field_select0==0 ||field_select0==1);\n            assert(field_select1==0 ||field_select1==1);\n            init_interlaced_ref(s, 0);\n            if(p_type){\n                s->p_field_select_table[0][mb_xy]= field_select0;\n                s->p_field_select_table[1][mb_xy]= field_select1;\n                *(uint32_t*)s->p_field_mv_table[0][field_select0][mb_xy]= *(uint32_t*)p->motion_val[0][xy ];\n                *(uint32_t*)s->p_field_mv_table[1][field_select1][mb_xy]= *(uint32_t*)p->motion_val[0][xy2];\n                s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER_I;\n            }else{\n                s->b_field_select_table[0][0][mb_xy]= field_select0;\n                s->b_field_select_table[0][1][mb_xy]= field_select1;\n                *(uint32_t*)s->b_field_mv_table[0][0][field_select0][mb_xy]= *(uint32_t*)p->motion_val[0][xy ];\n                *(uint32_t*)s->b_field_mv_table[0][1][field_select1][mb_xy]= *(uint32_t*)p->motion_val[0][xy2];\n                s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_FORWARD_I;\n            }\n            x= p->motion_val[0][xy ][0];\n            y= p->motion_val[0][xy ][1];\n            d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select0, 0, cmpf, chroma_cmpf, flags);\n            x= p->motion_val[0][xy2][0];\n            y= p->motion_val[0][xy2][1];\n            d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select1, 1, cmpf, chroma_cmpf, flags);\n        }\n        if(USES_LIST(mb_type, 1)){\n            int field_select0= p->ref_index[1][xy ];\n            int field_select1= p->ref_index[1][xy2];\n            assert(field_select0==0 ||field_select0==1);\n            assert(field_select1==0 ||field_select1==1);\n            init_interlaced_ref(s, 2);\n            s->b_field_select_table[1][0][mb_xy]= field_select0;\n            s->b_field_select_table[1][1][mb_xy]= field_select1;\n            *(uint32_t*)s->b_field_mv_table[1][0][field_select0][mb_xy]= *(uint32_t*)p->motion_val[1][xy ];\n            *(uint32_t*)s->b_field_mv_table[1][1][field_select1][mb_xy]= *(uint32_t*)p->motion_val[1][xy2];\n            if(USES_LIST(mb_type, 0)){\n                s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_BIDIR_I;\n            }else{\n                s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_BACKWARD_I;\n            }\n            x= p->motion_val[1][xy ][0];\n            y= p->motion_val[1][xy ][1];\n            d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select0+2, 0, cmpf, chroma_cmpf, flags);\n            x= p->motion_val[1][xy2][0];\n            y= p->motion_val[1][xy2][1];\n            d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select1+2, 1, cmpf, chroma_cmpf, flags);\n        }\n        c->stride>>=1;\n        c->uvstride>>=1;\n    }else if(IS_8X8(mb_type)){\n        if(!(s->flags & CODEC_FLAG_4MV)){\n            av_log(c->avctx, AV_LOG_ERROR, "4MV macroblock selected but 4MV encoding disabled\\n");\n            return INT_MAX/2;\n        }\n        cmpf= s->dsp.sse[1];\n        chroma_cmpf= s->dsp.sse[1];\n        init_mv4_ref(c);\n        for(i=0; i<4; i++){\n            xy= s->block_index[i];\n            x= p->motion_val[0][xy][0];\n            y= p->motion_val[0][xy][1];\n            d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 1, 8, i, i, cmpf, chroma_cmpf, flags);\n        }\n        s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER4V;\n    }else{\n        if(USES_LIST(mb_type, 0)){\n            if(p_type){\n                *(uint32_t*)s->p_mv_table[mb_xy]= *(uint32_t*)p->motion_val[0][xy];\n                s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER;\n            }else if(USES_LIST(mb_type, 1)){\n                *(uint32_t*)s->b_bidir_forw_mv_table[mb_xy]= *(uint32_t*)p->motion_val[0][xy];\n                *(uint32_t*)s->b_bidir_back_mv_table[mb_xy]= *(uint32_t*)p->motion_val[1][xy];\n                s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_BIDIR;\n            }else{\n                *(uint32_t*)s->b_forw_mv_table[mb_xy]= *(uint32_t*)p->motion_val[0][xy];\n                s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_FORWARD;\n            }\n            x= p->motion_val[0][xy][0];\n            y= p->motion_val[0][xy][1];\n            d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 16, 0, 0, cmpf, chroma_cmpf, flags);\n        }else if(USES_LIST(mb_type, 1)){\n            *(uint32_t*)s->b_back_mv_table[mb_xy]= *(uint32_t*)p->motion_val[1][xy];\n            s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_BACKWARD;\n            x= p->motion_val[1][xy][0];\n            y= p->motion_val[1][xy][1];\n            d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 16, 2, 0, cmpf, chroma_cmpf, flags);\n        }else\n            s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTRA;\n    }\n    return d;\n}', 'static av_always_inline int cmp(MpegEncContext *s, const int x, const int y, const int subx, const int suby,\n                      const int size, const int h, int ref_index, int src_index,\n                      me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){\n    MotionEstContext * const c= &s->me;\n    const int stride= c->stride;\n    const int uvstride= c->uvstride;\n    const int qpel= flags&FLAG_QPEL;\n    const int chroma= flags&FLAG_CHROMA;\n    const int dxy= subx + (suby<<(1+qpel));\n    const int hx= subx + (x<<(1+qpel));\n    const int hy= suby + (y<<(1+qpel));\n    uint8_t * const * const ref= c->ref[ref_index];\n    uint8_t * const * const src= c->src[src_index];\n    int d;\n    if(flags&FLAG_DIRECT){\n        assert(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1));\n        if(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1)){\n            const int time_pp= s->pp_time;\n            const int time_pb= s->pb_time;\n            const int mask= 2*qpel+1;\n            if(s->mv_type==MV_TYPE_8X8){\n                int i;\n                for(i=0; i<4; i++){\n                    int fx = c->direct_basis_mv[i][0] + hx;\n                    int fy = c->direct_basis_mv[i][1] + hy;\n                    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));\n                    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));\n                    int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));\n                    int bxy= (bx&mask) + ((by&mask)<<(qpel+1));\n                    uint8_t *dst= c->temp + 8*(i&1) + 8*stride*(i>>1);\n                    if(qpel){\n                        c->qpel_put[1][fxy](dst, ref[0] + (fx>>2) + (fy>>2)*stride, stride);\n                        c->qpel_avg[1][bxy](dst, ref[8] + (bx>>2) + (by>>2)*stride, stride);\n                    }else{\n                        c->hpel_put[1][fxy](dst, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 8);\n                        c->hpel_avg[1][bxy](dst, ref[8] + (bx>>1) + (by>>1)*stride, stride, 8);\n                    }\n                }\n            }else{\n                int fx = c->direct_basis_mv[0][0] + hx;\n                int fy = c->direct_basis_mv[0][1] + hy;\n                int bx = hx ? fx - c->co_located_mv[0][0] : (c->co_located_mv[0][0]*(time_pb - time_pp)/time_pp);\n                int by = hy ? fy - c->co_located_mv[0][1] : (c->co_located_mv[0][1]*(time_pb - time_pp)/time_pp);\n                int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));\n                int bxy= (bx&mask) + ((by&mask)<<(qpel+1));\n                if(qpel){\n                    c->qpel_put[1][fxy](c->temp               , ref[0] + (fx>>2) + (fy>>2)*stride               , stride);\n                    c->qpel_put[1][fxy](c->temp + 8           , ref[0] + (fx>>2) + (fy>>2)*stride + 8           , stride);\n                    c->qpel_put[1][fxy](c->temp     + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride     + 8*stride, stride);\n                    c->qpel_put[1][fxy](c->temp + 8 + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8 + 8*stride, stride);\n                    c->qpel_avg[1][bxy](c->temp               , ref[8] + (bx>>2) + (by>>2)*stride               , stride);\n                    c->qpel_avg[1][bxy](c->temp + 8           , ref[8] + (bx>>2) + (by>>2)*stride + 8           , stride);\n                    c->qpel_avg[1][bxy](c->temp     + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride     + 8*stride, stride);\n                    c->qpel_avg[1][bxy](c->temp + 8 + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8 + 8*stride, stride);\n                }else{\n                    assert((fx>>1) + 16*s->mb_x >= -16);\n                    assert((fy>>1) + 16*s->mb_y >= -16);\n                    assert((fx>>1) + 16*s->mb_x <= s->width);\n                    assert((fy>>1) + 16*s->mb_y <= s->height);\n                    assert((bx>>1) + 16*s->mb_x >= -16);\n                    assert((by>>1) + 16*s->mb_y >= -16);\n                    assert((bx>>1) + 16*s->mb_x <= s->width);\n                    assert((by>>1) + 16*s->mb_y <= s->height);\n                    c->hpel_put[0][fxy](c->temp, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 16);\n                    c->hpel_avg[0][bxy](c->temp, ref[8] + (bx>>1) + (by>>1)*stride, stride, 16);\n                }\n            }\n            d = cmp_func(s, c->temp, src[0], stride, 16);\n        }else\n            d= 256*256*256*32;\n    }else{\n        int uvdxy;\n        if(dxy){\n            if(qpel){\n                c->qpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride);\n                if(chroma){\n                    int cx= hx/2;\n                    int cy= hy/2;\n                    cx= (cx>>1)|(cx&1);\n                    cy= (cy>>1)|(cy&1);\n                    uvdxy= (cx&1) + 2*(cy&1);\n                }\n            }else{\n                c->hpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride, h);\n                if(chroma)\n                    uvdxy= dxy | (x&1) | (2*(y&1));\n            }\n            d = cmp_func(s, c->temp, src[0], stride, h);\n        }else{\n            d = cmp_func(s, src[0], ref[0] + x + y*stride, stride, h);\n            if(chroma)\n                uvdxy= (x&1) + 2*(y&1);\n        }\n        if(chroma){\n            uint8_t * const uvtemp= c->temp + 16*stride;\n            c->hpel_put[size+1][uvdxy](uvtemp  , ref[1] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);\n            c->hpel_put[size+1][uvdxy](uvtemp+8, ref[2] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);\n            d += chroma_cmp_func(s, uvtemp  , src[1], uvstride, h>>1);\n            d += chroma_cmp_func(s, uvtemp+8, src[2], uvstride, h>>1);\n        }\n    }\n#if 0\n    if(full_pel){\n        const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\n        score_map[index]= d;\n    }\n    d += (c->mv_penalty[hx - c->pred_x] + c->mv_penalty[hy - c->pred_y])*c->penalty_factor;\n#endif\n    return d;\n}']