mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-09 17:35:42 +01:00
aplay/arecord: fix underrun/overrun time calculation for monotonic clock
Also, add librt check to configure.in. Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
parent
3924a249dd
commit
641556d963
3 changed files with 78 additions and 15 deletions
|
@ -1,5 +1,7 @@
|
|||
LIBRT = @LIBRT@
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include
|
||||
LDADD = $(LIBINTL)
|
||||
LDADD = $(LIBINTL) $(LIBRT)
|
||||
|
||||
# debug flags
|
||||
#LDFLAGS = -static
|
||||
|
|
|
@ -101,12 +101,14 @@ static snd_pcm_uframes_t buffer_frames = 0;
|
|||
static int avail_min = -1;
|
||||
static int start_delay = 0;
|
||||
static int stop_delay = 0;
|
||||
static int monotonic = 0;
|
||||
static int verbose = 0;
|
||||
static int vumeter = VUMETER_NONE;
|
||||
static int buffer_pos = 0;
|
||||
static size_t bits_per_sample, bits_per_frame;
|
||||
static size_t chunk_bytes;
|
||||
static int test_position = 0;
|
||||
static int test_nowait = 0;
|
||||
static snd_output_t *log;
|
||||
|
||||
static int fd = -1;
|
||||
|
@ -188,7 +190,8 @@ _("Usage: %s [OPTION]... [FILE]...\n"
|
|||
" --disable-channels disable automatic channel conversions\n"
|
||||
" --disable-format disable automatic format conversions\n"
|
||||
" --disable-softvol disable software volume control (softvol)\n"
|
||||
" --test-position test ring buffer position\n")
|
||||
" --test-position test ring buffer position\n"
|
||||
" --test-nowait do not wait for ring buffer - eats whole CPU\n")
|
||||
, command);
|
||||
printf(_("Recognized sample formats are:"));
|
||||
for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
|
||||
|
@ -350,7 +353,8 @@ enum {
|
|||
OPT_DISABLE_CHANNELS,
|
||||
OPT_DISABLE_FORMAT,
|
||||
OPT_DISABLE_SOFTVOL,
|
||||
OPT_TEST_POSITION
|
||||
OPT_TEST_POSITION,
|
||||
OPT_TEST_NOWAIT
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -389,6 +393,7 @@ int main(int argc, char *argv[])
|
|||
{"disable-format", 0, 0, OPT_DISABLE_FORMAT},
|
||||
{"disable-softvol", 0, 0, OPT_DISABLE_SOFTVOL},
|
||||
{"test-position", 0, 0, OPT_TEST_POSITION},
|
||||
{"test-nowait", 0, 0, OPT_TEST_NOWAIT},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
char *pcm_name = "default";
|
||||
|
@ -570,6 +575,9 @@ int main(int argc, char *argv[])
|
|||
case OPT_TEST_POSITION:
|
||||
test_position = 1;
|
||||
break;
|
||||
case OPT_TEST_NOWAIT:
|
||||
test_nowait = 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, _("Try `%s --help' for more information.\n"), command);
|
||||
return 1;
|
||||
|
@ -1017,6 +1025,7 @@ static void set_params(void)
|
|||
&buffer_frames);
|
||||
}
|
||||
assert(err >= 0);
|
||||
monotonic = snd_pcm_hw_params_is_monotonic(params);
|
||||
err = snd_pcm_hw_params(handle, params);
|
||||
if (err < 0) {
|
||||
error(_("Unable to install hw params:"));
|
||||
|
@ -1112,6 +1121,18 @@ do { \
|
|||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef timermsub
|
||||
#define timermsub(a, b, result) \
|
||||
do { \
|
||||
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
|
||||
(result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec; \
|
||||
if ((result)->tv_nsec < 0) { \
|
||||
--(result)->tv_sec; \
|
||||
(result)->tv_nsec += 1000000000L; \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* I/O error handler */
|
||||
static void xrun(void)
|
||||
{
|
||||
|
@ -1124,13 +1145,29 @@ static void xrun(void)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
|
||||
struct timeval now, diff, tstamp;
|
||||
gettimeofday(&now, 0);
|
||||
snd_pcm_status_get_trigger_tstamp(status, &tstamp);
|
||||
timersub(&now, &tstamp, &diff);
|
||||
fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
|
||||
stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
|
||||
diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
|
||||
if (monotonic) {
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
struct timespec now, diff, tstamp;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
snd_pcm_status_get_trigger_htstamp(status, &tstamp);
|
||||
printf("AAA: %li %li\n" "BBB\n", tstamp.tv_sec, now.tv_nsec);
|
||||
timermsub(&now, &tstamp, &diff);
|
||||
fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
|
||||
stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
|
||||
diff.tv_sec * 1000 + diff.tv_nsec / 10000000.0);
|
||||
#else
|
||||
fprintf(stderr, "%s !!!\n", _("underrun"));
|
||||
#endif
|
||||
} else {
|
||||
struct timeval now, diff, tstamp;
|
||||
gettimeofday(&now, 0);
|
||||
snd_pcm_status_get_trigger_tstamp(status, &tstamp);
|
||||
printf("AAA: %li %li\n", tstamp.tv_sec, now.tv_sec);
|
||||
timersub(&now, &tstamp, &diff);
|
||||
fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
|
||||
stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
|
||||
diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
|
||||
}
|
||||
if (verbose) {
|
||||
fprintf(stderr, _("Status:\n"));
|
||||
snd_pcm_status_dump(status, log);
|
||||
|
@ -1409,7 +1446,8 @@ static void do_test_position(void)
|
|||
delay < -4 * (snd_pcm_sframes_t)buffer_frames) {
|
||||
fprintf(stderr, "Suspicious buffer position (%i total): avail = %li, delay = %li, buffer = %li\n", ++counter, (long)avail, (long)delay, (long)buffer_frames);
|
||||
} else if (verbose) {
|
||||
fprintf(stderr, "Buffer position: %li/%li (%li)\n", (long)avail, (long)delay, (long)buffer_frames);
|
||||
if (avail != 0)
|
||||
fprintf(stderr, "Buffer position: %li/%li (%li)\n", (long)avail, (long)delay, (long)buffer_frames);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1433,7 +1471,8 @@ static ssize_t pcm_write(u_char *data, size_t count)
|
|||
if (test_position)
|
||||
do_test_position();
|
||||
if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
|
||||
snd_pcm_wait(handle, 1000);
|
||||
if (!test_nowait)
|
||||
snd_pcm_wait(handle, 1000);
|
||||
} else if (r == -EPIPE) {
|
||||
xrun();
|
||||
} else if (r == -ESTRPIPE) {
|
||||
|
@ -1478,7 +1517,8 @@ static ssize_t pcm_writev(u_char **data, unsigned int channels, size_t count)
|
|||
if (test_position)
|
||||
do_test_position();
|
||||
if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
|
||||
snd_pcm_wait(handle, 1000);
|
||||
if (!test_nowait)
|
||||
snd_pcm_wait(handle, 1000);
|
||||
} else if (r == -EPIPE) {
|
||||
xrun();
|
||||
} else if (r == -ESTRPIPE) {
|
||||
|
@ -1520,7 +1560,8 @@ static ssize_t pcm_read(u_char *data, size_t rcount)
|
|||
if (test_position)
|
||||
do_test_position();
|
||||
if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
|
||||
snd_pcm_wait(handle, 1000);
|
||||
if (!test_nowait)
|
||||
snd_pcm_wait(handle, 1000);
|
||||
} else if (r == -EPIPE) {
|
||||
xrun();
|
||||
} else if (r == -ESTRPIPE) {
|
||||
|
@ -1562,7 +1603,8 @@ static ssize_t pcm_readv(u_char **data, unsigned int channels, size_t rcount)
|
|||
if (test_position)
|
||||
do_test_position();
|
||||
if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
|
||||
snd_pcm_wait(handle, 1000);
|
||||
if (!test_nowait)
|
||||
snd_pcm_wait(handle, 1000);
|
||||
} else if (r == -EPIPE) {
|
||||
xrun();
|
||||
} else if (r == -ESTRPIPE) {
|
||||
|
|
19
configure.in
19
configure.in
|
@ -44,6 +44,23 @@ AM_CONDITIONAL(HAVE_MIXER, test "$have_mixer" = "yes")
|
|||
AM_CONDITIONAL(HAVE_RAWMIDI, test "$have_rawmidi" = "yes")
|
||||
AM_CONDITIONAL(HAVE_SEQ, test "$have_seq" = "yes")
|
||||
|
||||
dnl Check for librt
|
||||
LIBRT=""
|
||||
AC_MSG_CHECKING(for librt)
|
||||
AC_ARG_WITH(librt,
|
||||
AS_HELP_STRING([--with-librt], [Use librt for monotonic clock (default = yes)]),
|
||||
[ have_librt="$withval" ], [ have_librt="yes" ])
|
||||
if test "$have_librt" = "yes"; then
|
||||
AC_CHECK_LIB([rt], [clock_gettime], [HAVE_LIBRT="yes"])
|
||||
if test "$HAVE_LIBRT" = "yes" ; then
|
||||
LIBRT="-lrt"
|
||||
AC_DEFINE([HAVE_LIBRT], 1, [Have librt])
|
||||
AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [Have clock gettime])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
dnl Disable alsamixer
|
||||
CURSESINC=""
|
||||
CURSESLIB=""
|
||||
|
@ -160,6 +177,8 @@ AC_SYS_LARGEFILE
|
|||
|
||||
SAVE_UTIL_VERSION
|
||||
|
||||
AC_SUBST(LIBRT)
|
||||
|
||||
AC_OUTPUT(Makefile alsactl/Makefile alsactl/init/Makefile \
|
||||
alsamixer/Makefile amidi/Makefile amixer/Makefile \
|
||||
m4/Makefile po/Makefile.in \
|
||||
|
|
Loading…
Reference in a new issue