From 515cd2bb4f4ec548f464edeb5be7564fa5b0139f Mon Sep 17 00:00:00 2001 Message-Id: <515cd2bb4f4ec548f464edeb5be7564fa5b0139f.1715213284.git.mdw@distorted.org.uk> From: Mark Wooding Date: Fri, 5 Oct 2007 18:03:40 +0100 Subject: [PATCH] playrtp --oss uses device buffer size now Organization: Straylight/Edgeware From: rjk@greenend.org.uk <> --- clients/playrtp-oss.c | 96 ++++++++++++++++++++++++++++++++++--------- configure.ac | 2 +- 2 files changed, 77 insertions(+), 21 deletions(-) diff --git a/clients/playrtp-oss.c b/clients/playrtp-oss.c index a59e749..8a8f4c6 100644 --- a/clients/playrtp-oss.c +++ b/clients/playrtp-oss.c @@ -35,6 +35,9 @@ #include #include #include +#if HAVE_LINUX_EMPEG_H +# include +#endif #include "mem.h" #include "log.h" @@ -46,6 +49,15 @@ /** @brief /dev/dsp (or whatever) */ static int playrtp_oss_fd = -1; +/** @brief Audio buffer */ +static char *playrtp_oss_buffer; + +/** @brief Size of @ref playrtp_oss_buffer in bytes */ +static int playrtp_oss_bufsize; + +/** @brief Number of bytes used in @ref playrtp_oss_buffer */ +static int playrtp_oss_bufused; + /** @brief Open and configure the OSS audio device */ static void playrtp_oss_enable(void) { if(playrtp_oss_fd == -1) { @@ -68,10 +80,49 @@ static void playrtp_oss_enable(void) { fatal(errno, "ioctl SNDCTL_DSP_SPEED"); if(rate != 44100) error(0, "asking for 44100Hz, got %dHz", rate); + if(ioctl(playrtp_oss_fd, SNDCTL_DSP_GETBLKSIZE, &playrtp_oss_bufsize) < 0) + fatal(errno, "ioctl SNDCTL_DSP_GETBLKSIZE"); + playrtp_oss_buffer = xmalloc(playrtp_oss_bufsize); + playrtp_oss_bufused = 0; + info("OSS buffer size %d", playrtp_oss_bufsize); nonblock(playrtp_oss_fd); } } +/** @brief Flush the OSS output buffer + * @return 0 on success, non-0 on error + */ +static int playrtp_oss_flush(void) { + int nbyteswritten; + + if(!playrtp_oss_bufused) + return 0; /* nothing to do */ + /* 0 out the unused portion of the buffer */ + memset(playrtp_oss_buffer + playrtp_oss_bufused, 0, + playrtp_oss_bufsize - playrtp_oss_bufused); + for(;;) { + nbyteswritten = write(playrtp_oss_fd, + playrtp_oss_buffer, playrtp_oss_bufsize); + if(nbyteswritten < 0) { + switch(errno) { + case EINTR: + break; /* try again */ + case EAGAIN: + return 0; /* try later */ + default: + error(errno, "error writing to %s", device); + return -1; + } + } else { + if(nbyteswritten < playrtp_oss_bufsize) + error(0, "%s: short write (%d/%d)", + device, nbyteswritten, playrtp_oss_bufsize); + playrtp_oss_bufused = 0; + return 0; + } + } +} + /** @brief Wait until the audio device can accept more data */ static void playrtp_oss_wait(void) { struct pollfd fds[1]; @@ -91,11 +142,15 @@ static void playrtp_oss_wait(void) { * @param hard If nonzero, drop pending data */ static void playrtp_oss_disable(int hard) { - if(hard) + if(hard) { if(ioctl(playrtp_oss_fd, SNDCTL_DSP_RESET, 0) < 0) error(errno, "ioctl SNDCTL_DSP_RESET"); + } else + playrtp_oss_flush(); xclose(playrtp_oss_fd); playrtp_oss_fd = -1; + free(playrtp_oss_buffer); + playrtp_oss_buffer = 0; } /** @brief Write samples to OSS output device @@ -103,23 +158,23 @@ static void playrtp_oss_disable(int hard) { * @param nsamples Number of samples * @return 0 on success, non-0 on error */ -static int playrtp_oss_write(const void *data, size_t samples) { - const ssize_t nbyteswritten = write(playrtp_oss_fd, data, - samples * sizeof (int16_t)); - - if(nbyteswritten < 0) { - switch(errno) { - case EAGAIN: - case EINTR: - return 0; - default: - error(errno, "error writing to %s", device); - return -1; - } - } else { - next_timestamp += nbyteswritten / 2; - return 0; +static int playrtp_oss_write(const char *data, size_t samples) { + long bytes = samples * sizeof(int16_t); + while(bytes > 0) { + int n = playrtp_oss_bufsize - playrtp_oss_bufused; + + if(n > bytes) + n = bytes; + memcpy(playrtp_oss_buffer + playrtp_oss_bufused, data, n); + bytes -= n; + data += n; + playrtp_oss_bufused += n; + if(playrtp_oss_bufused == playrtp_oss_bufsize) + if(playrtp_oss_flush()) + return -1; } + next_timestamp += samples; + return 0; } /** @brief Play some data from packet @p p @@ -127,8 +182,9 @@ static int playrtp_oss_write(const void *data, size_t samples) { * @p p is assumed to contain @ref next_timestamp. */ static int playrtp_oss_play(const struct packet *p) { - return playrtp_oss_write(p->samples_raw + next_timestamp - p->timestamp, - (p->timestamp + p->nsamples) - next_timestamp); + return playrtp_oss_write + ((const char *)(p->samples_raw + next_timestamp - p->timestamp), + (p->timestamp + p->nsamples) - next_timestamp); } /** @brief Play some silence before packet @p p @@ -136,7 +192,7 @@ static int playrtp_oss_play(const struct packet *p) { * @p p is assumed to be entirely before @ref next_timestamp. */ static int playrtp_oss_infill(const struct packet *p) { - static const uint16_t zeros[INFILL_SAMPLES]; + static const char zeros[INFILL_SAMPLES * sizeof(int16_t)]; size_t samples_available = INFILL_SAMPLES; if(p && samples_available > p->timestamp - next_timestamp) diff --git a/configure.ac b/configure.ac index 4976ac1..32eaeaf 100644 --- a/configure.ac +++ b/configure.ac @@ -182,7 +182,7 @@ RJK_REQUIRE_PCRE_UTF8([-lpcre]) # Checks for header files. RJK_FIND_GC_H -AC_CHECK_HEADERS([inttypes.h CoreAudio/AudioHardware.h sys/soundcard.h alsa/asoundlib.h]) +AC_CHECK_HEADERS([inttypes.h CoreAudio/AudioHardware.h sys/soundcard.h alsa/asoundlib.h linux/empeg.h]) # We don't bother checking very standard stuff # Compilation will fail if any of these headers are missing, so we # check for them here and fail early. -- [mdw]