]> git.sesse.net Git - vlc/commitdiff
New sub-filter support add new "sub filter" capability for processing subpictures...
authorYuval Tze <yuvaltze@gmail.com>
Sat, 16 Apr 2011 22:38:32 +0000 (01:38 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Wed, 20 Apr 2011 08:48:22 +0000 (11:48 +0300)
Signed-off-by: Rémi Denis-Courmont <remi@remlab.net>
12 files changed:
include/vlc_filter.h
include/vlc_spu.h
modules/gui/qt4/components/extended_panels.cpp
src/libvlc-module.c
src/libvlccore.sym
src/misc/filter_chain.c
src/video_output/control.c
src/video_output/control.h
src/video_output/video_output.c
src/video_output/vout_internal.h
src/video_output/vout_intf.c
src/video_output/vout_subpictures.c

index 4c5e3208cb58364420f97127d500c655622bbe3b..070e53d5fcee42a5a48f7ee56987e011b4e76216 100644 (file)
@@ -116,6 +116,12 @@ struct filter_t
 #define pf_sub_buffer_del  u.sub.pf_buffer_del
 #define pf_sub_mouse       u.sub.pf_mouse
 
+        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 *,
@@ -401,6 +407,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.
  *
index 7977cddee4b75d080d4f8d59df35cf459aa395b1..d40327e51466dda00ea75e52df3548790c33f6af 100644 (file)
@@ -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
index 78c552bf1bd181630c2a34093930d1c4b2bfe3e7..ad759c8f3104db6c7ae5f938b7b81338e1f95ae9 100644 (file)
@@ -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);
index 2219bdf5e03118fa6c51803b02384eee65eb17b3..b3b25f2cdb4fd2d8f72eeaa6216b60cabd365688 100644 (file)
@@ -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 )
index a5d8e9810c7df69a196e56ebe1012696290a6481..2f2602a6428be782f1765fb5162253a132924cfe 100644 (file)
@@ -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
index 8aff88be3f6fe417f6341bc9b17e3794b3807bc2..859d4ad4c256e3119c4f8542ba4af59d4de0d973 100644 (file)
@@ -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;
index 1806137f7fe5b601d6912a98bb625d9b09b702bb..6e33b458f14b9d7a4bd3d54ac036db8a6ccbff0e 100644 (file)
@@ -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:
index 09325b5a599c5b3b64c5beea53c9f35dd64694ee..343411b0dac908f2a8d9b4ae88a2597ab2ff9d4b 100644 (file)
@@ -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,
index 2c3025790b2b565c4cb3a56a999353599653428b..430876185cbef148db8f099ef817d60c05df592e 100644 (file)
@@ -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;
index c48ff5bfeade5ea4c255d5dfbd018b999f6bbf4e..bea55c6274f7bb33a58ccd51fe47d73f53efefc6 100644 (file)
@@ -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);
 
 /* */
index 548867f4a426c4ec2d133e3d7e9050cd07075b04..43c11db6cbd1734cde0afad3eb40f11ded74881d 100644 (file)
@@ -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)
 {
index c9e2f8c1ae1465c4b9bc6a059c36304f516497d8..b7c41e8d5c0dd001cf22a8c72abd38d17d297cb2 100644 (file)
@@ -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 );
 }