Commit 6b546060 authored by Yuval Tze's avatar Yuval Tze Committed by Rémi Denis-Courmont

New sub-filter support add new "sub filter" capability for processing...

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
Signed-off-by: default avatarRémi Denis-Courmont <remi@remlab.net>
parent 9d86e0b6
...@@ -116,6 +116,12 @@ struct filter_t ...@@ -116,6 +116,12 @@ struct filter_t
#define pf_sub_buffer_del u.sub.pf_buffer_del #define pf_sub_buffer_del u.sub.pf_buffer_del
#define pf_sub_mouse u.sub.pf_mouse #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 struct
{ {
int (*pf_text) ( filter_t *, subpicture_region_t *, int (*pf_text) ( filter_t *, subpicture_region_t *,
...@@ -401,6 +407,15 @@ VLC_EXPORT( block_t *, filter_chain_AudioFilter, ( filter_chain_t *, block_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 ) ); 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. * Apply the filter chain to a mouse state.
* *
......
...@@ -97,6 +97,11 @@ VLC_EXPORT( void, spu_ClearChannel, ( spu_t *, int ) ); ...@@ -97,6 +97,11 @@ VLC_EXPORT( void, spu_ClearChannel, ( spu_t *, int ) );
*/ */
VLC_EXPORT( void, spu_ChangeSources, ( spu_t *, const char * ) ); 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 #ifdef __cplusplus
......
...@@ -303,6 +303,10 @@ void ExtVideo::ChangeVFiltersString( const char *psz_name, bool b_add ) ...@@ -303,6 +303,10 @@ void ExtVideo::ChangeVFiltersString( const char *psz_name, bool b_add )
{ {
psz_filter_type = "sub-source"; psz_filter_type = "sub-source";
} }
else if( module_provides( p_obj, "sub filter" ) )
{
psz_filter_type = "sub-filter";
}
else else
{ {
module_release (p_obj); module_release (p_obj);
......
...@@ -814,6 +814,11 @@ static const char *const ppsz_clock_descriptions[] = ...@@ -814,6 +814,11 @@ static const char *const ppsz_clock_descriptions[] =
"This adds so-called \"subpicture sources\". These filters overlay " \ "This adds so-called \"subpicture sources\". These filters overlay " \
"some images or text over the video (like a logo, arbitrary text, ...)." ) "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_TEXT N_("Autodetect subtitle files")
#define SUB_AUTO_LONGTEXT N_( \ #define SUB_AUTO_LONGTEXT N_( \
"Automatically detect a subtitle file, if no subtitle filename is " \ "Automatically detect a subtitle file, if no subtitle filename is " \
...@@ -1804,6 +1809,8 @@ vlc_module_begin () ...@@ -1804,6 +1809,8 @@ vlc_module_begin ()
set_section( N_( "Overlays" ) , NULL ) set_section( N_( "Overlays" ) , NULL )
add_module_list_cat( "sub-source", SUBCAT_VIDEO_SUBPIC, NULL, NULL, add_module_list_cat( "sub-source", SUBCAT_VIDEO_SUBPIC, NULL, NULL,
SUB_SOURCE_TEXT, SUB_SOURCE_LONGTEXT, false ) 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 */ /* Input options */
set_category( CAT_INPUT ) set_category( CAT_INPUT )
......
...@@ -133,6 +133,7 @@ filter_chain_MouseEvent ...@@ -133,6 +133,7 @@ filter_chain_MouseEvent
filter_chain_New filter_chain_New
filter_chain_Reset filter_chain_Reset
filter_chain_SubSource filter_chain_SubSource
filter_chain_SubFilter
filter_chain_VideoFilter filter_chain_VideoFilter
filter_chain_VideoFlush filter_chain_VideoFlush
filter_ConfigureBlend filter_ConfigureBlend
...@@ -400,6 +401,7 @@ spu_Create ...@@ -400,6 +401,7 @@ spu_Create
spu_Destroy spu_Destroy
spu_PutSubpicture spu_PutSubpicture
spu_ChangeSources spu_ChangeSources
spu_ChangeFilters
spu_Render spu_Render
spu_RegisterChannel spu_RegisterChannel
spu_ClearChannel spu_ClearChannel
......
...@@ -306,6 +306,20 @@ void filter_chain_SubSource( filter_chain_t *p_chain, ...@@ -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 ) 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; vlc_mouse_t current = *p_src;
......
...@@ -46,6 +46,7 @@ void vout_control_cmd_Clean(vout_control_cmd_t *cmd) ...@@ -46,6 +46,7 @@ void vout_control_cmd_Clean(vout_control_cmd_t *cmd)
case VOUT_CONTROL_OSD_TITLE: case VOUT_CONTROL_OSD_TITLE:
case VOUT_CONTROL_CHANGE_FILTERS: case VOUT_CONTROL_CHANGE_FILTERS:
case VOUT_CONTROL_CHANGE_SUB_SOURCES: case VOUT_CONTROL_CHANGE_SUB_SOURCES:
case VOUT_CONTROL_CHANGE_SUB_FILTERS:
free(cmd->u.string); free(cmd->u.string);
break; break;
default: default:
......
...@@ -40,6 +40,7 @@ enum { ...@@ -40,6 +40,7 @@ enum {
VOUT_CONTROL_OSD_TITLE, /* string */ VOUT_CONTROL_OSD_TITLE, /* string */
VOUT_CONTROL_CHANGE_FILTERS, /* string */ VOUT_CONTROL_CHANGE_FILTERS, /* string */
VOUT_CONTROL_CHANGE_SUB_SOURCES, /* string */ VOUT_CONTROL_CHANGE_SUB_SOURCES, /* string */
VOUT_CONTROL_CHANGE_SUB_FILTERS, /* string */
VOUT_CONTROL_CHANGE_SUB_MARGIN, /* integer */ VOUT_CONTROL_CHANGE_SUB_MARGIN, /* integer */
VOUT_CONTROL_PAUSE, VOUT_CONTROL_PAUSE,
......
...@@ -557,6 +557,11 @@ void vout_ControlChangeSubSources(vout_thread_t *vout, const char *filters) ...@@ -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, vout_control_PushString(&vout->p->control, VOUT_CONTROL_CHANGE_SUB_SOURCES,
filters); 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) void vout_ControlChangeSubMargin(vout_thread_t *vout, int margin)
{ {
vout_control_PushInteger(&vout->p->control, VOUT_CONTROL_CHANGE_SUB_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) ...@@ -1176,6 +1181,12 @@ static void ThreadChangeSubSources(vout_thread_t *vout, const char *filters)
{ {
spu_ChangeSources(vout->p->spu, 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) static void ThreadChangeSubMargin(vout_thread_t *vout, int margin)
{ {
spu_ChangeMargin(vout->p->spu, margin); spu_ChangeMargin(vout->p->spu, margin);
...@@ -1518,6 +1529,9 @@ static void *Thread(void *object) ...@@ -1518,6 +1529,9 @@ static void *Thread(void *object)
case VOUT_CONTROL_CHANGE_SUB_SOURCES: case VOUT_CONTROL_CHANGE_SUB_SOURCES:
ThreadChangeSubSources(vout, cmd.u.string); ThreadChangeSubSources(vout, cmd.u.string);
break; break;
case VOUT_CONTROL_CHANGE_SUB_FILTERS:
ThreadChangeSubFilters(vout, cmd.u.string);
break;
case VOUT_CONTROL_CHANGE_SUB_MARGIN: case VOUT_CONTROL_CHANGE_SUB_MARGIN:
ThreadChangeSubMargin(vout, cmd.u.integer); ThreadChangeSubMargin(vout, cmd.u.integer);
break; break;
......
...@@ -150,6 +150,7 @@ void vout_ControlChangeCropWindow(vout_thread_t *, int x, int y, int width, int ...@@ -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_ControlChangeCropBorder(vout_thread_t *, int left, int top, int right, int bottom);
void vout_ControlChangeFilters(vout_thread_t *, const char *); void vout_ControlChangeFilters(vout_thread_t *, const char *);
void vout_ControlChangeSubSources(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); void vout_ControlChangeSubMargin(vout_thread_t *, int);
/* */ /* */
......
...@@ -67,6 +67,8 @@ static int VideoFilterCallback( vlc_object_t *, char const *, ...@@ -67,6 +67,8 @@ static int VideoFilterCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * ); vlc_value_t, vlc_value_t, void * );
static int SubSourceCallback( vlc_object_t *, char const *, static int SubSourceCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * ); 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 *, static int SubMarginCallback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * ); vlc_value_t, vlc_value_t, void * );
...@@ -320,6 +322,12 @@ void vout_IntfInit( vout_thread_t *p_vout ) ...@@ -320,6 +322,12 @@ void vout_IntfInit( vout_thread_t *p_vout )
var_AddCallback( p_vout, "sub-source", SubSourceCallback, NULL ); var_AddCallback( p_vout, "sub-source", SubSourceCallback, NULL );
var_TriggerCallback( p_vout, "sub-source" ); 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 */ /* Add sub-margin variable */
var_Create( p_vout, "sub-margin", var_Create( p_vout, "sub-margin",
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND ); 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, ...@@ -470,6 +478,10 @@ void vout_EnableFilter( vout_thread_t *p_vout, const char *psz_name,
{ {
psz_filter_type = "sub-source"; psz_filter_type = "sub-source";
} }
else if( module_provides( p_obj, "sub filter" ) )
{
psz_filter_type = "sub-filter";
}
else else
{ {
module_release( p_obj ); module_release( p_obj );
...@@ -663,6 +675,16 @@ static int SubSourceCallback( vlc_object_t *p_this, char const *psz_cmd, ...@@ -663,6 +675,16 @@ static int SubSourceCallback( vlc_object_t *p_this, char const *psz_cmd,
return VLC_SUCCESS; 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, static int SubMarginCallback( vlc_object_t *p_this, char const *psz_cmd,
vlc_value_t oldval, vlc_value_t newval, void *p_data) vlc_value_t oldval, vlc_value_t newval, void *p_data)
{ {
......
...@@ -83,9 +83,12 @@ struct spu_private_t ...@@ -83,9 +83,12 @@ struct spu_private_t
uint8_t palette[4][4]; /**< forced palette */ uint8_t palette[4][4]; /**< forced palette */
/* Subpiture filters */ /* Subpiture filters */
char *psz_chain_update; char *psz_source_chain_update;
vlc_mutex_t chain_lock; vlc_mutex_t source_chain_lock;
filter_chain_t *p_chain; 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; mtime_t i_last_sort_date;
...@@ -1317,12 +1320,18 @@ spu_t *spu_Create( vlc_object_t *p_this ) ...@@ -1317,12 +1320,18 @@ spu_t *spu_Create( vlc_object_t *p_this )
/* Register the default subpicture channel */ /* Register the default subpicture channel */
p_sys->i_channel = SPU_DEFAULT_CHANNEL + 1; p_sys->i_channel = SPU_DEFAULT_CHANNEL + 1;
p_sys->psz_chain_update = NULL; p_sys->psz_source_chain_update = NULL;
vlc_mutex_init( &p_sys->chain_lock ); p_sys->psz_filter_chain_update = NULL;
p_sys->p_chain = filter_chain_New( p_spu, "sub source", false, 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, SubSourceAllocationInit,
SubSourceAllocationClean, SubSourceAllocationClean,
p_spu ); p_spu );
p_sys->p_filter_chain = filter_chain_New( p_spu, "sub filter", false,
NULL,
NULL,
p_spu );
/* Load text and scale module */ /* Load text and scale module */
p_sys->p_text = SpuRenderCreateAndLoadText( p_spu ); p_sys->p_text = SpuRenderCreateAndLoadText( p_spu );
...@@ -1361,9 +1370,12 @@ void spu_Destroy( spu_t *p_spu ) ...@@ -1361,9 +1370,12 @@ void spu_Destroy( spu_t *p_spu )
if( p_sys->p_scale ) if( p_sys->p_scale )
FilterRelease( p_sys->p_scale ); FilterRelease( p_sys->p_scale );
filter_chain_Delete( p_sys->p_chain ); filter_chain_Delete( p_sys->p_source_chain );
vlc_mutex_destroy( &p_sys->chain_lock ); filter_chain_Delete( p_sys->p_filter_chain );
free( p_sys->psz_chain_update ); 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 */ /* Destroy all remaining subpictures */
SpuHeapClean( &p_sys->heap ); SpuHeapClean( &p_sys->heap );
...@@ -1417,9 +1429,9 @@ int spu_ProcessMouse( spu_t *p_spu, ...@@ -1417,9 +1429,9 @@ int spu_ProcessMouse( spu_t *p_spu,
{ {
spu_private_t *p_sys = p_spu->p; spu_private_t *p_sys = p_spu->p;
vlc_mutex_lock( &p_sys->chain_lock ); vlc_mutex_lock( &p_sys->source_chain_lock );
filter_chain_MouseEvent( p_sys->p_chain, p_mouse, p_fmt ); filter_chain_MouseEvent( p_sys->p_source_chain, p_mouse, p_fmt );
vlc_mutex_unlock( &p_sys->chain_lock ); vlc_mutex_unlock( &p_sys->source_chain_lock );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -1436,6 +1448,28 @@ void spu_PutSubpicture( spu_t *p_spu, subpicture_t *p_subpic ) ...@@ -1436,6 +1448,28 @@ void spu_PutSubpicture( spu_t *p_spu, subpicture_t *p_subpic )
{ {
spu_private_t *p_sys = p_spu->p; 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 */ /* SPU_DEFAULT_CHANNEL always reset itself */
if( p_subpic->i_channel == SPU_DEFAULT_CHANNEL ) if( p_subpic->i_channel == SPU_DEFAULT_CHANNEL )
spu_ClearChannel( p_spu, SPU_DEFAULT_CHANNEL ); spu_ClearChannel( p_spu, SPU_DEFAULT_CHANNEL );
...@@ -1468,22 +1502,22 @@ subpicture_t *spu_Render( spu_t *p_spu, ...@@ -1468,22 +1502,22 @@ subpicture_t *spu_Render( spu_t *p_spu,
/* Update sub-source chain */ /* Update sub-source chain */
vlc_mutex_lock( &p_sys->lock ); vlc_mutex_lock( &p_sys->lock );
char *psz_chain_update = p_sys->psz_chain_update; char *psz_chain_update = p_sys->psz_source_chain_update;
p_sys->psz_chain_update = NULL; p_sys->psz_source_chain_update = NULL;
vlc_mutex_unlock( &p_sys->lock ); 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 ) 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 ); free( psz_chain_update );
} }
/* Run subpicture sources */ /* Run subpicture sources */
filter_chain_SubSource( p_sys->p_chain, render_osd_date ); filter_chain_SubSource( p_sys->p_source_chain, render_osd_date );
vlc_mutex_unlock( &p_sys->chain_lock ); vlc_mutex_unlock( &p_sys->source_chain_lock );
static const vlc_fourcc_t p_chroma_list_default_yuv[] = { static const vlc_fourcc_t p_chroma_list_default_yuv[] = {
VLC_CODEC_YUVA, VLC_CODEC_YUVA,
...@@ -1603,8 +1637,20 @@ void spu_ChangeSources( spu_t *p_spu, const char *psz_filters ) ...@@ -1603,8 +1637,20 @@ void spu_ChangeSources( spu_t *p_spu, const char *psz_filters )
vlc_mutex_lock( &p_sys->lock ); vlc_mutex_lock( &p_sys->lock );
free( p_sys->psz_chain_update ); free( p_sys->psz_source_chain_update );
p_sys->psz_chain_update = strdup( psz_filters ); 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 ); vlc_mutex_unlock( &p_sys->lock );
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment