[vlc-commits] deinterlace: move Phosphor MMX acceleration to a separate function

Rémi Denis-Courmont git at videolan.org
Mon Dec 17 20:17:00 CET 2012


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Mon Dec 17 21:11:22 2012 +0200| [86ca82559b5f28aaa80a3029d07a3a51578bd3af] | committer: Rémi Denis-Courmont

deinterlace: move Phosphor MMX acceleration to a separate function

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=86ca82559b5f28aaa80a3029d07a3a51578bd3af
---

 modules/video_filter/deinterlace/algo_phosphor.c |  191 ++++++++++++++--------
 1 file changed, 124 insertions(+), 67 deletions(-)

diff --git a/modules/video_filter/deinterlace/algo_phosphor.c b/modules/video_filter/deinterlace/algo_phosphor.c
index 191de23..30f5e4b 100644
--- a/modules/video_filter/deinterlace/algo_phosphor.c
+++ b/modules/video_filter/deinterlace/algo_phosphor.c
@@ -78,11 +78,6 @@ static void DarkenField( picture_t *p_dst,
 
     /* Bitwise ANDing with this clears the i_strength highest bits
        of each byte */
-#ifdef CAN_COMPILE_MMXEXT
-    const bool mmxext = vlc_CPU_MMXEXT();
-    uint64_t i_strength_u64 = i_strength; /* for MMX version (needs to know
-                                             number of bits) */
-#endif
     const uint8_t  remove_high_u8 = 0xFF >> i_strength;
     const uint64_t remove_high_u64 = remove_high_u8 *
                                             INT64_C(0x0101010101010101);
@@ -92,7 +87,7 @@ static void DarkenField( picture_t *p_dst,
        For luma, the operation is just a shift + bitwise AND, so we vectorize
        even in the C version.
 
-       There is an MMX version, too, because it performs about twice faster.
+       There is an MMX version too, because it performs about twice faster.
     */
     int i_plane = Y_PLANE;
     uint8_t *p_out, *p_out_end;
@@ -112,26 +107,90 @@ static void DarkenField( picture_t *p_dst,
         uint64_t *po = (uint64_t *)p_out;
         int x = 0;
 
-#ifdef CAN_COMPILE_MMXEXT
-        if( mmxext )
+        for( ; x < w8; x += 8, ++po )
+            (*po) = ( ((*po) >> i_strength) & remove_high_u64 );
+
+        /* handle the width remainder */
+        uint8_t *po_temp = (uint8_t *)po;
+        for( ; x < w; ++x, ++po_temp )
+            (*po_temp) = ( ((*po_temp) >> i_strength) & remove_high_u8 );
+    }
+
+    /* Process chroma if the field chromas are independent.
+
+       The origin (black) is at YUV = (0, 128, 128) in the uint8 format.
+       The chroma processing is a bit more complicated than luma,
+       and needs MMX for vectorization.
+    */
+    if( process_chroma )
+    {
+        for( i_plane++ /* luma already handled*/;
+             i_plane < p_dst->i_planes;
+             i_plane++ )
         {
-            movq_m2r( i_strength_u64,  mm1 );
-            movq_m2r( remove_high_u64, mm2 );
-            for( ; x < w8; x += 8 )
+            int w = p_dst->p[i_plane].i_visible_pitch;
+            p_out = p_dst->p[i_plane].p_pixels;
+            p_out_end = p_out + p_dst->p[i_plane].i_pitch
+                              * p_dst->p[i_plane].i_visible_lines;
+
+            /* skip first line for bottom field */
+            if( i_field == 1 )
+                p_out += p_dst->p[i_plane].i_pitch;
+
+            for( ; p_out < p_out_end ; p_out += 2*p_dst->p[i_plane].i_pitch )
             {
-                movq_m2r( (*po), mm0 );
+                /* Handle the width remainder */
+                uint8_t *po = p_out;
+                for( int x = 0; x < w; ++x, ++po )
+                    (*po) = 128 + ( ((*po) - 128) / (1 << i_strength) );
+            } /* for p_out... */
+        } /* for i_plane... */
+    } /* if process_chroma */
+}
 
-                psrlq_r2r( mm1, mm0 );
-                pand_r2r(  mm2, mm0 );
+#ifdef CAN_COMPILE_MMXEXT
+VLC_MMX
+static void DarkenFieldMMX( picture_t *p_dst,
+                            const int i_field, const int i_strength,
+                            bool process_chroma )
+{
+    assert( p_dst != NULL );
+    assert( i_field == 0 || i_field == 1 );
+    assert( i_strength >= 1 && i_strength <= 3 );
 
-                movq_r2m( mm0, (*po++) );
-            }
-        }
-        else
-#endif
+    uint64_t i_strength_u64 = i_strength; /* needs to know number of bits */
+    const uint8_t  remove_high_u8 = 0xFF >> i_strength;
+    const uint64_t remove_high_u64 = remove_high_u8 *
+                                            INT64_C(0x0101010101010101);
+
+    int i_plane = Y_PLANE;
+    uint8_t *p_out, *p_out_end;
+    int w = p_dst->p[i_plane].i_visible_pitch;
+    p_out = p_dst->p[i_plane].p_pixels;
+    p_out_end = p_out + p_dst->p[i_plane].i_pitch
+                      * p_dst->p[i_plane].i_visible_lines;
+
+    /* skip first line for bottom field */
+    if( i_field == 1 )
+        p_out += p_dst->p[i_plane].i_pitch;
+
+    int wm8 = w % 8;   /* remainder */
+    int w8  = w - wm8; /* part of width that is divisible by 8 */
+    for( ; p_out < p_out_end ; p_out += 2*p_dst->p[i_plane].i_pitch )
+    {
+        uint64_t *po = (uint64_t *)p_out;
+        int x = 0;
+
+        movq_m2r( i_strength_u64,  mm1 );
+        movq_m2r( remove_high_u64, mm2 );
+        for( ; x < w8; x += 8 )
         {
-            for( ; x < w8; x += 8, ++po )
-                (*po) = ( ((*po) >> i_strength) & remove_high_u64 );
+            movq_m2r( (*po), mm0 );
+
+            psrlq_r2r( mm1, mm0 );
+            pand_r2r(  mm2, mm0 );
+
+            movq_r2m( mm0, (*po++) );
         }
 
         /* handle the width remainder */
@@ -148,16 +207,14 @@ static void DarkenField( picture_t *p_dst,
     */
     if( process_chroma )
     {
-        for( i_plane = 0 ; i_plane < p_dst->i_planes ; i_plane++ )
+        for( i_plane++ /* luma already handled */;
+             i_plane < p_dst->i_planes;
+             i_plane++ )
         {
-            if( i_plane == Y_PLANE )
-                continue; /* luma already handled */
-
             int w = p_dst->p[i_plane].i_visible_pitch;
-#ifdef CAN_COMPILE_MMXEXT
             int wm8 = w % 8;   /* remainder */
             int w8  = w - wm8; /* part of width that is divisible by 8 */
-#endif
+
             p_out = p_dst->p[i_plane].p_pixels;
             p_out_end = p_out + p_dst->p[i_plane].i_pitch
                               * p_dst->p[i_plane].i_visible_lines;
@@ -170,42 +227,36 @@ static void DarkenField( picture_t *p_dst,
             {
                 int x = 0;
 
-#ifdef CAN_COMPILE_MMXEXT
                 /* See also easy-to-read C version below. */
-                if( mmxext )
+                static const mmx_t b128 = { .uq = 0x8080808080808080ULL };
+                movq_m2r( b128, mm5 );
+                movq_m2r( i_strength_u64,  mm6 );
+                movq_m2r( remove_high_u64, mm7 );
+
+                uint64_t *po8 = (uint64_t *)p_out;
+                for( ; x < w8; x += 8 )
                 {
-                    static const mmx_t b128 = { .uq = 0x8080808080808080ULL };
-                    movq_m2r( b128, mm5 );
-                    movq_m2r( i_strength_u64,  mm6 );
-                    movq_m2r( remove_high_u64, mm7 );
-
-                    uint64_t *po = (uint64_t *)p_out;
-                    for( ; x < w8; x += 8 )
-                    {
-                        movq_m2r( (*po), mm0 );
-
-                        movq_r2r( mm5, mm2 ); /* 128 */
-                        movq_r2r( mm0, mm1 ); /* copy of data */
-                        psubusb_r2r( mm2, mm1 ); /* mm1 = max(data - 128, 0) */
-                        psubusb_r2r( mm0, mm2 ); /* mm2 = max(128 - data, 0) */
-
-                        /* >> i_strength */
-                        psrlq_r2r( mm6, mm1 );
-                        psrlq_r2r( mm6, mm2 );
-                        pand_r2r(  mm7, mm1 );
-                        pand_r2r(  mm7, mm2 );
-
-                        /* collect results from pos./neg. parts */
-                        psubb_r2r( mm2, mm1 );
-                        paddb_r2r( mm5, mm1 );
-
-                        movq_r2m( mm1, (*po++) );
-                    }
+                    movq_m2r( (*po8), mm0 );
+
+                    movq_r2r( mm5, mm2 ); /* 128 */
+                    movq_r2r( mm0, mm1 ); /* copy of data */
+                    psubusb_r2r( mm2, mm1 ); /* mm1 = max(data - 128, 0) */
+                    psubusb_r2r( mm0, mm2 ); /* mm2 = max(128 - data, 0) */
+
+                    /* >> i_strength */
+                    psrlq_r2r( mm6, mm1 );
+                    psrlq_r2r( mm6, mm2 );
+                    pand_r2r(  mm7, mm1 );
+                    pand_r2r(  mm7, mm2 );
+
+                    /* collect results from pos./neg. parts */
+                    psubb_r2r( mm2, mm1 );
+                    paddb_r2r( mm5, mm1 );
+
+                    movq_r2m( mm1, (*po8++) );
                 }
-#endif
 
-                /* C version - handle the width remainder
-                   (or everything if no MMX) */
+                /* C version - handle the width remainder */
                 uint8_t *po = p_out;
                 for( ; x < w; ++x, ++po )
                     (*po) = 128 + ( ((*po) - 128) / (1 << i_strength) );
@@ -213,11 +264,9 @@ static void DarkenField( picture_t *p_dst,
         } /* for i_plane... */
     } /* if process_chroma */
 
-#ifdef CAN_COMPILE_MMXEXT
-    if( mmxext )
-        emms();
-#endif
+    emms();
 }
+#endif
 
 /*****************************************************************************
  * Public functions
@@ -303,9 +352,17 @@ int RenderPhosphor( filter_t *p_filter,
        In most use cases the dimmer is used.
     */
     if( p_sys->phosphor.i_dimmer_strength > 0 )
-        DarkenField( p_dst, !i_field, p_sys->phosphor.i_dimmer_strength,
-                     p_sys->chroma->p[1].h.num == p_sys->chroma->p[1].h.den &&
-                     p_sys->chroma->p[2].h.num == p_sys->chroma->p[2].h.den );
-
+    {
+#ifdef CAN_COMPILE_MMXEXT
+        if( vlc_CPU_MMXEXT() )
+            DarkenFieldMMX( p_dst, !i_field, p_sys->phosphor.i_dimmer_strength,
+                p_sys->chroma->p[1].h.num == p_sys->chroma->p[1].h.den &&
+                p_sys->chroma->p[2].h.num == p_sys->chroma->p[2].h.den );
+        else
+#endif
+            DarkenField( p_dst, !i_field, p_sys->phosphor.i_dimmer_strength,
+                p_sys->chroma->p[1].h.num == p_sys->chroma->p[1].h.den &&
+                p_sys->chroma->p[2].h.num == p_sys->chroma->p[2].h.den );
+    }
     return VLC_SUCCESS;
 }



More information about the vlc-commits mailing list