]> git.sesse.net Git - vlc/blobdiff - modules/video_filter/sepia.c
HTTP: deal with https in warning too
[vlc] / modules / video_filter / sepia.c
index 249d10feb9b8f5d2135898de8882b37fbdbd580d..cdab59eddb2f6255a3b4d2d75facb4d4427bca10 100644 (file)
@@ -47,8 +47,6 @@ static void RVSepia( picture_t *, picture_t *, int );
 static void PlanarI420Sepia( picture_t *, picture_t *, int);
 static void PackedYUVSepia( picture_t *, picture_t *, int);
 static picture_t *Filter( filter_t *, picture_t * );
-inline void Sepia8ySSE41( uint8_t *, const uint8_t *, volatile uint8_t * );
-inline void Memcpy8BMMX( uint8_t *, const uint8_t * );
 static const char *const ppsz_filter_options[] = {
     "intensity", NULL
 };
@@ -68,7 +66,7 @@ vlc_module_begin ()
     set_category( CAT_VIDEO )
     set_subcategory( SUBCAT_VIDEO_VFILTER )
     set_capability( "video filter2", 0 )
-    add_integer_with_range( CFG_PREFIX "intensity", 100, 0, 255, NULL,
+    add_integer_with_range( CFG_PREFIX "intensity", 120, 0, 255,
                            SEPIA_INTENSITY_TEXT, SEPIA_INTENSITY_LONGTEXT,
                            false )
     set_callbacks( Create, Destroy )
@@ -200,6 +198,37 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
     return CopyInfoAndRelease( p_outpic, p_pic );
 }
 
+#if defined(CAN_COMPILE_SSE2)
+/*****************************************************************************
+ * Sepia8ySSE2
+ *****************************************************************************
+ * This function applies sepia effect to eight bytes of yellow using SSE4.1
+ * instructions. It copies those 8 bytes to 128b register and fills the gaps
+ * with zeroes and following operations are made with word-operating instructs.
+ *****************************************************************************/
+static inline void Sepia8ySSE2(uint8_t * dst, const uint8_t * src,
+                         int i_intensity_spread)
+{
+    __asm__ volatile (
+        // y = y - y / 4 + i_intensity / 4
+        "movq            (%1), %%xmm1\n"
+        "punpcklbw     %%xmm7, %%xmm1\n"
+        "movq            (%1), %%xmm2\n" // store bytes as words with 0s in between
+        "punpcklbw     %%xmm7, %%xmm2\n"
+        "movd              %2, %%xmm3\n"
+        "pshufd    $0, %%xmm3, %%xmm3\n"
+        "psrlw             $2, %%xmm2\n"    // rotate right 2
+        "psubusb       %%xmm1, %%xmm2\n"    // subtract
+        "psrlw             $2, %%xmm3\n"
+        "paddsb        %%xmm1, %%xmm3\n"    // add
+        "packuswb      %%xmm2, %%xmm1\n"    // pack back to bytes
+        "movq          %%xmm1, (%0)  \n"    // load to dest
+        :
+        :"r" (dst), "r"(src), "r"(i_intensity_spread)
+        :"memory");
+}
+#endif
+
 /*****************************************************************************
  * PlanarI420Sepia: Applies sepia to one frame of the planar I420 video
  *****************************************************************************
@@ -215,22 +244,15 @@ static void PlanarI420Sepia( picture_t *p_pic, picture_t *p_outpic,
     const uint8_t filling_const_8u = 128 - i_intensity / 6;
     const uint8_t filling_const_8v = 128 + i_intensity / 14;
 
-    #if defined(CAN_COMPILE_SSE4_1) && 1
-    if (vlc_CPU() & CPU_CAPABILITY_SSE4_1)
+#if defined(CAN_COMPILE_SSE2)
+    if (vlc_CPU() & CPU_CAPABILITY_SSE2)
     {
-        /*prepare array of values to copy with mmx, compute only once
-          to improve speed */
-        volatile uint8_t intensity_array[8] = { i_intensity, i_intensity,
-            i_intensity, i_intensity, i_intensity, i_intensity,
-            i_intensity, i_intensity };
-        const uint8_t filling_array_8u[8] =
-            { filling_const_8u, filling_const_8u, filling_const_8u,
-            filling_const_8u, filling_const_8u, filling_const_8u,
-            filling_const_8u, filling_const_8u };
-        const uint8_t filling_array_8v[8] =
-            { filling_const_8v, filling_const_8v, filling_const_8v,
-            filling_const_8v, filling_const_8v, filling_const_8v,
-            filling_const_8v, filling_const_8v };
+        /* prepared value for faster broadcasting in xmm register */
+        int i_intensity_spread = 0x10001 * (uint8_t) i_intensity;
+
+        __asm__ volatile(
+            "pxor      %%xmm7, %%xmm7\n"
+        ::);
 
         /* iterate for every two visible line in the frame */
         for (int y = 0; y < p_pic->p[Y_PLANE].i_visible_lines - 1; y += 2)
@@ -244,35 +266,36 @@ static void PlanarI420Sepia( picture_t *p_pic, picture_t *p_outpic,
             (y / 2) * p_outpic->p[V_PLANE].i_pitch;
             int x = 0;
             /* iterate for every visible line in the frame (eight values at once) */
-            for (; x < p_pic->p[Y_PLANE].i_visible_pitch - 15; x += 16)
+            for ( ; x < p_pic->p[Y_PLANE].i_visible_pitch - 15; x += 16 )
             {
                 /* Compute yellow channel values with asm function */
-                Sepia8ySSE41(
-                          &p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_start + x],
-                          &p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x],
-                          intensity_array );
-                Sepia8ySSE41(
-                          &p_outpic->p[Y_PLANE].p_pixels[i_dy_line2_start + x],
-                          &p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x],
-                          intensity_array );
-                Sepia8ySSE41(
-                          &p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_start + x + 8],
-                          &p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x + 8],
-                          intensity_array );
-                Sepia8ySSE41(
-                          &p_outpic->p[Y_PLANE].p_pixels[i_dy_line2_start + x + 8],
-                          &p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x + 8],
-                          intensity_array );
-                /* Copy precomputed values to destination image memory location */
-                Memcpy8BMMX(
-                          &p_outpic->p[U_PLANE].p_pixels[i_du_line_start + (x / 2)],
-                          filling_array_8u );
-                Memcpy8BMMX(&p_outpic->p[V_PLANE].p_pixels[i_dv_line_start + (x / 2)],
-                          filling_array_8v );
+                Sepia8ySSE2(
+                    &p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_start + x],
+                    &p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x],
+                    i_intensity_spread );
+                Sepia8ySSE2(
+                    &p_outpic->p[Y_PLANE].p_pixels[i_dy_line2_start + x],
+                    &p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x],
+                    i_intensity_spread );
+                Sepia8ySSE2(
+                    &p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_start + x + 8],
+                    &p_pic->p[Y_PLANE].p_pixels[i_dy_line1_start + x + 8],
+                    i_intensity_spread );
+                Sepia8ySSE2(
+                    &p_outpic->p[Y_PLANE].p_pixels[i_dy_line2_start + x + 8],
+                    &p_pic->p[Y_PLANE].p_pixels[i_dy_line2_start + x + 8],
+                    i_intensity_spread );
+                /* Copy precomputed values to destination memory location */
+                vlc_memset(
+                    &p_outpic->p[U_PLANE].p_pixels[i_du_line_start + (x / 2)],
+                    filling_const_8u, 8 );
+                vlc_memset(
+                    &p_outpic->p[V_PLANE].p_pixels[i_dv_line_start + (x / 2)],
+                    filling_const_8v, 8 );
             }
             /* Completing the job, the cycle above takes really big chunks, so
               this makes sure the job will be done completely */
-            for (; x < p_pic->p[Y_PLANE].i_visible_pitch - 1; x += 2)
+            for ( ; x < p_pic->p[Y_PLANE].i_visible_pitch - 1; x += 2 )
             {
                 // y = y - y/4 {to prevent overflow} + intensity / 4
                 p_outpic->p[Y_PLANE].p_pixels[i_dy_line1_start + x] =
@@ -299,7 +322,8 @@ static void PlanarI420Sepia( picture_t *p_pic, picture_t *p_outpic,
                     filling_const_8v;
             }
         }
-    } else
+    }
+    else
 #endif
     {
         /* iterate for every two visible line in the frame */
@@ -369,68 +393,7 @@ static void PackedYUVSepia( picture_t *p_pic, picture_t *p_outpic,
     p_in_end = p_in + p_pic->p[0].i_visible_lines
         * p_pic->p[0].i_pitch;
     p_out = p_outpic->p[0].p_pixels;
-#if defined(CAN_COMPILE_SSE4_1)
-    if (vlc_CPU() & CPU_CAPABILITY_SSE4_1)
-    {
-        /*prepare array of values to copy with mmx, compute only once
-          to improve speed */
-        volatile uint8_t intensity_array[8] = { i_intensity, i_intensity,
-            i_intensity, i_intensity, i_intensity, i_intensity,
-            i_intensity,
-            i_intensity
-        };
-        const uint8_t filling_array_8u[8] =
-            { filling_const_8u, filling_const_8u,
-            filling_const_8u, filling_const_8u, filling_const_8u,
-            filling_const_8u,
-            filling_const_8u, filling_const_8u
-        };
-        const uint8_t filling_array_8v[8] =
-            { filling_const_8v, filling_const_8v,
-            filling_const_8v, filling_const_8v, filling_const_8v,
-            filling_const_8v,
-            filling_const_8v, filling_const_8v
-        };
 
-        /* iterate for every two visible line in the frame */
-        while (p_in < p_in_end)
-        {
-            p_line_end = p_in + p_pic->p[0].i_visible_pitch;
-            while (p_in < p_line_end)
-            {
-                Sepia8ySSE41(&p_out[i_yindex], &p_in[i_yindex],
-                          intensity_array);
-                Sepia8ySSE41(&p_out[i_yindex + 8], &p_in[i_yindex + 8],
-                          intensity_array);
-                Sepia8ySSE41(&p_out[i_yindex + 16], &p_in[i_yindex + 16],
-                          intensity_array);
-                Sepia8ySSE41(&p_out[i_yindex + 24], &p_in[i_yindex + 24],
-                          intensity_array);
-                Memcpy8BMMX(&p_out[i_uindex], filling_array_8u);
-                Memcpy8BMMX(&p_out[i_vindex], filling_array_8v);
-
-                p_in += 32;
-                p_out += 32;
-            }
-            while (p_in < p_line_end)
-            {
-                p_out[i_yindex] =
-                    p_in[i_yindex] - (p_in[i_yindex] >> 2) +
-                    (i_intensity >> 2);
-                p_out[i_yindex + 2] =
-                    p_in[i_yindex + 2] - (p_in[i_yindex + 2] >> 2) +
-                    (i_intensity >> 2);
-                p_out[i_uindex] = filling_const_8u;
-                p_out[i_vindex] = filling_const_8v;
-                p_in += 4;
-                p_out += 4;
-            }
-            p_in += p_pic->p[0].i_pitch - p_pic->p[0].i_visible_pitch;
-            p_out += p_outpic->p[0].i_pitch
-            - p_outpic->p[0].i_visible_pitch;
-        }
-    } else
-#endif
     {
         while( p_in < p_in_end )
         {
@@ -525,50 +488,6 @@ static void RVSepia( picture_t *p_pic, picture_t *p_outpic, int i_intensity )
 #undef FIX
 }
 
-/*****************************************************************************
- * Sepia8ySSE41
- *****************************************************************************
- * This function applies sepia effect to eight bytes of yellow using SSE4.1
- * instructions. It copies those 8 bytes to 128b register and fills the gaps
- * with zeroes and following operations are made with word-operating instructs.
- *****************************************************************************/
-inline void Sepia8ySSE41(uint8_t * dst, const uint8_t * src,
-               volatile uint8_t * i_intensity)
-{
-#if defined(CAN_COMPILE_SSE4_1) && 1
-    __asm__ volatile (
-              "pmovzxbw      (%1),   %%xmm1\n"    // y = y - y / 4 + i_intensity / 4
-              "pmovzxbw      (%1),   %%xmm2\n"    // store bytes as words with 0s in between
-              "pmovzxbw      (%2),   %%xmm3\n"
-              "psrlw          $2,    %%xmm2\n"    // rotate right 2
-              "psubusb       %%xmm1, %%xmm2\n"    // subtract
-              "psrlw          $2,    %%xmm3\n"
-              "paddsb        %%xmm1, %%xmm3\n"    // add
-              "packuswb      %%xmm2, %%xmm1\n"    // pack back to bytes
-              "movq          %%xmm1, (%0)  \n"    // load to dest
-              :
-              :"r" (dst), "r"(src), "r"(i_intensity)
-              :"memory");
-#endif
-}
-
-/*****************************************************************************
- * Memcpy8BMMX: Copies 8 bytes of memory in two instructions
- *****************************************************************************
- * Not quite clean, but it should be fast.
- *****************************************************************************/
-inline void Memcpy8BMMX(uint8_t * dst, const uint8_t * src)
-{
-#if defined(CAN_COMPILE_MMX) && 1
-    __asm__ volatile (
-              "movq       (%1), %%xmm0\n"
-              "movq       %%xmm0, (%0)\n"
-              :
-              :"r" (dst), "r"(src)
-              :"memory");
-#endif
-}
-
 static int FilterCallback ( vlc_object_t *p_this, char const *psz_var,
                             vlc_value_t oldval, vlc_value_t newval,
                             void *p_data )