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: https://origsvn.digium.com/svn/asterisk/trunk@47822 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.6.0
Luigi Rizzo 19 years ago
parent 6dcb17baaf
commit 34ec231da7

@ -530,7 +530,7 @@ static int soundcard_writeframe(struct chan_oss_pvt *o, short *data)
return 0; return 0;
} }
o->w_errors = 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 */ l = s->samplen - l_sampsent; /* # of available samples */
if (l > 0) { if (l > 0) {
start = l_sampsent % s->datalen; /* source offset */ start = l_sampsent % s->datalen; /* source offset */
if (l > FRAME_SIZE - ofs) /* don't overflow the frame */ l = MIN(l, FRAME_SIZE - ofs); /* don't overflow the frame */
l = FRAME_SIZE - ofs; l = MIN(l, s->datalen - start); /* don't overflow the source */
if (l > s->datalen - start) /* don't overflow the source */
l = s->datalen - start;
bcopy(s->data + start, myframe + ofs, l * 2); bcopy(s->data + start, myframe + ofs, l * 2);
if (0) if (0)
ast_log(LOG_WARNING, "send_sound sound %d/%d of %d into %d\n", l_sampsent, l, s->samplen, ofs); 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; l += s->silencelen;
if (l > 0) { if (l > 0) {
if (l > FRAME_SIZE - ofs) l = MIN(l, FRAME_SIZE - ofs);
l = FRAME_SIZE - ofs;
bcopy(silence, myframe + ofs, l * 2); bcopy(silence, myframe + ofs, l * 2);
l_sampsent += l; l_sampsent += l;
} else { /* silence is over, restart sound if loop */ } else { /* silence is over, restart sound if loop */
@ -605,6 +602,7 @@ static void *sound_thread(void *arg)
for (;;) { for (;;) {
fd_set rfds, wfds; fd_set rfds, wfds;
int maxfd, res; int maxfd, res;
struct timeval *to = NULL, t;
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_ZERO(&wfds); FD_ZERO(&wfds);
@ -620,13 +618,19 @@ static void *sound_thread(void *arg)
maxfd = MAX(o->sounddev, maxfd); maxfd = MAX(o->sounddev, maxfd);
} }
if (o->cursound > -1) { 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 */ /* ast_select emulates linux behaviour in terms of timeout handling */
res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL); res = ast_select(maxfd + 1, &rfds, &wfds, NULL, to);
if (res < 1) { if (res < 0) {
ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno)); ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
sleep(1); sleep(1);
continue; continue;
@ -650,7 +654,7 @@ static void *sound_thread(void *arg)
if (o->sounddev > -1) { if (o->sounddev > -1) {
if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */ if (FD_ISSET(o->sounddev, &rfds)) /* read and ignore errors */
read(o->sounddev, ign, sizeof(ign)); read(o->sounddev, ign, sizeof(ign));
if (FD_ISSET(o->sounddev, &wfds)) if (to != NULL) /* maybe it is possible to write */
send_sound(o); send_sound(o);
} }
} }

Loading…
Cancel
Save