[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