static inline void MPV_motion(MpegEncContext *s,
                              uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
                              int dir, uint8_t **ref_picture,
                              op_pixels_func (*pix_op)[4], qpel_mc_func (*qpix_op)[16])
{
    int dxy, mx, my, src_x, src_y, motion_x, motion_y;
    int mb_x, mb_y, i;
    uint8_t *ptr, *dest;
    mb_x = s->mb_x;
    mb_y = s->mb_y;
    prefetch_motion(s, ref_picture, dir);
    if(s->obmc && s->pict_type != FF_B_TYPE){
        int16_t mv_cache[4][4][2];
        const int xy= s->mb_x + s->mb_y*s->mb_stride;
        const int mot_stride= s->b8_stride;
        const int mot_xy= mb_x*2 + mb_y*2*mot_stride;
        assert(!s->mb_skipped);
        memcpy(mv_cache[1][1], s->current_picture.motion_val[0][mot_xy           ], sizeof(int16_t)*4);
        memcpy(mv_cache[2][1], s->current_picture.motion_val[0][mot_xy+mot_stride], sizeof(int16_t)*4);
        memcpy(mv_cache[3][1], s->current_picture.motion_val[0][mot_xy+mot_stride], sizeof(int16_t)*4);
        if(mb_y==0 || IS_INTRA(s->current_picture.mb_type[xy-s->mb_stride])){
            memcpy(mv_cache[0][1], mv_cache[1][1], sizeof(int16_t)*4);
        }else{
            memcpy(mv_cache[0][1], s->current_picture.motion_val[0][mot_xy-mot_stride], sizeof(int16_t)*4);
        }
        if(mb_x==0 || IS_INTRA(s->current_picture.mb_type[xy-1])){
            *(int32_t*)mv_cache[1][0]= *(int32_t*)mv_cache[1][1];
            *(int32_t*)mv_cache[2][0]= *(int32_t*)mv_cache[2][1];
        }else{
            *(int32_t*)mv_cache[1][0]= *(int32_t*)s->current_picture.motion_val[0][mot_xy-1];
            *(int32_t*)mv_cache[2][0]= *(int32_t*)s->current_picture.motion_val[0][mot_xy-1+mot_stride];
        }
        if(mb_x+1>=s->mb_width || IS_INTRA(s->current_picture.mb_type[xy+1])){
            *(int32_t*)mv_cache[1][3]= *(int32_t*)mv_cache[1][2];
            *(int32_t*)mv_cache[2][3]= *(int32_t*)mv_cache[2][2];
        }else{
            *(int32_t*)mv_cache[1][3]= *(int32_t*)s->current_picture.motion_val[0][mot_xy+2];
            *(int32_t*)mv_cache[2][3]= *(int32_t*)s->current_picture.motion_val[0][mot_xy+2+mot_stride];
        }
        mx = 0;
        my = 0;
        for(i=0;i<4;i++) {
            const int x= (i&1)+1;
            const int y= (i>>1)+1;
            int16_t mv[5][2]= {
                {mv_cache[y][x  ][0], mv_cache[y][x  ][1]},
                {mv_cache[y-1][x][0], mv_cache[y-1][x][1]},
                {mv_cache[y][x-1][0], mv_cache[y][x-1][1]},
                {mv_cache[y][x+1][0], mv_cache[y][x+1][1]},
                {mv_cache[y+1][x][0], mv_cache[y+1][x][1]}};
            obmc_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize,
                        ref_picture[0],
                        mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8,
                        pix_op[1],
                        mv);
            mx += mv[0][0];
            my += mv[0][1];
        }
        if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY))
            chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my);
        return;
    }
    switch(s->mv_type) {
    case MV_TYPE_16X16:
        if(s->mcsel){
            if(s->real_sprite_warping_points==1){
                gmc1_motion(s, dest_y, dest_cb, dest_cr,
                            ref_picture);
            }else{
                gmc_motion(s, dest_y, dest_cb, dest_cr,
                            ref_picture);
            }
        }else if(s->quarter_sample){
            qpel_motion(s, dest_y, dest_cb, dest_cr,
                        0, 0, 0,
                        ref_picture, pix_op, qpix_op,
                        s->mv[dir][0][0], s->mv[dir][0][1], 16);
        }else if(ENABLE_WMV2 && s->mspel){
            ff_mspel_motion(s, dest_y, dest_cb, dest_cr,
                        ref_picture, pix_op,
                        s->mv[dir][0][0], s->mv[dir][0][1], 16);
        }else
        {
            mpeg_motion(s, dest_y, dest_cb, dest_cr,
                        0, 0, 0,
                        ref_picture, pix_op,
                        s->mv[dir][0][0], s->mv[dir][0][1], 16);
        }
        break;
    case MV_TYPE_8X8:
        mx = 0;
        my = 0;
        if(s->quarter_sample){
            for(i=0;i<4;i++) {
                motion_x = s->mv[dir][i][0];
                motion_y = s->mv[dir][i][1];
                dxy = ((motion_y & 3) << 2) | (motion_x & 3);
                src_x = mb_x * 16 + (motion_x >> 2) + (i & 1) * 8;
                src_y = mb_y * 16 + (motion_y >> 2) + (i >>1) * 8;
                src_x = av_clip(src_x, -16, s->width);
                if (src_x == s->width)
                    dxy &= ~3;
                src_y = av_clip(src_y, -16, s->height);
                if (src_y == s->height)
                    dxy &= ~12;
                ptr = ref_picture[0] + (src_y * s->linesize) + (src_x);
                if(s->flags&CODEC_FLAG_EMU_EDGE){
                    if(   (unsigned)src_x > s->h_edge_pos - (motion_x&3) - 8
                       || (unsigned)src_y > s->v_edge_pos - (motion_y&3) - 8 ){
                        ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->linesize, 9, 9, src_x, src_y, s->h_edge_pos, s->v_edge_pos);
                        ptr= s->edge_emu_buffer;
                    }
                }
                dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize;
                qpix_op[1][dxy](dest, ptr, s->linesize);
                mx += s->mv[dir][i][0]/2;
                my += s->mv[dir][i][1]/2;
            }
        }else{
            for(i=0;i<4;i++) {
                hpel_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize,
                            ref_picture[0], 0, 0,
                            mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8,
                            s->width, s->height, s->linesize,
                            s->h_edge_pos, s->v_edge_pos,
                            8, 8, pix_op[1],
                            s->mv[dir][i][0], s->mv[dir][i][1]);
                mx += s->mv[dir][i][0];
                my += s->mv[dir][i][1];
            }
        }
        if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY))
            chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my);
        break;
    case MV_TYPE_FIELD:
        if (s->picture_structure == PICT_FRAME) {
            if(s->quarter_sample){
                for(i=0; i<2; i++){
                    qpel_motion(s, dest_y, dest_cb, dest_cr,
                                1, i, s->field_select[dir][i],
                                ref_picture, pix_op, qpix_op,
                                s->mv[dir][i][0], s->mv[dir][i][1], 8);
                }
            }else{
                mpeg_motion(s, dest_y, dest_cb, dest_cr,
                            1, 0, s->field_select[dir][0],
                            ref_picture, pix_op,
                            s->mv[dir][0][0], s->mv[dir][0][1], 8);
                mpeg_motion(s, dest_y, dest_cb, dest_cr,
                            1, 1, s->field_select[dir][1],
                            ref_picture, pix_op,
                            s->mv[dir][1][0], s->mv[dir][1][1], 8);
            }
        } else {
            if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != FF_B_TYPE && !s->first_field){
                ref_picture= s->current_picture_ptr->data;
            }
            mpeg_motion(s, dest_y, dest_cb, dest_cr,
                        0, 0, s->field_select[dir][0],
                        ref_picture, pix_op,
                        s->mv[dir][0][0], s->mv[dir][0][1], 16);
        }
        break;
    case MV_TYPE_16X8:
        for(i=0; i<2; i++){
            uint8_t ** ref2picture;
            if(s->picture_structure == s->field_select[dir][i] + 1 || s->pict_type == FF_B_TYPE || s->first_field){
                ref2picture= ref_picture;
            }else{
                ref2picture= s->current_picture_ptr->data;
            }
            mpeg_motion(s, dest_y, dest_cb, dest_cr,
                        0, 0, s->field_select[dir][i],
                        ref2picture, pix_op,
                        s->mv[dir][i][0], s->mv[dir][i][1] + 16*i, 8);
            dest_y += 16*s->linesize;
            dest_cb+= (16>>s->chroma_y_shift)*s->uvlinesize;
            dest_cr+= (16>>s->chroma_y_shift)*s->uvlinesize;
        }
        break;
    case MV_TYPE_DMV:
        if(s->picture_structure == PICT_FRAME){
            for(i=0; i<2; i++){
                int j;
                for(j=0; j<2; j++){
                    mpeg_motion(s, dest_y, dest_cb, dest_cr,
                                1, j, j^i,
                                ref_picture, pix_op,
                                s->mv[dir][2*i + j][0], s->mv[dir][2*i + j][1], 8);
                }
                pix_op = s->dsp.avg_pixels_tab;
            }
        }else{
            for(i=0; i<2; i++){
                mpeg_motion(s, dest_y, dest_cb, dest_cr,
                            0, 0, s->picture_structure != i+1,
                            ref_picture, pix_op,
                            s->mv[dir][2*i][0],s->mv[dir][2*i][1],16);
                pix_op=s->dsp.avg_pixels_tab;
                if(!s->first_field){
                    ref_picture = s->current_picture_ptr->data;
                }
            }
        }
    break;
    default: assert(0);
    }
}
['static inline void MPV_motion(MpegEncContext *s,\n                              uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,\n                              int dir, uint8_t **ref_picture,\n                              op_pixels_func (*pix_op)[4], qpel_mc_func (*qpix_op)[16])\n{\n    int dxy, mx, my, src_x, src_y, motion_x, motion_y;\n    int mb_x, mb_y, i;\n    uint8_t *ptr, *dest;\n    mb_x = s->mb_x;\n    mb_y = s->mb_y;\n    prefetch_motion(s, ref_picture, dir);\n    if(s->obmc && s->pict_type != FF_B_TYPE){\n        int16_t mv_cache[4][4][2];\n        const int xy= s->mb_x + s->mb_y*s->mb_stride;\n        const int mot_stride= s->b8_stride;\n        const int mot_xy= mb_x*2 + mb_y*2*mot_stride;\n        assert(!s->mb_skipped);\n        memcpy(mv_cache[1][1], s->current_picture.motion_val[0][mot_xy           ], sizeof(int16_t)*4);\n        memcpy(mv_cache[2][1], s->current_picture.motion_val[0][mot_xy+mot_stride], sizeof(int16_t)*4);\n        memcpy(mv_cache[3][1], s->current_picture.motion_val[0][mot_xy+mot_stride], sizeof(int16_t)*4);\n        if(mb_y==0 || IS_INTRA(s->current_picture.mb_type[xy-s->mb_stride])){\n            memcpy(mv_cache[0][1], mv_cache[1][1], sizeof(int16_t)*4);\n        }else{\n            memcpy(mv_cache[0][1], s->current_picture.motion_val[0][mot_xy-mot_stride], sizeof(int16_t)*4);\n        }\n        if(mb_x==0 || IS_INTRA(s->current_picture.mb_type[xy-1])){\n            *(int32_t*)mv_cache[1][0]= *(int32_t*)mv_cache[1][1];\n            *(int32_t*)mv_cache[2][0]= *(int32_t*)mv_cache[2][1];\n        }else{\n            *(int32_t*)mv_cache[1][0]= *(int32_t*)s->current_picture.motion_val[0][mot_xy-1];\n            *(int32_t*)mv_cache[2][0]= *(int32_t*)s->current_picture.motion_val[0][mot_xy-1+mot_stride];\n        }\n        if(mb_x+1>=s->mb_width || IS_INTRA(s->current_picture.mb_type[xy+1])){\n            *(int32_t*)mv_cache[1][3]= *(int32_t*)mv_cache[1][2];\n            *(int32_t*)mv_cache[2][3]= *(int32_t*)mv_cache[2][2];\n        }else{\n            *(int32_t*)mv_cache[1][3]= *(int32_t*)s->current_picture.motion_val[0][mot_xy+2];\n            *(int32_t*)mv_cache[2][3]= *(int32_t*)s->current_picture.motion_val[0][mot_xy+2+mot_stride];\n        }\n        mx = 0;\n        my = 0;\n        for(i=0;i<4;i++) {\n            const int x= (i&1)+1;\n            const int y= (i>>1)+1;\n            int16_t mv[5][2]= {\n                {mv_cache[y][x  ][0], mv_cache[y][x  ][1]},\n                {mv_cache[y-1][x][0], mv_cache[y-1][x][1]},\n                {mv_cache[y][x-1][0], mv_cache[y][x-1][1]},\n                {mv_cache[y][x+1][0], mv_cache[y][x+1][1]},\n                {mv_cache[y+1][x][0], mv_cache[y+1][x][1]}};\n            obmc_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize,\n                        ref_picture[0],\n                        mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8,\n                        pix_op[1],\n                        mv);\n            mx += mv[0][0];\n            my += mv[0][1];\n        }\n        if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY))\n            chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my);\n        return;\n    }\n    switch(s->mv_type) {\n    case MV_TYPE_16X16:\n        if(s->mcsel){\n            if(s->real_sprite_warping_points==1){\n                gmc1_motion(s, dest_y, dest_cb, dest_cr,\n                            ref_picture);\n            }else{\n                gmc_motion(s, dest_y, dest_cb, dest_cr,\n                            ref_picture);\n            }\n        }else if(s->quarter_sample){\n            qpel_motion(s, dest_y, dest_cb, dest_cr,\n                        0, 0, 0,\n                        ref_picture, pix_op, qpix_op,\n                        s->mv[dir][0][0], s->mv[dir][0][1], 16);\n        }else if(ENABLE_WMV2 && s->mspel){\n            ff_mspel_motion(s, dest_y, dest_cb, dest_cr,\n                        ref_picture, pix_op,\n                        s->mv[dir][0][0], s->mv[dir][0][1], 16);\n        }else\n        {\n            mpeg_motion(s, dest_y, dest_cb, dest_cr,\n                        0, 0, 0,\n                        ref_picture, pix_op,\n                        s->mv[dir][0][0], s->mv[dir][0][1], 16);\n        }\n        break;\n    case MV_TYPE_8X8:\n        mx = 0;\n        my = 0;\n        if(s->quarter_sample){\n            for(i=0;i<4;i++) {\n                motion_x = s->mv[dir][i][0];\n                motion_y = s->mv[dir][i][1];\n                dxy = ((motion_y & 3) << 2) | (motion_x & 3);\n                src_x = mb_x * 16 + (motion_x >> 2) + (i & 1) * 8;\n                src_y = mb_y * 16 + (motion_y >> 2) + (i >>1) * 8;\n                src_x = av_clip(src_x, -16, s->width);\n                if (src_x == s->width)\n                    dxy &= ~3;\n                src_y = av_clip(src_y, -16, s->height);\n                if (src_y == s->height)\n                    dxy &= ~12;\n                ptr = ref_picture[0] + (src_y * s->linesize) + (src_x);\n                if(s->flags&CODEC_FLAG_EMU_EDGE){\n                    if(   (unsigned)src_x > s->h_edge_pos - (motion_x&3) - 8\n                       || (unsigned)src_y > s->v_edge_pos - (motion_y&3) - 8 ){\n                        ff_emulated_edge_mc(s->edge_emu_buffer, ptr, s->linesize, 9, 9, src_x, src_y, s->h_edge_pos, s->v_edge_pos);\n                        ptr= s->edge_emu_buffer;\n                    }\n                }\n                dest = dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize;\n                qpix_op[1][dxy](dest, ptr, s->linesize);\n                mx += s->mv[dir][i][0]/2;\n                my += s->mv[dir][i][1]/2;\n            }\n        }else{\n            for(i=0;i<4;i++) {\n                hpel_motion(s, dest_y + ((i & 1) * 8) + (i >> 1) * 8 * s->linesize,\n                            ref_picture[0], 0, 0,\n                            mb_x * 16 + (i & 1) * 8, mb_y * 16 + (i >>1) * 8,\n                            s->width, s->height, s->linesize,\n                            s->h_edge_pos, s->v_edge_pos,\n                            8, 8, pix_op[1],\n                            s->mv[dir][i][0], s->mv[dir][i][1]);\n                mx += s->mv[dir][i][0];\n                my += s->mv[dir][i][1];\n            }\n        }\n        if(!ENABLE_GRAY || !(s->flags&CODEC_FLAG_GRAY))\n            chroma_4mv_motion(s, dest_cb, dest_cr, ref_picture, pix_op[1], mx, my);\n        break;\n    case MV_TYPE_FIELD:\n        if (s->picture_structure == PICT_FRAME) {\n            if(s->quarter_sample){\n                for(i=0; i<2; i++){\n                    qpel_motion(s, dest_y, dest_cb, dest_cr,\n                                1, i, s->field_select[dir][i],\n                                ref_picture, pix_op, qpix_op,\n                                s->mv[dir][i][0], s->mv[dir][i][1], 8);\n                }\n            }else{\n                mpeg_motion(s, dest_y, dest_cb, dest_cr,\n                            1, 0, s->field_select[dir][0],\n                            ref_picture, pix_op,\n                            s->mv[dir][0][0], s->mv[dir][0][1], 8);\n                mpeg_motion(s, dest_y, dest_cb, dest_cr,\n                            1, 1, s->field_select[dir][1],\n                            ref_picture, pix_op,\n                            s->mv[dir][1][0], s->mv[dir][1][1], 8);\n            }\n        } else {\n            if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != FF_B_TYPE && !s->first_field){\n                ref_picture= s->current_picture_ptr->data;\n            }\n            mpeg_motion(s, dest_y, dest_cb, dest_cr,\n                        0, 0, s->field_select[dir][0],\n                        ref_picture, pix_op,\n                        s->mv[dir][0][0], s->mv[dir][0][1], 16);\n        }\n        break;\n    case MV_TYPE_16X8:\n        for(i=0; i<2; i++){\n            uint8_t ** ref2picture;\n            if(s->picture_structure == s->field_select[dir][i] + 1 || s->pict_type == FF_B_TYPE || s->first_field){\n                ref2picture= ref_picture;\n            }else{\n                ref2picture= s->current_picture_ptr->data;\n            }\n            mpeg_motion(s, dest_y, dest_cb, dest_cr,\n                        0, 0, s->field_select[dir][i],\n                        ref2picture, pix_op,\n                        s->mv[dir][i][0], s->mv[dir][i][1] + 16*i, 8);\n            dest_y += 16*s->linesize;\n            dest_cb+= (16>>s->chroma_y_shift)*s->uvlinesize;\n            dest_cr+= (16>>s->chroma_y_shift)*s->uvlinesize;\n        }\n        break;\n    case MV_TYPE_DMV:\n        if(s->picture_structure == PICT_FRAME){\n            for(i=0; i<2; i++){\n                int j;\n                for(j=0; j<2; j++){\n                    mpeg_motion(s, dest_y, dest_cb, dest_cr,\n                                1, j, j^i,\n                                ref_picture, pix_op,\n                                s->mv[dir][2*i + j][0], s->mv[dir][2*i + j][1], 8);\n                }\n                pix_op = s->dsp.avg_pixels_tab;\n            }\n        }else{\n            for(i=0; i<2; i++){\n                mpeg_motion(s, dest_y, dest_cb, dest_cr,\n                            0, 0, s->picture_structure != i+1,\n                            ref_picture, pix_op,\n                            s->mv[dir][2*i][0],s->mv[dir][2*i][1],16);\n                pix_op=s->dsp.avg_pixels_tab;\n                if(!s->first_field){\n                    ref_picture = s->current_picture_ptr->data;\n                }\n            }\n        }\n    break;\n    default: assert(0);\n    }\n}']