X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fmisc%2Ffilter_chain.c;h=cbf553e224e9f1d67240a0de64a951e77bef1ee5;hb=180fef5efbb7d0fed04bd79f5a72746ef4b37712;hp=87f3feed9f90e412ceed753cc9d7b5d1d2c9d3c5;hpb=24c96490ebea5843e389de91b87670b408b3267c;p=vlc diff --git a/src/misc/filter_chain.c b/src/misc/filter_chain.c index 87f3feed9f..cbf553e224 100644 --- a/src/misc/filter_chain.c +++ b/src/misc/filter_chain.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -45,6 +46,7 @@ typedef struct chained_filter_t /* Private filter chain data (shhhh!) */ struct chained_filter_t *prev, *next; vlc_mouse_t *mouse; + picture_t *pending; } chained_filter_t; /* Only use this with filter objects from _this_ C module */ @@ -97,15 +99,18 @@ static int filter_chain_DeleteFilterInternal( filter_chain_t *, filter_t * ); static int UpdateBufferFunctions( filter_chain_t * ); +static void FilterDeletePictures( filter_t *, picture_t * ); + +#undef filter_chain_New /** * Filter chain initialisation */ -filter_chain_t *__filter_chain_New( vlc_object_t *p_this, - const char *psz_capability, - bool b_allow_fmt_out_change, - int (*pf_buffer_allocation_init)( filter_t *, void * ), - void (*pf_buffer_allocation_clean)( filter_t * ), - void *p_buffer_allocation_data ) +filter_chain_t *filter_chain_New( vlc_object_t *p_this, + const char *psz_capability, + bool b_allow_fmt_out_change, + int (*pf_buffer_allocation_init)( filter_t *, void * ), + void (*pf_buffer_allocation_clean)( filter_t * ), + void *p_buffer_allocation_data ) { assert( p_this ); assert( psz_capability ); @@ -219,19 +224,62 @@ const es_format_t *filter_chain_GetFmtOut( filter_chain_t *p_chain ) return &p_chain->fmt_out; } -picture_t *filter_chain_VideoFilter( filter_chain_t *p_chain, picture_t *p_pic ) +static picture_t *FilterChainVideoFilter( chained_filter_t *f, picture_t *p_pic ) { - for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next ) + for( ; f != NULL; f = f->next ) { filter_t *p_filter = &f->filter; - p_pic = p_filter->pf_video_filter( p_filter, p_pic ); if( !p_pic ) break; + if( f->pending ) + { + msg_Warn( p_filter, "dropping pictures" ); + FilterDeletePictures( p_filter, f->pending ); + } + f->pending = p_pic->p_next; + p_pic->p_next = NULL; } return p_pic; } +picture_t *filter_chain_VideoFilter( filter_chain_t *p_chain, picture_t *p_pic ) +{ + if( p_pic ) + { + p_pic = FilterChainVideoFilter( p_chain->first, p_pic ); + if( p_pic ) + return p_pic; + } + for( chained_filter_t *b = p_chain->last; b != NULL; b = b->prev ) + { + p_pic = b->pending; + if( !p_pic ) + continue; + b->pending = p_pic->p_next; + p_pic->p_next = NULL; + + p_pic = FilterChainVideoFilter( b->next, p_pic ); + if( p_pic ) + return p_pic; + } + return NULL; +} + +void filter_chain_VideoFlush( filter_chain_t *p_chain ) +{ + for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next ) + { + filter_t *p_filter = &f->filter; + + FilterDeletePictures( p_filter, f->pending ); + f->pending = NULL; + + filter_FlushPictures( p_filter ); + } +} + + block_t *filter_chain_AudioFilter( filter_chain_t *p_chain, block_t *p_block ) { for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next ) @@ -267,13 +315,13 @@ int filter_chain_MouseFilter( filter_chain_t *p_chain, vlc_mouse_t *p_dst, const filter_t *p_filter = &f->filter; vlc_mouse_t *p_mouse = f->mouse; - if( p_filter->pf_mouse && p_mouse ) + if( p_filter->pf_video_mouse && p_mouse ) { vlc_mouse_t old = *p_mouse; vlc_mouse_t filtered; *p_mouse = current; - if( p_filter->pf_mouse( p_filter, &filtered, &old, ¤t ) ) + if( p_filter->pf_video_mouse( p_filter, &filtered, &old, ¤t ) ) return VLC_EGENERIC; current = filtered; } @@ -283,6 +331,25 @@ int filter_chain_MouseFilter( filter_chain_t *p_chain, vlc_mouse_t *p_dst, const return VLC_SUCCESS; } +int filter_chain_MouseEvent( filter_chain_t *p_chain, + const vlc_mouse_t *p_mouse, + const video_format_t *p_fmt ) +{ + for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next ) + { + filter_t *p_filter = &f->filter; + + if( p_filter->pf_sub_mouse ) + { + vlc_mouse_t old = *f->mouse; + *f->mouse = *p_mouse; + if( p_filter->pf_sub_mouse( p_filter, &old, p_mouse, p_fmt ) ) + return VLC_EGENERIC; + } + } + + return VLC_SUCCESS; +} /* Helpers */ static filter_t *filter_chain_AppendFilterInternal( filter_chain_t *p_chain, @@ -348,6 +415,7 @@ static filter_t *filter_chain_AppendFilterInternal( filter_chain_t *p_chain, if( p_mouse ) vlc_mouse_Init( p_mouse ); p_chained->mouse = p_mouse; + p_chained->pending = NULL; msg_Dbg( p_chain->p_this, "Filter '%s' (%p) appended to chain", psz_name ? psz_name : module_get_name(p_filter->p_module, false), @@ -366,7 +434,6 @@ error: module_unneed( p_filter, p_filter->p_module ); es_format_Clean( &p_filter->fmt_in ); es_format_Clean( &p_filter->fmt_out ); - vlc_object_detach( p_filter ); vlc_object_release( p_filter ); return NULL; } @@ -432,13 +499,14 @@ static int filter_chain_DeleteFilterInternal( filter_chain_t *p_chain, msg_Dbg( p_chain->p_this, "Filter %p removed from chain", p_filter ); + FilterDeletePictures( &p_chained->filter, p_chained->pending ); + /* Destroy the filter object */ if( IsInternalVideoAllocator( p_chained ) ) AllocatorClean( &internal_video_allocator, p_chained ); else AllocatorClean( &p_chain->allocator, p_chained ); - vlc_object_detach( p_filter ); if( p_filter->p_module ) module_unneed( p_filter, p_filter->p_module ); free( p_chained->mouse ); @@ -449,6 +517,16 @@ static int filter_chain_DeleteFilterInternal( filter_chain_t *p_chain, return VLC_SUCCESS; } +static void FilterDeletePictures( filter_t *filter, picture_t *picture ) +{ + while( picture ) + { + picture_t *next = picture->p_next; + filter_DeletePicture( filter, picture ); + picture = next; + } +} + /** * Internal chain buffer handling */ @@ -518,20 +596,20 @@ static int InternalVideoInit( filter_t *p_filter, void *p_data ) { VLC_UNUSED(p_data); - p_filter->pf_vout_buffer_new = VideoBufferNew; - p_filter->pf_vout_buffer_del = VideoBufferDelete; + p_filter->pf_video_buffer_new = VideoBufferNew; + p_filter->pf_video_buffer_del = VideoBufferDelete; return VLC_SUCCESS; } static void InternalVideoClean( filter_t *p_filter ) { - p_filter->pf_vout_buffer_new = NULL; - p_filter->pf_vout_buffer_del = NULL; + p_filter->pf_video_buffer_new = NULL; + p_filter->pf_video_buffer_del = NULL; } static bool IsInternalVideoAllocator( chained_filter_t *p_filter ) { - return p_filter->filter.pf_vout_buffer_new == VideoBufferNew; + return p_filter->filter.pf_video_buffer_new == VideoBufferNew; } /* */