[vlc-devel] [PATCH 2/5] New sub-filter support add new "sub filter" capability for processing subpictures add new "sub-filter" parameter / configuration string add new filter chain to the spu and apply it on every new subpicture

Yuval Tze yuvaltze at gmail.com
Sun Apr 17 00:38:32 CEST 2011


---
 include/vlc_filter.h                           |   15 ++++
 include/vlc_spu.h                              |    5 ++
 modules/gui/qt4/components/extended_panels.cpp |    4 +
 src/libvlc-module.c                            |    7 ++
 src/libvlccore.sym                             |    2 +
 src/misc/filter_chain.c                        |   14 ++++
 src/video_output/control.c                     |    1 +
 src/video_output/control.h                     |    1 +
 src/video_output/video_output.c                |   14 ++++
 src/video_output/vout_internal.h               |    1 +
 src/video_output/vout_intf.c                   |   22 ++++++
 src/video_output/vout_subpictures.c            |   88 ++++++++++++++++++------
 12 files changed, 153 insertions(+), 21 deletions(-)

diff --git a/include/vlc_filter.h b/include/vlc_filter.h
index 4c5e320..070e53d 100644
--- a/include/vlc_filter.h
+++ b/include/vlc_filter.h
@@ -118,6 +118,12 @@ struct filter_t
 
         struct
         {
+            subpicture_t * (*pf_filter) ( filter_t *, subpicture_t * );
+        } subf;
+#define pf_sub_filter      u.subf.pf_filter
+
+        struct
+        {
             int         (*pf_text) ( filter_t *, subpicture_region_t *,
                                      subpicture_region_t * );
             int         (*pf_html) ( filter_t *, subpicture_region_t *,
@@ -402,6 +408,15 @@ VLC_EXPORT( block_t *, filter_chain_AudioFilter, ( filter_chain_t *, block_t * )
 VLC_EXPORT( void, filter_chain_SubSource, ( filter_chain_t *, mtime_t ) );
 
 /**
+ * Apply filter chain to subpictures.
+ *
+ * \param p_chain pointer to filter chain
+ * \param p_subpicture subpicture to apply filters on
+ * \return modified subpicture after applying all subpicture filters
+ */
+VLC_EXPORT( subpicture_t *, filter_chain_SubFilter, ( filter_chain_t *, subpicture_t * ) );
+
+/**
  * Apply the filter chain to a mouse state.
  *
  * It will be applied from the output to the input. It makes sense only
diff --git a/include/vlc_spu.h b/include/vlc_spu.h
index 7977cdd..d40327e 100644
--- a/include/vlc_spu.h
+++ b/include/vlc_spu.h
@@ -97,6 +97,11 @@ VLC_EXPORT( void, spu_ClearChannel, ( spu_t *, int ) );
  */
 VLC_EXPORT( void, spu_ChangeSources, ( spu_t *, const char * ) );
 
+/**
+ * It changes the sub filters list
+ */
+VLC_EXPORT( void, spu_ChangeFilters, ( spu_t *, const char * ) );
+
 /** @}*/
 
 #ifdef __cplusplus
diff --git a/modules/gui/qt4/components/extended_panels.cpp b/modules/gui/qt4/components/extended_panels.cpp
index 78c552b..ad759c8 100644
--- a/modules/gui/qt4/components/extended_panels.cpp
+++ b/modules/gui/qt4/components/extended_panels.cpp
@@ -303,6 +303,10 @@ void ExtVideo::ChangeVFiltersString( const char *psz_name, bool b_add )
     {
         psz_filter_type = "sub-source";
     }
+    else if( module_provides( p_obj, "sub filter" ) )
+    {
+        psz_filter_type = "sub-filter";
+    }
     else
     {
         module_release (p_obj);
diff --git a/src/libvlc-module.c b/src/libvlc-module.c
index 2219bdf..b3b25f2 100644
--- a/src/libvlc-module.c
+++ b/src/libvlc-module.c
@@ -814,6 +814,11 @@ static const char *const ppsz_clock_descriptions[] =
     "This adds so-called \"subpicture sources\". These filters overlay " \
     "some images or text over the video (like a logo, arbitrary text, ...)." )
 
+#define SUB_FILTER_TEXT N_("Subpictures filter module")
+#define SUB_FILTER_LONGTEXT N_( \
+    "This adds so-called \"subpicture filters\". These filter subpictures " \
+    "created by subtitles decoders or other subpictures sources." )
+
 #define SUB_AUTO_TEXT N_("Autodetect subtitle files")
 #define SUB_AUTO_LONGTEXT N_( \
     "Automatically detect a subtitle file, if no subtitle filename is " \
@@ -1804,6 +1809,8 @@ vlc_module_begin ()
     set_section( N_( "Overlays" ) , NULL )
     add_module_list_cat( "sub-source", SUBCAT_VIDEO_SUBPIC, NULL, NULL,
                 SUB_SOURCE_TEXT, SUB_SOURCE_LONGTEXT, false )
+    add_module_list_cat( "sub-filter", SUBCAT_VIDEO_SUBPIC, NULL, NULL,
+                SUB_FILTER_TEXT, SUB_FILTER_LONGTEXT, false )
 
 /* Input options */
     set_category( CAT_INPUT )
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index a5d8e98..2f2602a 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -133,6 +133,7 @@ filter_chain_MouseEvent
 filter_chain_New
 filter_chain_Reset
 filter_chain_SubSource
+filter_chain_SubFilter
 filter_chain_VideoFilter
 filter_chain_VideoFlush
 filter_ConfigureBlend
@@ -400,6 +401,7 @@ spu_Create
 spu_Destroy
 spu_PutSubpicture
 spu_ChangeSources
+spu_ChangeFilters
 spu_Render
 spu_RegisterChannel
 spu_ClearChannel
diff --git a/src/misc/filter_chain.c b/src/misc/filter_chain.c
index 8aff88b..859d4ad 100644
--- a/src/misc/filter_chain.c
+++ b/src/misc/filter_chain.c
@@ -306,6 +306,20 @@ void filter_chain_SubSource( filter_chain_t *p_chain,
     }
 }
 
+subpicture_t *filter_chain_SubFilter( filter_chain_t *p_chain, subpicture_t *p_subpic )
+{
+    for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next )
+    {
+        filter_t *p_filter = &f->filter;
+
+        p_subpic = p_filter->pf_sub_filter( p_filter, p_subpic );
+
+        if( !p_subpic )
+            break;
+    }
+    return p_subpic;
+}
+
 int filter_chain_MouseFilter( filter_chain_t *p_chain, vlc_mouse_t *p_dst, const vlc_mouse_t *p_src )
 {
     vlc_mouse_t current = *p_src;
diff --git a/src/video_output/control.c b/src/video_output/control.c
index 1806137..6e33b45 100644
--- a/src/video_output/control.c
+++ b/src/video_output/control.c
@@ -46,6 +46,7 @@ void vout_control_cmd_Clean(vout_control_cmd_t *cmd)
     case VOUT_CONTROL_OSD_TITLE:
     case VOUT_CONTROL_CHANGE_FILTERS:
     case VOUT_CONTROL_CHANGE_SUB_SOURCES:
+    case VOUT_CONTROL_CHANGE_SUB_FILTERS:
         free(cmd->u.string);
         break;
     default:
diff --git a/src/video_output/control.h b/src/video_output/control.h
index 09325b5..343411b 100644
--- a/src/video_output/control.h
+++ b/src/video_output/control.h
@@ -40,6 +40,7 @@ enum {
     VOUT_CONTROL_OSD_TITLE,             /* string */
     VOUT_CONTROL_CHANGE_FILTERS,        /* string */
     VOUT_CONTROL_CHANGE_SUB_SOURCES,    /* string */
+    VOUT_CONTROL_CHANGE_SUB_FILTERS,    /* string */
     VOUT_CONTROL_CHANGE_SUB_MARGIN,     /* integer */
 
     VOUT_CONTROL_PAUSE,
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 2c30257..4308761 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -557,6 +557,11 @@ void vout_ControlChangeSubSources(vout_thread_t *vout, const char *filters)
     vout_control_PushString(&vout->p->control, VOUT_CONTROL_CHANGE_SUB_SOURCES,
                             filters);
 }
+void vout_ControlChangeSubFilters(vout_thread_t *vout, const char *filters)
+{
+    vout_control_PushString(&vout->p->control, VOUT_CONTROL_CHANGE_SUB_FILTERS,
+                            filters);
+}
 void vout_ControlChangeSubMargin(vout_thread_t *vout, int margin)
 {
     vout_control_PushInteger(&vout->p->control, VOUT_CONTROL_CHANGE_SUB_MARGIN,
@@ -1176,6 +1181,12 @@ static void ThreadChangeSubSources(vout_thread_t *vout, const char *filters)
 {
     spu_ChangeSources(vout->p->spu, filters);
 }
+
+static void ThreadChangeSubFilters(vout_thread_t *vout, const char *filters)
+{
+    spu_ChangeFilters(vout->p->spu, filters);
+}
+
 static void ThreadChangeSubMargin(vout_thread_t *vout, int margin)
 {
     spu_ChangeMargin(vout->p->spu, margin);
@@ -1518,6 +1529,9 @@ static void *Thread(void *object)
             case VOUT_CONTROL_CHANGE_SUB_SOURCES:
                 ThreadChangeSubSources(vout, cmd.u.string);
                 break;
+            case VOUT_CONTROL_CHANGE_SUB_FILTERS:
+                ThreadChangeSubFilters(vout, cmd.u.string);
+                break;
             case VOUT_CONTROL_CHANGE_SUB_MARGIN:
                 ThreadChangeSubMargin(vout, cmd.u.integer);
                 break;
diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h
index c48ff5b..bea55c6 100644
--- a/src/video_output/vout_internal.h
+++ b/src/video_output/vout_internal.h
@@ -150,6 +150,7 @@ void vout_ControlChangeCropWindow(vout_thread_t *, int x, int y, int width, int
 void vout_ControlChangeCropBorder(vout_thread_t *, int left, int top, int right, int bottom);
 void vout_ControlChangeFilters(vout_thread_t *, const char *);
 void vout_ControlChangeSubSources(vout_thread_t *, const char *);
+void vout_ControlChangeSubFilters(vout_thread_t *, const char *);
 void vout_ControlChangeSubMargin(vout_thread_t *, int);
 
 /* */
diff --git a/src/video_output/vout_intf.c b/src/video_output/vout_intf.c
index 548867f..43c11db 100644
--- a/src/video_output/vout_intf.c
+++ b/src/video_output/vout_intf.c
@@ -67,6 +67,8 @@ static int VideoFilterCallback( vlc_object_t *, char const *,
                                 vlc_value_t, vlc_value_t, void * );
 static int SubSourceCallback( vlc_object_t *, char const *,
                               vlc_value_t, vlc_value_t, void * );
+static int SubFilterCallback( vlc_object_t *, char const *,
+                              vlc_value_t, vlc_value_t, void * );
 static int SubMarginCallback( vlc_object_t *, char const *,
                               vlc_value_t, vlc_value_t, void * );
 
@@ -320,6 +322,12 @@ void vout_IntfInit( vout_thread_t *p_vout )
     var_AddCallback( p_vout, "sub-source", SubSourceCallback, NULL );
     var_TriggerCallback( p_vout, "sub-source" );
 
+    /* Add a sub-filter variable */
+    var_Create( p_vout, "sub-filter",
+                VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
+    var_AddCallback( p_vout, "sub-filter", SubFilterCallback, NULL );
+    var_TriggerCallback( p_vout, "sub-filter" );
+
     /* Add sub-margin variable */
     var_Create( p_vout, "sub-margin",
                 VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
@@ -470,6 +478,10 @@ void vout_EnableFilter( vout_thread_t *p_vout, const char *psz_name,
     {
         psz_filter_type = "sub-source";
     }
+    else if( module_provides( p_obj, "sub filter" ) )
+    {
+        psz_filter_type = "sub-filter";
+    }
     else
     {
         module_release( p_obj );
@@ -663,6 +675,16 @@ static int SubSourceCallback( vlc_object_t *p_this, char const *psz_cmd,
     return VLC_SUCCESS;
 }
 
+static int SubFilterCallback( vlc_object_t *p_this, char const *psz_cmd,
+                              vlc_value_t oldval, vlc_value_t newval, void *p_data)
+{
+    vout_thread_t *p_vout = (vout_thread_t *)p_this;
+    VLC_UNUSED(psz_cmd); VLC_UNUSED(oldval); VLC_UNUSED(p_data);
+
+    vout_ControlChangeSubFilters( p_vout, newval.psz_string );
+    return VLC_SUCCESS;
+}
+
 static int SubMarginCallback( vlc_object_t *p_this, char const *psz_cmd,
                               vlc_value_t oldval, vlc_value_t newval, void *p_data)
 {
diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c
index c9e2f8c..b7c41e8 100644
--- a/src/video_output/vout_subpictures.c
+++ b/src/video_output/vout_subpictures.c
@@ -83,9 +83,12 @@ struct spu_private_t
     uint8_t palette[4][4];                               /**< forced palette */
 
     /* Subpiture filters */
-    char           *psz_chain_update;
-    vlc_mutex_t    chain_lock;
-    filter_chain_t *p_chain;
+    char           *psz_source_chain_update;
+    vlc_mutex_t    source_chain_lock;
+    filter_chain_t *p_source_chain;
+    char           *psz_filter_chain_update;
+    vlc_mutex_t    filter_chain_lock;
+    filter_chain_t *p_filter_chain;
 
     /* */
     mtime_t i_last_sort_date;
@@ -1317,12 +1320,18 @@ spu_t *spu_Create( vlc_object_t *p_this )
     /* Register the default subpicture channel */
     p_sys->i_channel = SPU_DEFAULT_CHANNEL + 1;
 
-    p_sys->psz_chain_update = NULL;
-    vlc_mutex_init( &p_sys->chain_lock );
-    p_sys->p_chain = filter_chain_New( p_spu, "sub source", false,
+    p_sys->psz_source_chain_update = NULL;
+    p_sys->psz_filter_chain_update = NULL;
+    vlc_mutex_init( &p_sys->source_chain_lock );
+    vlc_mutex_init( &p_sys->filter_chain_lock );
+    p_sys->p_source_chain = filter_chain_New( p_spu, "sub source", false,
                                        SubSourceAllocationInit,
                                        SubSourceAllocationClean,
                                        p_spu );
+    p_sys->p_filter_chain = filter_chain_New( p_spu, "sub filter", false,
+                                       NULL,
+                                       NULL,
+                                       p_spu );
 
     /* Load text and scale module */
     p_sys->p_text = SpuRenderCreateAndLoadText( p_spu );
@@ -1361,9 +1370,12 @@ void spu_Destroy( spu_t *p_spu )
     if( p_sys->p_scale )
         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 );
+    filter_chain_Delete( p_sys->p_source_chain );
+    filter_chain_Delete( p_sys->p_filter_chain );
+    vlc_mutex_destroy( &p_sys->source_chain_lock );
+    vlc_mutex_destroy( &p_sys->filter_chain_lock );
+    free( p_sys->psz_source_chain_update );
+    free( p_sys->psz_filter_chain_update );
 
     /* Destroy all remaining subpictures */
     SpuHeapClean( &p_sys->heap );
@@ -1417,9 +1429,9 @@ int spu_ProcessMouse( spu_t *p_spu,
 {
     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 );
+    vlc_mutex_lock( &p_sys->source_chain_lock );
+    filter_chain_MouseEvent( p_sys->p_source_chain, p_mouse, p_fmt );
+    vlc_mutex_unlock( &p_sys->source_chain_lock );
 
     return VLC_SUCCESS;
 }
@@ -1436,6 +1448,28 @@ void spu_PutSubpicture( spu_t *p_spu, subpicture_t *p_subpic )
 {
     spu_private_t *p_sys = p_spu->p;
 
+    /* Update sub-filter chain */
+    vlc_mutex_lock( &p_sys->lock );
+    char *psz_chain_update = p_sys->psz_filter_chain_update;
+    p_sys->psz_filter_chain_update = NULL;
+    vlc_mutex_unlock( &p_sys->lock );
+
+    vlc_mutex_lock( &p_sys->filter_chain_lock );
+    if( psz_chain_update )
+    {
+        filter_chain_Reset( p_sys->p_filter_chain, NULL, NULL );
+
+        filter_chain_AppendFromString( p_spu->p->p_filter_chain, psz_chain_update );
+
+        free( psz_chain_update );
+    }
+    vlc_mutex_unlock( &p_sys->filter_chain_lock );
+
+    /* Run filter chain on the new subpicture */
+    p_subpic = filter_chain_SubFilter(p_spu->p->p_filter_chain, p_subpic);
+    if( !p_subpic )
+        return;
+
     /* SPU_DEFAULT_CHANNEL always reset itself */
     if( p_subpic->i_channel == SPU_DEFAULT_CHANNEL )
         spu_ClearChannel( p_spu, SPU_DEFAULT_CHANNEL );
@@ -1468,22 +1502,22 @@ subpicture_t *spu_Render( spu_t *p_spu,
 
     /* Update sub-source chain */
     vlc_mutex_lock( &p_sys->lock );
-    char *psz_chain_update = p_sys->psz_chain_update;
-    p_sys->psz_chain_update = NULL;
+    char *psz_chain_update = p_sys->psz_source_chain_update;
+    p_sys->psz_source_chain_update = NULL;
     vlc_mutex_unlock( &p_sys->lock );
 
-    vlc_mutex_lock( &p_sys->chain_lock );
+    vlc_mutex_lock( &p_sys->source_chain_lock );
     if( psz_chain_update )
     {
-        filter_chain_Reset( p_sys->p_chain, NULL, NULL );
+        filter_chain_Reset( p_sys->p_source_chain, NULL, NULL );
 
-        filter_chain_AppendFromString( p_spu->p->p_chain, psz_chain_update );
+        filter_chain_AppendFromString( p_spu->p->p_source_chain, psz_chain_update );
 
         free( psz_chain_update );
     }
     /* Run subpicture sources */
-    filter_chain_SubSource( p_sys->p_chain, render_osd_date );
-    vlc_mutex_unlock( &p_sys->chain_lock );
+    filter_chain_SubSource( p_sys->p_source_chain, render_osd_date );
+    vlc_mutex_unlock( &p_sys->source_chain_lock );
 
     static const vlc_fourcc_t p_chroma_list_default_yuv[] = {
         VLC_CODEC_YUVA,
@@ -1603,8 +1637,20 @@ void spu_ChangeSources( spu_t *p_spu, const char *psz_filters )
 
     vlc_mutex_lock( &p_sys->lock );
 
-    free( p_sys->psz_chain_update );
-    p_sys->psz_chain_update = strdup( psz_filters );
+    free( p_sys->psz_source_chain_update );
+    p_sys->psz_source_chain_update = strdup( psz_filters );
+
+    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_filter_chain_update );
+    p_sys->psz_filter_chain_update = strdup( psz_filters );
 
     vlc_mutex_unlock( &p_sys->lock );
 }
-- 
1.7.1




More information about the vlc-devel mailing list