audioconvert: allow empty mix matrix
authorMathieu Duponchelle <mathieu@centricular.com>
Wed, 11 Oct 2017 16:03:20 +0000 (18:03 +0200)
committerMathieu Duponchelle <mathieu@centricular.com>
Wed, 11 Oct 2017 20:57:38 +0000 (22:57 +0200)
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

gst-libs/gst/audio/audio-channel-mixer.c
gst-libs/gst/audio/audio-converter.c
gst/audioconvert/gstaudioconvert.c
gst/audioconvert/gstaudioconvert.h

index 7e1e950ad10bdbe99fa0cb8dbc348edee5182efa..d6407119d7c0ca3f1c2d3e67e9860d854fd2a85c 100644 (file)
@@ -796,8 +796,8 @@ gst_audio_channel_mixer_mix_double (GstAudioChannelMixer * mix,
  * @in_channels: number of input channels
  * @out_channels: number of output channels
  * @matrix: (transfer full) (nullable): channel conversion matrix, m[@in_channels][@out_channels].
- *   If identity matrix, passthrough applies. If %NULL, @in_channels must be
- *   equal to @out_channels, in which case an identity matrix is generated.
+ *   If identity matrix, passthrough applies. If %NULL, a (potentially truncated)
+ *   identity matrix is generated.
  *
  * 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);
   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 (matrix != NULL || in_channels == out_channels, NULL);
 
   mix = g_slice_new0 (GstAudioChannelMixer);
   mix->in_channels = in_channels;
   mix->out_channels = out_channels;
 
   if (!matrix) {
-    /* Generate identity matrix */
+    /* Generate (potentially truncated) identity matrix */
     gint i, j;
 
     mix->matrix = g_new0 (gfloat *, in_channels);
index 36bca569a7e44d6c45aaedc7862d2e98da2237e8..b8f20152cb63baef071b5920ddcffbe25a57dbff 100644 (file)
@@ -637,6 +637,10 @@ check_mix_matrix (guint in_channels, guint out_channels, const GValue * value)
 {
   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) {
     GST_ERROR ("Invalid mix matrix size, should be %d", out_channels);
     goto fail;
@@ -704,8 +708,11 @@ chain_mix (GstAudioConverter * convert, AudioChain * prev)
   convert->current_channels = out->channels;
 
   if (opt_matrix) {
-    gfloat **matrix =
-        mix_matrix_from_g_value (in->channels, out->channels, opt_matrix);
+    gfloat **matrix = NULL;
+
+    if (gst_value_array_get_size (opt_matrix))
+      matrix =
+          mix_matrix_from_g_value (in->channels, out->channels, opt_matrix);
 
     convert->mix =
         gst_audio_channel_mixer_new_with_matrix (0, format, in->channels,
index 27a85af44c2b06a6e44703ba97566dfcb50dd8e6..fa3d024095b54c70f87ba09ae2e5dacbfb3cab6a 100644 (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
  * ]|
+ *
+ * > 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,
    * 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) ||
       (mask != 0 || (gst_structure_get_int (s, "channels", &channels)
               && channels == 1))) {
@@ -733,7 +736,7 @@ gst_audio_convert_set_caps (GstBaseTransform * base, GstCaps * incaps,
       GST_AUDIO_CONVERTER_OPT_NOISE_SHAPING_METHOD,
       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,
         &this->mix_matrix);
 
@@ -933,7 +936,8 @@ gst_audio_convert_set_property (GObject * object, guint prop_id,
       break;
     case PROP_MIX_MATRIX:
       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 {
         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_copy (value, &this->mix_matrix);
+          this->mix_matrix_was_set = TRUE;
         } else {
           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);
       break;
     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);
       break;
     default:
index d4ae33843af5868b0e5a9d7745d18425b5041008..3efbfe08aa7b2c5f0d6159b793f2bd13e0e52eb7 100644 (file)
@@ -48,6 +48,7 @@ struct _GstAudioConvert
   GstAudioDitherMethod dither;
   GstAudioNoiseShapingMethod ns;
   GValue mix_matrix;
+  gboolean mix_matrix_was_set;
 
   GstAudioInfo in_info;
   GstAudioInfo out_info;