audioconvert: allow empty mix matrix

When an empty mix matrix is passed, audio-channel-mixer
will now generate a (potentially truncated) identity matrix,
this replicates the behaviour of audiomixmatrix in first-channels
mode.

https://bugzilla.gnome.org/show_bug.cgi?id=788833
This commit is contained in:
Mathieu Duponchelle 2017-10-11 18:03:20 +02:00
parent 464d10f5c2
commit d4db88772b
4 changed files with 22 additions and 10 deletions

View file

@ -796,8 +796,8 @@ gst_audio_channel_mixer_mix_double (GstAudioChannelMixer * mix,
* @in_channels: number of input channels * @in_channels: number of input channels
* @out_channels: number of output channels * @out_channels: number of output channels
* @matrix: (transfer full) (nullable): channel conversion matrix, m[@in_channels][@out_channels]. * @matrix: (transfer full) (nullable): channel conversion matrix, m[@in_channels][@out_channels].
* If identity matrix, passthrough applies. If %NULL, @in_channels must be * If identity matrix, passthrough applies. If %NULL, a (potentially truncated)
* equal to @out_channels, in which case an identity matrix is generated. * identity matrix is generated.
* *
* Create a new channel mixer object for the given parameters. * Create a new channel mixer object for the given parameters.
* *
@ -820,14 +820,13 @@ gst_audio_channel_mixer_new_with_matrix (GstAudioChannelMixerFlags flags,
|| format == GST_AUDIO_FORMAT_F64, NULL); || format == GST_AUDIO_FORMAT_F64, NULL);
g_return_val_if_fail (in_channels > 0 && in_channels < 64, NULL); g_return_val_if_fail (in_channels > 0 && in_channels < 64, NULL);
g_return_val_if_fail (out_channels > 0 && out_channels < 64, NULL); g_return_val_if_fail (out_channels > 0 && out_channels < 64, NULL);
g_return_val_if_fail (matrix != NULL || in_channels == out_channels, NULL);
mix = g_slice_new0 (GstAudioChannelMixer); mix = g_slice_new0 (GstAudioChannelMixer);
mix->in_channels = in_channels; mix->in_channels = in_channels;
mix->out_channels = out_channels; mix->out_channels = out_channels;
if (!matrix) { if (!matrix) {
/* Generate identity matrix */ /* Generate (potentially truncated) identity matrix */
gint i, j; gint i, j;
mix->matrix = g_new0 (gfloat *, in_channels); mix->matrix = g_new0 (gfloat *, in_channels);

View file

@ -637,6 +637,10 @@ check_mix_matrix (guint in_channels, guint out_channels, const GValue * value)
{ {
guint i, j; guint i, j;
/* audio-channel-mixer will generate an identity matrix */
if (gst_value_array_get_size (value) == 0)
return TRUE;
if (gst_value_array_get_size (value) != out_channels) { if (gst_value_array_get_size (value) != out_channels) {
GST_ERROR ("Invalid mix matrix size, should be %d", out_channels); GST_ERROR ("Invalid mix matrix size, should be %d", out_channels);
goto fail; goto fail;
@ -704,8 +708,11 @@ chain_mix (GstAudioConverter * convert, AudioChain * prev)
convert->current_channels = out->channels; convert->current_channels = out->channels;
if (opt_matrix) { if (opt_matrix) {
gfloat **matrix = gfloat **matrix = NULL;
mix_matrix_from_g_value (in->channels, out->channels, opt_matrix);
if (gst_value_array_get_size (opt_matrix))
matrix =
mix_matrix_from_g_value (in->channels, out->channels, opt_matrix);
convert->mix = convert->mix =
gst_audio_channel_mixer_new_with_matrix (0, format, in->channels, gst_audio_channel_mixer_new_with_matrix (0, format, in->channels,

View file

@ -72,6 +72,9 @@
* |[ * |[
* gst-launch-1.0 audiotestsrc ! audio/x-raw, channels=4 ! audioconvert mix-matrix="<<(float)1.0, (float)0.0, (float)0.0, (float)0.0>, <(float)0.0, (float)1.0, (float)0.0, (float)0.0>>" ! audio/x-raw,channels=2 ! autoaudiosink * gst-launch-1.0 audiotestsrc ! audio/x-raw, channels=4 ! audioconvert mix-matrix="<<(float)1.0, (float)0.0, (float)0.0, (float)0.0>, <(float)0.0, (float)1.0, (float)0.0, (float)0.0>>" ! audio/x-raw,channels=2 ! autoaudiosink
* ]| * ]|
*
* > If an empty mix matrix is specified, a (potentially truncated)
* > identity matrix will be generated.
*/ */
/* /*
@ -300,7 +303,7 @@ remove_channels_from_structure (GstCapsFeatures * features, GstStructure * s,
/* Only remove the channels and channel-mask for non-NONE layouts, /* Only remove the channels and channel-mask for non-NONE layouts,
* or if a mix matrix was manually specified */ * or if a mix matrix was manually specified */
if (gst_value_array_get_size (&this->mix_matrix) || if (this->mix_matrix_was_set ||
!gst_structure_get (s, "channel-mask", GST_TYPE_BITMASK, &mask, NULL) || !gst_structure_get (s, "channel-mask", GST_TYPE_BITMASK, &mask, NULL) ||
(mask != 0 || (gst_structure_get_int (s, "channels", &channels) (mask != 0 || (gst_structure_get_int (s, "channels", &channels)
&& channels == 1))) { && channels == 1))) {
@ -733,7 +736,7 @@ gst_audio_convert_set_caps (GstBaseTransform * base, GstCaps * incaps,
GST_AUDIO_CONVERTER_OPT_NOISE_SHAPING_METHOD, GST_AUDIO_CONVERTER_OPT_NOISE_SHAPING_METHOD,
GST_TYPE_AUDIO_NOISE_SHAPING_METHOD, this->ns, NULL); GST_TYPE_AUDIO_NOISE_SHAPING_METHOD, this->ns, NULL);
if (gst_value_array_get_size (&this->mix_matrix)) if (this->mix_matrix_was_set)
gst_structure_set_value (config, GST_AUDIO_CONVERTER_OPT_MIX_MATRIX, gst_structure_set_value (config, GST_AUDIO_CONVERTER_OPT_MIX_MATRIX,
&this->mix_matrix); &this->mix_matrix);
@ -933,7 +936,8 @@ gst_audio_convert_set_property (GObject * object, guint prop_id,
break; break;
case PROP_MIX_MATRIX: case PROP_MIX_MATRIX:
if (!gst_value_array_get_size (value)) { if (!gst_value_array_get_size (value)) {
g_warning ("Empty mix matrix"); g_value_copy (value, &this->mix_matrix);
this->mix_matrix_was_set = TRUE;
} else { } else {
const GValue *first_row = gst_value_array_get_value (value, 0); const GValue *first_row = gst_value_array_get_value (value, 0);
@ -942,6 +946,7 @@ gst_audio_convert_set_property (GObject * object, guint prop_id,
g_value_unset (&this->mix_matrix); g_value_unset (&this->mix_matrix);
g_value_copy (value, &this->mix_matrix); g_value_copy (value, &this->mix_matrix);
this->mix_matrix_was_set = TRUE;
} else { } else {
g_warning ("Empty mix matrix's first row"); g_warning ("Empty mix matrix's first row");
} }
@ -967,7 +972,7 @@ gst_audio_convert_get_property (GObject * object, guint prop_id,
g_value_set_enum (value, this->ns); g_value_set_enum (value, this->ns);
break; break;
case PROP_MIX_MATRIX: case PROP_MIX_MATRIX:
if (gst_value_array_get_size (&this->mix_matrix)) if (this->mix_matrix_was_set)
g_value_copy (&this->mix_matrix, value); g_value_copy (&this->mix_matrix, value);
break; break;
default: default:

View file

@ -48,6 +48,7 @@ struct _GstAudioConvert
GstAudioDitherMethod dither; GstAudioDitherMethod dither;
GstAudioNoiseShapingMethod ns; GstAudioNoiseShapingMethod ns;
GValue mix_matrix; GValue mix_matrix;
gboolean mix_matrix_was_set;
GstAudioInfo in_info; GstAudioInfo in_info;
GstAudioInfo out_info; GstAudioInfo out_info;