aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorKa Ho Ng <[email protected]>2021-01-19 10:50:37 +0800
committerPaul Adenot <[email protected]>2021-01-19 13:28:14 +0100
commitda818aad241d197acf8997ced717b7245b24ef7c (patch)
tree594c70da1d7c17b944baf8135587695654e0d49a /src
parent860bf2b31531e4ef49478a433ff22ffb4303b805 (diff)
downloadcubeb-da818aad241d197acf8997ced717b7245b24ef7c.tar.gz
cubeb-da818aad241d197acf8997ced717b7245b24ef7c.zip
oss: Fix CPU spinning 100% for playback-only stream
Diffstat (limited to 'src')
-rw-r--r--src/cubeb_oss.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/src/cubeb_oss.c b/src/cubeb_oss.c
index 32a4bf6..8c44c9e 100644
--- a/src/cubeb_oss.c
+++ b/src/cubeb_oss.c
@@ -781,6 +781,28 @@ oss_put_play_frames(cubeb_stream * s, unsigned int nframes)
return 0;
}
+static int
+oss_wait_playfd_for_space(cubeb_stream * s)
+{
+ /* For non-duplex stream we have to wait until we have space in the
+ * buffer */
+ int rate = s->play.info.sample_rate;
+ struct pollfd pfd;
+
+ pfd.events = POLLOUT|POLLHUP;
+ pfd.revents = 0;
+ pfd.fd = s->play.fd;
+
+ if (poll(&pfd, 1, s->nfr * 1000 + rate - 1 / rate) == -1) {
+ return CUBEB_ERROR;
+ }
+
+ if (pfd.revents & POLLHUP) {
+ return CUBEB_ERROR;
+ }
+ return 0;
+}
+
/* 1 - Stopped by cubeb_stream_stop, otherwise 0 */
static int
oss_audio_loop(cubeb_stream * s, cubeb_state *new_state)
@@ -873,26 +895,31 @@ oss_audio_loop(cubeb_stream * s, cubeb_state *new_state)
goto breakdown;
}
- audio_buf_info bi;
if (play_on) {
- if (ioctl(s->play.fd, SNDCTL_DSP_GETOSPACE, &bi)) {
- state = CUBEB_STATE_ERROR;
- goto breakdown;
- }
/*
* In duplex mode, playback direction drives recording direction to
* prevent building up latencies.
*/
+
+ if (oss_wait_playfd_for_space(s) != 0) {
+ state = CUBEB_STATE_ERROR;
+ goto breakdown;
+ }
+
+ audio_buf_info bi;
+ if (ioctl(s->play.fd, SNDCTL_DSP_GETOSPACE, &bi)) {
+ state = CUBEB_STATE_ERROR;
+ goto breakdown;
+ }
nfr = bi.fragsize * bi.fragments / s->play.frame_size;
if (nfr > s->bufframes) {
nfr = s->bufframes;
}
+ } else {
+ nfr = s->nfr;
}
if (record_on) {
- if (nfr == 0) {
- nfr = s->nfr;
- }
if (oss_get_rec_frames(s, nfr) == CUBEB_ERROR) {
state = CUBEB_STATE_ERROR;
goto breakdown;