node: add xrun counter in clock io

Add an xrun counter in the clock that accumulated the duration of
xruns. Fill this in in alsa-pcm.

A client could use this to dectect xruns (when it changes) and to align
the position and nsec after an xrun.
This commit is contained in:
Wim Taymans 2023-08-28 12:26:11 +02:00
parent f134abdac0
commit e90cab1cde
2 changed files with 9 additions and 5 deletions

View file

@ -117,7 +117,7 @@ struct spa_io_clock {
* is unique per clock and can be used to check if nodes * is unique per clock and can be used to check if nodes
* share the same clock. */ * share the same clock. */
uint64_t nsec; /**< time in nanoseconds against monotonic clock */ uint64_t nsec; /**< time in nanoseconds against monotonic clock */
struct spa_fraction rate; /**< rate for position/duration/delay */ struct spa_fraction rate; /**< rate for position/duration/delay/xrun */
uint64_t position; /**< current position */ uint64_t position; /**< current position */
uint64_t duration; /**< duration of current cycle */ uint64_t duration; /**< duration of current cycle */
int64_t delay; /**< delay between position and hardware, int64_t delay; /**< delay between position and hardware,
@ -129,8 +129,8 @@ struct spa_io_clock {
uint64_t target_duration; /**< target duration of next cycle */ uint64_t target_duration; /**< target duration of next cycle */
uint32_t target_seq; /**< seq counter. must be equal at start and uint32_t target_seq; /**< seq counter. must be equal at start and
* end of read and lower bit must be 0 */ * end of read and lower bit must be 0 */
uint32_t padding;
uint32_t padding[3]; uint64_t xrun; /**< estimated accumulated xrun duration */
}; };
/* the size of the video in this cycle */ /* the size of the video in this cycle */

View file

@ -1931,14 +1931,18 @@ static int alsa_recover(struct state *state, int err)
delay = SPA_TIMEVAL_TO_USEC(&diff); delay = SPA_TIMEVAL_TO_USEC(&diff);
missing = delay * state->rate / SPA_USEC_PER_SEC; missing = delay * state->rate / SPA_USEC_PER_SEC;
if (missing == 0)
missing = state->threshold;
spa_log_trace(state->log, "%p: xrun of %"PRIu64" usec %"PRIu64, spa_log_trace(state->log, "%p: xrun of %"PRIu64" usec %"PRIu64,
state, delay, missing); state, delay, missing);
if (state->clock)
state->clock->xrun += missing;
state->sample_count += missing;
spa_node_call_xrun(&state->callbacks, spa_node_call_xrun(&state->callbacks,
SPA_TIMEVAL_TO_USEC(&trigger), delay, NULL); SPA_TIMEVAL_TO_USEC(&trigger), delay, NULL);
state->sample_count += missing ? missing : state->threshold;
break; break;
} }
case SND_PCM_STATE_SUSPENDED: case SND_PCM_STATE_SUSPENDED: