diff mbox

alsa-lib: pcm_plug: fix float conversion for user specified ttable

Message ID 1402933971.835286264@f359.i.mail.ru (mailing list archive)
State New, archived
Headers show

Commit Message

Sergey June 16, 2014, 3:52 p.m. UTC
Move custom ttable with equal channels case from a separate ttable_last
exception into a common plugins insertion loop.
Fixes plug with ttable for float pcms (jack, ladspa).
Example: aplay -fFLOAT_LE /dev/zero
pcm.!default {
    type plug
    slave.pcm { type null }
    ttable.0.0 1
}
---
 src/pcm/pcm_plug.c |   36 +++++++++++-------------------------
 1 file changed, 11 insertions(+), 25 deletions(-)

Comments

Raymond Yau June 17, 2014, 2:23 a.m. UTC | #1
2014-6-16 ??11:53 ? "Sergey" <sergemp@mail.ru> ???
>
> Move custom ttable with equal channels case from a separate ttable_last
> exception into a common plugins insertion loop.
> Fixes plug with ttable for float pcms (jack, ladspa).
> Example: aplay -fFLOAT_LE /dev/zero
> pcm.!default {
>     type plug
>     slave.pcm { type null }
>     ttable.0.0 1
> }

Any reason to use type null in your test case since type null seem can
support all format ?
Jaroslav Kysela June 17, 2014, 1:06 p.m. UTC | #2
Date 16.6.2014 17:52, Sergey wrote:
> Move custom ttable with equal channels case from a separate ttable_last
> exception into a common plugins insertion loop.
> Fixes plug with ttable for float pcms (jack, ladspa).
> Example: aplay -fFLOAT_LE /dev/zero
> pcm.!default {
>     type plug
>     slave.pcm { type null }
>     ttable.0.0 1
> }
> ---
>  src/pcm/pcm_plug.c |   36 +++++++++++-------------------------
>  1 file changed, 11 insertions(+), 25 deletions(-)
> 
> diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c
> index ede9c15..6d0454f 100644
> --- a/src/pcm/pcm_plug.c
> +++ b/src/pcm/pcm_plug.c
> @@ -53,7 +53,7 @@ typedef struct {
>  	const snd_config_t *rate_converter;
>  	enum snd_pcm_plug_route_policy route_policy;
>  	snd_pcm_route_ttable_entry_t *ttable;
> -	int ttable_ok, ttable_last;
> +	int ttable_ok;
>  	unsigned int tt_ssize, tt_cused, tt_sused;
>  } snd_pcm_plug_t;
>  
> @@ -380,7 +380,7 @@ static int snd_pcm_plug_change_channels(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm
>  	snd_pcm_route_ttable_entry_t *ttable;
>  	int err;
>  	if (clt->channels == slv->channels &&
> -	    (!plug->ttable || !plug->ttable_last))
> +	    (!plug->ttable || plug->ttable_ok))
>  		return 0;
>  	if (clt->rate != slv->rate &&
>  	    clt->channels > slv->channels)
> @@ -485,13 +485,15 @@ static int snd_pcm_plug_change_format(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_p
>  	/* No conversion is needed */
>  	if (clt->format == slv->format &&
>  	    clt->rate == slv->rate &&
> -	    clt->channels == slv->channels)
> +	    clt->channels == slv->channels &&
> +	    (!plug->ttable || plug->ttable_ok))
>  		return 0;
>  
>  	if (snd_pcm_format_linear(slv->format)) {
>  		/* Conversion is done in another plugin */
>  		if (clt->rate != slv->rate ||
> -		    clt->channels != slv->channels)
> +		    clt->channels != slv->channels ||
> +		    (plug->ttable && !plug->ttable_ok))
>  			return 0;
>  		cfmt = clt->format;
>  		switch (clt->format) {
> @@ -525,7 +527,8 @@ static int snd_pcm_plug_change_format(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_p
>  		if (snd_pcm_format_linear(clt->format)) {
>  			cfmt = clt->format;
>  			f = snd_pcm_lfloat_open;
> -		} else if (clt->rate != slv->rate || clt->channels != slv->channels) {
> +		} else if (clt->rate != slv->rate || clt->channels != slv->channels ||
> +		           (plug->ttable && !plug->ttable_ok)) {
>  			cfmt = SND_PCM_FORMAT_S16;
>  			f = snd_pcm_lfloat_open;
>  		} else
> @@ -641,11 +644,12 @@ static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm,
>  	};
>  	snd_pcm_plug_params_t p = *slave;
>  	unsigned int k = 0;
> -	plug->ttable_ok = plug->ttable_last = 0;
> +	plug->ttable_ok = 0;
>  	while (client->format != p.format ||
>  	       client->channels != p.channels ||
>  	       client->rate != p.rate ||
> -	       client->access != p.access) {
> +	       client->access != p.access ||
> +	       (plug->ttable && !plug->ttable_ok)) {
>  		snd_pcm_t *new;
>  		int err;
>  		if (k >= sizeof(funcs)/sizeof(*funcs))
> @@ -660,24 +664,6 @@ static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm,
>  		}
>  		k++;
>  	}
> -#ifdef BUILD_PCM_PLUGIN_ROUTE
> -	/* it's exception, user specified ttable, but no reduction/expand */
> -	if (plug->ttable && !plug->ttable_ok) {
> -		snd_pcm_t *new;
> -		int err;
> -		plug->ttable_last = 1;
> -		err = snd_pcm_plug_change_channels(pcm, &new, client, &p);
> -		if (err < 0) {
> -			snd_pcm_plug_clear(pcm);
> -			return err;
> -		}
> -		assert(err);
> -		assert(plug->ttable_ok);
> -		plug->gen.slave = new;
> -		pcm->fast_ops = new->fast_ops;
> -		pcm->fast_op_arg = new->fast_op_arg;
> -	}
> -#endif
>  	return 0;
>  }
>  
> 

Thanks. Looks good. Applied.

					Jaroslav
Sergey June 17, 2014, 4:19 p.m. UTC | #3
June 17 2014 Raymond Yau wrote:

>> Move custom ttable with equal channels case from a separate ttable_last
>> exception into a common plugins insertion loop.
>> Fixes plug with ttable for float pcms (jack, ladspa).
>> Example: aplay -fFLOAT_LE /dev/zero
>> pcm.!default {
>>     type plug
>>     slave.pcm { type null }
>>     ttable.0.0 1
>> }
> 
> Any reason to use type null in your test case since type null seem can
> support all format ?

It was the shortest test to reproduce the bug.

A more restricted config:
# aplay -fFLOAT_LE /dev/zero
pcm.!default {
    type plug
    slave.pcm { type null }
    slave.format FLOAT_LE
    ttable.0.0 1
}
But that test was enough to reproduce "Assertion failed" bug too.

Actually I've hit this bug with a complex ladspa upmixing code:
pcm.upmix {
    type plug
    slave.pcm {
        type ladspa
        slave.pcm {
            type plug
            slave.pcm "..."
            ttable { ... }
        }
        plugins [ ... ]
    }
    ttable { ... }
}
similar to this:
  http://forums.gentoo.org/viewtopic-p-4528619.html#4528619

This bug crashed the application for me (it generates SIGABRT)
so I thought that it should be fixed.
diff mbox

Patch

diff --git a/src/pcm/pcm_plug.c b/src/pcm/pcm_plug.c
index ede9c15..6d0454f 100644
--- a/src/pcm/pcm_plug.c
+++ b/src/pcm/pcm_plug.c
@@ -53,7 +53,7 @@  typedef struct {
 	const snd_config_t *rate_converter;
 	enum snd_pcm_plug_route_policy route_policy;
 	snd_pcm_route_ttable_entry_t *ttable;
-	int ttable_ok, ttable_last;
+	int ttable_ok;
 	unsigned int tt_ssize, tt_cused, tt_sused;
 } snd_pcm_plug_t;
 
@@ -380,7 +380,7 @@  static int snd_pcm_plug_change_channels(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm
 	snd_pcm_route_ttable_entry_t *ttable;
 	int err;
 	if (clt->channels == slv->channels &&
-	    (!plug->ttable || !plug->ttable_last))
+	    (!plug->ttable || plug->ttable_ok))
 		return 0;
 	if (clt->rate != slv->rate &&
 	    clt->channels > slv->channels)
@@ -485,13 +485,15 @@  static int snd_pcm_plug_change_format(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_p
 	/* No conversion is needed */
 	if (clt->format == slv->format &&
 	    clt->rate == slv->rate &&
-	    clt->channels == slv->channels)
+	    clt->channels == slv->channels &&
+	    (!plug->ttable || plug->ttable_ok))
 		return 0;
 
 	if (snd_pcm_format_linear(slv->format)) {
 		/* Conversion is done in another plugin */
 		if (clt->rate != slv->rate ||
-		    clt->channels != slv->channels)
+		    clt->channels != slv->channels ||
+		    (plug->ttable && !plug->ttable_ok))
 			return 0;
 		cfmt = clt->format;
 		switch (clt->format) {
@@ -525,7 +527,8 @@  static int snd_pcm_plug_change_format(snd_pcm_t *pcm, snd_pcm_t **new, snd_pcm_p
 		if (snd_pcm_format_linear(clt->format)) {
 			cfmt = clt->format;
 			f = snd_pcm_lfloat_open;
-		} else if (clt->rate != slv->rate || clt->channels != slv->channels) {
+		} else if (clt->rate != slv->rate || clt->channels != slv->channels ||
+		           (plug->ttable && !plug->ttable_ok)) {
 			cfmt = SND_PCM_FORMAT_S16;
 			f = snd_pcm_lfloat_open;
 		} else
@@ -641,11 +644,12 @@  static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm,
 	};
 	snd_pcm_plug_params_t p = *slave;
 	unsigned int k = 0;
-	plug->ttable_ok = plug->ttable_last = 0;
+	plug->ttable_ok = 0;
 	while (client->format != p.format ||
 	       client->channels != p.channels ||
 	       client->rate != p.rate ||
-	       client->access != p.access) {
+	       client->access != p.access ||
+	       (plug->ttable && !plug->ttable_ok)) {
 		snd_pcm_t *new;
 		int err;
 		if (k >= sizeof(funcs)/sizeof(*funcs))
@@ -660,24 +664,6 @@  static int snd_pcm_plug_insert_plugins(snd_pcm_t *pcm,
 		}
 		k++;
 	}
-#ifdef BUILD_PCM_PLUGIN_ROUTE
-	/* it's exception, user specified ttable, but no reduction/expand */
-	if (plug->ttable && !plug->ttable_ok) {
-		snd_pcm_t *new;
-		int err;
-		plug->ttable_last = 1;
-		err = snd_pcm_plug_change_channels(pcm, &new, client, &p);
-		if (err < 0) {
-			snd_pcm_plug_clear(pcm);
-			return err;
-		}
-		assert(err);
-		assert(plug->ttable_ok);
-		plug->gen.slave = new;
-		pcm->fast_ops = new->fast_ops;
-		pcm->fast_op_arg = new->fast_op_arg;
-	}
-#endif
 	return 0;
 }