[vlc-commits] [Git][videolan/vlc][master] 4 commits: decoder: acknowledge all pause requests

Steve Lhomme (@robUx4) gitlab at videolan.org
Wed Jul 8 11:17:29 UTC 2026



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
7e78a995 by Thomas Guillem at 2026-07-08T10:45:04+00:00
decoder: acknowledge all pause requests

A pause and a resume requested in quick succession can cancel each other
out before the decoder thread wakes up: the output ends up in the
correct state but the last request is never acknowledged. Each pause
request will now produce a pause event.

Fixes #29960
(test_src_player_pause hangs, ~2% of runs with 100 parallel instances)

- - - - -
ef2f3434 by Thomas Guillem at 2026-07-08T10:45:04+00:00
player: pass a valid date to the PLAYING timer event

input->pause_date is reset just before being passed, so the PLAYING
timer event always carried VLC_TICK_INVALID. The date is unused for
this event so far; the next commit needs it.

- - - - -
aaf1673e by Thomas Guillem at 2026-07-08T10:45:04+00:00
player: timer: don't update the state from stale pause events

A pause acknowledgement from an ES output use the same request date and
can be delivered after that pause was resumed. Don't update the timer
state from it: the state follows the input timeline. It is still
reported to the source: events of a given ES are delivered in order, a
late pause is delayed, never reordered.

Replace the pause_reported flag with the date of the last reported
pause. No more reset on PLAYING: clearing it while an acknowledgement
was in flight was reporting a stale pause and eating the next one.

Fixes the following assert in `test_src_player_pause` (20% repro rate
since `--start-paused` fixes, but unrelated):

```
test_src_player_pause: ../../test/src/player/pause.c:101: test_pause: Assertion `get_timer_report(player, &video_timer).type == REPORT_TIMER_PAUSED' failed.
```

- - - - -
0567f08a by Thomas Guillem at 2026-07-08T10:45:04+00:00
test: player: pause: check the date of the second pause

A stale report from the first pause could satisfy the type-only wait.

- - - - -


5 changed files:

- src/input/decoder.c
- src/player/input.c
- src/player/player.h
- src/player/timer.c
- test/src/player/pause.c


Changes:

=====================================
src/input/decoder.c
=====================================
@@ -225,7 +225,7 @@ struct vlc_input_decoder_t
 #define PREROLL_FORCED VLC_TICK_MAX
 
     /* Pause & Rate */
-    vlc_tick_t pause_date;
+    vlc_tick_t pause_date, output_pause_date;
     vlc_tick_t delay, output_delay;
     float rate, output_rate;
     int frames_countdown;
@@ -2011,9 +2011,16 @@ static void *DecoderThread( void *p_data )
             continue;
         }
 
-        if( p_owner->paused != p_owner->output_paused )
+        /* Also compare the request dates: a pause and a resume requested in
+         * quick succession can cancel each other out, but each request must
+         * still be acknowledged via decoder_Notify() */
+        if( p_owner->paused != p_owner->output_paused
+         || p_owner->pause_date != p_owner->output_pause_date )
         {   /* Update playing/paused status of the output */
-            Decoder_ChangeOutputPause( p_owner, p_owner->paused, p_owner->pause_date );
+            if( p_owner->paused != p_owner->output_paused )
+                Decoder_ChangeOutputPause( p_owner, p_owner->paused,
+                                           p_owner->pause_date );
+            p_owner->output_pause_date = p_owner->pause_date;
             decoder_Notify(p_owner, on_output_paused, p_owner->paused,
                            p_owner->pause_date);
             if (unlikely(p_owner->paused && p_owner->cat == VIDEO_ES
@@ -2182,7 +2189,7 @@ CreateDecoder( vlc_object_t *p_parent, const struct vlc_input_decoder_cfg *cfg )
     p_owner->output_delay = p_owner->delay = 0;
     p_owner->output_rate = p_owner->rate = 1.f;
     p_owner->output_paused = p_owner->paused = false;
-    p_owner->pause_date = VLC_TICK_INVALID;
+    p_owner->output_pause_date = p_owner->pause_date = VLC_TICK_INVALID;
     p_owner->frames_countdown = 0;
 
     p_owner->b_waiting = false;


=====================================
src/player/input.c
=====================================
@@ -299,7 +299,7 @@ vlc_player_input_HandleState(struct vlc_player_input *input,
             vlc_player_SignalAtoBLoop(player);
             vlc_player_UpdateTimerEvent(player, NULL,
                                         VLC_PLAYER_TIMER_EVENT_PLAYING,
-                                        input->pause_date);
+                                        state_date);
             /* fall through */
         case VLC_PLAYER_STATE_STARTED:
             if (player->started &&


=====================================
src/player/player.h
=====================================
@@ -196,10 +196,9 @@ struct vlc_player_timer_source
     struct vlc_player_timer_point point;
     bool seeking;
 
-    /* Set once a pause has been reported to this source's listener.
-     * The input might signal paused clock and then output
-     * would signal it. This flag filters this case here. */
-    bool pause_reported;
+    /* Date of the last reported pause, to report a pause signaled by both
+     * the input and the output only once */
+    vlc_tick_t reported_pause_date;
 
     union
     {
@@ -243,6 +242,9 @@ struct vlc_player_timer
         UPDATE_STATE_RESUMING,
     } update_state;
     vlc_tick_t pause_date;
+    /* Date of the last input PLAYING event, to detect ES PAUSED events
+     * delivered after their pause was resumed */
+    vlc_tick_t last_resume_date;
     bool stopping;
 
     struct vlc_player_timer_source sources[VLC_PLAYER_TIMER_TYPE_COUNT];


=====================================
src/player/timer.c
=====================================
@@ -42,6 +42,7 @@ vlc_player_ResetTimer(vlc_player_t *player)
     player->timer.seek_position = -1;
     player->timer.update_state = UPDATE_STATE_RESUMED;
     player->timer.pause_date = VLC_TICK_INVALID;
+    player->timer.last_resume_date = VLC_TICK_INVALID;
     player->timer.stopping = false;
 
     vlc_mutex_unlock(&player->timer.lock);
@@ -262,8 +263,17 @@ vlc_player_UpdateTimerEvent(vlc_player_t *player, vlc_es_id_t *es_source,
 
         case VLC_PLAYER_TIMER_EVENT_PAUSED:
             assert(system_date != VLC_TICK_INVALID);
-            player->timer.update_state = UPDATE_STATE_PAUSED;
-            player->timer.pause_date = system_date;
+
+            /* An ES PAUSED event can be delivered after its pause was
+             * resumed. It is still reported: per-ES events are delivered
+             * in order, but it should not touch player timer state. */
+            if (es_source == NULL
+             || player->timer.last_resume_date == VLC_TICK_INVALID
+             || system_date >= player->timer.last_resume_date)
+            {
+                player->timer.update_state = UPDATE_STATE_PAUSED;
+                player->timer.pause_date = system_date;
+            }
 
             for (size_t i = 0; i < VLC_PLAYER_TIMER_TYPE_COUNT; ++i)
             {
@@ -271,11 +281,11 @@ vlc_player_UpdateTimerEvent(vlc_player_t *player, vlc_es_id_t *es_source,
                 if (source->es != es_source)
                     continue;
 
-                /* The input might signal paused clock and then output
-                 * would signal it. This flag filters this case here. */
-                if (source->pause_reported)
+                /* The input and the output signal the same pause with the
+                 * same date */
+                if (source->reported_pause_date == system_date)
                     continue;
-                source->pause_reported = true;
+                source->reported_pause_date = system_date;
                 vlc_player_SendTimerPause(player, source, system_date,
                                           i == VLC_PLAYER_TIMER_TYPE_SMPTE);
             }
@@ -284,9 +294,9 @@ vlc_player_UpdateTimerEvent(vlc_player_t *player, vlc_es_id_t *es_source,
 
         case VLC_PLAYER_TIMER_EVENT_PLAYING:
             assert(!player->timer.stopping);
+            if (system_date != VLC_TICK_INVALID)
+                player->timer.last_resume_date = system_date;
             player->timer.update_state = UPDATE_STATE_RESUMING;
-            for (size_t i = 0; i < VLC_PLAYER_TIMER_TYPE_COUNT; ++i)
-                player->timer.sources[i].pause_reported = false;
             break;
 
         case VLC_PLAYER_TIMER_EVENT_STOPPING:
@@ -763,7 +773,7 @@ vlc_player_InitTimer(vlc_player_t *player)
         player->timer.sources[i].point.system_date = VLC_TICK_INVALID;
         player->timer.sources[i].es = NULL;
         player->timer.sources[i].seeking = false;
-        player->timer.sources[i].pause_reported = false;
+        player->timer.sources[i].reported_pause_date = VLC_TICK_INVALID;
     }
     vlc_player_ResetTimer(player);
 }


=====================================
test/src/player/pause.c
=====================================
@@ -85,9 +85,13 @@ test_pause(struct ctx *ctx)
 
     wait_state(ctx, VLC_PLAYER_STATE_PAUSED);
 
-    /* Ensure all timers are paused */
-    wait_timer_report(player, &video_timer, REPORT_TIMER_PAUSED);
-    wait_timer_report(player, &timer, REPORT_TIMER_PAUSED);
+    /* Ensure all timers are paused, on the second pause (and not on a stale
+     * report from the first one) */
+    struct report_timer video_paused =
+        wait_timer_report(player, &video_timer, REPORT_TIMER_PAUSED);
+    struct report_timer regular_paused =
+        wait_timer_report(player, &timer, REPORT_TIMER_PAUSED);
+    assert(video_paused.paused_date == regular_paused.paused_date);
 
     /* Ensure we stay paused */
     vlc_tick_sleep(VLC_TICK_FROM_MS(100));



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/ca7612ed6a340d17b842ebcf51bc8dd81b307288...0567f08aaf0a5f430a82cdcca63e9e57666b880c

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/ca7612ed6a340d17b842ebcf51bc8dd81b307288...0567f08aaf0a5f430a82cdcca63e9e57666b880c
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help




More information about the vlc-commits mailing list