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
#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.
*
......
......@@ -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
......
......@@ -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);
......
......@@ -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 )
......
......@@ -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
......
......@@ -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;
......
......@@ -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:
......
......@@ -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,
......
......@@ -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;
......
......@@ -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);
/* */
......
......@@ -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)
{
......
......@@ -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 );
}
......
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