alsa: Port to the new multichannel caps
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Tue, 20 Dec 2011 10:44:27 +0000 (11:44 +0100)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 5 Jan 2012 09:34:20 +0000 (10:34 +0100)
ext/alsa/gstalsa.c
ext/alsa/gstalsa.h
ext/alsa/gstalsasink.c
ext/alsa/gstalsasrc.c

index 2a2410a..8da665b 100644 (file)
@@ -204,26 +204,23 @@ get_channel_free_structure (const GstStructure * in_structure)
   return s;
 }
 
+#define ONE_64 G_GUINT64_CONSTANT (1)
+#define CHANNEL_MASK_STEREO ((ONE_64<<GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT) | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT))
+#define CHANNEL_MASK_2_1    (CHANNEL_MASK_STEREO | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_LFE1))
+#define CHANNEL_MASK_4_0    (CHANNEL_MASK_STEREO | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_REAR_LEFT) | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT))
+#define CHANNEL_MASK_5_1    (CHANNEL_MASK_4_0 | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER) | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_LFE1))
+#define CHANNEL_MASK_7_1    (CHANNEL_MASK_5_1 | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT) | (ONE_64<<GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT))
+
 static void
 caps_add_channel_configuration (GstCaps * caps,
     const GstStructure * in_structure, gint min_chans, gint max_chans)
 {
-  GstAudioChannelPosition pos[8] = {
-    GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-    GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-    GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-    GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
-    GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
-    GST_AUDIO_CHANNEL_POSITION_LFE,
-    GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
-    GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT
-  };
   GstStructure *s = NULL;
   gint c;
 
-  if (min_chans == max_chans && max_chans <= 2) {
+  if (min_chans == max_chans && max_chans == 1) {
     s = get_channel_free_structure (in_structure);
-    gst_structure_set (s, "channels", G_TYPE_INT, max_chans, NULL);
+    gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
     gst_caps_append_structure (caps, s);
     return;
   }
@@ -233,11 +230,16 @@ caps_add_channel_configuration (GstCaps * caps,
   /* mono and stereo don't need channel configurations */
   if (min_chans == 2) {
     s = get_channel_free_structure (in_structure);
-    gst_structure_set (s, "channels", G_TYPE_INT, 2, NULL);
+    gst_structure_set (s, "channels", G_TYPE_INT, 2, "channel-mask",
+        GST_TYPE_BITMASK, CHANNEL_MASK_STEREO, NULL);
     gst_caps_append_structure (caps, s);
   } else if (min_chans == 1 && max_chans >= 2) {
     s = get_channel_free_structure (in_structure);
-    gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL);
+    gst_structure_set (s, "channels", G_TYPE_INT, 2, "channel-mask",
+        GST_TYPE_BITMASK, CHANNEL_MASK_STEREO, NULL);
+    gst_caps_append_structure (caps, s);
+    s = get_channel_free_structure (in_structure);
+    gst_structure_set (s, "channels", G_TYPE_INT, 1, NULL);
     gst_caps_append_structure (caps, s);
   }
 
@@ -245,41 +247,44 @@ caps_add_channel_configuration (GstCaps * caps,
    * alsa might work around that/fix it somehow. Can we tell alsa
    * what our channel layout is like? */
   if (max_chans >= 3 && min_chans <= 3) {
-    GstAudioChannelPosition pos_21[3] = {
-      GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-      GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-      GST_AUDIO_CHANNEL_POSITION_LFE
-    };
-
     s = get_channel_free_structure (in_structure);
-    gst_structure_set (s, "channels", G_TYPE_INT, 3, NULL);
-    gst_audio_set_channel_positions (s, pos_21);
+    gst_structure_set (s, "channels", G_TYPE_INT, 3, "channel-mask",
+        GST_TYPE_BITMASK, CHANNEL_MASK_2_1, NULL);
     gst_caps_append_structure (caps, s);
   }
 
   /* everything else (4, 6, 8 channels) needs a channel layout */
   for (c = MAX (4, min_chans); c <= 8; c += 2) {
     if (max_chans >= c) {
+      guint64 channel_mask;
+
       s = get_channel_free_structure (in_structure);
-      gst_structure_set (s, "channels", G_TYPE_INT, c, NULL);
-      gst_audio_set_channel_positions (s, pos);
+      switch (c) {
+        case 4:
+          channel_mask = CHANNEL_MASK_4_0;
+          break;
+        case 6:
+          channel_mask = CHANNEL_MASK_5_1;
+          break;
+        case 8:
+          channel_mask = CHANNEL_MASK_7_1;
+          break;
+        default:
+          g_assert_not_reached ();
+          break;
+      }
+      gst_structure_set (s, "channels", G_TYPE_INT, c, "channel-mask",
+          GST_TYPE_BITMASK, channel_mask, NULL);
       gst_caps_append_structure (caps, s);
     }
   }
 
+  /* NONE layouts for everything else */
   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_structure_set (s, "channels", G_TYPE_INT, c, "channel-mask",
+        GST_TYPE_BITMASK, G_GUINT64_CONSTANT (0), NULL);
     gst_caps_append_structure (caps, s);
-    g_free (ch_layout);
   }
 }
 
@@ -599,3 +604,55 @@ gst_alsa_find_device_name (GstObject * obj, const gchar * device,
 
   return ret;
 }
+
+/* ALSA channel positions */
+const GstAudioChannelPosition alsa_position[][8] = {
+  {
+      GST_AUDIO_CHANNEL_POSITION_MONO},
+  {
+        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+      GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT},
+  {
+        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
+      GST_AUDIO_CHANNEL_POSITION_LFE1},
+  {
+        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
+        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
+      GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT},
+  {
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+      GST_AUDIO_CHANNEL_POSITION_INVALID},
+  {
+        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
+        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
+        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
+        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
+      GST_AUDIO_CHANNEL_POSITION_LFE1},
+  {
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+        GST_AUDIO_CHANNEL_POSITION_INVALID,
+      GST_AUDIO_CHANNEL_POSITION_INVALID},
+  {
+        GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
+        GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
+        GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
+        GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
+        GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
+        GST_AUDIO_CHANNEL_POSITION_LFE1,
+        GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
+      GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}
+};
index 92466d2..ee813ae 100644 (file)
@@ -31,6 +31,7 @@
 #include <alsa/control.h>
 #include <alsa/error.h>
 #include <gst/gst.h>
+#include <gst/audio/audio.h>
 
 #define GST_CHECK_ALSA_VERSION(major,minor,micro) \
     (SND_LIB_MAJOR > (major) || \
@@ -56,5 +57,9 @@ gchar *   gst_alsa_find_card_name   (GstObject        * obj,
                                      const gchar      * devcard,
                                      snd_pcm_stream_t   stream);
 
+void      gst_alsa_add_channel_reorder_map (GstObject * obj,
+                                            GstCaps   * caps);
+
+extern const GstAudioChannelPosition alsa_position[][8];
 
 #endif /* __GST_ALSA_H__ */
index 090114a..7ae9e51 100644 (file)
@@ -713,6 +713,10 @@ alsasink_parse_spec (GstAlsaSink * alsa, GstAudioRingBufferSpec * spec)
   alsa->period_time = spec->latency_time;
   alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
 
+  if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9)
+    gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SINK
+        (alsa)->ringbuffer, alsa_position[alsa->channels - 1]);
+
   return TRUE;
 
   /* ERRORS */
index 223cf64..2d21c88 100644 (file)
@@ -642,6 +642,10 @@ alsasrc_parse_spec (GstAlsaSrc * alsa, GstAudioRingBufferSpec * spec)
   alsa->period_time = spec->latency_time;
   alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED;
 
+  if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9)
+    gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
+        (alsa)->ringbuffer, alsa_position[alsa->channels - 1]);
+
   return TRUE;
 
   /* ERRORS */