[vlc-devel] [PATCH v1 10/33] filter_chain: allow filtering into a sink with filter_chain_VideoFilterInto

Steve Lhomme robux4 at ycbcr.xyz
Fri Sep 25 16:46:46 CEST 2020


Intermediate filters send their output to a local sink filling
---
 include/vlc_filter.h    | 12 ++++++++
 src/libvlccore.sym      |  1 +
 src/misc/filter_chain.c | 67 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/include/vlc_filter.h b/include/vlc_filter.h
index e660e8c6d18..f8f1d48a417 100644
--- a/include/vlc_filter.h
+++ b/include/vlc_filter.h
@@ -541,6 +541,18 @@ VLC_API vlc_video_context *filter_chain_GetVideoCtxOut(const filter_chain_t *cha
 VLC_API picture_t *filter_chain_VideoFilter(filter_chain_t *chain,
                                             picture_t *pic);
 
+/**
+ * Apply the filter chain to a video picture and send the results to the video sink.
+ *
+ * \param chain pointer to filter chain
+ * \param pic picture to apply filters to
+ * \param sink video sinking receiving the filtered picture(s)
+ * \return VLC_SUCCESS if pictures were sent to the sink
+ */
+VLC_API int filter_chain_VideoFilterInto(filter_chain_t *chain,
+                                         picture_t *pic,
+                                         struct vlc_video_sink *sink);
+
 /**
  * Flush a video filter chain.
  */
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index fec60a194cf..d7b93d5bc4a 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -120,6 +120,7 @@ filter_chain_Reset
 filter_chain_Clear
 filter_chain_SubFilter
 filter_chain_VideoFilter
+filter_chain_VideoFilterInto
 filter_chain_VideoFlush
 filter_chain_ForEach
 filter_ConfigureBlend
diff --git a/src/misc/filter_chain.c b/src/misc/filter_chain.c
index 176135bc0d2..3019d67e749 100644
--- a/src/misc/filter_chain.c
+++ b/src/misc/filter_chain.c
@@ -424,6 +424,13 @@ vlc_video_context *filter_chain_GetVideoCtxOut(const filter_chain_t *p_chain)
     return p_chain->vctx_in;
 }
 
+static int PushFilteredPic(struct vlc_video_sink *sink, picture_t *pic)
+{
+    vlc_picture_chain_t *p_chain = sink->sys;
+    vlc_picture_chain_Append(p_chain, pic);
+    return VLC_SUCCESS;
+}
+
 static picture_t *FilterChainVideoFilter( chained_filter_t *f, picture_t *p_pic )
 {
     for( ; f != NULL; f = f->next )
@@ -464,6 +471,66 @@ picture_t *filter_chain_VideoFilter( filter_chain_t *p_chain, picture_t *p_pic )
     return NULL;
 }
 
+int filter_chain_VideoFilterInto(filter_chain_t *p_chain, picture_t *p_pic,
+                                 struct vlc_video_sink *sink)
+{
+    assert( p_pic != NULL ); // handle caching of pushed pictures on your side
+    int res = VLC_SUCCESS;
+    chained_filter_t *f = p_chain->first;
+    if (f == NULL)
+        res = vlc_video_sink_PutPicture( sink, p_pic );
+    else
+    {
+        vlc_picture_chain_t src_chain;
+        vlc_picture_chain_Init( &src_chain );
+        vlc_picture_chain_Append( &src_chain, p_pic );
+        for( ; f != NULL; f = f->next )
+        {
+            vlc_picture_chain_t filtered_chain;
+            vlc_picture_chain_Init( &filtered_chain );
+            struct vlc_video_sink fsink;
+            if (f->next)
+                fsink = (struct vlc_video_sink) { &filtered_chain, PushFilteredPic };
+            else
+                fsink = *sink;
+
+            filter_t *p_filter = &f->filter;
+            picture_t *front;
+            for (front = vlc_picture_chain_PopFront(&src_chain); front != NULL;
+                 front = vlc_picture_chain_PopFront(&src_chain) )
+            {
+                if ( p_filter->pf_video_filter_into != NULL )
+                {
+                    res = p_filter->pf_video_filter_into( p_filter, front, &fsink );
+                    if (res != VLC_SUCCESS)
+                        break;
+                }
+                else
+                {
+                    assert(p_filter->pf_video_filter != NULL);
+                    picture_t *filtered = p_filter->pf_video_filter( p_filter, front );
+                    if (filtered != NULL)
+                    {
+                        vlc_picture_chain_t chained = picture_GetAndResetChain( filtered );
+                        fsink.pf_push_picture(fsink.sys, filtered);
+                        while ( !vlc_picture_chain_IsEmpty( &chained ) )
+                        {
+                            picture_t *next = vlc_picture_chain_PopFront( &chained );
+                            fsink.pf_push_picture(fsink.sys, next);
+                        }
+                    }
+                }
+            }
+
+            // we have filtered pictures in filtered_chain, move them in src_chain
+            // for the next iteration
+            while ((front = vlc_picture_chain_PopFront( &filtered_chain )) != NULL)
+                vlc_picture_chain_Append(&src_chain,  front);
+        }
+    }
+    return res;
+}
+
 void filter_chain_VideoFlush( filter_chain_t *p_chain )
 {
     for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next )
-- 
2.26.2



More information about the vlc-devel mailing list