[xiph-commits] r18779 - in trunk/ao: . doc src/plugins/alsa src/plugins/pulse
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Mon Jan 21 20:41:11 PST 2013
Author: xiphmont
Date: 2013-01-21 20:41:11 -0800 (Mon, 21 Jan 2013)
New Revision: 18779
Modified:
trunk/ao/configure.ac
trunk/ao/doc/drivers.html
trunk/ao/src/plugins/alsa/ao_alsa.c
trunk/ao/src/plugins/pulse/Makefile.am
trunk/ao/src/plugins/pulse/ao_pulse.c
Log:
Further tweaking of latency setup in ALSA; set default period_time ot 1/4 of buffer time
Add latency management the Pulse plugin, along with "buffer_time" option
Add drain() bug workaround to pulse ao_plugin_close(); should eliminate the long wait on teardown
Modified: trunk/ao/configure.ac
===================================================================
--- trunk/ao/configure.ac 2013-01-22 02:35:11 UTC (rev 18778)
+++ trunk/ao/configure.ac 2013-01-22 04:41:11 UTC (rev 18779)
@@ -452,9 +452,8 @@
if test "x$BUILD_PULSE" = "xyes" ; then
PKG_CHECK_MODULES(PULSE, [ libpulse-simple >= 0.9 ],
[have_pulse=yes],[have_pulse=no])
- AC_SUBST(PULSE_LIBS)
- AC_SUBST(PULSE_CFLAGS)
fi
+AC_SUBST(PULSE_LIBS)
AM_CONDITIONAL(HAVE_PULSE,test "x$have_pulse" = xyes)
Modified: trunk/ao/doc/drivers.html
===================================================================
--- trunk/ao/doc/drivers.html 2013-01-22 02:35:11 UTC (rev 18778)
+++ trunk/ao/doc/drivers.html 2013-01-22 04:41:11 UTC (rev 18779)
@@ -245,6 +245,7 @@
<p>
<b>Option keys:</b>
<ul>
+<li>"buffer_time" - Override the default hardware buffer size (in milliseconds).
<li>"dev" - (see 'Standard Driver Options' above). This maps to a specific Pulse sink; it may be specified by Pulse sink name, or by number.
<li>"id" - (see 'Standard Driver Options' above). Maps to a specific pulse sink number.
<li>"server" - Specifies Pulseaudio server to use.
Modified: trunk/ao/src/plugins/alsa/ao_alsa.c
===================================================================
--- trunk/ao/src/plugins/alsa/ao_alsa.c 2013-01-22 02:35:11 UTC (rev 18778)
+++ trunk/ao/src/plugins/alsa/ao_alsa.c 2013-01-22 04:41:11 UTC (rev 18779)
@@ -43,8 +43,8 @@
/* default 20 millisecond buffer */
#define AO_ALSA_BUFFER_TIME 20000
-/* default 5ms transfer size */
-#define AO_ALSA_PERIOD_TIME 5000
+/* default we be calculated to be 1/4 of the buffer time */
+#define AO_ALSA_PERIOD_TIME 0
/* set mmap to default if enabled at compile time, otherwise, mmap isn't
the default */
@@ -353,7 +353,18 @@
"by the hardware, using %u\n", format->rate, rate);
}
+ /* set the length of the hardware sample buffer in microseconds */
+ err = snd_pcm_hw_params_set_buffer_time_near(internal->pcm_handle,
+ params, &(internal->buffer_time), 0);
+ if (err < 0){
+ adebug("snd_pcm_hw_params_set_buffer_time_near() failed.\n");
+ return err;
+ }
+
/* set the time per hardware sample transfer */
+ if(internal->period_time==0)
+ internal->period_time=internal->buffer_time/4;
+
err = snd_pcm_hw_params_set_period_time_near(internal->pcm_handle,
params, &(internal->period_time), 0);
if (err < 0){
@@ -361,14 +372,6 @@
return err;
}
- /* set the length of the hardware sample buffer in microseconds */
- err = snd_pcm_hw_params_set_buffer_time_near(internal->pcm_handle,
- params, &(internal->buffer_time), 0);
- if (err < 0){
- adebug("snd_pcm_hw_params_set_buffer_time_near() failed.\n");
- return err;
- }
-
/* commit the params structure to the hardware via ALSA */
err = snd_pcm_hw_params(internal->pcm_handle, params);
if (err < 0){
@@ -773,7 +776,6 @@
/* something went wrong; fall back */
snd_pcm_drain(internal->pcm_handle);
}else{
- fprintf(stderr,"s=%f(%d)",s,(int)sframes);
if(s>0){
struct timespec sleep,wake;
sleep.tv_sec = (int)s;
Modified: trunk/ao/src/plugins/pulse/Makefile.am
===================================================================
--- trunk/ao/src/plugins/pulse/Makefile.am 2013-01-22 02:35:11 UTC (rev 18778)
+++ trunk/ao/src/plugins/pulse/Makefile.am 2013-01-22 04:41:11 UTC (rev 18779)
@@ -19,9 +19,8 @@
libdir = $(plugindir)
lib_LTLIBRARIES = $(pulseltlibs)
-libpulse_la_LDFLAGS= @PLUGIN_LDFLAGS@
-libpulse_la_SOURCES=$(pulsesources)
-libpulse_la_LIBADD=$(AM_LIBADD) $(PULSE_LIBS)
-libpulse_la_CFLAGS=$(AM_CFLAGS) $(PULSE_CFLAGS)
+libpulse_la_LDFLAGS = @PLUGIN_LDFLAGS@
+libpulse_la_LIBADD = @PULSE_LIBS@
+libpulse_la_SOURCES = $(pulsesources)
EXTRA_DIST = ao_pulse.c
Modified: trunk/ao/src/plugins/pulse/ao_pulse.c
===================================================================
--- trunk/ao/src/plugins/pulse/ao_pulse.c 2013-01-22 02:35:11 UTC (rev 18778)
+++ trunk/ao/src/plugins/pulse/ao_pulse.c 2013-01-22 04:41:11 UTC (rev 18779)
@@ -40,6 +40,8 @@
#include <ao/ao.h>
#include <ao/plugin.h>
+#define AO_PULSE_BUFFER_TIME 20000
+
/* Unfortunately libao doesn't allow "const" for these structures... */
static char * ao_pulse_options[] = {
"server",
@@ -51,6 +53,7 @@
"matrix",
"debug",
"client_name"
+ "buffer_time"
};
static ao_info ao_pulse_info = {
@@ -68,6 +71,8 @@
typedef struct ao_pulse_internal {
struct pa_simple *simple;
char *server, *sink, *client_name;
+ pa_usec_t static_delay;
+ pa_usec_t buffer_time;
} ao_pulse_internal;
/* Yes, this is very ugly, but required nonetheless... */
@@ -142,6 +147,7 @@
internal->server = NULL;
internal->sink = NULL;
internal->client_name = NULL;
+ internal->buffer_time = AO_PULSE_BUFFER_TIME;
device->internal = internal;
device->output_matrix_order = AO_OUTPUT_MATRIX_PERMUTABLE;
@@ -167,6 +173,8 @@
} else if (!strcmp(key, "client_name")) {
free(internal->client_name);
internal->client_name = strdup(value);
+ }else if (!strcmp(key, "buffer_time")){
+ internal->buffer_time = atoi(value) * 1000;
} else
return 0;
@@ -178,6 +186,7 @@
ao_pulse_internal *internal;
struct pa_sample_spec ss;
struct pa_channel_map map;
+ struct pa_buffer_attr battr;
size_t allocated = 128;
assert(device && device->internal && format);
@@ -246,14 +255,25 @@
}
}
+ /* buffering attributes */
+ battr.prebuf = battr.minreq = battr.fragsize = -1;
+
+ battr.tlength = (int)(internal->buffer_time * format->rate) / 1000000 *
+ ((format->bits+7)/8) + device->output_channels;
+ battr.minreq = battr.tlength/4;
+ battr.maxlength = battr.tlength+battr.minreq;
+
internal->simple = pa_simple_new(internal->server, t, PA_STREAM_PLAYBACK,
internal->sink, t2, &ss,
- (device->input_map ? &map : NULL), NULL, NULL);
+ (device->input_map ? &map : NULL), &battr, NULL);
if (!internal->simple)
return 0;
device->driver_byte_format = AO_FMT_NATIVE;
+ internal->static_delay = pa_simple_get_latency(internal->simple, NULL);
+ if(internal->static_delay<0) internal->static_delay = 0;
+
return 1;
}
@@ -270,7 +290,32 @@
ao_pulse_internal *internal = (ao_pulse_internal *) device->internal;
if(internal->simple){
- pa_simple_drain(internal->simple, NULL);
+
+ /* this is a PulseAudio ALSA bug workaround;
+ pa_simple_drain() always takes about 2 seconds, even if
+ there's nothing to drain. Rather than wait for no
+ reason, determine the current playback depth, wait
+ that long, then kill the stream. Remove this code
+ once Pulse gets fixed. */
+
+ pa_usec_t us = pa_simple_get_latency(internal->simple, NULL);
+ if(us<0 || us>1000000){
+ pa_simple_drain(internal->simple, NULL);
+ }else{
+ us -= internal->static_delay;
+ if(us>0){
+ struct timespec sleep,wake;
+ sleep.tv_sec = (int)(us/1000000);
+ sleep.tv_nsec = (us-sleep.tv_sec*1000000)*1000;
+ while(nanosleep(&sleep,&wake)<0){
+ if(errno==EINTR)
+ sleep=wake;
+ else
+ break;
+ }
+ }
+ }
+
pa_simple_free(internal->simple);
internal->simple = NULL;
}
More information about the commits
mailing list