Increase AudioBufferTime for OSS.

This commit is contained in:
Johns 2012-03-01 17:50:57 +01:00
parent 3b4ace14cf
commit b5e9077c74
2 changed files with 59 additions and 52 deletions

View File

@ -1,6 +1,7 @@
User johns User johns
Date: Date:
OSS needs bigger audio buffers.
Improved audio drift correction support. Improved audio drift correction support.
Experimental audio drift correction support. Experimental audio drift correction support.
Add SVDRP HOTK command support. Add SVDRP HOTK command support.

110
audio.c
View File

@ -1277,6 +1277,7 @@ static int OssPcmFildes = -1; ///< pcm file descriptor
static int OssMixerFildes = -1; ///< mixer file descriptor static int OssMixerFildes = -1; ///< mixer file descriptor
static int OssMixerChannel; ///< mixer channel index static int OssMixerChannel; ///< mixer channel index
static RingBuffer *OssRingBuffer; ///< audio ring buffer static RingBuffer *OssRingBuffer; ///< audio ring buffer
static int OssFragmentTime; ///< fragment time in ms
static unsigned OssStartThreshold; ///< start play, if filled static unsigned OssStartThreshold; ///< start play, if filled
#ifdef USE_AUDIO_THREAD #ifdef USE_AUDIO_THREAD
@ -1366,7 +1367,7 @@ static int OssPlayRingbuffer(void)
Error(_("audio/oss: write error: %s\n"), strerror(errno)); Error(_("audio/oss: write error: %s\n"), strerror(errno));
return 1; return 1;
} }
Error(_("audio/oss: error not all bytes written\n")); Warning(_("audio/oss: error not all bytes written\n"));
} }
// advance how many could written // advance how many could written
RingBufferReadAdvance(OssRingBuffer, n); RingBufferReadAdvance(OssRingBuffer, n);
@ -1479,10 +1480,10 @@ static void OssThread(void)
fds[0].fd = OssPcmFildes; fds[0].fd = OssPcmFildes;
fds[0].events = POLLOUT | POLLERR; fds[0].events = POLLOUT | POLLERR;
// wait for space in kernel buffers // wait for space in kernel buffers
err = poll(fds, 1, 100); err = poll(fds, 1, OssFragmentTime);
if (err < 0) { if (err < 0) {
Error(_("audio/oss: error poll %s\n"), strerror(errno)); Error(_("audio/oss: error poll %s\n"), strerror(errno));
usleep(100 * 1000); usleep(OssFragmentTime * 1000);
continue; continue;
} }
@ -1495,7 +1496,7 @@ static void OssThread(void)
break; break;
} }
pthread_yield(); pthread_yield();
usleep(20 * 1000); // let fill/empty the buffers usleep(OssFragmentTime * 1000); // let fill/empty the buffers
} }
} }
} }
@ -1685,18 +1686,14 @@ static uint64_t OssGetDelay(void)
strerror(errno)); strerror(errno));
return 0UL; return 0UL;
} }
if (delay == -1) { if (delay < 0) {
delay = 0UL; delay = 0;
} }
pts = ((uint64_t) delay * 90 * 1000) pts = ((uint64_t) (delay + RingBufferUsedBytes(OssRingBuffer)) * 90 * 1000)
/ (AudioSampleRate * AudioChannels * AudioBytesProSample); / (AudioSampleRate * AudioChannels * AudioBytesProSample);
pts += ((uint64_t) RingBufferUsedBytes(OssRingBuffer) * 90 * 1000) Debug(4, "audio/oss: hw+sw delay %zd %" PRId64 " ms\n",
/ (AudioSampleRate * AudioChannels * AudioBytesProSample); RingBufferUsedBytes(OssRingBuffer), pts / 90);
if (pts > 600 * 90) {
Debug(4, "audio/oss: hw+sw delay %zd %" PRId64 " ms\n",
RingBufferUsedBytes(OssRingBuffer), pts / 90);
}
return pts; return pts;
} }
@ -1719,6 +1716,7 @@ static int OssSetup(int *freq, int *channels, int use_ac3)
int ret; int ret;
int tmp; int tmp;
int delay; int delay;
audio_buf_info bi;
if (OssPcmFildes == -1) { // OSS not ready if (OssPcmFildes == -1) { // OSS not ready
return -1; return -1;
@ -1782,46 +1780,54 @@ static int OssSetup(int *freq, int *channels, int use_ac3)
// FIXME: setup buffers // FIXME: setup buffers
if (1) { #ifdef SNDCTL_DSP_POLICY
audio_buf_info bi; tmp = 3;
if (ioctl(OssPcmFildes, SNDCTL_DSP_POLICY, &tmp) == -1) {
if (ioctl(OssPcmFildes, SNDCTL_DSP_GETOSPACE, &bi) == -1) { Error(_("audio/oss: ioctl(SNDCTL_DSP_POLICY): %s\n"), strerror(errno));
Error(_("audio/oss: ioctl(SNDCTL_DSP_GETOSPACE): %s\n"), } else {
strerror(errno)); Info("audio/oss: set policy to %d\n", tmp);
} else {
Debug(3, "audio/oss: %d bytes buffered\n", bi.bytes);
}
tmp = -1;
if (ioctl(OssPcmFildes, SNDCTL_DSP_GETODELAY, &tmp) == -1) {
Error(_("audio/oss: ioctl(SNDCTL_DSP_GETODELAY): %s\n"),
strerror(errno));
// FIXME: stop player, set setup failed flag
return -1;
}
if (tmp == -1) {
tmp = 0;
}
// start when enough bytes for initial write
OssStartThreshold = bi.bytes + tmp;
// buffer time/delay in ms
delay = AudioBufferTime;
if (VideoAudioDelay > 0) {
delay += VideoAudioDelay / 90;
}
if (OssStartThreshold <
(*freq * *channels * AudioBytesProSample * delay) / 1000U) {
OssStartThreshold =
(*freq * *channels * AudioBytesProSample * delay) / 1000U;
}
// no bigger, than the buffer
if (OssStartThreshold > RingBufferFreeBytes(OssRingBuffer)) {
OssStartThreshold = RingBufferFreeBytes(OssRingBuffer);
}
Info(_("audio/oss: delay %u ms\n"), (OssStartThreshold * 1000)
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
} }
#endif
if (ioctl(OssPcmFildes, SNDCTL_DSP_GETOSPACE, &bi) == -1) {
Error(_("audio/oss: ioctl(SNDCTL_DSP_GETOSPACE): %s\n"),
strerror(errno));
bi.fragsize = 4096;
bi.fragstotal = 16;
} else {
Debug(3, "audio/oss: %d bytes buffered\n", bi.bytes);
}
OssFragmentTime = (bi.fragsize * 1000)
/ (AudioSampleRate * AudioChannels * AudioBytesProSample);
Info(_("audio/oss: buffer size %d %dms, fragment size %d %dms\n"),
bi.fragsize * bi.fragstotal, (bi.fragsize * bi.fragstotal * 1000)
/ (AudioSampleRate * AudioChannels * AudioBytesProSample), bi.fragsize,
OssFragmentTime);
// start when enough bytes for initial write
OssStartThreshold = (bi.fragsize - 1) * bi.fragstotal;
// buffer time/delay in ms
delay = AudioBufferTime + 300;
if (VideoAudioDelay > 0) {
delay += VideoAudioDelay / 90;
}
if (OssStartThreshold <
(AudioSampleRate * AudioChannels * AudioBytesProSample * delay) /
1000U) {
OssStartThreshold =
(AudioSampleRate * AudioChannels * AudioBytesProSample * delay) /
1000U;
}
// no bigger, than the buffer
if (OssStartThreshold > RingBufferFreeBytes(OssRingBuffer)) {
OssStartThreshold = RingBufferFreeBytes(OssRingBuffer);
}
Info(_("audio/oss: delay %u ms\n"), (OssStartThreshold * 1000)
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
return ret; return ret;
} }