[vlc-commits] [Git][videolan/vlc][master] 5 commits: transcode: video: don't wait for drain to update output

Steve Lhomme (@robUx4) gitlab at videolan.org
Mon Aug 22 10:42:06 UTC 2022



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
3caee1e3 by Alaric Senat at 2022-08-22T10:30:21+00:00
transcode: video: don't wait for drain to update output

Fix a regression introduced by d8c883e273f333d7e2d8c2c2df1e35b280021df5
where video processing was waiting for drain input to feed the output
frame chain.

This goes back to the previous behaviour where transcode input also
unloads the decoder output fifo and sends it.

- - - - -
34e0caed by Alaric Senat at 2022-08-22T10:30:21+00:00
test: transcode: constify global module variable

- - - - -
66da270a by Alaric Senat at 2022-08-22T10:30:21+00:00
test: transcode: switch to `vlc_frame_t`

- - - - -
b770b27a by Alaric Senat at 2022-08-22T10:30:21+00:00
test: transcode: add an output checker module

This module will be used to watch the end of the transcode pipeline.

- - - - -
72512a84 by Alaric Senat at 2022-08-22T10:30:21+00:00
test: transcode: validate tests at frame output

... Instead of validating at encoder output.

With the last transcode refactors, a regression requiring encoder drain
to have any output of the transcode pipeline wasn't caught by the
current testing suite. [1]

This allows us to validate the output of the transcode pipeline as a
whole and covers more potential regressions.

[1] 2c8db7d8009894f0bedb0eb9f7143a0ac5c54a63

- - - - -


4 changed files:

- modules/stream_out/transcode/video.c
- test/modules/stream_out/transcode.c
- test/modules/stream_out/transcode.h
- test/modules/stream_out/transcode_scenarios.c


Changes:

=====================================
modules/stream_out/transcode/video.c
=====================================
@@ -559,13 +559,14 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
     if( ret != VLCDEC_SUCCESS )
         return VLC_EGENERIC;
 
-    /* Only drain if we drained the decoder too. */
-    if (in != NULL)
+    /*
+     * Encoder creation depends on decoder's update_format which is only
+     * created once a few frames have been passed to the decoder.
+     */
+    if( id->encoder == NULL )
         return VLC_SUCCESS;
 
-    /* Drain encoder */
     vlc_fifo_Lock( id->output_fifo );
-    assert(id->encoder);
     if( unlikely( !id->b_error && in == NULL ) && transcode_encoder_opened( id->encoder ) )
     {
         msg_Dbg( p_stream, "Flushing thread and waiting that");


=====================================
test/modules/stream_out/transcode.c
=====================================
@@ -43,6 +43,7 @@ const char vlc_module_name[] = MODULE_STRING;
 #include <vlc_filter.h>
 #include <vlc_threads.h>
 #include <vlc_sout.h>
+#include <vlc_frame.h>
 
 #include <limits.h>
 
@@ -71,9 +72,9 @@ static int OpenDecoderDevice(
     return VLC_SUCCESS;
 }
 
-static int DecoderDecode(decoder_t *dec, block_t *block)
+static int DecoderDecode(decoder_t *dec, vlc_frame_t *frame)
 {
-    if (block == NULL)
+    if (frame == NULL)
         return VLC_SUCCESS;
 
     const picture_resource_t resource = {
@@ -81,8 +82,8 @@ static int DecoderDecode(decoder_t *dec, block_t *block)
     };
     picture_t *pic = picture_NewFromResource(&dec->fmt_out.video, &resource);
     assert(pic);
-    pic->date = block->i_pts;
-    block_Release(block);
+    pic->date = frame->i_pts;
+    vlc_frame_Release(frame);
 
     struct transcode_scenario *scenario = &transcode_scenarios[current_scenario];
     assert(scenario->decoder_decode != NULL);
@@ -165,18 +166,18 @@ static int OpenConverter(vlc_object_t *obj)
     return VLC_SUCCESS;
 }
 
-static block_t *EncodeVideo(encoder_t *enc, picture_t *pic)
+static vlc_frame_t *EncodeVideo(encoder_t *enc, picture_t *pic)
 {
     if (pic == NULL)
         return NULL;
 
     assert(pic->format.i_chroma == enc->fmt_in.video.i_chroma);
-    block_t *block = block_Alloc(4);
+    vlc_frame_t *frame = vlc_frame_Alloc(4);
 
     struct transcode_scenario *scenario = &transcode_scenarios[current_scenario];
     if (scenario->encoder_encode != NULL)
         scenario->encoder_encode(enc, pic);
-    return block;
+    return frame;
 }
 
 static void CloseEncoder(encoder_t *enc)
@@ -211,11 +212,11 @@ static int OpenEncoder(vlc_object_t *obj)
     return VLC_SUCCESS;
 }
 
-static int ErrorCheckerSend(sout_stream_t *stream, void *id, block_t *b)
+static int ErrorCheckerSend(sout_stream_t *stream, void *id, vlc_frame_t *f)
 {
     struct transcode_scenario *scenario = &transcode_scenarios[current_scenario];
 
-    int ret = sout_StreamIdSend(stream->p_next, id, b);
+    int ret = sout_StreamIdSend(stream->p_next, id, f);
     if (ret != VLC_SUCCESS)
         scenario->report_error(stream);
     return VLC_SUCCESS;
@@ -239,6 +240,41 @@ static int OpenErrorChecker(vlc_object_t *obj)
     return VLC_SUCCESS;
 }
 
+static int OutputCheckerSend(sout_stream_t *stream, void *id, vlc_frame_t *f)
+{
+    (void)stream; (void)id;
+    struct transcode_scenario *scenario = &transcode_scenarios[current_scenario];
+
+    assert(scenario->report_output != NULL);
+    scenario->report_output(f);
+
+    vlc_frame_ChainRelease(f);
+
+    return VLC_SUCCESS;
+}
+
+static void *OutputCheckerAdd(sout_stream_t *stream, const es_format_t *fmt)
+{
+    (void)stream; (void)fmt;
+    return (void*)0x42;
+}
+
+static void OutputCheckerDel(sout_stream_t *stream, void *id)
+    { (void)stream; (void)id; }
+
+static int OpenOutputChecker(vlc_object_t *obj)
+{
+    sout_stream_t *stream = (sout_stream_t *)obj;
+
+    static const struct sout_stream_operations ops = {
+        .add = OutputCheckerAdd,
+        .del = OutputCheckerDel,
+        .send = OutputCheckerSend,
+    };
+    stream->ops = &ops;
+    return VLC_SUCCESS;
+}
+
 static void on_state_changed(vlc_player_t *player, enum vlc_player_state state, void *opaque)
 {
     (void)player; (void)state; (void) opaque;
@@ -330,6 +366,11 @@ vlc_module_begin()
         set_capability("sout filter", 0)
         add_shortcut("error_checker")
 
+    add_submodule()
+        set_callback(OpenOutputChecker)
+        set_capability("sout output", 0)
+        add_shortcut("output_checker")
+
     add_submodule()
         set_callback(OpenDecoderDevice)
         set_capability("decoder device", 0)
@@ -355,7 +396,7 @@ vlc_module_end()
 /* Helper typedef for vlc_static_modules */
 typedef int (*vlc_plugin_cb)(vlc_set_cb, void*);
 
-VLC_EXPORT vlc_plugin_cb vlc_static_modules[] = {
+VLC_EXPORT const vlc_plugin_cb vlc_static_modules[] = {
     VLC_SYMBOL(vlc_entry),
     NULL
 };


=====================================
test/modules/stream_out/transcode.h
=====================================
@@ -40,6 +40,7 @@ struct transcode_scenario {
     void (*filter_setup)(filter_t *);
     void (*converter_setup)(filter_t *);
     void (*report_error)(sout_stream_t *);
+    void (*report_output)(const vlc_frame_t *);
 };
 
 


=====================================
test/modules/stream_out/transcode_scenarios.c
=====================================
@@ -29,6 +29,8 @@
 #undef __PLUGIN__
 
 #include <vlc_common.h>
+#include <vlc_frame.h>
+
 #include "transcode.h"
 
 #include <vlc_filter.h>
@@ -37,7 +39,7 @@ static struct scenario_data
 {
     vlc_sem_t wait_stop;
     struct vlc_video_context *decoder_vctx;
-    unsigned encoder_picture_count;
+    unsigned output_frame_count;
     bool converter_opened;
     bool encoder_opened;
     bool encoder_closed;
@@ -200,20 +202,28 @@ static void encoder_encode_dummy(encoder_t *enc, picture_t *pic)
 {
     (void)enc; (void)pic;
     msg_Info(enc, "Encode");
-    vlc_sem_post(&scenario_data.wait_stop);
 }
 
-static void encoder_encode_wait_10_images(encoder_t *enc, picture_t *pic)
+static void encoder_close(encoder_t *enc)
 {
-    (void)enc; (void)pic;
-    if (scenario_data.encoder_picture_count++ == 10)
+    (void)enc;
+    scenario_data.encoder_closed = true;
+}
+
+static void wait_output_10_frames_reported(const vlc_frame_t *out)
+{
+    // Count frame output.
+    for (; out != NULL; out = out->p_next )
+        ++scenario_data.output_frame_count;
+
+    if (scenario_data.output_frame_count == 10)
         vlc_sem_post(&scenario_data.wait_stop);
 }
 
-static void encoder_close(encoder_t *enc)
+static void wait_output_reported(const vlc_frame_t *out)
 {
-    (void)enc;
-    scenario_data.encoder_closed = true;
+    (void)out;
+    vlc_sem_post(&scenario_data.wait_stop);
 }
 
 static void converter_fixed_size(filter_t *filter, vlc_fourcc_t chroma_in,
@@ -257,64 +267,71 @@ const char source_800_600[] = "mock://video_track_count=1;length=100000000000;vi
 struct transcode_scenario transcode_scenarios[] =
 {{
     .source = source_800_600,
-    .sout = "sout=#transcode:dummy",
+    .sout = "sout=#transcode:output_checker",
     .decoder_setup = decoder_i420_800_600,
     .decoder_decode = decoder_decode_dummy,
     .encoder_setup = encoder_i420_800_600,
     .encoder_encode = encoder_encode_dummy,
     .encoder_close = encoder_close,
+    .report_output = wait_output_reported,
 },{
     .source = source_800_600,
-    .sout = "sout=#transcode:dummy",
+    .sout = "sout=#transcode:output_checker",
     .decoder_setup = decoder_nv12_800_600,
     .decoder_decode = decoder_decode_dummy,
     .encoder_setup = encoder_nv12_800_600,
     .encoder_encode = encoder_encode_dummy,
     .encoder_close = encoder_close,
+    .report_output = wait_output_reported,
 },{
     .source = source_800_600,
-    .sout = "sout=#transcode:dummy",
+    .sout = "sout=#transcode:output_checker",
     .decoder_setup = decoder_i420_800_600,
     .decoder_decode = decoder_decode_dummy,
     .encoder_setup = encoder_nv12_800_600,
     .encoder_encode = encoder_encode_dummy,
     .encoder_close = encoder_close,
     .converter_setup = converter_i420_to_nv12_800_600,
+    .report_output = wait_output_reported,
 },{
     .source = source_800_600,
-    .sout = "sout=#transcode:dummy",
+    .sout = "sout=#transcode:output_checker",
     .decoder_setup = decoder_nv12_800_600,
     .decoder_decode = decoder_decode_dummy,
     .encoder_setup = encoder_i420_800_600,
     .encoder_encode = encoder_encode_dummy,
     .encoder_close = encoder_close,
     .converter_setup = converter_nv12_to_i420_800_600,
+    .report_output = wait_output_reported,
 },{
     .source = source_800_600,
-    .sout = "sout=#transcode:dummy",
+    .sout = "sout=#transcode:output_checker",
     .decoder_setup = decoder_i420_800_600_vctx,
     .decoder_decode = decoder_decode_vctx,
     .encoder_setup = encoder_i420_800_600_vctx,
     .encoder_encode = encoder_encode_dummy,
     .encoder_close = encoder_close,
+    .report_output = wait_output_reported,
 },{
     .source = source_800_600,
-    .sout = "sout=#transcode:dummy",
+    .sout = "sout=#transcode:output_checker",
     .decoder_setup = decoder_i420_800_600_vctx,
     .decoder_decode = decoder_decode_vctx,
     .encoder_setup = encoder_nv12_800_600,
     .encoder_encode = encoder_encode_dummy,
     .encoder_close = encoder_close,
     .converter_setup = converter_i420_to_nv12_800_600,
+    .report_output = wait_output_reported,
 },{
     /* Make sure fps filter in transcode will forward the video context */
     .source = source_800_600,
-    .sout = "sout=#transcode{fps=1}:dummy",
+    .sout = "sout=#transcode{fps=1}:output_checker",
     .decoder_setup = decoder_i420_800_600_vctx,
     .decoder_decode = decoder_decode_vctx,
     .encoder_setup = encoder_i420_800_600_vctx,
     .encoder_encode = encoder_encode_dummy,
     .encoder_close = encoder_close,
+    .report_output = wait_output_reported,
 },{
     // - Decoder format with video context
     // - Encoder format request a different chroma
@@ -322,25 +339,27 @@ struct transcode_scenario transcode_scenarios[] =
     //   but it doesn't forward any video context
     /* Make sure converter will receive the video context */
     .source = source_800_600,
-    .sout = "sout=#transcode:dummy",
+    .sout = "sout=#transcode:output_checker",
     .decoder_setup = decoder_i420_800_600_vctx,
     .decoder_decode = decoder_decode_vctx,
     .encoder_setup = encoder_nv12_800_600,
     .encoder_encode = encoder_encode_dummy,
     .encoder_close = encoder_close,
     .converter_setup = converter_i420_to_nv12_800_600_vctx,
+    .report_output = wait_output_reported,
 },{
     /* Make sure a change in format will lead to the addition of a converter.
      * Here, decoder_decode_vctx_update will change format after the first
      * frame. */
     .source = source_800_600,
-    .sout = "sout=#transcode:dummy",
+    .sout = "sout=#transcode:output_checker",
     .decoder_setup = decoder_i420_800_600_vctx,
     .decoder_decode = decoder_decode_vctx_update,
     .encoder_setup = encoder_i420_800_600,
-    .encoder_encode = encoder_encode_wait_10_images,
+    .encoder_encode = encoder_encode_dummy,
     .encoder_close = encoder_close,
     .converter_setup = converter_nv12_to_i420_800_600_vctx,
+    .report_output = wait_output_10_frames_reported,
 },{
     /* Ensure that error are correctly forwarded back to the stream output
      * pipeline. */
@@ -356,7 +375,7 @@ size_t transcode_scenarios_count = ARRAY_SIZE(transcode_scenarios);
 void transcode_scenario_init(void)
 {
     scenario_data.decoder_vctx = NULL;
-    scenario_data.encoder_picture_count = 0;
+    scenario_data.output_frame_count = 0;
     scenario_data.converter_opened = false;
     scenario_data.encoder_opened = false;
     vlc_sem_init(&scenario_data.wait_stop, 0);



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a1e6e4dab2cc03ae63b1a39864fe39d74eb73e23...72512a8494a7d5a7da60f0303f42122bf9360db2

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a1e6e4dab2cc03ae63b1a39864fe39d74eb73e23...72512a8494a7d5a7da60f0303f42122bf9360db2
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