]> git.sesse.net Git - vlc/blobdiff - src/video_output/vout_subpictures.c
Gives the input_thread_t to use to vout_Request().
[vlc] / src / video_output / vout_subpictures.c
index a4e7c60e9731aecdd65751aeeeaa10180a25348c..123d4da3e18856a9d6149eeb0ddc8c1931586329 100644 (file)
@@ -37,7 +37,7 @@
 #include <vlc_vout.h>
 #include <vlc_block.h>
 #include <vlc_filter.h>
-#include <vlc_osd.h>
+#include <vlc_spu.h>
 #include "../libvlc.h"
 #include "vout_internal.h"
 #include <vlc_image.h>
@@ -88,6 +88,7 @@ struct spu_private_t
 
     /* Subpiture filters */
     char           *psz_chain_update;
+    vlc_mutex_t    chain_lock;
     filter_chain_t *p_chain;
 
     /* */
@@ -163,10 +164,6 @@ static int  CropCallback( vlc_object_t *, char const *,
 static int MarginCallback( vlc_object_t *, char const *,
                            vlc_value_t, vlc_value_t, void * );
 
-static int SpuControl( spu_t *, int, va_list );
-
-static void SpuClearChannel( spu_t *p_spu, int i_channel );
-
 /* Buffer allocation for SPU filter (blend, scale, ...) */
 static subpicture_t *spu_new_buffer( filter_t * );
 static void spu_del_buffer( filter_t *, subpicture_t * );
@@ -174,9 +171,6 @@ static picture_t *spu_new_video_buffer( filter_t * );
 static void spu_del_video_buffer( filter_t *, picture_t * );
 
 /* Buffer aloccation fir SUB filter */
-static int SubFilterCallback( vlc_object_t *, char const *,
-                              vlc_value_t, vlc_value_t, void * );
-
 static int SubFilterAllocationInit( filter_t *, void * );
 static void SubFilterAllocationClean( filter_t * );
 
@@ -207,7 +201,6 @@ spu_t *spu_Create( vlc_object_t *p_this )
     vlc_object_attach( p_spu, p_this );
 
     /* Initialize spu fields */
-    p_spu->pf_control = SpuControl;
     p_spu->p = p_sys = (spu_private_t*)&p_spu[1];
 
     /* Initialize private fields */
@@ -226,6 +219,7 @@ spu_t *spu_Create( vlc_object_t *p_this )
     p_sys->i_channel = 2;
 
     p_sys->psz_chain_update = NULL;
+    vlc_mutex_init( &p_sys->chain_lock );
     p_sys->p_chain = filter_chain_New( p_spu, "sub filter", false,
                                        SubFilterAllocationInit,
                                        SubFilterAllocationClean,
@@ -241,20 +235,6 @@ spu_t *spu_Create( vlc_object_t *p_this )
     return p_spu;
 }
 
-/**
- * Initialise the subpicture unit
- *
- * \param p_spu the subpicture unit object
- */
-int spu_Init( spu_t *p_spu )
-{
-    var_Create( p_spu, "sub-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
-    var_AddCallback( p_spu, "sub-filter", SubFilterCallback, p_spu );
-    var_TriggerCallback( p_spu, "sub-filter" );
-
-    return VLC_SUCCESS;
-}
-
 /**
  * Destroy the subpicture unit
  *
@@ -264,8 +244,6 @@ void spu_Destroy( spu_t *p_spu )
 {
     spu_private_t *p_sys = p_spu->p;
 
-    var_DelCallback( p_spu, "sub-filter", SubFilterCallback, p_spu );
-
     if( p_sys->p_blend )
         filter_DeleteBlend( p_sys->p_blend );
 
@@ -279,6 +257,7 @@ void spu_Destroy( spu_t *p_spu )
         FilterRelease( p_sys->p_scale );
 
     filter_chain_Delete( p_sys->p_chain );
+    vlc_mutex_destroy( &p_sys->chain_lock );
     free( p_sys->psz_chain_update );
 
     /* Destroy all remaining subpictures */
@@ -295,14 +274,8 @@ void spu_Destroy( spu_t *p_spu )
  * \param p_this the object in which to destroy the subpicture unit
  * \param b_attach to select attach or detach
  */
-void spu_Attach( spu_t *p_spu, vlc_object_t *p_this, bool b_attach )
+void spu_Attach( spu_t *p_spu, vlc_object_t *p_input, bool b_attach )
 {
-    vlc_object_t *p_input;
-
-    p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT );
-    if( !p_input )
-        return;
-
     if( b_attach )
     {
         UpdateSPU( p_spu, VLC_OBJECT(p_input) );
@@ -313,8 +286,6 @@ void spu_Attach( spu_t *p_spu, vlc_object_t *p_this, bool b_attach )
         vlc_mutex_lock( &p_spu->p->lock );
         p_spu->p->i_margin = var_GetInteger( p_input, "sub-margin" );
         vlc_mutex_unlock( &p_spu->p->lock );
-
-        vlc_object_release( p_input );
     }
     else
     {
@@ -322,10 +293,25 @@ void spu_Attach( spu_t *p_spu, vlc_object_t *p_this, bool b_attach )
         var_DelCallback( p_input, "sub-margin", MarginCallback, p_spu->p );
         var_DelCallback( p_input, "highlight", CropCallback, p_spu );
         var_Destroy( p_input, "highlight" );
-        vlc_object_release( p_input );
     }
 }
 
+/**
+ * Inform the SPU filters of mouse event
+ */
+int spu_ProcessMouse( spu_t *p_spu,
+                      const vlc_mouse_t *p_mouse,
+                      const video_format_t *p_fmt )
+{
+    spu_private_t *p_sys = p_spu->p;
+
+    vlc_mutex_lock( &p_sys->chain_lock );
+    filter_chain_MouseEvent( p_sys->p_chain, p_mouse, p_fmt );
+    vlc_mutex_unlock( &p_sys->chain_lock );
+
+    return VLC_SUCCESS;
+}
+
 /**
  * Display a subpicture
  *
@@ -338,9 +324,9 @@ void spu_DisplaySubpicture( spu_t *p_spu, subpicture_t *p_subpic )
 {
     spu_private_t *p_sys = p_spu->p;
 
-    /* DEFAULT_CHAN always reset itself */
-    if( p_subpic->i_channel == DEFAULT_CHAN )
-        SpuClearChannel( p_spu, DEFAULT_CHAN );
+    /* SPU_DEFAULT_CHANNEL always reset itself */
+    if( p_subpic->i_channel == SPU_DEFAULT_CHANNEL )
+        spu_ClearChannel( p_spu, SPU_DEFAULT_CHANNEL );
 
     /* p_private is for spu only and cannot be non NULL here */
     for( subpicture_region_t *r = p_subpic->p_region; r != NULL; r = r->p_next )
@@ -552,6 +538,7 @@ subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t render_subtitle_date,
     p_sys->psz_chain_update = NULL;
     vlc_mutex_unlock( &p_sys->lock );
 
+    vlc_mutex_lock( &p_sys->chain_lock );
     if( psz_chain_update )
     {
         filter_chain_Reset( p_sys->p_chain, NULL, NULL );
@@ -560,9 +547,9 @@ subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t render_subtitle_date,
 
         free( psz_chain_update );
     }
-
     /* Run subpicture filters */
     filter_chain_SubFilter( p_sys->p_chain, render_osd_date );
+    vlc_mutex_unlock( &p_sys->chain_lock );
 
     vlc_mutex_lock( &p_sys->lock );
 
@@ -695,6 +682,52 @@ void spu_OffsetSubtitleDate( spu_t *p_spu, mtime_t i_duration )
     vlc_mutex_unlock( &p_sys->lock );
 }
 
+int spu_RegisterChannel( spu_t *p_spu )
+{
+    spu_private_t *p_sys = p_spu->p;
+
+    vlc_mutex_lock( &p_sys->lock );
+    int i_channel = p_sys->i_channel++;
+    vlc_mutex_unlock( &p_sys->lock );
+
+    return i_channel;
+}
+
+void spu_ClearChannel( spu_t *p_spu, int i_channel )
+{
+    spu_private_t *p_sys = p_spu->p;
+
+    vlc_mutex_lock( &p_sys->lock );
+
+    for( int i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
+    {
+        spu_heap_entry_t *p_entry = &p_sys->heap.p_entry[i_subpic];
+        subpicture_t *p_subpic = p_entry->p_subpicture;
+
+        if( !p_subpic )
+            continue;
+        if( p_subpic->i_channel != i_channel && ( i_channel != -1 || p_subpic->i_channel == SPU_DEFAULT_CHANNEL ) )
+            continue;
+
+        /* You cannot delete subpicture outside of spu_SortSubpictures */
+        p_entry->b_reject = true;
+    }
+
+    vlc_mutex_unlock( &p_sys->lock );
+}
+
+void spu_ChangeFilters( spu_t *p_spu, const char *psz_filters )
+{
+    spu_private_t *p_sys = p_spu->p;
+
+    vlc_mutex_lock( &p_sys->lock );
+
+    free( p_sys->psz_chain_update );
+    p_sys->psz_chain_update = strdup( psz_filters );
+
+    vlc_mutex_unlock( &p_sys->lock );
+}
+
 /*****************************************************************************
  * subpicture_t allocation
  *****************************************************************************/
@@ -1355,25 +1388,6 @@ static void SpuRegionPlace( int *pi_x, int *pi_y,
         i_y = i_delta_y;
     }
 
-    /* Margin shifts all subpictures */
-    /* NOTE We have margin only for subtitles, so we don't really need this here
-    if( i_margin_y != 0 )
-        i_y -= i_margin_y;*/
-
-    /* Clamp offset to not go out of the screen (when possible) */
-    /* NOTE Again, useful only for subtitles, otherwise goes against the alignment logic above
-    const int i_error_x = (i_x + p_region->fmt.i_width) - p_subpic->i_original_picture_width;
-    if( i_error_x > 0 )
-        i_x -= i_error_x;
-    if( i_x < 0 )
-        i_x = 0;
-
-    const int i_error_y = (i_y + p_region->fmt.i_height) - p_subpic->i_original_picture_height;
-    if( i_error_y > 0 )
-        i_y -= i_error_y;
-    if( i_y < 0 )
-        i_y = 0;*/
-
     *pi_x = i_x;
     *pi_y = i_y;
 }
@@ -1480,12 +1494,11 @@ static void SpuRenderRegion( spu_t *p_spu,
 
     /* apply margin to subtitles and correct if they go over the picture edge */
     if( p_subpic->b_subtitle )
-    {
         restrained.i_y -= i_margin_y;
-        spu_area_t display = spu_area_create( 0, 0, p_fmt->i_width, p_fmt->i_height,
-                                              spu_scale_unit() );
-        SpuAreaFitInside( &restrained, &display );
-    }
+
+    spu_area_t display = spu_area_create( 0, 0, p_fmt->i_width, p_fmt->i_height,
+                                          spu_scale_unit() );
+    SpuAreaFitInside( &restrained, &display );
 
     /* Fix the position for the current scale_size */
     i_x_offset = spu_scale_w( restrained.i_x, restrained.scale );
@@ -1739,67 +1752,6 @@ static int SubpictureCmp( const void *s0, const void *s1 )
     return r;
 }
 
-/*****************************************************************************
- * SpuClearChannel: clear an spu channel
- *****************************************************************************
- * This function destroys the subpictures which belong to the spu channel
- * corresponding to i_channel_id.
- *****************************************************************************/
-static void SpuClearChannel( spu_t *p_spu, int i_channel )
-{
-    spu_private_t *p_sys = p_spu->p;
-    int          i_subpic;                               /* subpicture index */
-
-    vlc_mutex_lock( &p_sys->lock );
-
-    for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
-    {
-        spu_heap_entry_t *p_entry = &p_sys->heap.p_entry[i_subpic];
-        subpicture_t *p_subpic = p_entry->p_subpicture;
-
-        if( !p_subpic )
-            continue;
-        if( p_subpic->i_channel != i_channel && ( i_channel != -1 || p_subpic->i_channel == DEFAULT_CHAN ) )
-            continue;
-
-        /* You cannot delete subpicture outside of spu_SortSubpictures */
-        p_entry->b_reject = true;
-    }
-
-    vlc_mutex_unlock( &p_sys->lock );
-}
-
-/*****************************************************************************
- * spu_ControlDefault: default methods for the subpicture unit control.
- *****************************************************************************/
-static int SpuControl( spu_t *p_spu, int i_query, va_list args )
-{
-    spu_private_t *p_sys = p_spu->p;
-    int *pi, i;
-
-    switch( i_query )
-    {
-    case SPU_CHANNEL_REGISTER:
-        pi = (int *)va_arg( args, int * );
-        vlc_mutex_lock( &p_sys->lock );
-        if( pi )
-            *pi = p_sys->i_channel++;
-        vlc_mutex_unlock( &p_sys->lock );
-        break;
-
-    case SPU_CHANNEL_CLEAR:
-        i = (int)va_arg( args, int );
-        SpuClearChannel( p_spu, i );
-        break;
-
-    default:
-        msg_Dbg( p_spu, "control query not supported" );
-        return VLC_EGENERIC;
-    }
-
-    return VLC_SUCCESS;
-}
-
 /*****************************************************************************
  * Object variables callbacks
  *****************************************************************************/
@@ -1935,7 +1887,7 @@ static int SubFilterAllocationInit( filter_t *p_filter, void *p_data )
     p_filter->pf_sub_buffer_del = sub_del_buffer;
 
     p_filter->p_owner = p_sys;
-    spu_Control( p_spu, SPU_CHANNEL_REGISTER, &p_sys->i_channel );
+    p_sys->i_channel = spu_RegisterChannel( p_spu );
     p_sys->p_spu = p_spu;
 
     return VLC_SUCCESS;
@@ -1945,24 +1897,7 @@ static void SubFilterAllocationClean( filter_t *p_filter )
 {
     filter_owner_sys_t *p_sys = p_filter->p_owner;
 
-    SpuClearChannel( p_sys->p_spu, p_sys->i_channel );
+    spu_ClearChannel( p_sys->p_spu, p_sys->i_channel );
     free( p_filter->p_owner );
 }
 
-static int SubFilterCallback( vlc_object_t *p_object, char const *psz_var,
-                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    spu_t *p_spu = p_data;
-    spu_private_t *p_sys = p_spu->p;
-
-    VLC_UNUSED(p_object); VLC_UNUSED(oldval); VLC_UNUSED(psz_var);
-
-    vlc_mutex_lock( &p_sys->lock );
-
-    free( p_sys->psz_chain_update );
-    p_sys->psz_chain_update = strdup( newval.psz_string );
-
-    vlc_mutex_unlock( &p_sys->lock );
-    return VLC_SUCCESS;
-}
-