[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