[vlc-commits] [Git][videolan/vlc][master] 5 commits: input: decoder: fix format cleaning on destroy

Steve Lhomme (@robUx4) gitlab at videolan.org
Wed Nov 23 14:34:45 UTC 2022



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
3007bc4a by Alexandre Janniaux at 2022-11-23T14:06:19+00:00
input: decoder: fix format cleaning on destroy

When destroying the decoder, the decoder module can be triggering a
decoder_UpdateVideoFormat call which will check the format we've been
clearing.

Regression from 08b24866dc443c30df8f9d5ee4f7e2045bf62956.

Refs #27532

- - - - -
d794eac3 by Alexandre Janniaux at 2022-11-23T14:06:19+00:00
test: input: decoder: check decoder destruction

Check that the decoder is correctly destroyed, even if it is being
running a decoder_UpdateVideoOutput at the point of destruction.

Refs #27532

- - - - -
1dbe1fe2 by Alexandre Janniaux at 2022-11-23T14:06:19+00:00
test: input: decoder: handle VLCDEC_RELOAD

When VLCDEC_RELOAD is returned by the decoder_t::pf_decode method, the
vlc_frame_t block will be reused for the next decoder, and cannot be
released.

- - - - -
2e928f40 by Alexandre Janniaux at 2022-11-23T14:06:19+00:00
input: decoder: fix format cleaning on reload

When reloading the decoder, the decoder module can be triggering a
decoder_UpdateVideoFormat call which will check the format we've been
clearing.

Regression from 08b24866dc443c30df8f9d5ee4f7e2045bf62956.

Refs #27532

- - - - -
579d97da by Alexandre Janniaux at 2022-11-23T14:06:19+00:00
test: input: decoder: check decoder reload

Check that the decoder is correctly reload, even if it is being
running a decoder_UpdateVideoOutput at the point of reloading.

Fixes #27532

- - - - -


4 changed files:

- src/input/decoder.c
- test/src/input/decoder/input_decoder.c
- test/src/input/decoder/input_decoder.h
- test/src/input/decoder/input_decoder_scenarios.c


Changes:

=====================================
src/input/decoder.c
=====================================
@@ -309,8 +309,8 @@ static int DecoderThread_Reload( vlc_input_decoder_t *p_owner,
     }
 
     /* Restart the decoder module */
-    es_format_Clean( &p_owner->dec_fmt_in );
     decoder_Clean( p_dec );
+    es_format_Clean( &p_owner->dec_fmt_in );
     p_owner->error = false;
 
     if( reload == RELOAD_DECODER_AOUT )
@@ -2015,9 +2015,8 @@ static void DeleteDecoder( vlc_input_decoder_t *p_owner, enum es_format_category
     msg_Dbg( p_dec, "killing decoder fourcc `%4.4s'",
              (char*)&p_dec->fmt_in->i_codec );
 
-    es_format_Clean( &p_owner->dec_fmt_in );
-    es_format_Clean( &p_owner->pktz_fmt_in );
     decoder_Clean( p_dec );
+
     if ( p_owner->out_pool )
     {
         picture_pool_Release( p_owner->out_pool );
@@ -2089,6 +2088,8 @@ static void DeleteDecoder( vlc_input_decoder_t *p_owner, enum es_format_category
             vlc_assert_unreachable();
     }
 
+    es_format_Clean( &p_owner->dec_fmt_in );
+    es_format_Clean( &p_owner->pktz_fmt_in );
     es_format_Clean( &p_owner->fmt );
 
     if( p_owner->p_description )


=====================================
test/src/input/decoder/input_decoder.c
=====================================
@@ -84,11 +84,13 @@ static int DecoderDecode(decoder_t *dec, block_t *block)
     assert(pic);
     pic->date = block->i_pts;
     pic->b_progressive = true;
-    block_Release(block);
 
     struct input_decoder_scenario *scenario = &input_decoder_scenarios[current_scenario];
     assert(scenario->decoder_decode != NULL);
-    return scenario->decoder_decode(dec, pic);
+    int ret = scenario->decoder_decode(dec, pic);
+    if (ret != VLCDEC_RELOAD)
+        block_Release(block);
+    return ret;
 }
 
 static void DecoderFlush(decoder_t *dec)
@@ -100,7 +102,11 @@ static void DecoderFlush(decoder_t *dec)
 
 static void CloseDecoder(vlc_object_t *obj)
 {
+    struct input_decoder_scenario *scenario = &input_decoder_scenarios[current_scenario];
     decoder_t *dec = (decoder_t*)obj;
+
+    if (scenario->decoder_destroy != NULL)
+        scenario->decoder_destroy(dec);
     struct vlc_video_context *vctx = dec->p_sys;
     if (vctx)
         vlc_video_context_Release(vctx);


=====================================
test/src/input/decoder/input_decoder.h
=====================================
@@ -32,6 +32,7 @@ struct input_decoder_scenario {
     const char *source;
     const char *sout;
     void (*decoder_setup)(decoder_t *);
+    void (*decoder_destroy)(decoder_t *);
     int (*decoder_decode)(decoder_t *, picture_t *);
     void (*decoder_flush)(decoder_t *);
     void (*display_prepare)(vout_display_t *vd, picture_t *pic);


=====================================
test/src/input/decoder/input_decoder_scenarios.c
=====================================
@@ -44,6 +44,7 @@ static struct scenario_data
     vlc_sem_t wait_ready_to_flush;
     struct vlc_video_context *decoder_vctx;
     bool skip_decoder;
+    bool has_reload;
     bool stream_out_sent;
     size_t decoder_image_sent;
 } scenario_data;
@@ -65,6 +66,12 @@ static void decoder_fixed_size(decoder_t *dec, vlc_fourcc_t chroma,
 static void decoder_i420_800_600(decoder_t *dec)
     { decoder_fixed_size(dec, VLC_CODEC_I420, 800, 600); }
 
+static void decoder_i420_800_600_stop(decoder_t *dec)
+{
+    decoder_i420_800_600(dec);
+    vlc_sem_post(&scenario_data.wait_stop);
+}
+
 static int decoder_decode_check_cc(decoder_t *dec, picture_t *pic)
 {
     vlc_tick_t date = pic->date;
@@ -204,6 +211,36 @@ static void decoder_flush_signal(decoder_t *dec)
     vlc_sem_post(&scenario_data.wait_stop);
 }
 
+static void* SendUpdateOutput(void *opaque)
+{
+    decoder_t *dec = opaque;
+    decoder_UpdateVideoOutput(dec, NULL);
+    return NULL;
+}
+
+static void decoder_destroy_trigger_update(decoder_t *dec)
+{
+    /* Use another thread to ensure we don't double-lock, but
+     * at most deadlock instead. */
+    vlc_thread_t thread;
+    int ret = vlc_clone(&thread, SendUpdateOutput, dec);
+    assert(ret == VLC_SUCCESS);
+    vlc_join(thread, NULL);
+}
+
+static int decoder_decode_trigger_reload(decoder_t *dec, picture_t *pic)
+{
+    (void)dec;
+    picture_Release(pic);
+
+    if (!scenario_data.has_reload)
+    {
+        vlc_sem_post(&scenario_data.wait_stop);
+        return VLCDEC_RELOAD;
+    }
+    return VLCDEC_SUCCESS;
+}
+
 static void display_prepare_signal(vout_display_t *vd, picture_t *pic)
 {
     (void)vd;
@@ -311,6 +348,23 @@ struct input_decoder_scenario input_decoder_scenarios[] =
     .sout_filter_send = sout_filter_send,
     .sout_filter_flush = sout_filter_flush,
     .interface_setup = interface_setup_check_flush,
+},
+{
+    /* Check that releasing a decoder while it is triggering an update
+     * of the video output format doesn't lead to a crash. Non-regression
+     * test from issue #27532. */
+    .source = source_800_600,
+    .decoder_setup = decoder_i420_800_600_stop,
+    .decoder_destroy = decoder_destroy_trigger_update,
+},
+{
+    /* Check that reloading a decoder while it is triggering an update
+     * of the video output format doesn't lead to a crash. Non-regression
+     * test from issue #27532. */
+    .source = source_800_600,
+    .decoder_setup = decoder_i420_800_600,
+    .decoder_decode = decoder_decode_trigger_reload,
+    .decoder_destroy = decoder_destroy_trigger_update,
 }};
 size_t input_decoder_scenarios_count = ARRAY_SIZE(input_decoder_scenarios);
 
@@ -318,6 +372,7 @@ void input_decoder_scenario_init(void)
 {
     scenario_data.decoder_vctx = NULL;
     scenario_data.skip_decoder = false;
+    scenario_data.has_reload = false;
     scenario_data.stream_out_sent = false;
     scenario_data.decoder_image_sent = 0;
     vlc_sem_init(&scenario_data.wait_stop, 0);



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/5e7d2af4277a508f856d8b65f3a60765e35a4313...579d97daa24134e7ea8bd393c572069bcfc3a729

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/5e7d2af4277a508f856d8b65f3a60765e35a4313...579d97daa24134e7ea8bd393c572069bcfc3a729
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