[pulseaudio-discuss] Couple problems when using 0.9.11 and fixes
Jyri Sarha
lepbtetfmvbz at spammotel.com
Thu Sep 4 04:56:17 PDT 2008
Hi,
I found couple of problems when upgrading to pulseaduio 0.9.11. The
both are related to a case when tsched turned off on alsa-sink. First,
problem appears when trying the select a specific number fragment with
module-alsa-sink parameters, for instance this:
load-module module-alsa-sink device=hw:0 rate=44100 fragment_size=882 fragments=2 tsched=0
The above produces three fragments of 588 bytes each. The actual bug
appears to be in alsa-lib, but it can be by-passed without breaking
things when alsa-lib gets fixed. To do that apply
fix_incremented_number_of_fragments.patch.
The other problem appears when trying to use alsa-sink with tsched=0 on a
slow CPU. After writing a set of samples to device alsa-sink checks whether
there is room to write some more samples. On a slow CPU there is always room
for couple of samples more and alsa-sink keeps busy looping in the write
function. "parameter_to_set_minimum_write_size.patch" adds a parameter to
module-alsa-sink to set the minimum number of samples to write on device,
setting this parameter to a reasonable value fixes the above problem,
like this:
load-module module-alsa-sink device=hw:0 rate=44100 fragment_size=882 fragments=2 tsched=0 hwbuf_min_frames_to_write=32
Alsa-source would need a similar patch too. In the end I decided
to forward port the old alsa- sink and source from 0.9.10 to 0.9.11,
because they seem to work more reliably and generate much less load, when
fragment-size and number of fragments is pushed to the minimum and
tsched is not used. I can post those patches too if anybody is interested.
Cheers,
Jyri
===File ~/fix_incremented_number_of_fragments.patch=========
diff --git a/src/modules/alsa-util.c b/src/modules/alsa-util.c
index 8abf834..64b4eff 100644
--- a/src/modules/alsa-util.c
+++ b/src/modules/alsa-util.c
@@ -369,12 +369,15 @@ int pa_alsa_set_hw_params(
goto finish;
if (_periods > 0) {
- dir = 1;
- if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
- dir = -1;
- if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0)
- goto finish;
- }
+ dir = 0;
+ if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
+ dir = 1;
+ if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
+ dir = -1;
+ if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0)
+ goto finish;
+ }
+ }
}
if (_period_size > 0)
============================================================
===File ~/parameter_to_set_minimum_write_size.patch=========
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 8e66f79..0135a0b 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -69,7 +69,8 @@ PA_MODULE_USAGE(
"tsched=<enable system timer based scheduling mode?> "
"tsched_buffer_size=<buffer size when using timer based scheduling> "
"tsched_buffer_watermark=<lower fill watermark> "
- "mixer_reset=<reset hw volume and mute settings to sane defaults when falling back to software?>");
+ "mixer_reset=<reset hw volume and mute settings to sane defaults when falling back to software?>"
+ "hwbuf_min_frames_to_write=<minimum number of available frames in hwbuf to fill>");
static const char* const valid_modargs[] = {
"sink_name",
@@ -86,6 +87,7 @@ static const char* const valid_modargs[] = {
"tsched_buffer_size",
"tsched_buffer_watermark",
"mixer_reset",
+ "hwbuf_min_frames_to_write",
NULL
};
@@ -132,6 +134,7 @@ struct userdata {
uint64_t since_start;
snd_pcm_sframes_t hwbuf_unused_frames;
+ snd_pcm_sframes_t hwbuf_min_frames_to_write;
};
static void fix_tsched_watermark(struct userdata *u) {
@@ -278,7 +281,7 @@ static int mmap_write(struct userdata *u, pa_usec_t *sleep_usec) {
if (pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) > process_usec+max_sleep_usec/2)
break;
- if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
+ if (PA_UNLIKELY(n <= u->hwbuf_min_frames_to_write || n <= u->hwbuf_unused_frames))
break;
n -= u->hwbuf_unused_frames;
@@ -390,7 +393,7 @@ static int unix_write(struct userdata *u, pa_usec_t *sleep_usec) {
if (pa_bytes_to_usec(left_to_play, &u->sink->sample_spec) > process_usec+max_sleep_usec/2)
break;
- if (PA_UNLIKELY(n <= u->hwbuf_unused_frames))
+ if (PA_UNLIKELY(n <= u->hwbuf_min_frames_to_write || n <= u->hwbuf_unused_frames))
break;
n -= u->hwbuf_unused_frames;
@@ -1103,6 +1106,7 @@ int pa__init(pa_module*m) {
pa_bool_t use_mmap = TRUE, b, use_tsched = TRUE, d, mixer_reset = TRUE;
pa_usec_t usec;
pa_sink_new_data data;
+ int32_t hwbuf_min_frames_to_write = 0;
snd_pcm_info_alloca(&pcm_info);
@@ -1162,6 +1166,11 @@ int pa__init(pa_module*m) {
goto fail;
}
+ if (pa_modargs_get_value_s32(ma, "hwbuf_min_frames_to_write", &hwbuf_min_frames_to_write) < 0) {
+ pa_log("Failed to parse hwbuf_min_frames_to_write argument");
+ goto fail;
+ }
+
u = pa_xnew0(struct userdata, 1);
u->core = m->core;
u->module = m;
@@ -1316,6 +1325,7 @@ int pa__init(pa_module*m) {
u->fragment_size = frag_size = period_frames * frame_size;
u->nfragments = nfrags;
u->hwbuf_size = u->fragment_size * nfrags;
+ u->hwbuf_min_frames_to_write = hwbuf_min_frames_to_write;
u->hwbuf_unused_frames = 0;
u->tsched_watermark = tsched_watermark;
u->frame_index = 0;
============================================================
More information about the pulseaudio-discuss
mailing list