[vlc-commits] [Git][videolan/vlc][master] 15 commits: adaptive: remove unused now unused decodersDrained()

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Fri Feb 7 19:38:55 UTC 2025



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
989e5e54 by Thomas Guillem at 2025-02-07T19:15:26+00:00
adaptive: remove unused now unused decodersDrained()

- - - - -
0841e130 by Thomas Guillem at 2025-02-07T19:15:26+00:00
es_out: rename GET_EMPTY to DRAIN

Because it is actually stopping buffering and often used to for that
purpose.

This will be modified to drain after stopping the buffering in a
upcoming commit, since all users also except this behavior.

- - - - -
38862bee by Thomas Guillem at 2025-02-07T19:15:26+00:00
es_out: move p_sys->p_pgrm check

To make it more explicit.

- - - - -
6c3ad4d0 by Thomas Guillem at 2025-02-07T19:15:26+00:00
es_out: split EsOutDrain()

Into EsOutDrain() and EsOutIsEmpty()

EsOutIsEmpty() must be called while buffering.

- - - - -
aa0de80c by Thomas Guillem at 2025-02-07T19:15:26+00:00
es_out: add ES_OUT_IS_EMPTY

Check if the es_out is empty without touching the buffering state.

- - - - -
87df46b1 by Thomas Guillem at 2025-02-07T19:15:26+00:00
es_out: stop buffering from EOS

Call EsOutDrain(), that is only stopping buffering for now.

Therefore, ES_OUT_IS_EMPTY can be called from input.c when EOF.

- - - - -
a962934a by Thomas Guillem at 2025-02-07T19:15:26+00:00
input: call ES_OUT_IS_EMPTY

This control is called after EOF, no need to stop buffering.

- - - - -
1ebb26bb by Thomas Guillem at 2025-02-07T19:15:26+00:00
es_out: don't return the empty state from ES_OUT_DRAIN

but return if the call was successful.

- - - - -
8b2fa700 by Thomas Guillem at 2025-02-07T19:15:26+00:00
decoder: check if draining from IsEmpty()

Temporary commit that restore the behavior from 0dd8096f46a9. This
allows demuxers to check if empty without draining the decoders. This
behavior i undefined as this could lead to audio underrun.

This is needed to no break bisect while fixing the dvdnav module. This
will be reverted just after.

- - - - -
48bb67d3 by Thomas Guillem at 2025-02-07T19:15:26+00:00
dvdnav: fix DemuxForceStill()

Wait for the es_out to be empty/drained in order to avoid flushing past
video/subtitles.

This also fixes an undefined behavior (that could lead to no audio) when
DemuxForceStill() was called but the PCR was not reset (cf. the other
call to DemuxForceStill() not showing in this diff).

- - - - -
84e86024 by Thomas Guillem at 2025-02-07T19:15:26+00:00
dvdnav: ensure spus are processed after the last I-frame

SPUs packets might be beyond the final reference frame sectors
(vobu_*ref_ea), causing them to be skipped if we drain the es_out
immediately after the last I-frame. By preferring vobu_ea when it is
nonzero, we ensure SPUs to be properly displayed.

cf. fdb3c7365247ad2faf4a4b7d65e04c1bb7cb1f93

- - - - -
b67ea0ff by Thomas Guillem at 2025-02-07T19:15:26+00:00
es_out: drain from ES_OUT_DRAIN

- - - - -
97a21197 by Thomas Guillem at 2025-02-07T19:15:26+00:00
es_out: remove extra drain call

- - - - -
4ae4fe9b by Thomas Guillem at 2025-02-07T19:15:26+00:00
Revert "decoder: check if draining from IsEmpty()"

This was a temporary commit, to not break bisect while fixing dvdnav.

- - - - -
863a5b8d by Thomas Guillem at 2025-02-07T19:15:26+00:00
dvdnav: don't send EOS packet

Not needed since decoders are now drained.

- - - - -


14 changed files:

- include/vlc_es_out.h
- modules/access/bluray.c
- modules/access/dvdnav.c
- modules/demux/adaptive/Streams.cpp
- modules/demux/adaptive/Streams.hpp
- modules/demux/adaptive/plumbing/FakeESOut.cpp
- modules/demux/adaptive/plumbing/FakeESOut.hpp
- modules/demux/mp4/heif.c
- modules/stream_out/chromecast/chromecast_demux.cpp
- src/input/es_out.c
- src/input/es_out.h
- src/input/es_out_timeshift.c
- src/input/input.c
- test/src/input/demux-run.c


Changes:

=====================================
include/vlc_es_out.h
=====================================
@@ -86,12 +86,14 @@ enum es_out_query_e
     /* Set scrambled state for one es */
     ES_OUT_SET_ES_SCRAMBLED_STATE,  /* arg1=int i_group arg2=es_out_id_t* */
 
-    /* Stop any buffering being done, and ask if es_out has no more data to
-     * play.
+    /* Stop any buffering being done, and drain
      * It will not block and so MUST be used carefully. The only good reason
      * is for interactive playback (like for DVD menu).
-     * XXX You SHALL call ES_OUT_RESET_PCR before any other es_out_Control/Send calls. */
-    ES_OUT_GET_EMPTY,       /* arg1=bool*   res=cannot fail */
+     * XXX You SHALL call ES_OUT_RESET_PCR before any other es_out_Control/Send calls in case of success. */
+    ES_OUT_DRAIN, /* res=can fail */
+
+    /* Ask if es_out has no more data to play */
+    ES_OUT_IS_EMPTY, /* arg1=bool*               res=cannot fail */
 
     /* Set global meta data (The vlc_meta_t is not modified nor released) */
     ES_OUT_SET_META, /* arg1=const vlc_meta_t * */


=====================================
modules/access/bluray.c
=====================================
@@ -2769,8 +2769,7 @@ static void blurayStillImage( demux_t *p_demux, unsigned i_timeout )
         streamFlush(p_sys);
 
         /* stop buffering */
-        bool b_empty;
-        es_out_Control( p_demux->out, ES_OUT_GET_EMPTY, &b_empty );
+        es_out_Control( p_demux->out, ES_OUT_DRAIN );
     }
 
     /* avoid busy loops (read returns no data) */
@@ -3030,8 +3029,12 @@ static int blurayDemux(demux_t *p_demux)
 
     if(p_sys->b_draining)
     {
-        bool b_empty = false;
-        if(es_out_Control(p_sys->p_out, ES_OUT_GET_EMPTY, &b_empty) != VLC_SUCCESS || b_empty)
+        int ret = es_out_Control(p_sys->p_out, ES_OUT_DRAIN);
+
+        bool b_empty = true;
+        if (ret == VLC_SUCCESS)
+            es_out_Control(p_sys->p_out, ES_OUT_IS_EMPTY, &b_empty);
+        if (b_empty)
         {
             es_out_Control(p_sys->p_out, ES_OUT_RESET_PCR);
             p_sys->b_draining = false;


=====================================
modules/access/dvdnav.c
=====================================
@@ -126,6 +126,7 @@ typedef struct
     /* */
     bool        b_reset_pcr;
     bool        b_readahead;
+    bool        b_wait_empty;
 
     struct
     {
@@ -879,6 +880,20 @@ static int Demux( demux_t *p_demux )
     int32_t i_len;
     dvdnav_status_t status;
 
+    if( p_sys->b_wait_empty )
+    {
+        bool b_empty;
+        es_out_Control( p_sys->p_tf_out, ES_OUT_IS_EMPTY, &b_empty );
+        if( !b_empty )
+        {
+            vlc_tick_sleep( VLC_TICK_FROM_MS(40) );
+            return VLC_DEMUXER_SUCCESS;
+        }
+        p_sys->b_wait_empty = false;
+        /* Don't call RESET_PCR directly as we night need to handle NAV events */
+        p_sys->b_reset_pcr = true;
+    }
+
     if( p_sys->b_readahead )
         status = dvdnav_get_next_cache_block( p_sys->dvdnav, &packet, &i_event,
                                               &i_len );
@@ -951,11 +966,7 @@ static int Demux( demux_t *p_demux )
         vlc_mutex_unlock( &p_sys->still.lock );
 
         if( b_still_init )
-        {
             DemuxForceStill( p_demux );
-            p_sys->b_reset_pcr = true;
-        }
-        vlc_tick_sleep( VLC_TICK_FROM_MS(40) );
         break;
     }
 
@@ -1154,7 +1165,9 @@ static int Demux( demux_t *p_demux )
             if( unlikely(!p_dsi) )
                 break;
             const dsi_gi_t *p_dsi_gi = &p_dsi->dsi_gi;
-            if( p_dsi_gi->vobu_3rdref_ea != 0 )
+            if( p_dsi_gi->vobu_ea != 0 )
+                p_sys->i_vobu_flush = p_dsi_gi->vobu_ea;
+            else if( p_dsi_gi->vobu_3rdref_ea != 0 )
                 p_sys->i_vobu_flush = p_dsi_gi->vobu_3rdref_ea;
             else if( p_dsi_gi->vobu_2ndref_ea != 0 )
                 p_sys->i_vobu_flush = p_dsi_gi->vobu_2ndref_ea;
@@ -1210,8 +1223,10 @@ static int Demux( demux_t *p_demux )
     case DVDNAV_WAIT:
         msg_Dbg( p_demux, "DVDNAV_WAIT" );
 
-        bool b_empty;
-        es_out_Control( p_sys->p_tf_out, ES_OUT_GET_EMPTY, &b_empty );
+        bool b_empty = true;
+        int ret = es_out_Control( p_sys->p_tf_out, ES_OUT_DRAIN );
+        if( ret == VLC_SUCCESS )
+            es_out_Control( p_sys->p_tf_out, ES_OUT_IS_EMPTY, &b_empty );
         if( !b_empty )
         {
             vlc_tick_sleep( VLC_TICK_FROM_MS(40) );
@@ -1563,15 +1578,9 @@ static void DemuxForceStill( demux_t *p_demux )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
 
-    static const uint8_t buffer[] = {
-        0x00, 0x00, 0x01, 0xe0, 0x00, 0x07,
-        0x80, 0x00, 0x00,
-        0x00, 0x00, 0x01, 0xB7,
-    };
-    DemuxBlock( p_demux, buffer, sizeof(buffer) );
-
-    bool b_empty;
-    es_out_Control( p_sys->p_tf_out, ES_OUT_GET_EMPTY, &b_empty );
+    int ret = es_out_Control( p_sys->p_tf_out, ES_OUT_DRAIN );
+    if (ret == VLC_SUCCESS)
+        p_sys->b_wait_empty = true;
 }
 
 /*****************************************************************************


=====================================
modules/demux/adaptive/Streams.cpp
=====================================
@@ -342,11 +342,6 @@ void AbstractStream::setLivePause(bool b)
     }
 }
 
-bool AbstractStream::decodersDrained()
-{
-    return fakeEsOut()->decodersDrained();
-}
-
 vlc_tick_t AbstractStream::getDemuxedAmount(Times from) const
 {
     vlc_tick_t i_demuxed = fakeEsOut()->commandsQueue()->getDemuxedAmount(from).continuous;


=====================================
modules/demux/adaptive/Streams.hpp
=====================================
@@ -87,7 +87,6 @@ namespace adaptive
         BufferingStatus getBufferAndStatus(const Times &, vlc_tick_t, vlc_tick_t, vlc_tick_t *);
         vlc_tick_t getDemuxedAmount(Times) const;
         Status dequeue(Times, Times *);
-        bool decodersDrained();
 
         class StreamPosition
         {


=====================================
modules/demux/adaptive/plumbing/FakeESOut.cpp
=====================================
@@ -462,13 +462,6 @@ bool FakeESOut::hasSelectedEs(const AbstractFakeESOutID *id) const
     return false;
 }
 
-bool FakeESOut::decodersDrained()
-{
-    bool b_empty = true;
-    es_out_Control( real_es_out, ES_OUT_GET_EMPTY, &b_empty );
-    return b_empty;
-}
-
 bool FakeESOut::restarting() const
 {
     bool b = !recycle_candidates.empty();


=====================================
modules/demux/adaptive/plumbing/FakeESOut.hpp
=====================================
@@ -91,7 +91,6 @@ namespace adaptive
             size_t esCount() const;
             bool hasSelectedEs() const;
             bool hasSelectedEs(const AbstractFakeESOutID *) const;
-            bool decodersDrained();
             bool restarting() const;
             void setExtraInfoProvider( ExtraFMTInfoInterface * );
             vlc_tick_t fixTimestamp(vlc_tick_t);


=====================================
modules/demux/mp4/heif.c
=====================================
@@ -709,8 +709,10 @@ static int DemuxHEIF( demux_t *p_demux )
     /* Displaying a picture */
     if( p_sys->i_end_display_time > 0 )
     {
-        bool b_empty;
-        es_out_Control( p_demux->out, ES_OUT_GET_EMPTY, &b_empty );
+        bool b_empty = true;
+        int ret = es_out_Control( p_demux->out, ES_OUT_DRAIN );
+        if( ret == VLC_SUCCESS )
+            es_out_Control( p_demux->out, ES_OUT_IS_EMPTY, &b_empty );
         if( !b_empty || vlc_tick_now() <= p_sys->i_end_display_time )
         {
             vlc_tick_sleep( VLC_TICK_FROM_MS(40) );


=====================================
modules/stream_out/chromecast/chromecast_demux.cpp
=====================================
@@ -272,8 +272,10 @@ struct demux_cc
         {
             /* Signal EOF to the sout when the es_out is empty (so when the
              * DecoderThread fifo are empty) */
-            bool b_empty;
-            es_out_Control( p_demux->s->out, ES_OUT_GET_EMPTY, &b_empty );
+            bool b_empty = true;
+            int ret = es_out_Control( p_demux->s->out, ES_OUT_DRAIN );
+            if( ret == VLC_SUCCESS )
+                es_out_Control( p_demux->s->out, ES_OUT_IS_EMPTY, &b_empty );
             if( b_empty )
                 p_renderer->pf_send_input_event( p_renderer->p_opaque,
                                                  CC_INPUT_EVENT_EOF,


=====================================
src/input/es_out.c
=====================================
@@ -230,6 +230,7 @@ typedef struct
     vlc_tick_t  i_buffering_extra_initial;
     vlc_tick_t  i_buffering_extra_stream;
     vlc_tick_t  i_buffering_extra_system;
+    bool        b_draining;
 
     /* Record */
     sout_stream_t *p_sout_record;
@@ -262,6 +263,7 @@ static void EsOutChangePosition(es_out_sys_t *out, bool b_flush, es_out_id_t *p_
 static void EsOutProgramChangePause(es_out_sys_t *out, bool b_paused, vlc_tick_t i_date);
 static void EsOutProgramsChangeRate(es_out_sys_t *out);
 static void EsOutDecodersStopBuffering(es_out_sys_t *out, bool b_forced);
+static void EsOutDrainDecoder(es_out_sys_t *p_sys, es_out_id_t *es, bool wait);
 static void EsOutGlobalMeta(es_out_sys_t *p_out, const vlc_meta_t *p_meta);
 static void EsOutMeta(es_out_sys_t *p_out, const vlc_meta_t *p_meta, const vlc_meta_t *p_progmeta);
 static int EsOutEsUpdateFmt(es_out_id_t *es, const es_format_t *fmt);
@@ -695,17 +697,13 @@ static vlc_tick_t EsOutGetWakeup(es_out_sys_t *p_sys)
     return input_clock_GetWakeup( p_sys->p_pgrm->p_input_clock );
 }
 
-static bool EsOutDecodersIsEmpty(es_out_sys_t *p_sys)
-{
-    es_out_id_t *es;
 
-    if( p_sys->b_buffering && p_sys->p_pgrm )
-    {
-        EsOutDecodersStopBuffering(p_sys, true);
-        if( p_sys->b_buffering )
-            return true;
-    }
+static bool EsOutIsEmpty(es_out_sys_t *p_sys)
+{
+    if( p_sys->b_buffering )
+        return true;
 
+    es_out_id_t *es;
     foreach_es_then_es_slaves(es)
     {
         if( es->p_dec && !vlc_input_decoder_IsEmpty( es->p_dec ) )
@@ -716,6 +714,30 @@ static bool EsOutDecodersIsEmpty(es_out_sys_t *p_sys)
     return true;
 }
 
+static int EsOutDrain(es_out_sys_t *p_sys)
+{
+    if( p_sys->p_pgrm == NULL ) /* Nothing to drain, assume es_out is empty */
+        return VLC_SUCCESS;
+
+    if( p_sys->b_buffering )
+    {
+        EsOutDecodersStopBuffering(p_sys, true);
+        if( p_sys->b_buffering )
+            return VLC_EGENERIC;
+    }
+
+    if( !p_sys->b_draining )
+    {
+        es_out_id_t *id;
+        foreach_es_then_es_slaves(id)
+            if (id->p_dec != NULL)
+                EsOutDrainDecoder(p_sys, id, false);
+        p_sys->b_draining = true;
+    }
+
+    return VLC_SUCCESS;
+}
+
 static void EsOutUpdateDelayJitter(es_out_sys_t *p_sys)
 {
     /* Update the clock pts delay only if the extra tracks delay changed */
@@ -944,6 +966,7 @@ static void EsOutChangePosition(es_out_sys_t *p_sys, bool b_flush,
     p_sys->i_buffering_extra_initial = 0;
     p_sys->i_buffering_extra_stream = 0;
     p_sys->i_buffering_extra_system = 0;
+    p_sys->b_draining = false;
     p_sys->i_preroll_end = -1;
     p_sys->i_prev_stream_level = -1;
 }
@@ -2925,6 +2948,7 @@ static int EsOutSend(es_out_t *out, es_out_id_t *es, block_t *p_block )
     }
 
     vlc_mutex_lock( &p_sys->lock );
+    assert( !p_sys->b_draining );
 
     /* Shift all slaves timestamps with the main source normal time. This will
      * allow to synchronize 2 demuxers with different time bases. Remove the
@@ -3606,10 +3630,13 @@ static int EsOutVaControlLocked(es_out_sys_t *p_sys, input_source_t *source,
         return VLC_SUCCESS;
     }
 
-    case ES_OUT_GET_EMPTY:
+    case ES_OUT_DRAIN:
+        return EsOutDrain(p_sys);
+
+    case ES_OUT_IS_EMPTY:
     {
         bool *pb = va_arg( args, bool* );
-        *pb = EsOutDecodersIsEmpty(p_sys);
+        *pb = EsOutIsEmpty( p_sys );
         return VLC_SUCCESS;
     }
 
@@ -3962,10 +3989,7 @@ static int EsOutVaPrivControlLocked(es_out_sys_t *p_sys, input_source_t *source,
     }
     case ES_OUT_PRIV_SET_EOS:
     {
-        es_out_id_t *id;
-        foreach_es_then_es_slaves(id)
-            if (id->p_dec != NULL)
-                EsOutDrainDecoder(p_sys, id, false);
+        EsOutDrain(p_sys);
         return VLC_SUCCESS;
     }
     case ES_OUT_PRIV_SET_VBI_PAGE:
@@ -4097,6 +4121,7 @@ input_EsOutNew(input_thread_t *p_input, input_source_t *main_source, float rate,
     p_sys->rate = rate;
 
     p_sys->b_buffering = true;
+    p_sys->b_draining = false;
     p_sys->i_preroll_end = -1;
     p_sys->i_prev_stream_level = -1;
 


=====================================
src/input/es_out.h
=====================================
@@ -212,10 +212,10 @@ es_out_GetBuffering(struct vlc_input_es_out *out)
 }
 
 static inline bool
-es_out_GetEmpty(struct vlc_input_es_out *out)
+es_out_IsEmpty(struct vlc_input_es_out *out)
 {
     bool b;
-    int i_ret = es_out_Control(&out->out, ES_OUT_GET_EMPTY, &b);
+    int i_ret = es_out_Control(&out->out, ES_OUT_IS_EMPTY, &b);
 
     assert( !i_ret );
     return b;


=====================================
src/input/es_out_timeshift.c
=====================================
@@ -491,16 +491,16 @@ static inline int es_out_in_PrivControl(struct vlc_input_es_out *p_out,
 }
 
 static int
-ControlLockedGetEmpty(struct es_out_timeshift *p_sys,
-                      input_source_t *in,
-                      bool *pb_empty )
+ControlLockedIsEmpty(struct es_out_timeshift *p_sys, input_source_t *in,
+                     bool *pb_empty)
 {
     if( p_sys->b_delayed && TsHasCmd( p_sys->p_ts ) )
         *pb_empty = false;
     else
     {
-        int ret = es_out_in_Control( p_sys->p_out, in, ES_OUT_GET_EMPTY, pb_empty );
-        assert( ret == VLC_SUCCESS );
+        int ret = es_out_in_Control( p_sys->p_out, in, ES_OUT_IS_EMPTY,
+                                     pb_empty );
+        assert( !ret );
     }
 
     return VLC_SUCCESS;
@@ -654,6 +654,7 @@ static int ControlLocked( es_out_t *p_out, input_source_t *in, int i_query,
     case ES_OUT_SET_ES_STATE:
     case ES_OUT_SET_ES_CAT_POLICY:
     case ES_OUT_SET_ES_FMT:
+    case ES_OUT_DRAIN:
     {
         ts_cmd_control_t cmd;
         if( CmdInitControl( &cmd, in, i_query, args, p_sys->b_delayed ) )
@@ -711,10 +712,10 @@ static int ControlLocked( es_out_t *p_out, input_source_t *in, int i_query,
                                   p_es->p_es, p_hl );
     }
     /* Special internal input control */
-    case ES_OUT_GET_EMPTY:
+    case ES_OUT_IS_EMPTY:
     {
         bool *pb_empty = va_arg( args, bool* );
-        return ControlLockedGetEmpty(p_sys, in, pb_empty);
+        return ControlLockedIsEmpty(p_sys, in, pb_empty);
     }
 
     case ES_OUT_POST_SUBNODE:
@@ -1615,6 +1616,7 @@ static int CmdInitControl( ts_cmd_control_t *p_cmd, input_source_t *in,
         p_cmd->u.es_bool.b_bool = (bool)va_arg( args, int );
         break;
 
+    case ES_OUT_DRAIN:
     case ES_OUT_RESET_PCR:           /* no arg */
         break;
 
@@ -1746,6 +1748,7 @@ CmdExecuteControl(struct es_out_timeshift *p_sys,
         return es_out_in_Control( p_sys->p_out, in, i_query, p_cmd->u.int_i64.i_int,
                                   p_cmd->u.int_i64.i_i64 );
 
+    case ES_OUT_DRAIN:
     case ES_OUT_RESET_PCR:           /* no arg */
         return es_out_in_Control( p_sys->p_out, in, i_query );
 


=====================================
src/input/input.c
=====================================
@@ -667,7 +667,7 @@ static void MainLoop( input_thread_t *p_input, bool b_interactive )
 
                 b_paused_at_eof = false;
             }
-            else if( !es_out_GetEmpty( input_priv(p_input)->p_es_out ) )
+            else if( !es_out_IsEmpty( input_priv(p_input)->p_es_out ) )
             {
                 msg_Dbg( p_input, "waiting decoder fifos to empty" );
                 i_wakeup = vlc_tick_now() + INPUT_IDLE_SLEEP;


=====================================
test/src/input/demux-run.c
=====================================
@@ -185,8 +185,9 @@ static int EsOutControl(es_out_t *out, input_source_t* in, int query, va_list ar
         case ES_OUT_SET_GROUP_EPG:
         case ES_OUT_DEL_GROUP:
         case ES_OUT_SET_ES_SCRAMBLED_STATE:
+        case ES_OUT_DRAIN:
             break;
-        case ES_OUT_GET_EMPTY:
+        case ES_OUT_IS_EMPTY:
             *va_arg(args, bool *) = true;
             break;
         case ES_OUT_SET_META:



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/225ba6933afe5c624babc4391eb72ed98dc227be...863a5b8d5becd59d8eb1f8ad856c9d8f447c6c42

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/225ba6933afe5c624babc4391eb72ed98dc227be...863a5b8d5becd59d8eb1f8ad856c9d8f447c6c42
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