ext/alsa/: Add support for cards that (only) do more than 8 channels, like the Delta...
authorTim-Philipp Müller <tim@centricular.net>
Thu, 3 Aug 2006 14:16:06 +0000 (14:16 +0000)
committerTim-Philipp Müller <tim@centricular.net>
Thu, 3 Aug 2006 14:16:06 +0000 (14:16 +0000)
Original commit message from CVS:
* ext/alsa/gstalsa.c: (caps_add_channel_configuration),
(gst_alsa_detect_channels):
* ext/alsa/gstalsasink.c:
Add support for cards that (only) do more than 8 channels,
like the Delta 44 (#345188).
* gst-libs/gst/audio/multichannel.c:
(gst_audio_check_channel_positions):
* gst-libs/gst/audio/multichannel.h:
API: add GST_AUDIO_CHANNEL_POSITION_NONE, which stands for an
unspecified channel position and cannot be combined with any
of the other audio channel positions; adjust position layout
checks accordingly (#345188).

ChangeLog
ext/alsa/gstalsa.c
ext/alsa/gstalsasink.c
gst-libs/gst/audio/multichannel.c
gst-libs/gst/audio/multichannel.h

index b224404..9d1b6c3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2006-08-03  Tim-Philipp Müller  <tim at centricular dot net>
 
+       * ext/alsa/gstalsa.c: (caps_add_channel_configuration),
+       (gst_alsa_detect_channels):
+       * ext/alsa/gstalsasink.c:
+         Add support for cards that (only) do more than 8 channels,
+         like the Delta 44 (#345188).
+
+       * gst-libs/gst/audio/multichannel.c:
+       (gst_audio_check_channel_positions):
+       * gst-libs/gst/audio/multichannel.h:
+         API: add GST_AUDIO_CHANNEL_POSITION_NONE, which stands for an
+         unspecified channel position and cannot be combined with any
+         of the other audio channel positions; adjust position layout
+         checks accordingly (#345188).
+
+2006-08-03  Tim-Philipp Müller  <tim at centricular dot net>
+
        * gst/typefind/gsttypefindfunctions.c: (plugin_init):
          Recognise ancient RealAudio files (see #349779).
 
index e91d479..ef17600 100644 (file)
@@ -174,7 +174,7 @@ caps_add_channel_configuration (GstCaps * caps,
   GstStructure *s = NULL;
   gint c;
 
-  if (min_chans == max_chans) {
+  if (min_chans == max_chans && max_chans <= 2) {
     s = get_channel_free_structure (in_structure);
     gst_structure_set (s, "channels", G_TYPE_INT, max_chans, NULL);
     gst_caps_append_structure (caps, s);
@@ -197,7 +197,7 @@ caps_add_channel_configuration (GstCaps * caps,
   /* don't know whether to use 2.1 or 3.0 here - but I suspect
    * alsa might work around that/fix it somehow. Can we tell alsa
    * what our channel layout is like? */
-  if (max_chans >= 3) {
+  if (max_chans >= 3 && min_chans <= 3) {
     GstAudioChannelPosition pos_21[3] = {
       GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
       GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
@@ -211,7 +211,7 @@ caps_add_channel_configuration (GstCaps * caps,
   }
 
   /* everything else (4, 6, 8 channels) needs a channel layout */
-  for (c = 4; c <= 8; c += 2) {
+  for (c = MAX (4, min_chans); c <= 8; c += 2) {
     if (max_chans >= c) {
       s = get_channel_free_structure (in_structure);
       gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
@@ -219,6 +219,21 @@ caps_add_channel_configuration (GstCaps * caps,
       gst_caps_append_structure (caps, s);
     }
   }
+
+  for (c = MAX (9, min_chans); c <= max_chans; ++c) {
+    GstAudioChannelPosition *ch_layout;
+    guint i;
+
+    ch_layout = g_new (GstAudioChannelPosition, c);
+    for (i = 0; i < c; ++i) {
+      ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
+    }
+    s = get_channel_free_structure (in_structure);
+    gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
+    gst_audio_set_channel_positions (s, ch_layout);
+    gst_caps_append_structure (caps, s);
+    g_free (ch_layout);
+  }
 }
 
 static GstCaps *
@@ -259,8 +274,20 @@ gst_alsa_detect_channels (GstObject * obj, snd_pcm_hw_params_t * hw_params,
     max_chans = temp;
   }
 
-  min_chans = MAX (min_chans, 1);
-  max_chans = MIN (GST_ALSA_MAX_CHANNELS, max_chans);
+  /* pro cards seem to return large numbers for min_channels */
+  if (min_chans > GST_ALSA_MAX_CHANNELS) {
+    GST_DEBUG_OBJECT (obj, "min_chans = %u, looks like a pro card", min_chans);
+    if (max_chans < min_chans) {
+      max_chans = min_chans;
+    } else {
+      /* only support [max_chans; max_chans] for these cards for now
+       * to avoid inflating the source caps with loads of structures ... */
+      min_chans = max_chans;
+    }
+  } else {
+    min_chans = MAX (min_chans, 1);
+    max_chans = MIN (GST_ALSA_MAX_CHANNELS, max_chans);
+  }
 
   GST_DEBUG_OBJECT (obj, "Min. channels = %d (%d)", min_chans, min);
   GST_DEBUG_OBJECT (obj, "Max. channels = %d (%d)", max_chans, max);
index 1913960..216c185 100644 (file)
@@ -119,18 +119,18 @@ static GstStaticPadTemplate alsasink_sink_factory =
         "signed = (boolean) { TRUE, FALSE }, "
         "width = (int) 32, "
         "depth = (int) 32, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 8 ]; "
+        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
         "audio/x-raw-int, "
         "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, "
         "signed = (boolean) { TRUE, FALSE }, "
         "width = (int) 16, "
         "depth = (int) 16, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 8 ]; "
+        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; "
         "audio/x-raw-int, "
         "signed = (boolean) { TRUE, FALSE }, "
         "width = (int) 8, "
         "depth = (int) 8, "
-        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 8 ]")
+        "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]")
     );
 
 static void
index a09153d..1fbf511 100644 (file)
@@ -65,14 +65,32 @@ gst_audio_check_channel_positions (const GstAudioChannelPosition * pos,
     GST_AUDIO_CHANNEL_POSITION_INVALID}}
   };
 
+  g_assert (pos != NULL && channels > 0);
+
   /* check for invalid channel positions */
   for (n = 0; n < channels; n++) {
-    if (pos[n] == GST_AUDIO_CHANNEL_POSITION_INVALID) {
-      g_warning ("Position %d is invalid, not allowed", n);
+    if (pos[n] <= GST_AUDIO_CHANNEL_POSITION_INVALID ||
+        pos[n] >= GST_AUDIO_CHANNEL_POSITION_NUM) {
+      g_warning ("Channel position %d is invalid, not allowed", n);
       return FALSE;
     }
   }
 
+  /* either all channel positions are NONE or all are defined,
+   * but having only some channel positions NONE and others not
+   * is not allowed */
+  if (pos[0] == GST_AUDIO_CHANNEL_POSITION_NONE) {
+    for (n = 1; n < channels; ++n) {
+      if (pos[n] != GST_AUDIO_CHANNEL_POSITION_NONE) {
+        g_warning ("Either all channel positions must be defined, or all "
+            "be set to NONE, having only some defined is not allowed");
+        return FALSE;
+      }
+    }
+    /* all positions are NONE, we are done here */
+    return TRUE;
+  }
+
   /* check for multiple position occurrences */
   for (i = GST_AUDIO_CHANNEL_POSITION_INVALID + 1;
       i < GST_AUDIO_CHANNEL_POSITION_NUM; i++) {
@@ -83,6 +101,13 @@ gst_audio_check_channel_positions (const GstAudioChannelPosition * pos,
         count++;
     }
 
+    /* NONE may not occur mixed with other channel positions */
+    if (i == GST_AUDIO_CHANNEL_POSITION_NONE && count > 0) {
+      g_warning ("Either all channel positions must be defined, or all "
+          "be set to NONE, having only some defined is not allowed");
+      return FALSE;
+    }
+
     if (count > 1) {
       g_warning ("Channel position %d occurred %d times, not allowed",
           i, count);
index 3138e55..8af0adf 100644 (file)
@@ -51,6 +51,11 @@ typedef enum {
   GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
   GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT,
 
+  /* for multi-channel input and output with more than 8 channels,
+   * incompatible with all other positions, either all positions
+   * are defined or all positions are undefined, but can't mix'n'match  */
+  GST_AUDIO_CHANNEL_POSITION_NONE,
+
   /* don't use - counter */
   GST_AUDIO_CHANNEL_POSITION_NUM
 } GstAudioChannelPosition;