[vlc-commits] [Git][videolan/vlc][master] 7 commits: subpicture: use filter_chain_ForEach() to call source_sub()
Steve Lhomme (@robUx4)
gitlab at videolan.org
Sat Sep 30 15:01:03 UTC 2023
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
fe9d6458 by Steve Lhomme at 2023-09-30T14:40:09+00:00
subpicture: use filter_chain_ForEach() to call source_sub()
No need for a specific function in the core. filter_chain_ForEach() is already
use multiple times with `source_chain` a few lines above.
- - - - -
f788694e by Steve Lhomme at 2023-09-30T14:40:09+00:00
filter_chain: remove unused and unexported filter_chain_SubSource()
It can be done with filter_chain_ForEach() if needed.
- - - - -
259e2fd6 by Steve Lhomme at 2023-09-30T14:40:09+00:00
subpicture: use filter_chain_ForEach() to call filter_sub()
No need for a specific function in the core. filter_chain_ForEach() is already
use multiple times with `filter_chain` a few lines above.
- - - - -
6e3566f3 by Steve Lhomme at 2023-09-30T14:40:09+00:00
filter_chain: remove unused filter_chain_SubFilter()
It can be done with filter_chain_ForEach()if needed.
- - - - -
b89b01bb by Steve Lhomme at 2023-09-30T14:40:09+00:00
vlc_filter: document restriction on filter in filter_chain_DeleteFilter()
We can only remove filters that were created by filter_chain_AppendInner().
- - - - -
b716fc82 by Steve Lhomme at 2023-09-30T14:40:09+00:00
filter_chain: separate the code to filter from a chained_filter_t
- - - - -
c15c5c73 by Steve Lhomme at 2023-09-30T14:40:09+00:00
filter_chain: switch the list of filters to a vlc_list
Each chained_filter_t is slightly bigger, for now.
The node storage corresponds to the next/prev on an element.
The filter_list storage corresponds to the head/tail of the list.
- - - - -
4 changed files:
- include/vlc_filter.h
- src/libvlccore.sym
- src/misc/filter_chain.c
- src/video_output/vout_subpictures.c
Changes:
=====================================
include/vlc_filter.h
=====================================
@@ -563,6 +563,8 @@ VLC_API int filter_chain_AppendFromString(filter_chain_t *chain,
*
* \param chain filter chain to remove the filter from
* \param filter filter to remove from the chain and delete
+ *
+ * \note the filter must be created with filter_chain_AppendInner().
*/
VLC_API void filter_chain_DeleteFilter(filter_chain_t *chain,
filter_t *filter);
@@ -605,26 +607,6 @@ VLC_API picture_t *filter_chain_VideoFilter(filter_chain_t *chain,
*/
VLC_API void filter_chain_VideoFlush( filter_chain_t * );
-/**
- * Generate subpictures from a chain of subpicture source "filters".
- *
- * \param chain filter chain
- * \param spu an initialized subpicture unit
- * \param display_date of subpictures
- */
-void filter_chain_SubSource(filter_chain_t *chain, spu_t *spu,
- vlc_tick_t display_date);
-
-/**
- * Apply filter chain to subpictures.
- *
- * \param chain filter chain
- * \param subpic subpicture to apply filters on
- * \return modified subpicture after applying all subpicture filters
- */
-VLC_API subpicture_t *filter_chain_SubFilter(filter_chain_t *chain,
- subpicture_t *subpic);
-
/**
* Apply the filter chain to a mouse state.
*
=====================================
src/libvlccore.sym
=====================================
@@ -127,7 +127,6 @@ filter_chain_MouseFilter
filter_chain_NewVideo
filter_chain_Reset
filter_chain_Clear
-filter_chain_SubFilter
filter_chain_VideoFilter
filter_chain_VideoFlush
filter_chain_ForEach
=====================================
src/misc/filter_chain.c
=====================================
@@ -37,8 +37,7 @@ typedef struct chained_filter_t
{
/* Public part of the filter structure */
filter_t filter;
- /* Private filter chain data (shhhh!) */
- struct chained_filter_t *prev, *next;
+ struct vlc_list node;
vlc_mouse_t mouse;
vlc_picture_chain_t pending;
} chained_filter_t;
@@ -49,7 +48,7 @@ struct filter_chain_t
vlc_object_t *obj;
filter_owner_t parent_video_owner; /**< Owner (downstream) callbacks */
- chained_filter_t *first, *last; /**< List of filters */
+ struct vlc_list filter_list; /* chained_filter_t */
es_format_t fmt_in; /**< Chain input format (constant) */
vlc_video_context *vctx_in; /**< Chain input video context (set on Reset) */
@@ -76,8 +75,7 @@ static filter_chain_t *filter_chain_NewInner( vlc_object_t *obj,
return NULL;
chain->obj = obj;
- chain->first = NULL;
- chain->last = NULL;
+ vlc_list_init( &chain->filter_list );
es_format_Init( &chain->fmt_in, cat, 0 );
chain->vctx_in = NULL;
es_format_Init( &chain->fmt_out, cat, 0 );
@@ -98,7 +96,8 @@ static picture_t *filter_chain_VideoBufferNew( filter_t *filter )
{
picture_t *pic;
chained_filter_t *chained = container_of(filter, chained_filter_t, filter);
- if( chained->next != NULL )
+ filter_chain_t *chain = filter->owner.sys;
+ if( !vlc_list_is_last( &chained->node, &chain->filter_list ) )
{
// HACK as intermediate filters may not have the same video format as
// the last one handled by the owner
@@ -111,8 +110,6 @@ static picture_t *filter_chain_VideoBufferNew( filter_t *filter )
}
else
{
- filter_chain_t *chain = filter->owner.sys;
-
// the owner of the chain requires pictures from the last filter to be grabbed from its callback
/* XXX ugly */
filter_owner_t saved_owner = filter->owner;
@@ -162,8 +159,9 @@ filter_chain_t *filter_chain_NewVideo( vlc_object_t *obj, bool allow_change,
void filter_chain_Clear( filter_chain_t *p_chain )
{
- while( p_chain->first != NULL )
- filter_chain_DeleteFilter( p_chain, &p_chain->first->filter );
+ chained_filter_t *chained;
+ vlc_list_foreach( chained, &p_chain->filter_list, node )
+ filter_chain_DeleteFilter( p_chain, &chained->filter );
}
void filter_chain_Delete( filter_chain_t *p_chain )
@@ -211,10 +209,12 @@ static filter_t *filter_chain_AppendInner( filter_chain_t *chain,
const es_format_t *fmt_in;
vlc_video_context *vctx_in;
- if( chain->last != NULL )
+ chained_filter_t *last =
+ vlc_list_last_entry_or_null( &chain->filter_list, chained_filter_t, node );
+ if( last != NULL )
{
- fmt_in = &chain->last->filter.fmt_out;
- vctx_in = chain->last->filter.vctx_out;
+ fmt_in = &last->filter.fmt_out;
+ vctx_in = last->filter.vctx_out;
}
else
{
@@ -257,16 +257,7 @@ static filter_t *filter_chain_AppendInner( filter_chain_t *chain,
goto error;
assert( filter->ops != NULL );
- if( chain->last == NULL )
- {
- assert( chain->first == NULL );
- chain->first = chained;
- }
- else
- chain->last->next = chained;
- chained->prev = chain->last;
- chain->last = chained;
- chained->next = NULL;
+ vlc_list_append( &chained->node, &chain->filter_list );
vlc_mouse_Init( &chained->mouse );
vlc_picture_chain_Init( &chained->pending );
@@ -304,24 +295,10 @@ int filter_chain_AppendConverter( filter_chain_t *chain,
void filter_chain_DeleteFilter( filter_chain_t *chain, filter_t *filter )
{
- chained_filter_t *chained = (chained_filter_t *)filter;
+ chained_filter_t *chained = container_of(filter, chained_filter_t, filter);
/* Remove it from the chain */
- if( chained->prev != NULL )
- chained->prev->next = chained->next;
- else
- {
- assert( chained == chain->first );
- chain->first = chained->next;
- }
-
- if( chained->next != NULL )
- chained->next->prev = chained->prev;
- else
- {
- assert( chained == chain->last );
- chain->last = chained->prev;
- }
+ vlc_list_remove( &chained->node );
filter_Close( filter );
module_unneed( filter, filter->p_module );
@@ -374,7 +351,10 @@ int filter_chain_AppendFromString( filter_chain_t *chain, const char *str )
error:
while( ret > 0 ) /* Unwind */
{
- filter_chain_DeleteFilter( chain, &chain->last->filter );
+ chained_filter_t *last =
+ vlc_list_last_entry_or_null( &chain->filter_list, chained_filter_t, node );
+ assert( last != NULL );
+ filter_chain_DeleteFilter( chain, &last->filter );
ret--;
}
free( buf );
@@ -384,7 +364,8 @@ error:
int filter_chain_ForEach( filter_chain_t *chain,
int (*cb)( filter_t *, void * ), void *opaque )
{
- for( chained_filter_t *f = chain->first; f != NULL; f = f->next )
+ chained_filter_t *f;
+ vlc_list_foreach( f, &chain->filter_list, node )
{
int ret = cb( &f->filter, opaque );
if( ret )
@@ -395,13 +376,15 @@ int filter_chain_ForEach( filter_chain_t *chain,
bool filter_chain_IsEmpty(const filter_chain_t *chain)
{
- return chain->first == NULL;
+ return vlc_list_is_empty( &chain->filter_list );
}
const es_format_t *filter_chain_GetFmtOut( const filter_chain_t *p_chain )
{
- if( p_chain->last != NULL )
- return &p_chain->last->filter.fmt_out;
+ chained_filter_t *last =
+ vlc_list_last_entry_or_null( &p_chain->filter_list, chained_filter_t, node );
+ if( last != NULL )
+ return &last->filter.fmt_out;
/* Unless filter_chain_Reset has been called we are doomed */
return &p_chain->fmt_out;
@@ -409,29 +392,29 @@ const es_format_t *filter_chain_GetFmtOut( const filter_chain_t *p_chain )
vlc_video_context *filter_chain_GetVideoCtxOut(const filter_chain_t *p_chain)
{
- if( p_chain->last != NULL )
- return p_chain->last->filter.vctx_out;
+ chained_filter_t *last =
+ vlc_list_last_entry_or_null( &p_chain->filter_list, chained_filter_t, node );
+ if( last != NULL )
+ return last->filter.vctx_out;
/* No filter was added, the filter chain has no effect, make sure the chromas are compatible */
assert( video_format_IsSameChroma( &p_chain->fmt_in.video, &p_chain->fmt_out.video ) );
return p_chain->vctx_in;
}
-static picture_t *FilterChainVideoFilter( chained_filter_t *f, picture_t *p_pic )
+static picture_t *FilterSingleChainedFilter( chained_filter_t *f, picture_t *p_pic )
{
- for( ; f != NULL; f = f->next )
+ filter_t *p_filter = &f->filter;
+ p_pic = p_filter->ops->filter_video( p_filter, p_pic );
+ if( !p_pic )
+ return NULL;
+
+ if( !vlc_picture_chain_IsEmpty( &f->pending ) )
{
- filter_t *p_filter = &f->filter;
- p_pic = p_filter->ops->filter_video( p_filter, p_pic );
- if( !p_pic )
- break;
- if( !vlc_picture_chain_IsEmpty( &f->pending ) )
- {
- msg_Warn( p_filter, "dropping pictures" );
- FilterDeletePictures( &f->pending );
- }
- f->pending = picture_GetAndResetChain( p_pic );
+ msg_Warn( p_filter, "dropping pictures" );
+ FilterDeletePictures( &f->pending );
}
+ f->pending = picture_GetAndResetChain( p_pic );
return p_pic;
}
@@ -439,17 +422,36 @@ 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 );
+ chained_filter_t *f;
+ vlc_list_foreach( f, &p_chain->filter_list, node )
+ {
+ p_pic = FilterSingleChainedFilter( f, p_pic );
+ if( !p_pic )
+ break;
+ }
if( p_pic )
return p_pic;
}
- for( chained_filter_t *b = p_chain->last; b != NULL; b = b->prev )
+
+ // look backward in filters for a pending picture
+ chained_filter_t *b;
+ vlc_list_reverse_foreach( b, &p_chain->filter_list, node )
{
- if( vlc_picture_chain_IsEmpty( &b->pending ) )
- continue;
p_pic = vlc_picture_chain_PopFront( &b->pending );
+ if (p_pic == NULL)
+ continue;
- p_pic = FilterChainVideoFilter( b->next, p_pic );
+ // iterate forward through the next filters
+ struct vlc_list_it f_it = vlc_list_it_b;
+ vlc_list_it_next(&f_it);
+ for ( ; vlc_list_it_continue(&f_it); vlc_list_it_next(&f_it) )
+ {
+ chained_filter_t *f =
+ container_of(f_it.current, chained_filter_t, node);
+ p_pic = FilterSingleChainedFilter( f, p_pic );
+ if( !p_pic )
+ break;
+ }
if( p_pic )
return p_pic;
}
@@ -458,7 +460,8 @@ picture_t *filter_chain_VideoFilter( filter_chain_t *p_chain, picture_t *p_pic )
void filter_chain_VideoFlush( filter_chain_t *p_chain )
{
- for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next )
+ chained_filter_t *f;
+ vlc_list_foreach( f, &p_chain->filter_list, node )
{
filter_t *p_filter = &f->filter;
@@ -468,37 +471,12 @@ void filter_chain_VideoFlush( filter_chain_t *p_chain )
}
}
-void filter_chain_SubSource( filter_chain_t *p_chain, spu_t *spu,
- vlc_tick_t display_date )
-{
- for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next )
- {
- filter_t *p_filter = &f->filter;
- subpicture_t *p_subpic = p_filter->ops->source_sub( p_filter, display_date );
- if( p_subpic )
- spu_PutSubpicture( spu, p_subpic );
- }
-}
-
-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->ops->filter_sub( 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;
+ chained_filter_t *f;
- for( chained_filter_t *f = p_chain->last; f != NULL; f = f->prev )
+ vlc_list_reverse_foreach( f, &p_chain->filter_list, node )
{
filter_t *p_filter = &f->filter;
=====================================
src/video_output/vout_subpictures.c
=====================================
@@ -1796,6 +1796,15 @@ void spu_SetClockRate(spu_t *spu, size_t channel_id, float rate)
vlc_mutex_unlock(&sys->lock);
}
+static int SubFilter( filter_t *p_filter, void *opaque )
+{
+ subpicture_t **pp_subpic = opaque;
+ *pp_subpic = p_filter->ops->filter_sub( p_filter, *pp_subpic );
+ if (*pp_subpic == NULL)
+ return VLC_EINVAL; // stop filtering
+ return VLC_SUCCESS;
+}
+
/**
* Display a subpicture
*
@@ -1861,7 +1870,7 @@ void spu_PutSubpicture(spu_t *spu, subpicture_t *subpic)
/* Run filter chain on the new subpicture */
vlc_mutex_lock(&sys->filter_chain_lock);
- subpic = filter_chain_SubFilter(spu->p->filter_chain, subpic);
+ filter_chain_ForEach( sys->filter_chain, SubFilter, &subpic );
vlc_mutex_unlock(&sys->filter_chain_lock);
if (!subpic || subpic->i_channel < 0)
{
@@ -1911,6 +1920,24 @@ void spu_PutSubpicture(spu_t *spu, subpicture_t *subpic)
vlc_mutex_unlock(&sys->lock);
}
+struct sub_source
+{
+ spu_t *spu;
+ vlc_tick_t display_date;
+};
+
+/**
+ * Generate subpictures from a chain of subpicture source "filters".
+ */
+static int SubSourceGenerate( filter_t *p_filter, void *opaque )
+{
+ const struct sub_source *spu_src = opaque;
+ subpicture_t *p_subpic = p_filter->ops->source_sub( p_filter, spu_src->display_date );
+ if( p_subpic )
+ spu_PutSubpicture( spu_src->spu, p_subpic );
+ return VLC_SUCCESS;
+}
+
subpicture_t *spu_Render(spu_t *spu,
const vlc_fourcc_t *chroma_list,
const video_format_t *fmt_dst,
@@ -1945,7 +1972,8 @@ subpicture_t *spu_Render(spu_t *spu,
free(chain_update);
}
/* Run subpicture sources */
- filter_chain_SubSource(sys->source_chain, spu, system_now);
+ struct sub_source sub_src = { spu, system_now };
+ filter_chain_ForEach(sys->source_chain, SubSourceGenerate, &sub_src);
static const vlc_fourcc_t chroma_list_default_yuv[] = {
VLC_CODEC_YUVA,
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/87b88369c3144a580c494c26c9be879bcb3d8153...c15c5c734b63b08a3dbd46d1a6c8378ccdb094bc
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/87b88369c3144a580c494c26c9be879bcb3d8153...c15c5c734b63b08a3dbd46d1a6c8378ccdb094bc
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list