# include "config.h"
#endif
+#include <assert.h>
+#include <limits.h>
+
#include <vlc_common.h>
#include <vlc_vout.h>
#include <vlc_block.h>
#include "vout_internal.h"
#include <vlc_image.h>
-#include <assert.h>
-#include <limits.h>
-
/*****************************************************************************
* Local prototypes
*****************************************************************************/
/* Subpiture filters */
char *psz_chain_update;
+ vlc_mutex_t chain_lock;
filter_chain_t *p_chain;
/* */
#define SCALE_UNIT (1000)
+static void SubpictureUpdate( subpicture_t *,
+ const video_format_t *p_fmt_src,
+ const video_format_t *p_fmt_dst,
+ mtime_t i_ts );
static void SubpictureChain( subpicture_t **pp_head, subpicture_t *p_subpic );
static int SubpictureCmp( const void *s0, const void *s1 );
/*****************************************************************************
* Public API
*****************************************************************************/
+
+#undef spu_Create
/**
* Creates the subpicture unit
*
* \param p_this the parent object which creates the subpicture unit
*/
-spu_t *__spu_Create( vlc_object_t *p_this )
+spu_t *spu_Create( vlc_object_t *p_this )
{
spu_t *p_spu;
spu_private_t *p_sys;
-
+
p_spu = vlc_custom_create( p_this, sizeof(spu_t) + sizeof(spu_private_t),
VLC_OBJECT_GENERIC, "subpicture" );
-
if( !p_spu )
return NULL;
+ vlc_object_attach( p_spu, p_this );
/* Initialize spu fields */
p_spu->pf_control = SpuControl;
/* Register the default subpicture channel */
p_sys->i_channel = 2;
- vlc_object_attach( p_spu, p_this );
-
p_sys->psz_chain_update = NULL;
+ vlc_mutex_init( &p_sys->chain_lock );
p_sys->p_chain = filter_chain_New( p_spu, "sub filter", false,
SubFilterAllocationInit,
SubFilterAllocationClean,
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 );
/* Destroy all remaining subpictures */
if( b_attach )
{
UpdateSPU( p_spu, VLC_OBJECT(p_input) );
+ var_Create( p_input, "highlight", VLC_VAR_BOOL );
var_AddCallback( p_input, "highlight", CropCallback, p_spu );
var_AddCallback( p_input, "sub-margin", MarginCallback, p_spu->p );
}
else
{
- /* Delete callback */
- var_DelCallback( p_input, "highlight", CropCallback, p_spu );
+ /* Delete callbacks */
var_DelCallback( p_input, "sub-margin", MarginCallback, p_spu->p );
+ var_DelCallback( p_input, "highlight", CropCallback, p_spu );
+ var_Destroy( p_input, "highlight" );
vlc_object_release( p_input );
}
}
+/**
+ * Inform the SPU filters of mouse event
+ */
+int spu_ProcessMouse( spu_t *p_spu,
+ const vlc_mouse_t *p_mouse,
+ const video_format_t *p_fmt )
+{
+ 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 );
+
+ return VLC_SUCCESS;
+}
+
/**
* Display a subpicture
*
p_subpic != NULL;
p_subpic = p_subpic->p_next )
{
- if( p_subpic->pf_update_regions )
- {
- video_format_t fmt_org = *p_fmt_dst;
- fmt_org.i_width =
- fmt_org.i_visible_width = i_source_video_width;
- fmt_org.i_height =
- fmt_org.i_visible_height = i_source_video_height;
-
- p_subpic->pf_update_regions( p_spu, p_subpic, &fmt_org,
- p_subpic->b_subtitle ? render_subtitle_date : render_osd_date );
- }
+ SubpictureUpdate( p_subpic,
+ p_fmt_src, p_fmt_dst,
+ p_subpic->b_subtitle ? render_subtitle_date : render_osd_date );
/* */
if( p_subpic->b_subtitle )
p_sys->psz_chain_update = NULL;
vlc_mutex_unlock( &p_sys->lock );
+ vlc_mutex_lock( &p_sys->chain_lock );
if( psz_chain_update )
{
filter_chain_Reset( p_sys->p_chain, NULL, NULL );
free( psz_chain_update );
}
-
/* Run subpicture filters */
filter_chain_SubFilter( p_sys->p_chain, render_osd_date );
+ vlc_mutex_unlock( &p_sys->chain_lock );
vlc_mutex_lock( &p_sys->lock );
/*****************************************************************************
* subpicture_t allocation
*****************************************************************************/
-subpicture_t *subpicture_New( void )
+struct subpicture_private_t
+{
+ video_format_t src;
+ video_format_t dst;
+};
+
+subpicture_t *subpicture_New( const subpicture_updater_t *p_upd )
{
subpicture_t *p_subpic = calloc( 1, sizeof(*p_subpic) );
if( !p_subpic )
p_subpic->b_subtitle = false;
p_subpic->i_alpha = 0xFF;
p_subpic->p_region = NULL;
- p_subpic->pf_destroy = NULL;
- p_subpic->p_sys = NULL;
+ if( p_upd )
+ {
+ subpicture_private_t *p_private = malloc( sizeof(*p_private) );
+ if( !p_private )
+ {
+ free( p_subpic );
+ return NULL;
+ }
+ video_format_Init( &p_private->src, 0 );
+ video_format_Init( &p_private->dst, 0 );
+
+ p_subpic->updater = *p_upd;
+ p_subpic->p_private = p_private;
+ }
+ else
+ {
+ p_subpic->p_private = NULL;
+
+ p_subpic->updater.pf_validate = NULL;
+ p_subpic->updater.pf_update = NULL;
+ p_subpic->updater.pf_destroy = NULL;
+ p_subpic->updater.p_sys = NULL;
+ }
return p_subpic;
}
subpicture_region_ChainDelete( p_subpic->p_region );
p_subpic->p_region = NULL;
- if( p_subpic->pf_destroy )
- {
- p_subpic->pf_destroy( p_subpic );
- }
+ if( p_subpic->updater.pf_destroy )
+ p_subpic->updater.pf_destroy( p_subpic );
+
+ free( p_subpic->p_private );
free( p_subpic );
}
if( !p_pip )
return NULL;
- subpicture_t *p_subpic = subpicture_New();
+ subpicture_t *p_subpic = subpicture_New( NULL );
if( !p_subpic )
{
picture_Release( p_pip );
return p_subpic;
}
+static void SubpictureUpdate( subpicture_t *p_subpicture,
+ const video_format_t *p_fmt_src,
+ const video_format_t *p_fmt_dst,
+ mtime_t i_ts )
+{
+ subpicture_updater_t *p_upd = &p_subpicture->updater;
+ subpicture_private_t *p_private = p_subpicture->p_private;
+
+ if( !p_upd->pf_validate )
+ return;
+ if( !p_upd->pf_validate( p_subpicture,
+ !video_format_IsSimilar( p_fmt_src,
+ &p_private->src ), p_fmt_src,
+ !video_format_IsSimilar( p_fmt_dst,
+ &p_private->dst ), p_fmt_dst,
+ i_ts ) )
+ return;
+
+ subpicture_region_ChainDelete( p_subpicture->p_region );
+ p_subpicture->p_region = NULL;
+
+ p_upd->pf_update( p_subpicture, p_fmt_src, p_fmt_dst, i_ts );
+
+ video_format_Clean( &p_private->src );
+ video_format_Clean( &p_private->dst );
+
+ video_format_Copy( &p_private->src, p_fmt_src );
+ video_format_Copy( &p_private->dst, p_fmt_dst );
+}
+
/*****************************************************************************
* subpicture_region_t allocation
*****************************************************************************/
p_region->p_picture = picture_NewFromFormat( p_fmt );
if( !p_region->p_picture )
{
- free( p_fmt->p_palette );
+ free( p_region->fmt.p_palette );
free( p_region );
return NULL;
}
{
filter_owner_sys_t *p_sys = p_filter->p_owner;
- subpicture_t *p_subpicture = subpicture_New();
+ subpicture_t *p_subpicture = subpicture_New( NULL );
if( p_subpicture )
p_subpicture->i_channel = p_sys->i_channel;
return p_subpicture;
static subpicture_t *spu_new_buffer( filter_t *p_filter )
{
VLC_UNUSED(p_filter);
- return subpicture_New();
+ return subpicture_New( NULL );
}
static void spu_del_buffer( filter_t *p_filter, subpicture_t *p_subpic )
{