Skip to content
Snippets Groups Projects
Commit c0bb3d7b authored by Romain Vimont's avatar Romain Vimont Committed by Rémi Denis-Courmont
Browse files

playlist: temporize on EOS bursts

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

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 playback end occurs less than 250ms 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
Refs vlc4/e759db90
parent a695dc03
No related branches found
No related tags found
2 merge requests!3533Backport MR 3236 to 3.0.x,!1661[3.0] playlist: temporize on EOS bursts
Pipeline #205140 passed with stages
in 21 minutes and 6 seconds
......@@ -261,7 +261,8 @@ playlist_t *playlist_Create( vlc_object_t *p_parent )
pl_priv(p_playlist)->status.p_item = NULL;
pl_priv(p_playlist)->status.p_node = p_playlist->p_playing;
pl_priv(p_playlist)->request.b_request = false;
pl_priv(p_playlist)->i_consecutive_errors = 0;
pl_priv(p_playlist)->last_eos = 0;
pl_priv(p_playlist)->eos_burst_count = 0;
p->request.input_dead = false;
if (ml != NULL)
......
......@@ -87,7 +87,15 @@ typedef struct playlist_private_t
int i_last_playlist_id; /**< Last id to an item */
bool b_reset_currently_playing; /** Reset current item array */
unsigned i_consecutive_errors; /**< Number of consecutive items in error */
/**
* 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_PLAYLIST_EOS_BURST_THRESHOLD (CLOCK_FREQ / 4) /* 250 ms */
mtime_t last_eos;
unsigned eos_burst_count;
bool b_tree; /**< Display as a tree */
bool b_preparse; /**< Preparse items */
......
......@@ -498,19 +498,31 @@ static void *Thread ( void *data )
/* Playlist in running state */
while( !p_sys->killed && Next( p_playlist ) )
{
bool ok = LoopInput( p_playlist );
if (ok)
p_sys->i_consecutive_errors = 0;
else
LoopInput( p_playlist );
if (p_sys->last_eos)
{
if (p_sys->i_consecutive_errors < 6)
p_sys->i_consecutive_errors++;
#define MAX_EOS_BURST 4
mtime_t diff = mdate() - p_sys->last_eos;
if (diff < VLC_PLAYLIST_EOS_BURST_THRESHOLD)
{
if (p_sys->eos_burst_count < MAX_EOS_BURST + 6)
++p_sys->eos_burst_count;
if (p_sys->eos_burst_count > MAX_EOS_BURST)
{
unsigned pow = p_sys->eos_burst_count - MAX_EOS_BURST;
unsigned slowdown = 1 << (pow - 1);
/* 100ms, 200ms, 400ms, 800ms, 1.6s, 3.2s */
mtime_t deadline = mdate() + slowdown * 100000L; /* usecs */
vlc_cond_timedwait(&p_sys->signal, &p_sys->lock, deadline);
}
int slowdown = 1 << (p_sys->i_consecutive_errors - 1);
/* 100ms, 200ms, 400ms, 800ms, 1.6s, 3.2s */
mtime_t deadline = mdate() + slowdown * 100000L; /* usecs */
vlc_cond_timedwait(&p_sys->signal, &p_sys->lock, deadline);
}
else
p_sys->eos_burst_count = 0;
}
p_sys->last_eos = mdate();
played = true;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment