[vlc-commits] [Git][videolan/vlc][master] player: temporize on EOS bursts

Hugo Beauzée-Luyssen (@chouquette) gitlab at videolan.org
Thu Mar 24 13:15:26 UTC 2022



Hugo Beauzée-Luyssen pushed to branch master at VideoLAN / VLC


Commits:
e759db90 by Romain Vimont at 2022-03-24T12:40:16+00:00
player: temporize on EOS bursts

A mechanism was implemented to temporize on consecutive input errors, to
mitigate infinite busy loops (see commit
d06622651fcd4a608c06cb35e725fad57bf38167).

Although it avoided the most common issues, this mechanism was not
triggered for other problematic cases:
 - empty inputs;
 - inputs with unreported errors from demuxers.

Therefore, to encompass these other cases, consider the number of
consecutive stops in a small period of time instead of relying on
reported errors:
 - if a VLC_PLAYER_STATE_STOPPED occurs less than 100ms after the
   previous one, then increment the EOS burst count;
 - when more than 4 EOS burst count occur successively, start
   temporizing:
     - 100ms for the 5th
     - 200ms for the 6th
     - 400ms for the 7th
     - 800ms for the 8th
     - 1.6s for the 9th
     - 3.2s for the following

Fixes #5901
Fixes #26733

- - - - -


3 changed files:

- src/player/input.c
- src/player/player.c
- src/player/player.h


Changes:

=====================================
src/player/input.c
=====================================
@@ -105,19 +105,21 @@ vlc_player_WaitRetryDelay(vlc_player_t *player)
 {
 #define RETRY_TIMEOUT_BASE VLC_TICK_FROM_MS(100)
 #define RETRY_TIMEOUT_MAX VLC_TICK_FROM_MS(3200)
-    if (player->error_count)
+#define MAX_EOS_BURST 4
+    /* Temporize only after a few successive EOS */
+    if (player->eos_burst_count > MAX_EOS_BURST)
     {
-        /* Delay the next opening in case of error to avoid busy loops */
+        unsigned pow = player->eos_burst_count - MAX_EOS_BURST;
+        /* Delay the next opening to avoid busy loops */
         vlc_tick_t delay = RETRY_TIMEOUT_BASE;
-        for (unsigned i = 1; i < player->error_count
-          && delay < RETRY_TIMEOUT_MAX; ++i)
+        for (unsigned i = 1; i < pow && delay < RETRY_TIMEOUT_MAX; ++i)
             delay *= 2; /* Wait 100, 200, 400, 800, 1600 and finally 3200ms */
         delay += vlc_tick_now();
 
-        while (player->error_count > 0
+        while (player->eos_burst_count != 0
             && vlc_cond_timedwait(&player->start_delay_cond, &player->lock,
                                   delay) == 0);
-        if (player->error_count == 0)
+        if (player->eos_burst_count == 0)
             return false; /* canceled */
     }
     return true;
@@ -156,13 +158,20 @@ vlc_player_input_HandleState(struct vlc_player_input *input,
 
             vlc_player_ResetTimer(player);
 
-            if (input->error != VLC_PLAYER_ERROR_NONE)
-                player->error_count++;
-            else
-                player->error_count = 0;
+            if (player->last_eos != VLC_TICK_INVALID)
+            {
+                vlc_tick_t diff = vlc_tick_now() - player->last_eos;
+                if (diff < VLC_PLAYER_EOS_BURST_THRESHOLD)
+                    ++player->eos_burst_count;
+                else
+                    player->eos_burst_count = 0;
+            }
 
             vlc_player_WaitRetryDelay(player);
 
+            /* Assign the current date after the wait */
+            player->last_eos = vlc_tick_now();
+
             if (!player->deleting)
                 vlc_player_OpenNextMedia(player);
             if (!player->input)


=====================================
src/player/player.c
=====================================
@@ -119,9 +119,9 @@ vlc_player_OpenNextMedia(vlc_player_t *player)
 static void
 vlc_player_CancelWaitError(vlc_player_t *player)
 {
-    if (player->error_count != 0)
+    if (player->eos_burst_count != 0)
     {
-        player->error_count = 0;
+        player->eos_burst_count = 0;
         vlc_cond_signal(&player->start_delay_cond);
     }
 }
@@ -1952,7 +1952,8 @@ vlc_player_New(vlc_object_t *parent, enum vlc_player_lock_type lock_type,
     player->global_state = VLC_PLAYER_STATE_STOPPED;
     player->started = false;
 
-    player->error_count = 0;
+    player->last_eos = VLC_TICK_INVALID;
+    player->eos_burst_count = 0;
 
     player->releasing_media = false;
     player->next_media_requested = false;


=====================================
src/player/player.h
=====================================
@@ -267,7 +267,14 @@ struct vlc_player_t
     enum vlc_player_state global_state;
     bool started;
 
-    unsigned error_count;
+    /**
+     * Playing a tiny stream (either empty, or with unreported errors) in a loop
+     * would cause high CPU usage. To mitigate the problem, temporize if
+     * several EOS are received too quickly.
+     */
+#define VLC_PLAYER_EOS_BURST_THRESHOLD VLC_TICK_FROM_MS(250)
+    vlc_tick_t last_eos;
+    unsigned eos_burst_count;
 
     bool deleting;
     struct



View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/e759db90d958305afee6655e52597c4fef446c34

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/e759db90d958305afee6655e52597c4fef446c34
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