aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authorrizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b>2006-11-18 08:19:41 +0000
committerrizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b>2006-11-18 08:19:41 +0000
commit85284832366a021ecb6f4695b13dc09396ed176d (patch)
tree6a4beb5d92416ec5eccc8e0e5a3cedf15e43068d /channels
parent9ed9bbabf4b8ff0294c44090db38596e4372f7ab (diff)
prevent the sound thread from consuming all the available CPU
doing busy-wait on the output audio device. As it is set now, it tries to push a frame every 10ms, which is still too frequent but avoids deep restructuring of the code (which i should do, though). Note, this is only for ring tones, regular audio coming from the network is still delivered as soon as it is available. Eventually this could well end up in the 1.4 branch, but since i am probably the only user of chan_oss there isn't much urgency to do that. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@47822 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_oss.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/channels/chan_oss.c b/channels/chan_oss.c
index 3e68628e7..cec9f565a 100644
--- a/channels/chan_oss.c
+++ b/channels/chan_oss.c
@@ -530,7 +530,7 @@ static int soundcard_writeframe(struct chan_oss_pvt *o, short *data)
return 0;
}
o->w_errors = 0;
- return write(o->sounddev, ((void *) data), FRAME_SIZE * 2);
+ return write(o->sounddev, (void *)data, FRAME_SIZE * 2);
}
/*
@@ -559,10 +559,8 @@ static void send_sound(struct chan_oss_pvt *o)
l = s->samplen - l_sampsent; /* # of available samples */
if (l > 0) {
start = l_sampsent % s->datalen; /* source offset */
- if (l > FRAME_SIZE - ofs) /* don't overflow the frame */
- l = FRAME_SIZE - ofs;
- if (l > s->datalen - start) /* don't overflow the source */
- l = s->datalen - start;
+ l = MIN(l, FRAME_SIZE - ofs); /* don't overflow the frame */
+ l = MIN(l, s->datalen - start); /* don't overflow the source */
bcopy(s->data + start, myframe + ofs, l * 2);
if (0)
ast_log(LOG_WARNING, "send_sound sound %d/%d of %d into %d\n", l_sampsent, l, s->samplen, ofs);
@@ -572,8 +570,7 @@ static void send_sound(struct chan_oss_pvt *o)
l += s->silencelen;
if (l > 0) {
- if (l > FRAME_SIZE - ofs)
- l = FRAME_SIZE - ofs;
+ l = MIN(l, FRAME_SIZE - ofs);
bcopy(silence, myframe + ofs, l * 2);
l_sampsent += l;
} else { /* silence is over, restart sound if loop */
@@ -605,6 +602,7 @@ static void *sound_thread(void *arg)
for (;;) {
fd_set rfds, wfds;
int maxfd, res;
+ struct timeval *to = NULL, t;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
@@ -620,13 +618,19 @@ static void *sound_thread(void *arg)
maxfd = MAX(o->sounddev, maxfd);
}
if (o->cursound > -1) {
- FD_SET(o->sounddev, &wfds);
- maxfd = MAX(o->sounddev, maxfd);
+ /*
+ * We would like to use select here, but the device
+ * is always writable, so this would become busy wait.
+ * So we rather set a timeout to 1/2 of the frame size.
+ */
+ t.tv_sec = 0;
+ t.tv_usec = (1000000 * FRAME_SIZE) / (5 * DEFAULT_SAMPLE_RATE);
+ to = &t;
}
}
/* ast_select emulates linux behaviour in terms of timeout handling */
- res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL);
- if (res < 1) {
+ res = ast_select(maxfd + 1, &rfds, &wfds, NULL, to);
+ if (res < 0) {
ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
sleep(1);
continue;
@@ -650,7 +654,7 @@ static void *sound_thread(void *arg)
if (o->sounddev > -1) {
if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */
read(o->sounddev, ign, sizeof(ign));
- if (FD_ISSET(o->sounddev, &wfds))
+ if (to != NULL) /* maybe it is possible to write */
send_sound(o);
}
}