Index: gst/audioconvert/audioconvert.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/gst/audioconvert/audioconvert.c,v
retrieving revision 1.12
diff -u -p -r1.12 audioconvert.c
--- gst/audioconvert/audioconvert.c	10 Oct 2006 12:49:01 -0000	1.12
+++ gst/audioconvert/audioconvert.c	23 Jan 2007 11:21:49 -0000
@@ -233,6 +233,8 @@ audio_convert_prepare_context (AudioConv
   ctx->in = *in;
   ctx->out = *out;
 
+  g_assert (in->unpositioned_layout == out->unpositioned_layout);
+
   gst_channel_mix_setup_matrix (ctx);
 
   idx = audio_convert_get_func_index (in);
Index: gst/audioconvert/audioconvert.h
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/gst/audioconvert/audioconvert.h,v
retrieving revision 1.5
diff -u -p -r1.5 audioconvert.h
--- gst/audioconvert/audioconvert.h	6 Dec 2005 19:41:56 -0000	1.5
+++ gst/audioconvert/audioconvert.h	23 Jan 2007 11:21:49 -0000
@@ -37,6 +37,7 @@ struct _AudioConvertFmt
   gint rate;
   gint channels;
   GstAudioChannelPosition *pos;
+  gboolean unpositioned_layout;
 
   /* int audio caps */
   gboolean sign;
Index: gst/audioconvert/gstaudioconvert.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/gst/audioconvert/gstaudioconvert.c,v
retrieving revision 1.106
diff -u -p -r1.106 gstaudioconvert.c
--- gst/audioconvert/gstaudioconvert.c	23 Sep 2006 15:24:54 -0000	1.106
+++ gst/audioconvert/gstaudioconvert.c	23 Jan 2007 11:21:50 -0000
@@ -96,6 +96,8 @@ static GstFlowReturn gst_audio_convert_t
     GstBuffer * inbuf, GstBuffer * outbuf);
 static GstFlowReturn gst_audio_convert_transform_ip (GstBaseTransform * base,
     GstBuffer * buf);
+static gboolean structure_has_fixed_channel_positions (GstStructure * s,
+    gboolean * unpositioned_layout);
 
 /* AudioConvert signals and args */
 enum
@@ -122,32 +124,32 @@ GST_BOILERPLATE_FULL (GstAudioConvert, g
 GST_STATIC_CAPS ( \
   "audio/x-raw-float, " \
     "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, 8 ], " \
+    "channels = (int) [ 1, MAX ], " \
     "endianness = (int) BYTE_ORDER, " \
     "width = (int) 32;" \
   "audio/x-raw-int, " \
     "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, 8 ], " \
+    "channels = (int) [ 1, MAX ], " \
     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
     "width = (int) 32, " \
     "depth = (int) [ 1, 32 ], " \
     "signed = (boolean) { true, false }; " \
   "audio/x-raw-int, "   \
     "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, 8 ], "       \
+    "channels = (int) [ 1, MAX ], "       \
     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, "        \
     "width = (int) 24, "        \
     "depth = (int) [ 1, 24 ], " "signed = (boolean) { true, false }; "  \
   "audio/x-raw-int, " \
     "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, 8 ], " \
+    "channels = (int) [ 1, MAX ], " \
     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
     "width = (int) 16, " \
     "depth = (int) [ 1, 16 ], " \
     "signed = (boolean) { true, false }; " \
   "audio/x-raw-int, " \
     "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, 8 ], " \
+    "channels = (int) [ 1, MAX ], " \
     "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \
     "width = (int) 8, " \
     "depth = (int) [ 1, 8 ], " \
@@ -251,6 +253,10 @@ gst_audio_convert_parse_caps (const GstC
     goto no_values;
   if (!(fmt->pos = gst_audio_get_channel_positions (structure)))
     goto no_values;
+
+  fmt->unpositioned_layout = FALSE;
+  structure_has_fixed_channel_positions (structure, &fmt->unpositioned_layout);
+
   if (!gst_structure_get_int (structure, "width", &fmt->width))
     goto no_values;
   if (!gst_structure_get_int (structure, "rate", &fmt->rate))
@@ -405,6 +411,42 @@ set_structure_widths (GstStructure * s, 
   g_value_unset (&list);
 }
 
+static gboolean
+structure_has_fixed_channel_positions (GstStructure * s,
+    gboolean * unpositioned_layout)
+{
+  GstAudioChannelPosition *pos;
+  const GValue *val;
+  gint channels = 0;
+
+  if (!gst_structure_get_int (s, "channels", &channels))
+    return FALSE; /* probably a range */
+
+  if (channels > 8) {
+    GST_LOG ("%d channels, undefined channel positions are implicit", channels);
+    *unpositioned_layout = TRUE;
+    return TRUE;
+  }
+
+  val = gst_structure_get_value (s, "channel-positions");
+  if (val == NULL || !gst_value_is_fixed (val)) {
+    GST_LOG ("no or unfixed channel-positions in %" GST_PTR_FORMAT, s);
+    return FALSE;
+  }
+
+  pos = gst_audio_get_channel_positions (s);
+  if ((pos && pos[0] == GST_AUDIO_CHANNEL_POSITION_NONE) || channels > 8) {
+    GST_LOG ("fixed undefined channel-positions in %" GST_PTR_FORMAT, s);
+    *unpositioned_layout = TRUE;
+  } else {
+    GST_LOG ("fixed defined channel-positions in %" GST_PTR_FORMAT, s);
+    *unpositioned_layout = FALSE;
+  }
+  g_free (pos);
+
+  return TRUE;
+}
+
 /* Audioconvert can perform all conversions on audio except for resampling. 
  * However, there are some conversions we _prefer_ not to do. For example, it's
  * better to convert format (float<->int, endianness, etc) than the number of
@@ -422,8 +464,8 @@ gst_audio_convert_transform_caps (GstBas
 {
   GstCaps *ret;
   GstStructure *s, *structure;
-  gboolean isfloat;
-  gint width, depth, channels;
+  gboolean isfloat, allow_mixing;
+  gint width, depth, channels = 0;
   const gchar *fields_used[] = {
     "width", "depth", "rate", "channels", "endianness", "signed"
   };
@@ -479,11 +521,18 @@ gst_audio_convert_transform_caps (GstBas
     }
   }
 
+  allow_mixing = TRUE;
   if (gst_structure_get_int (structure, "channels", &channels)) {
-    if (channels == 8)
-      gst_structure_set (s, "channels", G_TYPE_INT, 8, NULL);
-    else
-      gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, channels, 8, NULL);
+    gboolean unpositioned;
+
+    /* we don't support mixing for channels without channel positions */
+    if (structure_has_fixed_channel_positions (s, &unpositioned))
+      allow_mixing = (unpositioned == FALSE);
+  }
+  if (!allow_mixing) {
+    gst_structure_set (s, "channels", G_TYPE_INT, channels, NULL);
+  } else {
+    gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, channels, 8, NULL);
   }
   gst_caps_append_structure (ret, s);
 
@@ -518,7 +567,12 @@ gst_audio_convert_transform_caps (GstBas
    * it's very bad to drop channels entirely.
    */
   s = gst_structure_copy (s);
-  gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 8, NULL);
+  if (allow_mixing) {
+    gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 8, NULL);
+  } else {
+    /* allow_mixing can only be FALSE if we got a fixed number of channels */
+    gst_structure_set (s, "channels", G_TYPE_INT, channels, NULL);
+  }
   gst_caps_append_structure (ret, s);
 
   /* Same, plus a float<->int conversion */
Index: gst/audioconvert/gstchannelmix.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/gst/audioconvert/gstchannelmix.c,v
retrieving revision 1.14
diff -u -p -r1.14 gstchannelmix.c
--- gst/audioconvert/gstchannelmix.c	18 Jan 2007 16:23:35 -0000	1.14
+++ gst/audioconvert/gstchannelmix.c	23 Jan 2007 11:21:50 -0000
@@ -464,9 +464,12 @@ static void
 gst_channel_mix_fill_matrix (AudioConvertCtx * this)
 {
   gst_channel_mix_fill_identical (this);
-  gst_channel_mix_fill_compatible (this);
-  gst_channel_mix_fill_others (this);
-  gst_channel_mix_fill_normalize (this);
+
+  if (!this->in.unpositioned_layout) {
+    gst_channel_mix_fill_compatible (this);
+    gst_channel_mix_fill_others (this);
+    gst_channel_mix_fill_normalize (this);
+  }
 }
 
 /* only call after this->out and this->in are filled in */
