[vlc-devel] [PATCH v1 13/33] transcode: use filter chains with multiple output

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


For transcode+fps and user selected filters (we never know what the user will
manually add) the filter chains may output more than one picture per call. We
put all the results in a vlc_array and loop on that array to dequeue the
filtered pictures.

One array is for prerendered pictures (passed through "static" filters like
deinterlacing or fps), one array is for user filters. The final converter
should not receive more that one picture per call so we use
filter_chain_VideoFilter for that filter chain.
---
 modules/stream_out/transcode/video.c | 42 ++++++++++++++++++----------
 1 file changed, 28 insertions(+), 14 deletions(-)

diff --git a/modules/stream_out/transcode/video.c b/modules/stream_out/transcode/video.c
index dd3093a9692..40b41d61dc4 100644
--- a/modules/stream_out/transcode/video.c
+++ b/modules/stream_out/transcode/video.c
@@ -433,6 +433,12 @@ static void tag_last_block_with_flag( block_t **out, int i_flag )
     }
 }
 
+static int SinkIntoArray(struct vlc_video_sink *sink, picture_t *p_picture)
+{
+    vlc_array_t *p_array = sink->sys;
+    return vlc_array_append( p_array, p_picture ) == 0 ? VLC_SUCCESS : VLC_EGENERIC;
+}
+
 int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
                                     block_t *in, block_t **out )
 {
@@ -569,30 +575,38 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
             }
         }
 
+        vlc_array_t prerendered;
+        vlc_array_init( &prerendered );
+        struct vlc_video_sink prerender_sink = { &prerendered, SinkIntoArray };
+        if ( id->p_f_chain != NULL )
+            filter_chain_VideoFilterInto( id->p_f_chain, p_pic, &prerender_sink );
+        else
+            vlc_video_sink_PutPicture( &prerender_sink, p_pic );
+
         /* Run the filter and output chains; first with the picture,
          * and then with NULL as many times as we need until they
          * stop outputting frames.
          */
-        for ( picture_t *p_in = p_pic; ; p_in = NULL /* drain second time */ )
+        for ( size_t i = 0; i < vlc_array_count( &prerendered ) ; i++ )
         {
             /* Run filter chain */
-            if( id->p_f_chain )
-                p_in = filter_chain_VideoFilter( id->p_f_chain, p_in );
+            picture_t *p_in = vlc_array_item_at_index( &prerendered, i );
 
-            if( !p_in )
-                break;
+            vlc_array_t filtered;
+            vlc_array_init( &filtered );
+            struct vlc_video_sink sink = { &filtered, SinkIntoArray };
+            if ( id->p_uf_chain != NULL )
+                filter_chain_VideoFilterInto( id->p_uf_chain, p_in, &sink );
+            else
+                vlc_video_sink_PutPicture( &sink, p_in );
 
-            for ( ;; p_in = NULL /* drain second time */ )
+            for ( size_t j = 0; j < vlc_array_count( &filtered ) ; j++ )
             {
+                picture_t *p_in = vlc_array_item_at_index( &filtered, j );
+
                 /* Run user specified filter chain */
-                filter_chain_t * secondary_chains[] = { id->p_uf_chain,
-                                                        id->p_final_conv_static };
-                for( size_t i=0; p_in && i<ARRAY_SIZE(secondary_chains); i++ )
-                {
-                    if( !secondary_chains[i] )
-                        continue;
-                    p_in = filter_chain_VideoFilter( secondary_chains[i], p_in );
-                }
+                if( id->p_final_conv_static )
+                    p_in = filter_chain_VideoFilter( id->p_final_conv_static, p_in );
 
                 if( !p_in )
                     break;
-- 
2.26.2



More information about the vlc-devel mailing list