]> git.sesse.net Git - vlc/blobdiff - modules/video_filter/wrapper.c
Removed non converted opengl video output module.
[vlc] / modules / video_filter / wrapper.c
index 2ad2337a5c3e09b4384c6ad80381d86d3e62b4b7..99ff4276e7f409d8bcfae14a4600bcda1d7b8d94 100644 (file)
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * wrapper.c: a "video filter2" with mouse to "video filter" wrapper.
+ * wrapper.c: a "video filter2/splitter" with mouse to "video filter" wrapper.
  *****************************************************************************
  * Copyright (C) 2009 Laurent Aimar
  * $Id$
 #include <vlc_plugin.h>
 #include <vlc_vout.h>
 #include <vlc_filter.h>
+#include <vlc_video_splitter.h>
 
 #include "filter_common.h"
 
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
-static int  Open ( vlc_object_t *, const char *psz_name );
+static int  Open ( vlc_object_t *, const char *psz_name, bool b_filter );
 static void Close( vlc_object_t * );
 
-#define DECLARE_OPEN(name) \
-    static int  Open##name ( vlc_object_t *p_this ) { return Open( p_this, #name ); }
+#define DECLARE_OPEN(name,filter) \
+    static int  Open##name ( vlc_object_t *p_this ) { return Open( p_this, #name, filter ); }
 
-DECLARE_OPEN(magnify)
-DECLARE_OPEN(puzzle)
-DECLARE_OPEN(logo)
+DECLARE_OPEN(clone, false)
+DECLARE_OPEN(wall, false)
+DECLARE_OPEN(panoramix, false)
 
 #undef DECLARE_OPEN
 
@@ -63,13 +64,13 @@ vlc_module_begin()
     set_category( CAT_VIDEO )
     set_subcategory( SUBCAT_VIDEO_VFILTER )
 
-    DECLARE_MODULE(magnify)
+    DECLARE_MODULE(clone)
 
     add_submodule()
-    DECLARE_MODULE(puzzle)
+    DECLARE_MODULE(wall)
 
     add_submodule()
-    DECLARE_MODULE(logo)
+    DECLARE_MODULE(panoramix)
 
 vlc_module_end()
 
@@ -85,67 +86,106 @@ static int Control    ( vout_thread_t *, int, va_list );
 
 struct vout_sys_t
 {
-    vout_thread_t *p_vout;
+    int              i_vout;
+    vout_thread_t    **pp_vout;
 
-    es_format_t    fmt;
+    es_format_t      fmt;
 
-    vlc_mutex_t    lock;
-    filter_chain_t *p_chain;
-    vlc_mouse_t    mouse;
-};
+    vlc_mutex_t      lock;
+    filter_chain_t   *p_chain;
+    video_splitter_t *p_splitter;
 
-static int  MouseEvent( vlc_object_t *, char const *,
-                        vlc_value_t, vlc_value_t, void * );
+    vlc_mouse_t      *p_mouse_src;
+    vlc_mouse_t      mouse;
+};
 
+/* */
 static int  FilterAllocationInit ( filter_t *, void * );
 static void FilterAllocationClean( filter_t * );
 
+/* */
+static int  FullscreenEventDown( vlc_object_t *, char const *,
+                                 vlc_value_t, vlc_value_t, void * );
+static int  SplitterPictureNew( video_splitter_t *, picture_t *pp_picture[] );
+static void SplitterPictureDel( video_splitter_t *, picture_t *pp_picture[] );
+
+/* */
+static int  MouseEvent( vlc_object_t *, char const *,
+                        vlc_value_t, vlc_value_t, void * );
+static void VoutsClean( vout_thread_t *p_vout, int i_count );
+
 /**
  * Open our wrapper instance.
  */
-static int Open( vlc_object_t *p_this, const char *psz_name )
+static int Open( vlc_object_t *p_this, const char *psz_name, bool b_filter )
 {
     vout_thread_t *p_vout = (vout_thread_t *)p_this;
     vout_sys_t *p_sys;
 
-    msg_Err( p_vout, "Opening video filter wrapper for %s", psz_name );
-
-    /* Try to open our filter */
-    filter_chain_t *p_chain =
-        filter_chain_New( p_vout, "video filter2", false,
-                          FilterAllocationInit, FilterAllocationClean, p_vout );
-    if( !p_chain )
-        return VLC_ENOMEM;
+    msg_Err( p_vout, "Opening video %s wrapper for %s",
+             b_filter ? "filter" : "splitter", psz_name );
 
+    /* */
     es_format_t fmt;
     es_format_Init( &fmt, VIDEO_ES, p_vout->render.i_chroma );
     video_format_Setup( &fmt.video, p_vout->render.i_chroma,
                         p_vout->render.i_width, p_vout->render.i_height,
-                        p_vout->render.i_aspect );
+                        p_vout->render.i_aspect * p_vout->render.i_height,
+                        VOUT_ASPECT_FACTOR      * p_vout->render.i_width );
 
-    filter_chain_Reset( p_chain, &fmt, &fmt );
-
-    filter_t *p_filter =
-        filter_chain_AppendFilter( p_chain, psz_name, p_vout->p_cfg, &fmt, &fmt );
-
-    if( !p_filter )
+    /* Try to open our real module */
+    filter_chain_t   *p_chain = NULL;
+    video_splitter_t *p_splitter = NULL;
+    if( b_filter )
     {
-        msg_Err( p_vout, "Failed to open filter '%s'", psz_name );
-        filter_chain_Delete( p_chain );
-        return VLC_EGENERIC;
+        p_chain = filter_chain_New( p_vout, "video filter2", false,
+                                    FilterAllocationInit, FilterAllocationClean, p_vout );
+        if( !p_chain )
+            return VLC_ENOMEM;
+
+        filter_chain_Reset( p_chain, &fmt, &fmt );
+
+        filter_t *p_filter =
+            filter_chain_AppendFilter( p_chain, psz_name, p_vout->p_cfg, &fmt, &fmt );
+
+        if( !p_filter )
+        {
+            msg_Err( p_vout, "Failed to open filter '%s'", psz_name );
+            filter_chain_Delete( p_chain );
+            return VLC_EGENERIC;
+        }
+    }
+    else
+    {
+        p_splitter = video_splitter_New( VLC_OBJECT(p_vout), psz_name, &fmt.video );
+        if( !p_splitter )
+        {
+            msg_Err( p_vout, "Failed to open splitter '%s'", psz_name );
+            return VLC_EGENERIC;
+        }
+        assert( p_splitter->i_output > 0 );
+
+        p_splitter->p_owner = (video_splitter_owner_t*)p_vout;
+        p_splitter->pf_picture_new = SplitterPictureNew;
+        p_splitter->pf_picture_del = SplitterPictureDel;
     }
 
+    /* */
     p_vout->p_sys = p_sys = malloc( sizeof(*p_sys) );
     if( !p_sys )
-    {
-        filter_chain_Delete( p_chain );
-        return VLC_ENOMEM;
-    }
+        goto error;
+
+    p_sys->i_vout  = p_chain ? 1 : p_splitter->i_output;
+    p_sys->pp_vout = calloc( p_sys->i_vout, sizeof(*p_sys->pp_vout) );;
+    p_sys->p_mouse_src = calloc( p_sys->i_vout, sizeof(*p_sys->p_mouse_src) );
+
     p_sys->fmt = fmt;
     vlc_mutex_init( &p_sys->lock );
-    p_sys->p_chain = p_chain;
-    p_sys->p_vout = NULL;
+    p_sys->p_chain    = p_chain;
+    p_sys->p_splitter = p_splitter;
     vlc_mouse_Init( &p_sys->mouse );
+    for( int i = 0; i < p_sys->i_vout; i++ )
+        vlc_mouse_Init( &p_sys->p_mouse_src[i] );
 
     p_vout->pf_init = Init;
     p_vout->pf_end = End;
@@ -155,6 +195,13 @@ static int Open( vlc_object_t *p_this, const char *psz_name )
     p_vout->pf_control = Control;
 
     return VLC_SUCCESS;
+
+error:
+    if( p_chain )
+        filter_chain_Delete( p_chain );
+    if( p_splitter )
+        video_splitter_Delete( p_splitter );
+    return VLC_ENOMEM;
 }
 
 /**
@@ -165,9 +212,15 @@ static void Close( vlc_object_t *p_this )
     vout_thread_t *p_vout = (vout_thread_t *)p_this;
     vout_sys_t *p_sys = p_vout->p_sys;
 
-    filter_chain_Delete( p_sys->p_chain );
+    if( p_sys->p_chain )
+        filter_chain_Delete( p_sys->p_chain );
+    if( p_sys->p_splitter )
+        video_splitter_Delete( p_sys->p_splitter );
+
     vlc_mutex_destroy( &p_sys->lock );
     es_format_Clean( &p_sys->fmt );
+    free( p_sys->p_mouse_src );
+    free( p_sys->pp_vout );
 
     free( p_vout->p_sys );
 }
@@ -193,20 +246,69 @@ static int Init( vout_thread_t *p_vout )
     p_vout->fmt_out = p_vout->fmt_in;
 
     /* Try to open the real video output */
-    msg_Dbg( p_vout, "spawning the real video output" );
+    msg_Dbg( p_vout, "spawning the real video output(s)" );
 
     video_format_t fmt = p_vout->fmt_out;
-    p_sys->p_vout = vout_Create( p_vout, &fmt );
-    if( !p_sys->p_vout )
+
+    if( p_sys->p_chain )
     {
-        msg_Err( p_vout, "cannot open vout, aborting" );
-        return VLC_EGENERIC;
+        p_sys->pp_vout[0] = vout_Create( p_vout, &fmt );
+        if( !p_sys->pp_vout[0] )
+        {
+            msg_Err( p_vout, "cannot open vout, aborting" );
+            return VLC_EGENERIC;
+        }
+        vout_filter_AddChild( p_vout, p_sys->pp_vout[0], MouseEvent );
+    }
+    else
+    {
+        video_splitter_t *p_splitter = p_sys->p_splitter;
+
+        /* */
+        const int i_org_align = var_CreateGetInteger( p_vout, "align" );
+        const int i_org_x = var_CreateGetInteger( p_vout, "video-x" );
+        const int i_org_y = var_CreateGetInteger( p_vout, "video-y" );
+        const char *psz_org_vout = var_CreateGetNonEmptyString( p_vout, "vout" );
+
+        /* */
+        for( int i = 0; i < p_splitter->i_output; i++ )
+        {
+            const video_splitter_output_t *p_cfg = &p_splitter->p_output[i];
+
+            /* */
+            var_SetInteger( p_vout, "align", p_cfg->window.i_align);
+
+            var_SetInteger( p_vout, "video-x", i_org_x + p_cfg->window.i_x );
+            var_SetInteger( p_vout, "video-y", i_org_y + p_cfg->window.i_y );
+
+            if( p_cfg->psz_module )
+                var_SetString( p_vout, "vout", p_cfg->psz_module );
+
+            /* */
+            video_format_t fmt = p_cfg->fmt;
+            p_sys->pp_vout[i] = vout_Create( p_vout, &fmt );
+            if( !p_sys->pp_vout[i] )
+            {
+                msg_Err( p_vout, "cannot open vout, aborting" );
+                VoutsClean( p_vout, i );
+                return VLC_EGENERIC;
+            }
+        }
+
+        /* Attach once pp_vout is completly filed to avoid race conditions */
+        for( int i = 0; i < p_splitter->i_output; i++ )
+            vout_filter_SetupChild( p_vout, p_sys->pp_vout[i],
+                                    MouseEvent,
+                                    FullscreenEventDown, true );
+        /* Restore settings */
+        var_SetInteger( p_vout, "align", i_org_align );
+        var_SetInteger( p_vout, "video-x", i_org_x );
+        var_SetInteger( p_vout, "video-y", i_org_y );
+        var_SetString( p_vout, "vout", psz_org_vout ? psz_org_vout : "" );
     }
 
     vout_filter_AllocateDirectBuffers( p_vout, VOUT_MAX_PICTURES );
 
-    vout_filter_AddChild( p_vout, p_vout->p_sys->p_vout, MouseEvent );
-
     return VLC_SUCCESS;
 }
 
@@ -217,8 +319,7 @@ static void End( vout_thread_t *p_vout )
 {
     vout_sys_t *p_sys = p_vout->p_sys;
 
-    vout_filter_DelChild( p_vout, p_sys->p_vout, MouseEvent );
-    vout_CloseAndRelease( p_sys->p_vout );
+    VoutsClean( p_vout, p_sys->i_vout );
 
     vout_filter_ReleaseDirectBuffers( p_vout );
 }
@@ -228,7 +329,12 @@ static void End( vout_thread_t *p_vout )
  */
 static int Control( vout_thread_t *p_vout, int i_query, va_list args )
 {
-    return vout_vaControl( p_vout->p_sys->p_vout, i_query, args );
+    vout_sys_t *p_sys = p_vout->p_sys;
+    int i_ret = VLC_SUCCESS;
+
+    for( int i = 0; i < p_sys->i_vout; i++ )
+        i_ret = vout_vaControl( p_sys->pp_vout[i], i_query, args );
+    return i_ret;
 }
 
 /**
@@ -239,33 +345,123 @@ static void Render( vout_thread_t *p_vout, picture_t *p_src )
     vout_sys_t *p_sys = p_vout->p_sys;
 
     vlc_mutex_lock( &p_sys->lock );
-    picture_t *p_dst = filter_chain_VideoFilter( p_sys->p_chain, p_src );
-    if( p_dst )
-        vout_DisplayPicture( p_sys->p_vout, p_dst );
+
+    picture_t *pp_dst[p_sys->i_vout];
+
+    if( p_sys->p_chain )
+    {
+        pp_dst[0] = filter_chain_VideoFilter( p_sys->p_chain, p_src );
+    }
+    else
+    {
+        if( video_splitter_Filter( p_sys->p_splitter, pp_dst, p_src ) )
+        {
+            for( int i = 0; i < p_sys->i_vout; i++ )
+                pp_dst[i] = NULL;
+        }
+    }
+    for( int i = 0; i < p_sys->i_vout; i++ )
+    {
+        picture_t *p_dst = pp_dst[i];
+        if( p_dst )
+            vout_DisplayPicture( p_sys->pp_vout[i], p_dst );
+    }
+
     vlc_mutex_unlock( &p_sys->lock );
 }
 
+/* */
+static void VoutsClean( vout_thread_t *p_vout, int i_count )
+{
+    vout_sys_t *p_sys = p_vout->p_sys;
+
+    /* Detach all vouts before destroying them */
+    for( int i = 0; i < i_count; i++ )
+    {
+        if( p_sys->p_chain )
+            vout_filter_DelChild( p_vout, p_sys->pp_vout[i], MouseEvent );
+        else
+             vout_filter_SetupChild( p_vout, p_sys->pp_vout[i],
+                                     MouseEvent,
+                                     FullscreenEventDown, false );
+    }
+
+    for( int i = 0; i < i_count; i++ )
+        vout_CloseAndRelease( p_sys->pp_vout[i] );
+}
+static int VoutsNewPicture( vout_thread_t *p_vout, picture_t *pp_dst[] )
+{
+    vout_sys_t *p_sys = p_vout->p_sys;
+
+    for( int i = 0; i < p_sys->i_vout; i++ )
+    {
+        picture_t *p_picture = NULL;
+        for( ;; )
+        {
+            p_picture = vout_CreatePicture( p_sys->pp_vout[i], 0, 0, 0 );
+            if( p_picture )
+                break;
+
+            if( !vlc_object_alive( p_vout ) || p_vout->b_error )
+                break;
+            msleep( VOUT_OUTMEM_SLEEP );
+        }
+        /* FIXME what to do with the allocated picture ? */
+        if( !p_picture )
+            return VLC_EGENERIC;
+
+        pp_dst[i] = p_picture;
+    }
+    return VLC_SUCCESS;
+}
+
 /**
  * Callback for mouse events
  */
 static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
 {
+    VLC_UNUSED(psz_var); VLC_UNUSED(oldval); VLC_UNUSED(newval);
     vout_thread_t *p_vout = p_data;
     vout_sys_t *p_sys = p_vout->p_sys;
+    int i_index;
+
+    for( i_index = 0; i_index < p_sys->i_vout; i_index++ )
+    {
+        if( p_this == VLC_OBJECT(p_sys->pp_vout[i_index]) )
+            break;
+    }
+    if( i_index >= p_sys->i_vout )
+    {
+        msg_Err( p_vout, "Failed to find vout source in MouseEvent" );
+        return VLC_SUCCESS;
+    }
+
+    vout_thread_t *p_vout_src = p_sys->pp_vout[i_index];
 
     vlc_mouse_t m;
     vlc_mouse_Init( &m );
-    m.i_x = var_GetInteger( p_sys->p_vout, "mouse-x" );
-    m.i_y = var_GetInteger( p_sys->p_vout, "mouse-y" );
-    m.i_pressed = var_GetInteger( p_sys->p_vout, "mouse-button-down" );
+    var_GetCoords( p_vout_src, "mouse-moved", &m.i_x, &m.i_y );
+    m.i_pressed = var_GetInteger( p_vout_src, "mouse-button-down" );
 
     vlc_mutex_lock( &p_sys->lock );
 
     vlc_mouse_t nmouse;
     vlc_mouse_t omouse = p_sys->mouse;
 
-    int i_ret = filter_chain_MouseFilter( p_sys->p_chain, &nmouse, &m );
+    int i_ret;
+    if( p_sys->p_chain )
+    {
+        i_ret = filter_chain_MouseFilter( p_sys->p_chain, &nmouse, &m );
+    }
+    else
+    {
+        vlc_mouse_t *p_mouse_src = &p_sys->p_mouse_src[i_index];
+
+        i_ret = video_splitter_Mouse( p_sys->p_splitter, &nmouse, i_index, p_mouse_src, &m );
+        *p_mouse_src = m;
+    }
+
     if( !i_ret )
         p_sys->mouse = nmouse;
     vlc_mutex_unlock( &p_sys->lock );
@@ -275,15 +471,13 @@ static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
 
     if( vlc_mouse_HasMoved( &omouse, &nmouse ) )
     {
-        var_SetInteger( p_vout, "mouse-x", nmouse.i_x );
-        var_SetInteger( p_vout, "mouse-y", nmouse.i_y );
-        var_SetBool( p_vout, "mouse-moved", true );
+        var_SetCoords( p_vout, "mouse-moved", nmouse.i_x, nmouse.i_y );
     }
     if( vlc_mouse_HasButton( &omouse, &nmouse ) )
     {
         var_SetInteger( p_vout, "mouse-button-down", nmouse.i_pressed );
         if( vlc_mouse_HasPressed( &omouse, &nmouse, MOUSE_BUTTON_LEFT ) )
-            var_SetBool( p_vout, "mouse-clicked", true );
+            var_SetCoords( p_vout, "mouse-clicked", nmouse.i_x, nmouse.i_y );
     }
     if( m.b_double_click )
     {
@@ -293,23 +487,16 @@ static int MouseEvent( vlc_object_t *p_this, char const *psz_var,
     return VLC_SUCCESS;
 }
 
-/* */
+/* -- Filter callbacks -- */
+
 static picture_t *VideoBufferNew( filter_t *p_filter )
 {
     vout_thread_t *p_vout = (vout_thread_t*)p_filter->p_owner;
-    vout_sys_t *p_sys = p_vout->p_sys;
-
-    picture_t *p_picture;
-    for( ;; )
-    {
-        p_picture = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 );
-        if( p_picture )
-            return p_picture;
 
-        if( !vlc_object_alive( p_vout ) || p_vout->b_error )
-            return NULL;
-        msleep( VOUT_OUTMEM_SLEEP );
-    }
+    picture_t *pp_picture[1];
+    if( VoutsNewPicture( p_vout, pp_picture ) )
+        return NULL;
+    return pp_picture[0];
 }
 static void VideoBufferDelete( filter_t *p_filter, picture_t *p_picture )
 {
@@ -321,15 +508,44 @@ static int FilterAllocationInit( filter_t *p_filter, void *p_data )
 {
     VLC_UNUSED( p_data );
 
-    p_filter->pf_vout_buffer_new = VideoBufferNew;
-    p_filter->pf_vout_buffer_del = VideoBufferDelete;
+    p_filter->pf_video_buffer_new = VideoBufferNew;
+    p_filter->pf_video_buffer_del = VideoBufferDelete;
     p_filter->p_owner = p_data;
 
     return VLC_SUCCESS;
 }
 static void FilterAllocationClean( filter_t *p_filter )
 {
-    p_filter->pf_vout_buffer_new = NULL;
-    p_filter->pf_vout_buffer_del = NULL;
+    p_filter->pf_video_buffer_new = NULL;
+    p_filter->pf_video_buffer_del = NULL;
+}
+
+/* -- Splitter callbacks -- */
+
+static int FullscreenEventDown( vlc_object_t *p_this, char const *psz_var,
+                                vlc_value_t oldval, vlc_value_t newval, void *p_data )
+{
+    vout_thread_t *p_vout = (vout_thread_t*)p_this;
+    vout_sys_t *p_sys = p_vout->p_sys;
+    VLC_UNUSED(oldval); VLC_UNUSED(p_data); VLC_UNUSED(psz_var);
+
+    for( int i = 0; i < p_sys->i_vout; i++ )
+    {
+        vout_thread_t *p_child = p_sys->pp_vout[i];
+        var_SetBool( p_child, "fullscreen", newval.b_bool );
+    }
+    return VLC_SUCCESS;
+}
+
+static int  SplitterPictureNew( video_splitter_t *p_splitter, picture_t *pp_picture[] )
+{
+    vout_thread_t *p_vout = (vout_thread_t*)p_splitter->p_owner;
+
+    return VoutsNewPicture( p_vout, pp_picture );
+}
+static void SplitterPictureDel( video_splitter_t *p_splitter, picture_t *pp_picture[] )
+{
+    VLC_UNUSED(p_splitter); VLC_UNUSED(pp_picture);
+    /* FIXME is there anything to do ? */
 }