[pulseaudio-discuss] [PATCH] Don't use tsched on unsafe ALSA plugins

Alexander E. Patrakov patrakov at gmail.com
Sat Apr 19 14:21:11 PDT 2014


Since the dca ALSA plugin is based on extplug, it has a slave and therefore
a card. Thus, PulseAudio thinks that it looks like hardware and attempts
rewinds, which this plugin cannot handle correctly, because ALSA never
notifies extplug plugins about rewinds.

The same mishandling of rewinds applies to some other plugins.

Work around this ALSA bug by switching to IRQ-based scheduling on strange
plugin types.
---
I have not deleted the "does a card exist" check, but for the AC3 encoder
case (which is mentioned in the git log) it is now redundant. Feel free
to delete if no other triggering use case is known.

P.S. I see this line in alsa-lib/src/pcm/pcm_extplug.c:

        params->info &= ~(SND_PCM_INFO_MMAP | SND_PCM_INFO_MMAP_VALID);

but then also:

        snd_pcm_access_mask_t saccess_mask = { SND_PCM_ACCBIT_MMAP };

How should I understand this - is the intention here to disable mmap access
or enable it?

 src/modules/alsa/alsa-util.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index 1ce2e16..c6dd80c 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1384,12 +1384,60 @@ unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_
     return rates;
 }
 
+static bool pa_alsa_type_is_safe_for_rewind(snd_pcm_type_t type)
+{
+    /* Some ALSA plugins have a non-trivial dependency between input
+     * and output samples: one input sample can affect more than one
+     * output sample, and vice versa. ALSA does not handle rewinds
+     * on such plugins correctly. Notably, this affects extplug, which
+     * is used by dcaenc.
+     *
+     * So here is a whitelist of stateless plugin types, based on what
+     * ALSA uses as front and surround51 PCMs of the supported cards.
+     *
+     * Note: we should in fact check that every plugin in the slave
+     * chain is safe, but this information is not available.
+     */
+
+    if (type == SND_PCM_TYPE_HW) return true;        /* ovbiously */
+    if (type == SND_PCM_TYPE_HOOKS) return true;     /* HDMI on Intel HDA, SPDIF */
+    if (type == SND_PCM_TYPE_MULTI) return true;     /* EMU10K1, Audigy2, others */
+    if (type == SND_PCM_TYPE_LINEAR) return true;    /* SPDIF on ICE1724 */
+    if (type == SND_PCM_TYPE_ROUTE) return true;     /* ICE1712, VIA8237, others */
+    if (type == SND_PCM_TYPE_LINEAR_FLOAT) return true;  /* just in case */
+    if (type == SND_PCM_TYPE_SOFTVOL) return true;   /* many */
+
+    /* Specifically excluding these types as unsafe:
+     *
+     * SND_PCM_TYPE_ADPCM: uses history
+     * SND_PCM_TYPE_RATE: uses history
+     * SND_PCM_TYPE_LADSPA: may hide non-rewindable plugins
+     * SND_PCM_TYPE_IEC958: rewinding does not update the preamble-related counter
+     * SND_PCM_TYPE_IOPLUG: may hide non-rewindable encoders
+     * SND_PCM_TYPE_EXTPLUG: may hide non-rewindable encoders
+     *
+     * In theory, SND_PCM_TYPE_PLUG can hide ADPCM, and thus is unsafe.
+     * However, this doesn't happen with real-world sound cards. It can
+     * also hide a resampler, but we specifically disarm this capability.
+     * So it may be actually safe to whitelist, but, if we got to it, then
+     * we are already running on some weird hardware. Better safe than
+     * sorry for now.
+     */
+
+    return false;
+}
+
 bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
+    snd_pcm_type_t type;
     snd_pcm_info_t* info;
     snd_pcm_info_alloca(&info);
 
     pa_assert(pcm);
 
+    type = snd_pcm_type(pcm);
+    if (!pa_alsa_type_is_safe_for_rewind(type))
+        return false;
+
     if (snd_pcm_info(pcm, info) < 0)
         return false;
 
-- 
1.9.2



More information about the pulseaudio-discuss mailing list