[x264-devel] commit: x264_median_mv_mmxext (Loren Merritt )

git version control git at videolan.org
Tue May 20 12:08:26 CEST 2008


x264 | branch: master | Loren Merritt <pengvado at akuvian.org> | Sat May 17 03:39:59 2008 -0600| [a50d364ce947f9943458ca70ec6bf26f9e24475f]

x264_median_mv_mmxext
this is the first non-runtime-detected use of mmxext, but it has to be inlined

> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=a50d364ce947f9943458ca70ec6bf26f9e24475f
---

 common/common.h     |   27 +++++++++++++++------------
 common/macroblock.c |   20 ++++----------------
 common/x86/util.h   |   44 ++++++++++++++++++++++++++++++++++++++++++++
 encoder/slicetype.c |    4 +---
 4 files changed, 64 insertions(+), 31 deletions(-)

diff --git a/common/common.h b/common/common.h
index a53509b..425fc8f 100644
--- a/common/common.h
+++ b/common/common.h
@@ -116,20 +116,23 @@ static inline double x264_clip3f( double v, double f_min, double f_max )
 
 static inline int x264_median( int a, int b, int c )
 {
-    int min = a, max =a;
-    if( b < min )
-        min = b;
-    else
-        max = b;    /* no need to do 'b > max' (more consuming than always doing affectation) */
-
-    if( c < min )
-        min = c;
-    else if( c > max )
-        max = c;
-
-    return a + b + c - min - max;
+    int t = (a-b)&((a-b)>>31);
+    a -= t;
+    b += t;
+    b -= (b-c)&((b-c)>>31);
+    b += (a-b)&((a-b)>>31);
+    return b;
 }
 
+static inline void x264_median_mv( int16_t *dst, int16_t *a, int16_t *b, int16_t *c )
+{
+    dst[0] = x264_median( a[0], b[0], c[0] );
+    dst[1] = x264_median( a[1], b[1], c[1] );
+}
+
+#ifdef HAVE_MMX
+#include "x86/util.h"
+#endif
 
 /****************************************************************************
  *
diff --git a/common/macroblock.c b/common/macroblock.c
index d2fc0cb..7c8b939 100644
--- a/common/macroblock.c
+++ b/common/macroblock.c
@@ -140,10 +140,7 @@ void x264_mb_predict_mv( x264_t *h, int i_list, int idx, int i_width, int16_t mv
     if( i_refc == i_ref ) i_count++;
 
     if( i_count > 1 )
-    {
-        mvp[0] = x264_median( mv_a[0], mv_b[0], mv_c[0] );
-        mvp[1] = x264_median( mv_a[1], mv_b[1], mv_c[1] );
-    }
+        x264_median_mv( mvp, mv_a, mv_b, mv_c );
     else if( i_count == 1 )
     {
         if( i_refa == i_ref )
@@ -156,10 +153,7 @@ void x264_mb_predict_mv( x264_t *h, int i_list, int idx, int i_width, int16_t mv
     else if( i_refb == -2 && i_refc == -2 && i_refa != -2 )
         *(uint32_t*)mvp = *(uint32_t*)mv_a;
     else
-    {
-        mvp[0] = x264_median( mv_a[0], mv_b[0], mv_c[0] );
-        mvp[1] = x264_median( mv_a[1], mv_b[1], mv_c[1] );
-    }
+        x264_median_mv( mvp, mv_a, mv_b, mv_c );
 }
 
 void x264_mb_predict_mv_16x16( x264_t *h, int i_list, int i_ref, int16_t mvp[2] )
@@ -185,10 +179,7 @@ void x264_mb_predict_mv_16x16( x264_t *h, int i_list, int i_ref, int16_t mvp[2]
     if( i_refc == i_ref ) i_count++;
 
     if( i_count > 1 )
-    {
-        mvp[0] = x264_median( mv_a[0], mv_b[0], mv_c[0] );
-        mvp[1] = x264_median( mv_a[1], mv_b[1], mv_c[1] );
-    }
+        x264_median_mv( mvp, mv_a, mv_b, mv_c );
     else if( i_count == 1 )
     {
         if( i_refa == i_ref )
@@ -201,10 +192,7 @@ void x264_mb_predict_mv_16x16( x264_t *h, int i_list, int i_ref, int16_t mvp[2]
     else if( i_refb == -2 && i_refc == -2 && i_refa != -2 )
         *(uint32_t*)mvp = *(uint32_t*)mv_a;
     else
-    {
-        mvp[0] = x264_median( mv_a[0], mv_b[0], mv_c[0] );
-        mvp[1] = x264_median( mv_a[1], mv_b[1], mv_c[1] );
-    }
+        x264_median_mv( mvp, mv_a, mv_b, mv_c );
 }
 
 
diff --git a/common/x86/util.h b/common/x86/util.h
new file mode 100644
index 0000000..73f4904
--- /dev/null
+++ b/common/x86/util.h
@@ -0,0 +1,44 @@
+/*****************************************************************************
+ * mc.h: h264 encoder library
+ *****************************************************************************
+ * Copyright (C) 2008 Loren Merritt
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef X264_X86_UTIL_H
+#define X264_X86_UTIL_H
+
+#ifdef __GNUC__
+#define x264_median_mv x264_median_mv_mmxext
+static inline void x264_median_mv_mmxext( int16_t *dst, int16_t *a, int16_t *b, int16_t *c )
+{
+    asm(
+        "movd   %1,    %%mm0 \n"
+        "movd   %2,    %%mm1 \n"
+        "movq   %%mm0, %%mm3 \n"
+        "movd   %3,    %%mm2 \n"
+        "pmaxsw %%mm1, %%mm0 \n"
+        "pminsw %%mm3, %%mm1 \n"
+        "pminsw %%mm2, %%mm0 \n"
+        "pmaxsw %%mm1, %%mm0 \n"
+        "movd   %%mm0, %0    \n"
+        :"=m"(*(uint32_t*)dst)
+        :"m"(*(uint32_t*)a), "m"(*(uint32_t*)b), "m"(*(uint32_t*)c)
+    );
+}
+#endif
+
+#endif
diff --git a/encoder/slicetype.c b/encoder/slicetype.c
index 58e666b..fff7bc4 100644
--- a/encoder/slicetype.c
+++ b/encoder/slicetype.c
@@ -168,9 +168,7 @@ int x264_slicetype_mb_cost( x264_t *h, x264_mb_analysis_t *a,
                 MVC(fenc_mv[-i_mb_stride-1]);
         }
 #undef MVC
-        m[l].mvp[0] = x264_median( mvc[0][0], mvc[1][0], mvc[2][0] );
-        m[l].mvp[1] = x264_median( mvc[0][1], mvc[1][1], mvc[2][1] );
-
+        x264_median_mv( m[l].mvp, mvc[0], mvc[1], mvc[2] );
         x264_me_search( h, &m[l], mvc, i_mvc );
 
         m[l].cost -= 2; // remove mvcost from skip mbs



More information about the x264-devel mailing list