diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 6fe05eec1f750e16505b3bf8627ee35c08a235df..24fa453672b87694b1c6f43dc87a1910bd01f425 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -324,6 +324,7 @@ OBJS-$(CONFIG_MPEG1VIDEO_DECODER)      += mpeg12dec.o mpeg12.o mpeg12data.o
 OBJS-$(CONFIG_MPEG1VIDEO_ENCODER)      += mpeg12enc.o mpeg12.o
 OBJS-$(CONFIG_MPEG2VIDEO_DECODER)      += mpeg12dec.o mpeg12.o mpeg12data.o
 OBJS-$(CONFIG_MPEG2VIDEO_ENCODER)      += mpeg12enc.o mpeg12.o
+OBJS-$(CONFIG_MPEG4_DECODER)           += xvididct.o
 OBJS-$(CONFIG_MPL2_DECODER)            += mpl2dec.o ass.o
 OBJS-$(CONFIG_MSMPEG4V1_DECODER)       += msmpeg4dec.o msmpeg4.o msmpeg4data.o
 OBJS-$(CONFIG_MSMPEG4V2_DECODER)       += msmpeg4dec.o msmpeg4.o msmpeg4data.o
diff --git a/libavcodec/idctdsp.c b/libavcodec/idctdsp.c
index e91ba2e6c80db5252fa387112aaa617cec45103c..1c7a2aab74adfc86703887492e089d91d9d0d049 100644
--- a/libavcodec/idctdsp.c
+++ b/libavcodec/idctdsp.c
@@ -24,6 +24,7 @@
 #include "faanidct.h"
 #include "idctdsp.h"
 #include "simple_idct.h"
+#include "xvididct.h"
 
 av_cold void ff_init_scantable(uint8_t *permutation, ScanTable *st,
                                const uint8_t *src_scantable)
@@ -299,6 +300,9 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx)
     c->put_signed_pixels_clamped = put_signed_pixels_clamped_c;
     c->add_pixels_clamped        = add_pixels_clamped_c;
 
+    if (CONFIG_MPEG4_DECODER && avctx->idct_algo == FF_IDCT_XVIDMMX)
+        ff_xvididct_init(c, avctx);
+
     if (ARCH_ALPHA)
         ff_idctdsp_init_alpha(c, avctx, high_bit_depth);
     if (ARCH_ARM)
diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c
index 41a2ff992fc3ddb56d2bfbe76e10e198f41c6c1f..6ff9aaf36135998e4b5720fdeb06bfd00ddf0b4e 100644
--- a/libavcodec/mpeg4videodec.c
+++ b/libavcodec/mpeg4videodec.c
@@ -31,6 +31,7 @@
 #include "mpeg4video.h"
 #include "h263.h"
 #include "thread.h"
+#include "xvididct.h"
 
 /* The defines below define the number of bits that are read at once for
  * reading vlc values. Changing these may improve speed and data cache needs
@@ -2209,7 +2210,8 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx)
                ctx->divx_version, ctx->divx_build, s->divx_packed ? "p" : "");
 
 #if HAVE_MMX
-    if (s->codec_id == AV_CODEC_ID_MPEG4 && ctx->xvid_build >= 0 &&
+    if (CONFIG_MPEG4_DECODER && ctx->xvid_build >= 0 &&
+        s->codec_id == AV_CODEC_ID_MPEG4 &&
         avctx->idct_algo == FF_IDCT_AUTO &&
         (av_get_cpu_flags() & AV_CPU_FLAG_MMX)) {
         avctx->idct_algo = FF_IDCT_XVIDMMX;
@@ -2217,6 +2219,7 @@ int ff_mpeg4_workaround_bugs(AVCodecContext *avctx)
         return 1;
     }
 #endif
+
     return 0;
 }
 
diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile
index 74692939d5bde8aafa41f9164df9ed734a87d250..53e643b5d467a9ce754d53f1f4691052d2ae31e1 100644
--- a/libavcodec/x86/Makefile
+++ b/libavcodec/x86/Makefile
@@ -40,6 +40,7 @@ OBJS-$(CONFIG_DCA_DECODER)             += x86/dcadsp_init.o
 OBJS-$(CONFIG_DNXHD_ENCODER)           += x86/dnxhdenc_init.o
 OBJS-$(CONFIG_HEVC_DECODER)            += x86/hevcdsp_init.o
 OBJS-$(CONFIG_MLP_DECODER)             += x86/mlpdsp.o
+OBJS-$(CONFIG_MPEG4_DECODER)           += x86/xvididct_init.o
 OBJS-$(CONFIG_PNG_DECODER)             += x86/pngdsp_init.o
 OBJS-$(CONFIG_PRORES_DECODER)          += x86/proresdsp_init.o
 OBJS-$(CONFIG_PRORES_LGPL_DECODER)     += x86/proresdsp_init.o
@@ -61,10 +62,10 @@ OBJS-$(CONFIG_WEBP_DECODER)            += x86/vp8dsp_init.o
 MMX-OBJS-$(CONFIG_DIRAC_DECODER)       += x86/dirac_dwt.o
 MMX-OBJS-$(CONFIG_FDCTDSP)             += x86/fdct.o
 MMX-OBJS-$(CONFIG_IDCTDSP)             += x86/idctdsp_mmx.o             \
-                                          x86/idct_mmx_xvid.o           \
-                                          x86/idct_sse2_xvid.o          \
                                           x86/simple_idct.o
 
+MMX-OBJS-$(CONFIG_MPEG4_DECODER)       += x86/idct_mmx_xvid.o           \
+                                          x86/idct_sse2_xvid.o
 MMX-OBJS-$(CONFIG_SNOW_DECODER)        += x86/snowdsp.o
 MMX-OBJS-$(CONFIG_SNOW_ENCODER)        += x86/snowdsp.o
 MMX-OBJS-$(CONFIG_VC1_DECODER)         += x86/vc1dsp_mmx.o
diff --git a/libavcodec/x86/dct-test.c b/libavcodec/x86/dct-test.c
index 85d643aa6385c6295a1c56fd41a194c490aec479..3ade1f3ce4a699a45345d1d33b244e426420ea10 100644
--- a/libavcodec/x86/dct-test.c
+++ b/libavcodec/x86/dct-test.c
@@ -59,6 +59,9 @@ static const struct algo fdct_tab_arch[] = {
 static const struct algo idct_tab_arch[] = {
 #if HAVE_MMX_INLINE
     { "SIMPLE-MMX",  ff_simple_idct_mmx,  FF_IDCT_PERM_SIMPLE, AV_CPU_FLAG_MMX },
+#endif
+#if CONFIG_MPEG4_DECODER
+#if HAVE_MMX_INLINE
     { "XVID-MMX",    ff_idct_xvid_mmx,    FF_IDCT_PERM_NONE,   AV_CPU_FLAG_MMX,    1 },
 #endif
 #if HAVE_MMXEXT_INLINE
@@ -70,6 +73,7 @@ static const struct algo idct_tab_arch[] = {
     { "PR-SSE2",     ff_prores_idct_put_10_sse2_wrap, FF_IDCT_PERM_TRANSPOSE, AV_CPU_FLAG_SSE2, 1 },
 #endif
 #endif
+#endif /* CONFIG_MPEG4_DECODER */
     { 0 }
 };
 
diff --git a/libavcodec/x86/idctdsp_init.c b/libavcodec/x86/idctdsp_init.c
index 5bf5cc6eccd3ac9d45b339be06e9994d907301cb..6f54d80f870f2d657a5044896c941027dbbebc60 100644
--- a/libavcodec/x86/idctdsp_init.c
+++ b/libavcodec/x86/idctdsp_init.c
@@ -22,7 +22,6 @@
 #include "libavutil/x86/cpu.h"
 #include "libavcodec/avcodec.h"
 #include "libavcodec/idctdsp.h"
-#include "idct_xvid.h"
 #include "idctdsp.h"
 #include "simple_idct.h"
 
@@ -38,8 +37,6 @@ static const uint8_t simple_mmx_permutation[64] = {
     0x32, 0x3A, 0x36, 0x3B, 0x33, 0x3E, 0x37, 0x3F,
 };
 
-static const uint8_t idct_sse2_row_perm[8] = { 0, 4, 1, 5, 2, 6, 3, 7 };
-
 av_cold int ff_init_scantable_permutation_x86(uint8_t *idct_permutation,
                                               enum idct_permutation_type perm_type)
 {
@@ -50,10 +47,6 @@ av_cold int ff_init_scantable_permutation_x86(uint8_t *idct_permutation,
         for (i = 0; i < 64; i++)
             idct_permutation[i] = simple_mmx_permutation[i];
         return 1;
-    case FF_IDCT_PERM_SSE2:
-        for (i = 0; i < 64; i++)
-            idct_permutation[i] = (i & 0x38) | idct_sse2_row_perm[i & 7];
-        return 1;
     }
 
     return 0;
@@ -68,44 +61,20 @@ av_cold void ff_idctdsp_init_x86(IDCTDSPContext *c, AVCodecContext *avctx,
         c->put_pixels_clamped        = ff_put_pixels_clamped_mmx;
         c->add_pixels_clamped        = ff_add_pixels_clamped_mmx;
 
-        if (avctx->lowres == 0 && !high_bit_depth) {
-            switch (avctx->idct_algo) {
-            case FF_IDCT_AUTO:
-            case FF_IDCT_SIMPLEAUTO:
-            case FF_IDCT_SIMPLEMMX:
+        if (!high_bit_depth &&
+            avctx->lowres == 0 &&
+            (avctx->idct_algo == FF_IDCT_AUTO ||
+             avctx->idct_algo == FF_IDCT_SIMPLEAUTO ||
+             avctx->idct_algo == FF_IDCT_SIMPLEMMX)) {
                 c->idct_put  = ff_simple_idct_put_mmx;
                 c->idct_add  = ff_simple_idct_add_mmx;
                 c->idct      = ff_simple_idct_mmx;
                 c->perm_type = FF_IDCT_PERM_SIMPLE;
-                break;
-            case FF_IDCT_XVIDMMX:
-                c->idct_put  = ff_idct_xvid_mmx_put;
-                c->idct_add  = ff_idct_xvid_mmx_add;
-                c->idct      = ff_idct_xvid_mmx;
-                break;
-            }
         }
     }
     if (EXTERNAL_MMX(cpu_flags)) {
         c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_mmx;
     }
-
-    if (INLINE_MMXEXT(cpu_flags)) {
-        if (!high_bit_depth && avctx->idct_algo == FF_IDCT_XVIDMMX && avctx->lowres == 0) {
-            c->idct_put = ff_idct_xvid_mmxext_put;
-            c->idct_add = ff_idct_xvid_mmxext_add;
-            c->idct     = ff_idct_xvid_mmxext;
-        }
-    }
-
-    if (INLINE_SSE2(cpu_flags)) {
-        if (!high_bit_depth && avctx->idct_algo == FF_IDCT_XVIDMMX && avctx->lowres == 0) {
-            c->idct_put  = ff_idct_xvid_sse2_put;
-            c->idct_add  = ff_idct_xvid_sse2_add;
-            c->idct      = ff_idct_xvid_sse2;
-            c->perm_type = FF_IDCT_PERM_SSE2;
-        }
-    }
     if (EXTERNAL_SSE2(cpu_flags)) {
         c->put_signed_pixels_clamped = ff_put_signed_pixels_clamped_sse2;
     }
diff --git a/libavcodec/x86/xvididct_init.c b/libavcodec/x86/xvididct_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..2ea48100bcaca051f8c36d7cbdf09ffe1105ac1f
--- /dev/null
+++ b/libavcodec/x86/xvididct_init.c
@@ -0,0 +1,63 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
+#include "libavutil/x86/cpu.h"
+#include "libavcodec/idctdsp.h"
+#include "libavcodec/xvididct.h"
+#include "idct_xvid.h"
+#include "idctdsp.h"
+
+static const uint8_t idct_sse2_row_perm[8] = { 0, 4, 1, 5, 2, 6, 3, 7 };
+
+static av_cold void init_scantable_permutation_sse2(uint8_t *idct_permutation,
+                                                    enum idct_permutation_type perm_type)
+{
+    int i;
+
+    for (i = 0; i < 64; i++)
+        idct_permutation[i] = (i & 0x38) | idct_sse2_row_perm[i & 7];
+}
+
+av_cold void ff_xvididct_init_x86(IDCTDSPContext *c)
+{
+    int cpu_flags = av_get_cpu_flags();
+
+    if (INLINE_MMX(cpu_flags)) {
+        c->idct_put  = ff_idct_xvid_mmx_put;
+        c->idct_add  = ff_idct_xvid_mmx_add;
+        c->idct      = ff_idct_xvid_mmx;
+    }
+
+    if (INLINE_MMXEXT(cpu_flags)) {
+        c->idct_put  = ff_idct_xvid_mmxext_put;
+        c->idct_add  = ff_idct_xvid_mmxext_add;
+        c->idct      = ff_idct_xvid_mmxext;
+    }
+
+    if (INLINE_SSE2(cpu_flags)) {
+        c->idct_put  = ff_idct_xvid_sse2_put;
+        c->idct_add  = ff_idct_xvid_sse2_add;
+        c->idct      = ff_idct_xvid_sse2;
+        c->perm_type = FF_IDCT_PERM_SSE2;
+
+        init_scantable_permutation_sse2(c->idct_permutation, c->perm_type);
+    }
+}
diff --git a/libavcodec/xvididct.c b/libavcodec/xvididct.c
new file mode 100644
index 0000000000000000000000000000000000000000..36f65a6aafa593ab6808a592d4750dd3162c8203
--- /dev/null
+++ b/libavcodec/xvididct.c
@@ -0,0 +1,36 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "libavutil/attributes.h"
+#include "avcodec.h"
+#include "idctdsp.h"
+#include "xvididct.h"
+
+av_cold void ff_xvididct_init(IDCTDSPContext *c, AVCodecContext *avctx)
+{
+    const unsigned high_bit_depth = avctx->bits_per_raw_sample > 8;
+
+    if (high_bit_depth || avctx->lowres ||
+        !(avctx->idct_algo == FF_IDCT_AUTO ||
+          avctx->idct_algo == FF_IDCT_XVIDMMX))
+        return;
+
+    if (ARCH_X86)
+        ff_xvididct_init_x86(c);
+}
diff --git a/libavcodec/xvididct.h b/libavcodec/xvididct.h
new file mode 100644
index 0000000000000000000000000000000000000000..6678329201c04077cdbb8430e63e1c8fef82af9a
--- /dev/null
+++ b/libavcodec/xvididct.h
@@ -0,0 +1,29 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_XVIDIDCT_H
+#define AVCODEC_XVIDIDCT_H
+
+#include "avcodec.h"
+#include "idctdsp.h"
+
+void ff_xvididct_init(IDCTDSPContext *c, AVCodecContext *avctx);
+
+void ff_xvididct_init_x86(IDCTDSPContext *c);
+
+#endif /* AVCODEC_XVIDIDCT_H */