]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/x86/mpegvideoencdsp_init.c
Merge commit '3c650efb81aaa3b395ba4606ee68a47ee4efb57b'
[ffmpeg] / libavcodec / x86 / mpegvideoencdsp_init.c
index 16841893a4a4cbbfa1b9c1eb3daa70c66e47d654..d91b902187ebded004e9b336c67d7782c923c89a 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include "libavutil/attributes.h"
+#include "libavutil/avassert.h"
 #include "libavutil/cpu.h"
 #include "libavutil/x86/cpu.h"
 #include "libavcodec/avcodec.h"
@@ -96,6 +97,120 @@ int ff_pix_norm1_sse2(uint8_t *pix, int line_size);
 #undef PHADDD
 #endif /* HAVE_SSSE3_INLINE */
 
+/* Draw the edges of width 'w' of an image of size width, height
+ * this MMX version can only handle w == 8 || w == 16. */
+static void draw_edges_mmx(uint8_t *buf, int wrap, int width, int height,
+                           int w, int h, int sides)
+{
+    uint8_t *ptr, *last_line;
+    int i;
+
+    last_line = buf + (height - 1) * wrap;
+    /* left and right */
+    ptr = buf;
+    if (w == 8) {
+        __asm__ volatile (
+            "1:                             \n\t"
+            "movd            (%0), %%mm0    \n\t"
+            "punpcklbw      %%mm0, %%mm0    \n\t"
+            "punpcklwd      %%mm0, %%mm0    \n\t"
+            "punpckldq      %%mm0, %%mm0    \n\t"
+            "movq           %%mm0, -8(%0)   \n\t"
+            "movq      -8(%0, %2), %%mm1    \n\t"
+            "punpckhbw      %%mm1, %%mm1    \n\t"
+            "punpckhwd      %%mm1, %%mm1    \n\t"
+            "punpckhdq      %%mm1, %%mm1    \n\t"
+            "movq           %%mm1, (%0, %2) \n\t"
+            "add               %1, %0       \n\t"
+            "cmp               %3, %0       \n\t"
+            "jb                1b           \n\t"
+            : "+r" (ptr)
+            : "r" ((x86_reg) wrap), "r" ((x86_reg) width),
+              "r" (ptr + wrap * height));
+    } else if (w == 16) {
+        __asm__ volatile (
+            "1:                                 \n\t"
+            "movd            (%0), %%mm0        \n\t"
+            "punpcklbw      %%mm0, %%mm0        \n\t"
+            "punpcklwd      %%mm0, %%mm0        \n\t"
+            "punpckldq      %%mm0, %%mm0        \n\t"
+            "movq           %%mm0, -8(%0)       \n\t"
+            "movq           %%mm0, -16(%0)      \n\t"
+            "movq      -8(%0, %2), %%mm1        \n\t"
+            "punpckhbw      %%mm1, %%mm1        \n\t"
+            "punpckhwd      %%mm1, %%mm1        \n\t"
+            "punpckhdq      %%mm1, %%mm1        \n\t"
+            "movq           %%mm1,  (%0, %2)    \n\t"
+            "movq           %%mm1, 8(%0, %2)    \n\t"
+            "add               %1, %0           \n\t"
+            "cmp               %3, %0           \n\t"
+            "jb                1b               \n\t"
+            : "+r"(ptr)
+            : "r"((x86_reg)wrap), "r"((x86_reg)width), "r"(ptr + wrap * height)
+            );
+    } else {
+        av_assert1(w == 4);
+        __asm__ volatile (
+            "1:                             \n\t"
+            "movd            (%0), %%mm0    \n\t"
+            "punpcklbw      %%mm0, %%mm0    \n\t"
+            "punpcklwd      %%mm0, %%mm0    \n\t"
+            "movd           %%mm0, -4(%0)   \n\t"
+            "movd      -4(%0, %2), %%mm1    \n\t"
+            "punpcklbw      %%mm1, %%mm1    \n\t"
+            "punpckhwd      %%mm1, %%mm1    \n\t"
+            "punpckhdq      %%mm1, %%mm1    \n\t"
+            "movd           %%mm1, (%0, %2) \n\t"
+            "add               %1, %0       \n\t"
+            "cmp               %3, %0       \n\t"
+            "jb                1b           \n\t"
+            : "+r" (ptr)
+            : "r" ((x86_reg) wrap), "r" ((x86_reg) width),
+              "r" (ptr + wrap * height));
+    }
+
+    /* top and bottom (and hopefully also the corners) */
+    if (sides & EDGE_TOP) {
+        for (i = 0; i < h; i += 4) {
+            ptr = buf - (i + 1) * wrap - w;
+            __asm__ volatile (
+                "1:                             \n\t"
+                "movq (%1, %0), %%mm0           \n\t"
+                "movq    %%mm0, (%0)            \n\t"
+                "movq    %%mm0, (%0, %2)        \n\t"
+                "movq    %%mm0, (%0, %2, 2)     \n\t"
+                "movq    %%mm0, (%0, %3)        \n\t"
+                "add        $8, %0              \n\t"
+                "cmp        %4, %0              \n\t"
+                "jb         1b                  \n\t"
+                : "+r" (ptr)
+                : "r" ((x86_reg) buf - (x86_reg) ptr - w),
+                  "r" ((x86_reg) - wrap), "r" ((x86_reg) - wrap * 3),
+                  "r" (ptr + width + 2 * w));
+        }
+    }
+
+    if (sides & EDGE_BOTTOM) {
+        for (i = 0; i < h; i += 4) {
+            ptr = last_line + (i + 1) * wrap - w;
+            __asm__ volatile (
+                "1:                             \n\t"
+                "movq (%1, %0), %%mm0           \n\t"
+                "movq    %%mm0, (%0)            \n\t"
+                "movq    %%mm0, (%0, %2)        \n\t"
+                "movq    %%mm0, (%0, %2, 2)     \n\t"
+                "movq    %%mm0, (%0, %3)        \n\t"
+                "add        $8, %0              \n\t"
+                "cmp        %4, %0              \n\t"
+                "jb         1b                  \n\t"
+                : "+r" (ptr)
+                : "r" ((x86_reg) last_line - (x86_reg) ptr - w),
+                  "r" ((x86_reg) wrap), "r" ((x86_reg) wrap * 3),
+                  "r" (ptr + width + 2 * w));
+        }
+    }
+}
+
 #endif /* HAVE_INLINE_ASM */
 
 av_cold void ff_mpegvideoencdsp_init_x86(MpegvideoEncDSPContext *c,
@@ -124,6 +239,10 @@ av_cold void ff_mpegvideoencdsp_init_x86(MpegvideoEncDSPContext *c,
             c->try_8x8basis = try_8x8basis_mmx;
         }
         c->add_8x8basis = add_8x8basis_mmx;
+
+        if (avctx->bits_per_raw_sample <= 8) {
+            c->draw_edges = draw_edges_mmx;
+        }
     }
 
     if (INLINE_AMD3DNOW(cpu_flags)) {