]> git.sesse.net Git - vlc/blobdiff - modules/video_filter/transform.c
cdda/info: fix memleaks.
[vlc] / modules / video_filter / transform.c
index 538c41c38b300ab071bb4f1d139d157bd2ab33d1..e367817b717b095b793690ed7906e13f371c7957 100644 (file)
  * Preamble
  *****************************************************************************/
 
-#include <vlc/vlc.h>
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
 #include <vlc_vout.h>
 
 #include "filter_common.h"
@@ -48,6 +53,7 @@ static void End       ( vout_thread_t * );
 static void Render    ( vout_thread_t *, picture_t * );
 
 static void FilterPlanar( vout_thread_t *, const picture_t *, picture_t * );
+static void FilterI422( vout_thread_t *, const picture_t *, picture_t * );
 static void FilterYUYV( vout_thread_t *, const picture_t *, picture_t * );
 
 static int  SendEvents( vlc_object_t *, char const *,
@@ -59,30 +65,29 @@ static int  SendEvents( vlc_object_t *, char const *,
 #define TYPE_TEXT N_("Transform type")
 #define TYPE_LONGTEXT N_("One of '90', '180', '270', 'hflip' and 'vflip'")
 
-static const char *type_list[] = { "90", "180", "270", "hflip", "vflip" };
-static const char *type_list_text[] = { N_("Rotate by 90 degrees"),
+static const char *const type_list[] = { "90", "180", "270", "hflip", "vflip" };
+static const char *const type_list_text[] = { N_("Rotate by 90 degrees"),
   N_("Rotate by 180 degrees"), N_("Rotate by 270 degrees"),
   N_("Flip horizontally"), N_("Flip vertically") };
 
 #define CFG_PREFIX "transform-"
 
 vlc_module_begin();
-    set_description( _("Video transformation filter") );
-    set_shortname( _("Transformation"));
+    set_description( N_("Video transformation filter") );
+    set_shortname( N_("Transformation"));
     set_capability( "video filter", 0 );
     set_category( CAT_VIDEO );
     set_subcategory( SUBCAT_VIDEO_VFILTER );
 
     add_string( CFG_PREFIX "type", "90", NULL,
-                          TYPE_TEXT, TYPE_LONGTEXT, VLC_FALSE);
-        change_safe();
+                          TYPE_TEXT, TYPE_LONGTEXT, false);
         change_string_list( type_list, type_list_text, 0);
 
     add_shortcut( "transform" );
     set_callbacks( Create, Destroy );
 vlc_module_end();
 
-static const char *ppsz_filter_options[] = {
+static const char *const ppsz_filter_options[] = {
     "type", NULL
 };
 
@@ -95,7 +100,7 @@ static const char *ppsz_filter_options[] = {
 struct vout_sys_t
 {
     int i_mode;
-    vlc_bool_t b_rotation;
+    bool b_rotation;
     vout_thread_t *p_vout;
 
     void (*pf_filter)( vout_thread_t *, const picture_t *, picture_t * );
@@ -122,10 +127,7 @@ static int Create( vlc_object_t *p_this )
     /* Allocate structure */
     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
     if( p_vout->p_sys == NULL )
-    {
-        msg_Err( p_vout, "out of memory" );
         return VLC_ENOMEM;
-    }
 
     p_vout->pf_init = Init;
     p_vout->pf_end = End;
@@ -142,11 +144,16 @@ static int Create( vlc_object_t *p_this )
 
     switch( p_vout->fmt_in.i_chroma )
     {
-        CASE_PLANAR_YUV
+        CASE_PLANAR_YUV_SQUARE
         case VLC_FOURCC('G','R','E','Y'):
             p_vout->p_sys->pf_filter = FilterPlanar;
             break;
 
+        case VLC_FOURCC('I','4','2','2'):
+        case VLC_FOURCC('J','4','2','2'):
+            p_vout->p_sys->pf_filter = FilterI422;
+            break;
+
         CASE_PACKED_YUV_422
             p_vout->p_sys->pf_filter = FilterYUYV;
             break;
@@ -269,12 +276,18 @@ static void End( vout_thread_t *p_vout )
 {
     int i_index;
 
+    DEL_PARENT_CALLBACKS( SendEventsToChild );
+
+    DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
+
     /* Free the fake output buffers we allocated */
     for( i_index = I_OUTPUTPICTURES ; i_index ; )
     {
         i_index--;
         free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
     }
+
+    vout_CloseAndRelease( p_vout->p_sys->p_vout );
 }
 
 /*****************************************************************************
@@ -286,15 +299,6 @@ static void Destroy( vlc_object_t *p_this )
 {
     vout_thread_t *p_vout = (vout_thread_t *)p_this;
 
-    if( p_vout->p_sys->p_vout )
-    {
-        DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
-        vlc_object_detach( p_vout->p_sys->p_vout );
-        vout_Destroy( p_vout->p_sys->p_vout );
-    }
-
-    DEL_PARENT_CALLBACKS( SendEventsToChild );
-
     free( p_vout->p_sys );
 }
 
@@ -313,7 +317,7 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
     while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) )
               == NULL )
     {
-        if( p_vout->b_die || p_vout->b_error )
+        if( !vlc_object_alive (p_vout) || p_vout->b_error )
         {
             return;
         }
@@ -336,6 +340,7 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
 static int SendEvents( vlc_object_t *p_this, char const *psz_var,
                        vlc_value_t oldval, vlc_value_t newval, void *_p_vout )
 {
+    VLC_UNUSED(p_this); VLC_UNUSED(oldval);
     vout_thread_t *p_vout = (vout_thread_t *)_p_vout;
     vlc_value_t sentval = newval;
 
@@ -396,6 +401,7 @@ static int SendEvents( vlc_object_t *p_this, char const *psz_var,
 static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
+    VLC_UNUSED(p_data); VLC_UNUSED(oldval);
     vout_thread_t *p_vout = (vout_thread_t *)p_this;
     var_Set( p_vout->p_sys->p_vout, psz_var, newval );
     return VLC_SUCCESS;
@@ -510,8 +516,8 @@ static void FilterPlanar( vout_thread_t *p_vout,
                 for( ; p_in < p_in_end ; )
                 {
                     p_in_end -= p_pic->p[i_index].i_pitch;
-                    p_vout->p_libvlc->pf_memcpy( p_out, p_in_end,
-                                           p_pic->p[i_index].i_visible_pitch );
+                    vlc_memcpy( p_out, p_in_end,
+                                p_pic->p[i_index].i_visible_pitch );
                     p_out += p_pic->p[i_index].i_pitch;
                 }
             }
@@ -546,6 +552,156 @@ static void FilterPlanar( vout_thread_t *p_vout,
     }
 }
 
+static void FilterI422( vout_thread_t *p_vout,
+                        const picture_t *p_pic, picture_t *p_outpic )
+{
+    int i_index;
+    switch( p_vout->p_sys->i_mode )
+    {
+        case TRANSFORM_MODE_180:
+        case TRANSFORM_MODE_HFLIP:
+        case TRANSFORM_MODE_VFLIP:
+            /* Fall back on the default implementation */
+            FilterPlanar( p_vout, p_pic, p_outpic );
+            return;
+
+        case TRANSFORM_MODE_90:
+            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
+            {
+                int i_pitch = p_pic->p[i_index].i_pitch;
+
+                uint8_t *p_in = p_pic->p[i_index].p_pixels;
+
+                uint8_t *p_out = p_outpic->p[i_index].p_pixels;
+                uint8_t *p_out_end = p_out +
+                    p_outpic->p[i_index].i_visible_lines *
+                    p_outpic->p[i_index].i_pitch;
+
+                if( i_index == 0 )
+                {
+                    for( ; p_out < p_out_end ; )
+                    {
+                        uint8_t *p_line_end;
+
+                        p_out_end -= p_outpic->p[i_index].i_pitch
+                                      - p_outpic->p[i_index].i_visible_pitch;
+                        p_line_end = p_in + p_pic->p[i_index].i_visible_lines *
+                            i_pitch;
+
+                        for( ; p_in < p_line_end ; )
+                        {
+                            p_line_end -= i_pitch;
+                            *(--p_out_end) = *p_line_end;
+                        }
+
+                        p_in++;
+                    }
+                }
+                else /* i_index == 1 or 2 */
+                {
+                    for( ; p_out < p_out_end ; )
+                    {
+                        uint8_t *p_line_end, *p_out_end2;
+
+                        p_out_end -= p_outpic->p[i_index].i_pitch
+                                      - p_outpic->p[i_index].i_visible_pitch;
+                        p_out_end2 = p_out_end - p_outpic->p[i_index].i_pitch;
+                        p_line_end = p_in + p_pic->p[i_index].i_visible_lines *
+                            i_pitch;
+
+                        for( ; p_in < p_line_end ; )
+                        {
+                            uint8_t p1, p2;
+
+                            p_line_end -= i_pitch;
+                            p1 = *p_line_end;
+                            p_line_end -= i_pitch;
+                            p2 = *p_line_end;
+
+                            /* Trick for (x+y)/2 without overflow, based on
+                             *   x + y == (x ^ y) + 2 * (x & y) */
+                            *(--p_out_end) = (p1 & p2) + ((p1 ^ p2) / 2);
+                            *(--p_out_end2) = (p1 & p2) + ((p1 ^ p2) / 2);
+                        }
+
+                        p_out_end = p_out_end2;
+                        p_in++;
+                    }
+                }
+            }
+            break;
+
+        case TRANSFORM_MODE_270:
+            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
+            {
+                int i_pitch = p_pic->p[i_index].i_pitch;
+
+                uint8_t *p_in = p_pic->p[i_index].p_pixels;
+
+                uint8_t *p_out = p_outpic->p[i_index].p_pixels;
+                uint8_t *p_out_end = p_out +
+                    p_outpic->p[i_index].i_visible_lines *
+                    p_outpic->p[i_index].i_pitch;
+
+                if( i_index == 0 )
+                {
+                    for( ; p_out < p_out_end ; )
+                    {
+                        uint8_t *p_in_end;
+
+                        p_in_end = p_in + p_pic->p[i_index].i_visible_lines *
+                            i_pitch;
+
+                        for( ; p_in < p_in_end ; )
+                        {
+                            p_in_end -= i_pitch;
+                            *p_out++ = *p_in_end;
+                        }
+
+                        p_out += p_outpic->p[i_index].i_pitch
+                                  - p_outpic->p[i_index].i_visible_pitch;
+                        p_in++;
+                    }
+                }
+                else /* i_index == 1 or 2 */
+                {
+                    for( ; p_out < p_out_end ; )
+                    {
+                        uint8_t *p_in_end, *p_out2;
+
+                        p_in_end = p_in + p_pic->p[i_index].i_visible_lines *
+                            i_pitch;
+                        p_out2 = p_out + p_outpic->p[i_index].i_pitch;
+
+                        for( ; p_in < p_in_end ; )
+                        {
+                            uint8_t p1, p2;
+
+                            p_in_end -= i_pitch;
+                            p1 = *p_in_end;
+                            p_in_end -= i_pitch;
+                            p2 = *p_in_end;
+
+                            /* Trick for (x+y)/2 without overflow, based on
+                             *   x + y == (x ^ y) + 2 * (x & y) */
+                            *p_out++ = (p1 & p2) + ((p1 ^ p2) / 2);
+                            *p_out2++ = (p1 & p2) + ((p1 ^ p2) / 2);
+                        }
+
+                        p_out2 += p_outpic->p[i_index].i_pitch
+                                   - p_outpic->p[i_index].i_visible_pitch;
+                        p_out = p_out2;
+                        p_in++;
+                    }
+                }
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
 static void FilterYUYV( vout_thread_t *p_vout,
                         const picture_t *p_pic, picture_t *p_outpic )
 {
@@ -557,6 +713,11 @@ static void FilterYUYV( vout_thread_t *p_vout,
 
     switch( p_vout->p_sys->i_mode )
     {
+        case TRANSFORM_MODE_HFLIP:
+            /* Fall back on the default implementation */
+            FilterPlanar( p_vout, p_pic, p_outpic );
+            return;
+
         case TRANSFORM_MODE_90:
             for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
             {
@@ -679,25 +840,6 @@ static void FilterYUYV( vout_thread_t *p_vout,
             }
             break;
 
-        case TRANSFORM_MODE_HFLIP:
-            for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
-            {
-                uint8_t *p_in = p_pic->p[i_index].p_pixels;
-                uint8_t *p_in_end = p_in + p_pic->p[i_index].i_visible_lines
-                                            * p_pic->p[i_index].i_pitch;
-
-                uint8_t *p_out = p_outpic->p[i_index].p_pixels;
-
-                for( ; p_in < p_in_end ; )
-                {
-                    p_in_end -= p_pic->p[i_index].i_pitch;
-                    p_vout->p_libvlc->pf_memcpy( p_out, p_in_end,
-                                           p_pic->p[i_index].i_visible_pitch );
-                    p_out += p_pic->p[i_index].i_pitch;
-                }
-            }
-            break;
-
         case TRANSFORM_MODE_VFLIP:
             for( i_index = 0 ; i_index < p_pic->i_planes ; i_index++ )
             {