diff mbox series

[FFmpeg-devel,1/6] avcodec/mpegvideo_motion: Move mspel/gmc motion to mpeg4videodec.c

Message ID AS8P250MB07442BB411A6556D803295C78F229@AS8P250MB0744.EURP250.PROD.OUTLOOK.COM
State Accepted
Commit ac8afdb9b5228e79ab5582f932434b0dc0bbd186
Headers show
Series [FFmpeg-devel,1/6] avcodec/mpegvideo_motion: Move mspel/gmc motion to mpeg4videodec.c | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Andreas Rheinhardt Oct. 12, 2022, 6:03 p.m. UTC
It is the only codec for which mcsel is ever set.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
---
 libavcodec/mpeg4videodec.c    | 168 ++++++++++++++++++++++++++++++++++
 libavcodec/mpeg4videodec.h    |   3 +
 libavcodec/mpegvideo_motion.c | 166 +--------------------------------
 3 files changed, 174 insertions(+), 163 deletions(-)

Comments

Andreas Rheinhardt Oct. 19, 2022, 12:24 p.m. UTC | #1
Andreas Rheinhardt:
> It is the only codec for which mcsel is ever set.
> 
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
> ---
>  libavcodec/mpeg4videodec.c    | 168 ++++++++++++++++++++++++++++++++++
>  libavcodec/mpeg4videodec.h    |   3 +
>  libavcodec/mpegvideo_motion.c | 166 +--------------------------------
>  3 files changed, 174 insertions(+), 163 deletions(-)
> 
> diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
> index 4dbf37afe5..58a8ac9027 100644
> --- a/libavcodec/mpeg4videodec.c
> +++ b/libavcodec/mpeg4videodec.c
> @@ -72,6 +72,174 @@ static const int mb_type_b_map[4] = {
>      MB_TYPE_L0      | MB_TYPE_16x16,
>  };
>  
> +static void gmc1_motion(MpegEncContext *s,
> +                        uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
> +                        uint8_t *const *ref_picture)
> +{
> +    const uint8_t *ptr;
> +    int src_x, src_y, motion_x, motion_y;
> +    ptrdiff_t offset, linesize, uvlinesize;
> +    int emu = 0;
> +
> +    motion_x   = s->sprite_offset[0][0];
> +    motion_y   = s->sprite_offset[0][1];
> +    src_x      = s->mb_x * 16 + (motion_x >> (s->sprite_warping_accuracy + 1));
> +    src_y      = s->mb_y * 16 + (motion_y >> (s->sprite_warping_accuracy + 1));
> +    motion_x *= 1 << (3 - s->sprite_warping_accuracy);
> +    motion_y *= 1 << (3 - s->sprite_warping_accuracy);
> +    src_x      = av_clip(src_x, -16, s->width);
> +    if (src_x == s->width)
> +        motion_x = 0;
> +    src_y = av_clip(src_y, -16, s->height);
> +    if (src_y == s->height)
> +        motion_y = 0;
> +
> +    linesize   = s->linesize;
> +    uvlinesize = s->uvlinesize;
> +
> +    ptr = ref_picture[0] + src_y * linesize + src_x;
> +
> +    if ((unsigned)src_x >= FFMAX(s->h_edge_pos - 17, 0) ||
> +        (unsigned)src_y >= FFMAX(s->v_edge_pos - 17, 0)) {
> +        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
> +                                 linesize, linesize,
> +                                 17, 17,
> +                                 src_x, src_y,
> +                                 s->h_edge_pos, s->v_edge_pos);
> +        ptr = s->sc.edge_emu_buffer;
> +    }
> +
> +    if ((motion_x | motion_y) & 7) {
> +        s->mdsp.gmc1(dest_y, ptr, linesize, 16,
> +                     motion_x & 15, motion_y & 15, 128 - s->no_rounding);
> +        s->mdsp.gmc1(dest_y + 8, ptr + 8, linesize, 16,
> +                     motion_x & 15, motion_y & 15, 128 - s->no_rounding);
> +    } else {
> +        int dxy;
> +
> +        dxy = ((motion_x >> 3) & 1) | ((motion_y >> 2) & 2);
> +        if (s->no_rounding) {
> +            s->hdsp.put_no_rnd_pixels_tab[0][dxy](dest_y, ptr, linesize, 16);
> +        } else {
> +            s->hdsp.put_pixels_tab[0][dxy](dest_y, ptr, linesize, 16);
> +        }
> +    }
> +
> +    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
> +        return;
> +
> +    motion_x   = s->sprite_offset[1][0];
> +    motion_y   = s->sprite_offset[1][1];
> +    src_x      = s->mb_x * 8 + (motion_x >> (s->sprite_warping_accuracy + 1));
> +    src_y      = s->mb_y * 8 + (motion_y >> (s->sprite_warping_accuracy + 1));
> +    motion_x  *= 1 << (3 - s->sprite_warping_accuracy);
> +    motion_y  *= 1 << (3 - s->sprite_warping_accuracy);
> +    src_x      = av_clip(src_x, -8, s->width >> 1);
> +    if (src_x == s->width >> 1)
> +        motion_x = 0;
> +    src_y = av_clip(src_y, -8, s->height >> 1);
> +    if (src_y == s->height >> 1)
> +        motion_y = 0;
> +
> +    offset = (src_y * uvlinesize) + src_x;
> +    ptr    = ref_picture[1] + offset;
> +    if ((unsigned)src_x >= FFMAX((s->h_edge_pos >> 1) - 9, 0) ||
> +        (unsigned)src_y >= FFMAX((s->v_edge_pos >> 1) - 9, 0)) {
> +        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
> +                                 uvlinesize, uvlinesize,
> +                                 9, 9,
> +                                 src_x, src_y,
> +                                 s->h_edge_pos >> 1, s->v_edge_pos >> 1);
> +        ptr = s->sc.edge_emu_buffer;
> +        emu = 1;
> +    }
> +    s->mdsp.gmc1(dest_cb, ptr, uvlinesize, 8,
> +                 motion_x & 15, motion_y & 15, 128 - s->no_rounding);
> +
> +    ptr = ref_picture[2] + offset;
> +    if (emu) {
> +        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
> +                                 uvlinesize, uvlinesize,
> +                                 9, 9,
> +                                 src_x, src_y,
> +                                 s->h_edge_pos >> 1, s->v_edge_pos >> 1);
> +        ptr = s->sc.edge_emu_buffer;
> +    }
> +    s->mdsp.gmc1(dest_cr, ptr, uvlinesize, 8,
> +                 motion_x & 15, motion_y & 15, 128 - s->no_rounding);
> +}
> +
> +static void gmc_motion(MpegEncContext *s,
> +                       uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
> +                       uint8_t *const *ref_picture)
> +{
> +    const uint8_t *ptr;
> +    int linesize, uvlinesize;
> +    const int a = s->sprite_warping_accuracy;
> +    int ox, oy;
> +
> +    linesize   = s->linesize;
> +    uvlinesize = s->uvlinesize;
> +
> +    ptr = ref_picture[0];
> +
> +    ox = s->sprite_offset[0][0] + s->sprite_delta[0][0] * s->mb_x * 16 +
> +         s->sprite_delta[0][1] * s->mb_y * 16;
> +    oy = s->sprite_offset[0][1] + s->sprite_delta[1][0] * s->mb_x * 16 +
> +         s->sprite_delta[1][1] * s->mb_y * 16;
> +
> +    s->mdsp.gmc(dest_y, ptr, linesize, 16,
> +                ox, oy,
> +                s->sprite_delta[0][0], s->sprite_delta[0][1],
> +                s->sprite_delta[1][0], s->sprite_delta[1][1],
> +                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
> +                s->h_edge_pos, s->v_edge_pos);
> +    s->mdsp.gmc(dest_y + 8, ptr, linesize, 16,
> +                ox + s->sprite_delta[0][0] * 8,
> +                oy + s->sprite_delta[1][0] * 8,
> +                s->sprite_delta[0][0], s->sprite_delta[0][1],
> +                s->sprite_delta[1][0], s->sprite_delta[1][1],
> +                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
> +                s->h_edge_pos, s->v_edge_pos);
> +
> +    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
> +        return;
> +
> +    ox = s->sprite_offset[1][0] + s->sprite_delta[0][0] * s->mb_x * 8 +
> +         s->sprite_delta[0][1] * s->mb_y * 8;
> +    oy = s->sprite_offset[1][1] + s->sprite_delta[1][0] * s->mb_x * 8 +
> +         s->sprite_delta[1][1] * s->mb_y * 8;
> +
> +    ptr = ref_picture[1];
> +    s->mdsp.gmc(dest_cb, ptr, uvlinesize, 8,
> +                ox, oy,
> +                s->sprite_delta[0][0], s->sprite_delta[0][1],
> +                s->sprite_delta[1][0], s->sprite_delta[1][1],
> +                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
> +                (s->h_edge_pos + 1) >> 1, (s->v_edge_pos + 1) >> 1);
> +
> +    ptr = ref_picture[2];
> +    s->mdsp.gmc(dest_cr, ptr, uvlinesize, 8,
> +                ox, oy,
> +                s->sprite_delta[0][0], s->sprite_delta[0][1],
> +                s->sprite_delta[1][0], s->sprite_delta[1][1],
> +                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
> +                (s->h_edge_pos + 1) >> 1, (s->v_edge_pos + 1) >> 1);
> +}
> +
> +void ff_mpeg4_mcsel_motion(MpegEncContext *s,
> +                           uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
> +                           uint8_t *const *ref_picture)
> +{
> +    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);
> +    }
> +}
> +
>  void ff_mpeg4_decode_studio(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb,
>                              uint8_t *dest_cr, int block_size, int uvlinesize,
>                              int dct_linesize, int dct_offset)
> diff --git a/libavcodec/mpeg4videodec.h b/libavcodec/mpeg4videodec.h
> index 65d846aed0..8d1e121b67 100644
> --- a/libavcodec/mpeg4videodec.h
> +++ b/libavcodec/mpeg4videodec.h
> @@ -87,6 +87,9 @@ int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb,
>  void ff_mpeg4_decode_studio(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb,
>                              uint8_t *dest_cr, int block_size, int uvlinesize,
>                              int dct_linesize, int dct_offset);
> +void ff_mpeg4_mcsel_motion(MpegEncContext *s,
> +                           uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
> +                           uint8_t *const *ref_picture);
>  int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx);
>  int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx);
>  int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx);
> diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c
> index fe3bfc4454..8922f5b1a5 100644
> --- a/libavcodec/mpegvideo_motion.c
> +++ b/libavcodec/mpegvideo_motion.c
> @@ -31,164 +31,10 @@
>  #include "h261.h"
>  #include "mpegutils.h"
>  #include "mpegvideo.h"
> +#include "mpeg4videodec.h"
>  #include "qpeldsp.h"
>  #include "wmv2.h"
>  
> -static void gmc1_motion(MpegEncContext *s,
> -                        uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
> -                        uint8_t *const *ref_picture)
> -{
> -    const uint8_t *ptr;
> -    int src_x, src_y, motion_x, motion_y;
> -    ptrdiff_t offset, linesize, uvlinesize;
> -    int emu = 0;
> -
> -    motion_x   = s->sprite_offset[0][0];
> -    motion_y   = s->sprite_offset[0][1];
> -    src_x      = s->mb_x * 16 + (motion_x >> (s->sprite_warping_accuracy + 1));
> -    src_y      = s->mb_y * 16 + (motion_y >> (s->sprite_warping_accuracy + 1));
> -    motion_x *= 1 << (3 - s->sprite_warping_accuracy);
> -    motion_y *= 1 << (3 - s->sprite_warping_accuracy);
> -    src_x      = av_clip(src_x, -16, s->width);
> -    if (src_x == s->width)
> -        motion_x = 0;
> -    src_y = av_clip(src_y, -16, s->height);
> -    if (src_y == s->height)
> -        motion_y = 0;
> -
> -    linesize   = s->linesize;
> -    uvlinesize = s->uvlinesize;
> -
> -    ptr = ref_picture[0] + src_y * linesize + src_x;
> -
> -    if ((unsigned)src_x >= FFMAX(s->h_edge_pos - 17, 0) ||
> -        (unsigned)src_y >= FFMAX(s->v_edge_pos - 17, 0)) {
> -        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
> -                                 linesize, linesize,
> -                                 17, 17,
> -                                 src_x, src_y,
> -                                 s->h_edge_pos, s->v_edge_pos);
> -        ptr = s->sc.edge_emu_buffer;
> -    }
> -
> -    if ((motion_x | motion_y) & 7) {
> -        s->mdsp.gmc1(dest_y, ptr, linesize, 16,
> -                     motion_x & 15, motion_y & 15, 128 - s->no_rounding);
> -        s->mdsp.gmc1(dest_y + 8, ptr + 8, linesize, 16,
> -                     motion_x & 15, motion_y & 15, 128 - s->no_rounding);
> -    } else {
> -        int dxy;
> -
> -        dxy = ((motion_x >> 3) & 1) | ((motion_y >> 2) & 2);
> -        if (s->no_rounding) {
> -            s->hdsp.put_no_rnd_pixels_tab[0][dxy](dest_y, ptr, linesize, 16);
> -        } else {
> -            s->hdsp.put_pixels_tab[0][dxy](dest_y, ptr, linesize, 16);
> -        }
> -    }
> -
> -    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
> -        return;
> -
> -    motion_x   = s->sprite_offset[1][0];
> -    motion_y   = s->sprite_offset[1][1];
> -    src_x      = s->mb_x * 8 + (motion_x >> (s->sprite_warping_accuracy + 1));
> -    src_y      = s->mb_y * 8 + (motion_y >> (s->sprite_warping_accuracy + 1));
> -    motion_x  *= 1 << (3 - s->sprite_warping_accuracy);
> -    motion_y  *= 1 << (3 - s->sprite_warping_accuracy);
> -    src_x      = av_clip(src_x, -8, s->width >> 1);
> -    if (src_x == s->width >> 1)
> -        motion_x = 0;
> -    src_y = av_clip(src_y, -8, s->height >> 1);
> -    if (src_y == s->height >> 1)
> -        motion_y = 0;
> -
> -    offset = (src_y * uvlinesize) + src_x;
> -    ptr    = ref_picture[1] + offset;
> -    if ((unsigned)src_x >= FFMAX((s->h_edge_pos >> 1) - 9, 0) ||
> -        (unsigned)src_y >= FFMAX((s->v_edge_pos >> 1) - 9, 0)) {
> -        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
> -                                 uvlinesize, uvlinesize,
> -                                 9, 9,
> -                                 src_x, src_y,
> -                                 s->h_edge_pos >> 1, s->v_edge_pos >> 1);
> -        ptr = s->sc.edge_emu_buffer;
> -        emu = 1;
> -    }
> -    s->mdsp.gmc1(dest_cb, ptr, uvlinesize, 8,
> -                 motion_x & 15, motion_y & 15, 128 - s->no_rounding);
> -
> -    ptr = ref_picture[2] + offset;
> -    if (emu) {
> -        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
> -                                 uvlinesize, uvlinesize,
> -                                 9, 9,
> -                                 src_x, src_y,
> -                                 s->h_edge_pos >> 1, s->v_edge_pos >> 1);
> -        ptr = s->sc.edge_emu_buffer;
> -    }
> -    s->mdsp.gmc1(dest_cr, ptr, uvlinesize, 8,
> -                 motion_x & 15, motion_y & 15, 128 - s->no_rounding);
> -}
> -
> -static void gmc_motion(MpegEncContext *s,
> -                       uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
> -                       uint8_t *const *ref_picture)
> -{
> -    const uint8_t *ptr;
> -    int linesize, uvlinesize;
> -    const int a = s->sprite_warping_accuracy;
> -    int ox, oy;
> -
> -    linesize   = s->linesize;
> -    uvlinesize = s->uvlinesize;
> -
> -    ptr = ref_picture[0];
> -
> -    ox = s->sprite_offset[0][0] + s->sprite_delta[0][0] * s->mb_x * 16 +
> -         s->sprite_delta[0][1] * s->mb_y * 16;
> -    oy = s->sprite_offset[0][1] + s->sprite_delta[1][0] * s->mb_x * 16 +
> -         s->sprite_delta[1][1] * s->mb_y * 16;
> -
> -    s->mdsp.gmc(dest_y, ptr, linesize, 16,
> -                ox, oy,
> -                s->sprite_delta[0][0], s->sprite_delta[0][1],
> -                s->sprite_delta[1][0], s->sprite_delta[1][1],
> -                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
> -                s->h_edge_pos, s->v_edge_pos);
> -    s->mdsp.gmc(dest_y + 8, ptr, linesize, 16,
> -                ox + s->sprite_delta[0][0] * 8,
> -                oy + s->sprite_delta[1][0] * 8,
> -                s->sprite_delta[0][0], s->sprite_delta[0][1],
> -                s->sprite_delta[1][0], s->sprite_delta[1][1],
> -                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
> -                s->h_edge_pos, s->v_edge_pos);
> -
> -    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
> -        return;
> -
> -    ox = s->sprite_offset[1][0] + s->sprite_delta[0][0] * s->mb_x * 8 +
> -         s->sprite_delta[0][1] * s->mb_y * 8;
> -    oy = s->sprite_offset[1][1] + s->sprite_delta[1][0] * s->mb_x * 8 +
> -         s->sprite_delta[1][1] * s->mb_y * 8;
> -
> -    ptr = ref_picture[1];
> -    s->mdsp.gmc(dest_cb, ptr, uvlinesize, 8,
> -                ox, oy,
> -                s->sprite_delta[0][0], s->sprite_delta[0][1],
> -                s->sprite_delta[1][0], s->sprite_delta[1][1],
> -                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
> -                (s->h_edge_pos + 1) >> 1, (s->v_edge_pos + 1) >> 1);
> -
> -    ptr = ref_picture[2];
> -    s->mdsp.gmc(dest_cr, ptr, uvlinesize, 8,
> -                ox, oy,
> -                s->sprite_delta[0][0], s->sprite_delta[0][1],
> -                s->sprite_delta[1][0], s->sprite_delta[1][1],
> -                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
> -                (s->h_edge_pos + 1) >> 1, (s->v_edge_pos + 1) >> 1);
> -}
> -
>  static inline int hpel_motion(MpegEncContext *s,
>                                uint8_t *dest, uint8_t *src,
>                                int src_x, int src_y,
> @@ -849,14 +695,8 @@ static av_always_inline void mpv_motion_internal(MpegEncContext *s,
>  
>      switch (s->mv_type) {
>      case MV_TYPE_16X16:
> -        if (!is_mpeg12 && 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);
> -            }
> +        if (CONFIG_MPEG4_DECODER && !is_mpeg12 && s->mcsel) {
> +            ff_mpeg4_mcsel_motion(s, dest_y, dest_cb, dest_cr, ref_picture);
>          } else if (!is_mpeg12 && s->quarter_sample) {
>              qpel_motion(s, dest_y, dest_cb, dest_cr,
>                          0, 0, 0,

Will apply this patchset tomorrow unless there are objections.

- Andreas
diff mbox series

Patch

diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 4dbf37afe5..58a8ac9027 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -72,6 +72,174 @@  static const int mb_type_b_map[4] = {
     MB_TYPE_L0      | MB_TYPE_16x16,
 };
 
+static void gmc1_motion(MpegEncContext *s,
+                        uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
+                        uint8_t *const *ref_picture)
+{
+    const uint8_t *ptr;
+    int src_x, src_y, motion_x, motion_y;
+    ptrdiff_t offset, linesize, uvlinesize;
+    int emu = 0;
+
+    motion_x   = s->sprite_offset[0][0];
+    motion_y   = s->sprite_offset[0][1];
+    src_x      = s->mb_x * 16 + (motion_x >> (s->sprite_warping_accuracy + 1));
+    src_y      = s->mb_y * 16 + (motion_y >> (s->sprite_warping_accuracy + 1));
+    motion_x *= 1 << (3 - s->sprite_warping_accuracy);
+    motion_y *= 1 << (3 - s->sprite_warping_accuracy);
+    src_x      = av_clip(src_x, -16, s->width);
+    if (src_x == s->width)
+        motion_x = 0;
+    src_y = av_clip(src_y, -16, s->height);
+    if (src_y == s->height)
+        motion_y = 0;
+
+    linesize   = s->linesize;
+    uvlinesize = s->uvlinesize;
+
+    ptr = ref_picture[0] + src_y * linesize + src_x;
+
+    if ((unsigned)src_x >= FFMAX(s->h_edge_pos - 17, 0) ||
+        (unsigned)src_y >= FFMAX(s->v_edge_pos - 17, 0)) {
+        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
+                                 linesize, linesize,
+                                 17, 17,
+                                 src_x, src_y,
+                                 s->h_edge_pos, s->v_edge_pos);
+        ptr = s->sc.edge_emu_buffer;
+    }
+
+    if ((motion_x | motion_y) & 7) {
+        s->mdsp.gmc1(dest_y, ptr, linesize, 16,
+                     motion_x & 15, motion_y & 15, 128 - s->no_rounding);
+        s->mdsp.gmc1(dest_y + 8, ptr + 8, linesize, 16,
+                     motion_x & 15, motion_y & 15, 128 - s->no_rounding);
+    } else {
+        int dxy;
+
+        dxy = ((motion_x >> 3) & 1) | ((motion_y >> 2) & 2);
+        if (s->no_rounding) {
+            s->hdsp.put_no_rnd_pixels_tab[0][dxy](dest_y, ptr, linesize, 16);
+        } else {
+            s->hdsp.put_pixels_tab[0][dxy](dest_y, ptr, linesize, 16);
+        }
+    }
+
+    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
+        return;
+
+    motion_x   = s->sprite_offset[1][0];
+    motion_y   = s->sprite_offset[1][1];
+    src_x      = s->mb_x * 8 + (motion_x >> (s->sprite_warping_accuracy + 1));
+    src_y      = s->mb_y * 8 + (motion_y >> (s->sprite_warping_accuracy + 1));
+    motion_x  *= 1 << (3 - s->sprite_warping_accuracy);
+    motion_y  *= 1 << (3 - s->sprite_warping_accuracy);
+    src_x      = av_clip(src_x, -8, s->width >> 1);
+    if (src_x == s->width >> 1)
+        motion_x = 0;
+    src_y = av_clip(src_y, -8, s->height >> 1);
+    if (src_y == s->height >> 1)
+        motion_y = 0;
+
+    offset = (src_y * uvlinesize) + src_x;
+    ptr    = ref_picture[1] + offset;
+    if ((unsigned)src_x >= FFMAX((s->h_edge_pos >> 1) - 9, 0) ||
+        (unsigned)src_y >= FFMAX((s->v_edge_pos >> 1) - 9, 0)) {
+        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
+                                 uvlinesize, uvlinesize,
+                                 9, 9,
+                                 src_x, src_y,
+                                 s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+        ptr = s->sc.edge_emu_buffer;
+        emu = 1;
+    }
+    s->mdsp.gmc1(dest_cb, ptr, uvlinesize, 8,
+                 motion_x & 15, motion_y & 15, 128 - s->no_rounding);
+
+    ptr = ref_picture[2] + offset;
+    if (emu) {
+        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
+                                 uvlinesize, uvlinesize,
+                                 9, 9,
+                                 src_x, src_y,
+                                 s->h_edge_pos >> 1, s->v_edge_pos >> 1);
+        ptr = s->sc.edge_emu_buffer;
+    }
+    s->mdsp.gmc1(dest_cr, ptr, uvlinesize, 8,
+                 motion_x & 15, motion_y & 15, 128 - s->no_rounding);
+}
+
+static void gmc_motion(MpegEncContext *s,
+                       uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
+                       uint8_t *const *ref_picture)
+{
+    const uint8_t *ptr;
+    int linesize, uvlinesize;
+    const int a = s->sprite_warping_accuracy;
+    int ox, oy;
+
+    linesize   = s->linesize;
+    uvlinesize = s->uvlinesize;
+
+    ptr = ref_picture[0];
+
+    ox = s->sprite_offset[0][0] + s->sprite_delta[0][0] * s->mb_x * 16 +
+         s->sprite_delta[0][1] * s->mb_y * 16;
+    oy = s->sprite_offset[0][1] + s->sprite_delta[1][0] * s->mb_x * 16 +
+         s->sprite_delta[1][1] * s->mb_y * 16;
+
+    s->mdsp.gmc(dest_y, ptr, linesize, 16,
+                ox, oy,
+                s->sprite_delta[0][0], s->sprite_delta[0][1],
+                s->sprite_delta[1][0], s->sprite_delta[1][1],
+                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
+                s->h_edge_pos, s->v_edge_pos);
+    s->mdsp.gmc(dest_y + 8, ptr, linesize, 16,
+                ox + s->sprite_delta[0][0] * 8,
+                oy + s->sprite_delta[1][0] * 8,
+                s->sprite_delta[0][0], s->sprite_delta[0][1],
+                s->sprite_delta[1][0], s->sprite_delta[1][1],
+                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
+                s->h_edge_pos, s->v_edge_pos);
+
+    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
+        return;
+
+    ox = s->sprite_offset[1][0] + s->sprite_delta[0][0] * s->mb_x * 8 +
+         s->sprite_delta[0][1] * s->mb_y * 8;
+    oy = s->sprite_offset[1][1] + s->sprite_delta[1][0] * s->mb_x * 8 +
+         s->sprite_delta[1][1] * s->mb_y * 8;
+
+    ptr = ref_picture[1];
+    s->mdsp.gmc(dest_cb, ptr, uvlinesize, 8,
+                ox, oy,
+                s->sprite_delta[0][0], s->sprite_delta[0][1],
+                s->sprite_delta[1][0], s->sprite_delta[1][1],
+                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
+                (s->h_edge_pos + 1) >> 1, (s->v_edge_pos + 1) >> 1);
+
+    ptr = ref_picture[2];
+    s->mdsp.gmc(dest_cr, ptr, uvlinesize, 8,
+                ox, oy,
+                s->sprite_delta[0][0], s->sprite_delta[0][1],
+                s->sprite_delta[1][0], s->sprite_delta[1][1],
+                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
+                (s->h_edge_pos + 1) >> 1, (s->v_edge_pos + 1) >> 1);
+}
+
+void ff_mpeg4_mcsel_motion(MpegEncContext *s,
+                           uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
+                           uint8_t *const *ref_picture)
+{
+    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);
+    }
+}
+
 void ff_mpeg4_decode_studio(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb,
                             uint8_t *dest_cr, int block_size, int uvlinesize,
                             int dct_linesize, int dct_offset)
diff --git a/libavcodec/mpeg4videodec.h b/libavcodec/mpeg4videodec.h
index 65d846aed0..8d1e121b67 100644
--- a/libavcodec/mpeg4videodec.h
+++ b/libavcodec/mpeg4videodec.h
@@ -87,6 +87,9 @@  int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb,
 void ff_mpeg4_decode_studio(MpegEncContext *s, uint8_t *dest_y, uint8_t *dest_cb,
                             uint8_t *dest_cr, int block_size, int uvlinesize,
                             int dct_linesize, int dct_offset);
+void ff_mpeg4_mcsel_motion(MpegEncContext *s,
+                           uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
+                           uint8_t *const *ref_picture);
 int ff_mpeg4_decode_partitions(Mpeg4DecContext *ctx);
 int ff_mpeg4_decode_video_packet_header(Mpeg4DecContext *ctx);
 int ff_mpeg4_decode_studio_slice_header(Mpeg4DecContext *ctx);
diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c
index fe3bfc4454..8922f5b1a5 100644
--- a/libavcodec/mpegvideo_motion.c
+++ b/libavcodec/mpegvideo_motion.c
@@ -31,164 +31,10 @@ 
 #include "h261.h"
 #include "mpegutils.h"
 #include "mpegvideo.h"
+#include "mpeg4videodec.h"
 #include "qpeldsp.h"
 #include "wmv2.h"
 
-static void gmc1_motion(MpegEncContext *s,
-                        uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
-                        uint8_t *const *ref_picture)
-{
-    const uint8_t *ptr;
-    int src_x, src_y, motion_x, motion_y;
-    ptrdiff_t offset, linesize, uvlinesize;
-    int emu = 0;
-
-    motion_x   = s->sprite_offset[0][0];
-    motion_y   = s->sprite_offset[0][1];
-    src_x      = s->mb_x * 16 + (motion_x >> (s->sprite_warping_accuracy + 1));
-    src_y      = s->mb_y * 16 + (motion_y >> (s->sprite_warping_accuracy + 1));
-    motion_x *= 1 << (3 - s->sprite_warping_accuracy);
-    motion_y *= 1 << (3 - s->sprite_warping_accuracy);
-    src_x      = av_clip(src_x, -16, s->width);
-    if (src_x == s->width)
-        motion_x = 0;
-    src_y = av_clip(src_y, -16, s->height);
-    if (src_y == s->height)
-        motion_y = 0;
-
-    linesize   = s->linesize;
-    uvlinesize = s->uvlinesize;
-
-    ptr = ref_picture[0] + src_y * linesize + src_x;
-
-    if ((unsigned)src_x >= FFMAX(s->h_edge_pos - 17, 0) ||
-        (unsigned)src_y >= FFMAX(s->v_edge_pos - 17, 0)) {
-        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
-                                 linesize, linesize,
-                                 17, 17,
-                                 src_x, src_y,
-                                 s->h_edge_pos, s->v_edge_pos);
-        ptr = s->sc.edge_emu_buffer;
-    }
-
-    if ((motion_x | motion_y) & 7) {
-        s->mdsp.gmc1(dest_y, ptr, linesize, 16,
-                     motion_x & 15, motion_y & 15, 128 - s->no_rounding);
-        s->mdsp.gmc1(dest_y + 8, ptr + 8, linesize, 16,
-                     motion_x & 15, motion_y & 15, 128 - s->no_rounding);
-    } else {
-        int dxy;
-
-        dxy = ((motion_x >> 3) & 1) | ((motion_y >> 2) & 2);
-        if (s->no_rounding) {
-            s->hdsp.put_no_rnd_pixels_tab[0][dxy](dest_y, ptr, linesize, 16);
-        } else {
-            s->hdsp.put_pixels_tab[0][dxy](dest_y, ptr, linesize, 16);
-        }
-    }
-
-    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
-        return;
-
-    motion_x   = s->sprite_offset[1][0];
-    motion_y   = s->sprite_offset[1][1];
-    src_x      = s->mb_x * 8 + (motion_x >> (s->sprite_warping_accuracy + 1));
-    src_y      = s->mb_y * 8 + (motion_y >> (s->sprite_warping_accuracy + 1));
-    motion_x  *= 1 << (3 - s->sprite_warping_accuracy);
-    motion_y  *= 1 << (3 - s->sprite_warping_accuracy);
-    src_x      = av_clip(src_x, -8, s->width >> 1);
-    if (src_x == s->width >> 1)
-        motion_x = 0;
-    src_y = av_clip(src_y, -8, s->height >> 1);
-    if (src_y == s->height >> 1)
-        motion_y = 0;
-
-    offset = (src_y * uvlinesize) + src_x;
-    ptr    = ref_picture[1] + offset;
-    if ((unsigned)src_x >= FFMAX((s->h_edge_pos >> 1) - 9, 0) ||
-        (unsigned)src_y >= FFMAX((s->v_edge_pos >> 1) - 9, 0)) {
-        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
-                                 uvlinesize, uvlinesize,
-                                 9, 9,
-                                 src_x, src_y,
-                                 s->h_edge_pos >> 1, s->v_edge_pos >> 1);
-        ptr = s->sc.edge_emu_buffer;
-        emu = 1;
-    }
-    s->mdsp.gmc1(dest_cb, ptr, uvlinesize, 8,
-                 motion_x & 15, motion_y & 15, 128 - s->no_rounding);
-
-    ptr = ref_picture[2] + offset;
-    if (emu) {
-        s->vdsp.emulated_edge_mc(s->sc.edge_emu_buffer, ptr,
-                                 uvlinesize, uvlinesize,
-                                 9, 9,
-                                 src_x, src_y,
-                                 s->h_edge_pos >> 1, s->v_edge_pos >> 1);
-        ptr = s->sc.edge_emu_buffer;
-    }
-    s->mdsp.gmc1(dest_cr, ptr, uvlinesize, 8,
-                 motion_x & 15, motion_y & 15, 128 - s->no_rounding);
-}
-
-static void gmc_motion(MpegEncContext *s,
-                       uint8_t *dest_y, uint8_t *dest_cb, uint8_t *dest_cr,
-                       uint8_t *const *ref_picture)
-{
-    const uint8_t *ptr;
-    int linesize, uvlinesize;
-    const int a = s->sprite_warping_accuracy;
-    int ox, oy;
-
-    linesize   = s->linesize;
-    uvlinesize = s->uvlinesize;
-
-    ptr = ref_picture[0];
-
-    ox = s->sprite_offset[0][0] + s->sprite_delta[0][0] * s->mb_x * 16 +
-         s->sprite_delta[0][1] * s->mb_y * 16;
-    oy = s->sprite_offset[0][1] + s->sprite_delta[1][0] * s->mb_x * 16 +
-         s->sprite_delta[1][1] * s->mb_y * 16;
-
-    s->mdsp.gmc(dest_y, ptr, linesize, 16,
-                ox, oy,
-                s->sprite_delta[0][0], s->sprite_delta[0][1],
-                s->sprite_delta[1][0], s->sprite_delta[1][1],
-                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
-                s->h_edge_pos, s->v_edge_pos);
-    s->mdsp.gmc(dest_y + 8, ptr, linesize, 16,
-                ox + s->sprite_delta[0][0] * 8,
-                oy + s->sprite_delta[1][0] * 8,
-                s->sprite_delta[0][0], s->sprite_delta[0][1],
-                s->sprite_delta[1][0], s->sprite_delta[1][1],
-                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
-                s->h_edge_pos, s->v_edge_pos);
-
-    if (CONFIG_GRAY && s->avctx->flags & AV_CODEC_FLAG_GRAY)
-        return;
-
-    ox = s->sprite_offset[1][0] + s->sprite_delta[0][0] * s->mb_x * 8 +
-         s->sprite_delta[0][1] * s->mb_y * 8;
-    oy = s->sprite_offset[1][1] + s->sprite_delta[1][0] * s->mb_x * 8 +
-         s->sprite_delta[1][1] * s->mb_y * 8;
-
-    ptr = ref_picture[1];
-    s->mdsp.gmc(dest_cb, ptr, uvlinesize, 8,
-                ox, oy,
-                s->sprite_delta[0][0], s->sprite_delta[0][1],
-                s->sprite_delta[1][0], s->sprite_delta[1][1],
-                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
-                (s->h_edge_pos + 1) >> 1, (s->v_edge_pos + 1) >> 1);
-
-    ptr = ref_picture[2];
-    s->mdsp.gmc(dest_cr, ptr, uvlinesize, 8,
-                ox, oy,
-                s->sprite_delta[0][0], s->sprite_delta[0][1],
-                s->sprite_delta[1][0], s->sprite_delta[1][1],
-                a + 1, (1 << (2 * a + 1)) - s->no_rounding,
-                (s->h_edge_pos + 1) >> 1, (s->v_edge_pos + 1) >> 1);
-}
-
 static inline int hpel_motion(MpegEncContext *s,
                               uint8_t *dest, uint8_t *src,
                               int src_x, int src_y,
@@ -849,14 +695,8 @@  static av_always_inline void mpv_motion_internal(MpegEncContext *s,
 
     switch (s->mv_type) {
     case MV_TYPE_16X16:
-        if (!is_mpeg12 && 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);
-            }
+        if (CONFIG_MPEG4_DECODER && !is_mpeg12 && s->mcsel) {
+            ff_mpeg4_mcsel_motion(s, dest_y, dest_cb, dest_cr, ref_picture);
         } else if (!is_mpeg12 && s->quarter_sample) {
             qpel_motion(s, dest_y, dest_cb, dest_cr,
                         0, 0, 0,