pulse: Port to the new multichannel caps
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 4 Jan 2012 09:27:09 +0000 (10:27 +0100)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 5 Jan 2012 09:30:30 +0000 (10:30 +0100)
ext/pulse/pulsesink.h
ext/pulse/pulsesrc.c
ext/pulse/pulseutil.c

index 067f684..9f5ae22 100644 (file)
@@ -101,13 +101,17 @@ GType gst_pulsesink_get_type (void);
 #define _PULSE_SINK_CAPS_COMMON \
     "audio/x-raw, " \
       "format = (string) " FORMATS ", " \
+      "layout = (string) interleaved, " \
       "rate = (int) [ 1, MAX ], " \
       "channels = (int) [ 1, 32 ];" \
     "audio/x-alaw, " \
+      "layout = (string) interleaved, " \
       "rate = (int) [ 1, MAX], " \
       "channels = (int) [ 1, 32 ];" \
     "audio/x-mulaw, " \
-      "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ];"
+      "layout = (string) interleaved, " \
+      "rate = (int) [ 1, MAX], " \
+      "channels = (int) [ 1, 32 ];"
 
 #define _PULSE_SINK_CAPS_1_0 \
     "audio/x-ac3, framed = (boolean) true;" \
index 09acced..e8e91b2 100644 (file)
@@ -116,6 +116,7 @@ static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_ALWAYS,
     GST_STATIC_CAPS ("audio/x-raw, "
         "format = (string) " FORMATS ", "
+        "layout = (string) interleaved, "
         "rate = (int) [ 1, MAX ], "
         "channels = (int) [ 1, 32 ];"
         "audio/x-alaw, "
@@ -1136,22 +1137,48 @@ server_dead:
 }
 
 static gboolean
-gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps * caps)
+gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps ** caps)
 {
   pa_channel_map channel_map;
+  const pa_channel_map *m;
   GstStructure *s;
   gboolean need_channel_layout = FALSE;
   GstAudioRingBufferSpec spec;
   const gchar *name;
 
+  s = gst_caps_get_structure (*caps, 0);
+  gst_structure_get_int (s, "channels", &spec.info.channels);
+  if (!gst_structure_has_field (s, "channel-mask")) {
+    if (spec.info.channels == 1) {
+      pa_channel_map_init_mono (&channel_map);
+    } else if (spec.info.channels == 2) {
+      gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK,
+          GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT) |
+          GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT), NULL);
+      pa_channel_map_init_stereo (&channel_map);
+    } else {
+      need_channel_layout = TRUE;
+      gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK,
+          G_GUINT64_CONSTANT (0), NULL);
+    }
+  }
+
   memset (&spec, 0, sizeof (GstAudioRingBufferSpec));
   spec.latency_time = GST_SECOND;
-  if (!gst_audio_ring_buffer_parse_caps (&spec, caps))
+  if (!gst_audio_ring_buffer_parse_caps (&spec, *caps))
     goto invalid_caps;
 
   /* Keep the refcount of the caps at 1 to make them writable */
   gst_caps_unref (spec.caps);
 
+  if (!need_channel_layout
+      && !gst_pulse_gst_to_channel_map (&channel_map, &spec)) {
+    need_channel_layout = TRUE;
+    gst_structure_set (s, "channel-mask", GST_TYPE_BITMASK,
+        G_GUINT64_CONSTANT (0), NULL);
+    memset (spec.info.position, 0xff, sizeof (spec.info.position));
+  }
+
   if (!gst_pulse_fill_sample_spec (&spec, &pulsesrc->sample_spec))
     goto invalid_spec;
 
@@ -1160,17 +1187,6 @@ gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps * caps)
   if (!pulsesrc->context)
     goto bad_context;
 
-  s = gst_caps_get_structure (caps, 0);
-  if (!gst_structure_has_field (s, "channel-layout") ||
-      !gst_pulse_gst_to_channel_map (&channel_map, &spec)) {
-    if (spec.info.channels == 1)
-      pa_channel_map_init_mono (&channel_map);
-    else if (spec.info.channels == 2)
-      pa_channel_map_init_stereo (&channel_map);
-    else
-      need_channel_layout = TRUE;
-  }
-
   name = "Record Stream";
   if (pulsesrc->proplist) {
     if (!(pulsesrc->stream = pa_stream_new_with_proplist (pulsesrc->context,
@@ -1184,14 +1200,14 @@ gst_pulsesrc_create_stream (GstPulseSrc * pulsesrc, GstCaps * caps)
               (need_channel_layout) ? NULL : &channel_map)))
     goto create_failed;
 
-  if (need_channel_layout) {
-    const pa_channel_map *m = pa_stream_get_channel_map (pulsesrc->stream);
-
-    gst_pulse_channel_map_to_gst (m, &spec);
-    caps = spec.caps;
-  }
+  m = pa_stream_get_channel_map (pulsesrc->stream);
+  gst_pulse_channel_map_to_gst (m, &spec);
+  gst_audio_channel_positions_to_valid_order (spec.info.position,
+      spec.info.channels);
+  gst_caps_unref (*caps);
+  *caps = gst_audio_info_to_caps (&spec.info);
 
-  GST_DEBUG_OBJECT (pulsesrc, "Caps are %" GST_PTR_FORMAT, caps);
+  GST_DEBUG_OBJECT (pulsesrc, "Caps are %" GST_PTR_FORMAT, *caps);
 
   pa_stream_set_state_callback (pulsesrc->stream, gst_pulsesrc_stream_state_cb,
       pulsesrc);
@@ -1292,7 +1308,7 @@ gst_pulsesrc_negotiate (GstBaseSrc * basesrc)
         result = TRUE;
       } else if (gst_caps_is_fixed (caps)) {
         /* yay, fixed caps, use those then */
-        result = gst_pulsesrc_create_stream (pulsesrc, caps);
+        result = gst_pulsesrc_create_stream (pulsesrc, &caps);
         if (result)
           result = gst_base_src_set_caps (basesrc, caps);
       }
@@ -1321,6 +1337,16 @@ gst_pulsesrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
 
   pa_threaded_mainloop_lock (pulsesrc->mainloop);
 
+  {
+    GstAudioRingBufferSpec s = *spec;
+    const pa_channel_map *m;
+
+    m = pa_stream_get_channel_map (pulsesrc->stream);
+    gst_pulse_channel_map_to_gst (m, &s);
+    gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC
+        (pulsesrc)->ringbuffer, s.info.position);
+  }
+
   /* enable event notifications */
   GST_LOG_OBJECT (pulsesrc, "subscribing to context events");
   if (!(o = pa_context_subscribe (pulsesrc->context,
index e29e7e9..607fdd4 100644 (file)
@@ -24,7 +24,6 @@
 #endif
 
 #include "pulseutil.h"
-#include <gst/audio/multichannel.h>
 
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>            /* getpid on UNIX */
 # include <process.h>           /* getpid on win32 */
 #endif
 
-static const pa_channel_position_t gst_pos_to_pa[GST_AUDIO_CHANNEL_POSITION_NUM]
-    = {
-  [GST_AUDIO_CHANNEL_POSITION_FRONT_MONO] = PA_CHANNEL_POSITION_MONO,
-  [GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT] = PA_CHANNEL_POSITION_FRONT_LEFT,
-  [GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT] = PA_CHANNEL_POSITION_FRONT_RIGHT,
-  [GST_AUDIO_CHANNEL_POSITION_REAR_CENTER] = PA_CHANNEL_POSITION_REAR_CENTER,
-  [GST_AUDIO_CHANNEL_POSITION_REAR_LEFT] = PA_CHANNEL_POSITION_REAR_LEFT,
-  [GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT] = PA_CHANNEL_POSITION_REAR_RIGHT,
-  [GST_AUDIO_CHANNEL_POSITION_LFE] = PA_CHANNEL_POSITION_LFE,
-  [GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER] = PA_CHANNEL_POSITION_FRONT_CENTER,
-  [GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] =
-      PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
-  [GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] =
-      PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
-  [GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT] = PA_CHANNEL_POSITION_SIDE_LEFT,
-  [GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT] = PA_CHANNEL_POSITION_SIDE_RIGHT,
-  [GST_AUDIO_CHANNEL_POSITION_TOP_CENTER] = PA_CHANNEL_POSITION_TOP_CENTER,
-  [GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT] =
-      PA_CHANNEL_POSITION_TOP_FRONT_LEFT,
-  [GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT] =
-      PA_CHANNEL_POSITION_TOP_FRONT_RIGHT,
-  [GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER] =
-      PA_CHANNEL_POSITION_TOP_FRONT_CENTER,
-  [GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT] =
-      PA_CHANNEL_POSITION_TOP_REAR_LEFT,
-  [GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT] =
-      PA_CHANNEL_POSITION_TOP_REAR_RIGHT,
-  [GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER] =
-      PA_CHANNEL_POSITION_TOP_REAR_CENTER,
-  [GST_AUDIO_CHANNEL_POSITION_NONE] = PA_CHANNEL_POSITION_INVALID
-};
-
-/* All index are increased by one because PA_CHANNEL_POSITION_INVALID == -1 */
-static const GstAudioChannelPosition
-    pa_to_gst_pos[GST_AUDIO_CHANNEL_POSITION_NUM]
-    = {
-  [PA_CHANNEL_POSITION_MONO + 1] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO,
-  [PA_CHANNEL_POSITION_FRONT_LEFT + 1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
-  [PA_CHANNEL_POSITION_FRONT_RIGHT + 1] =
-      GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
-  [PA_CHANNEL_POSITION_REAR_CENTER + 1] =
-      GST_AUDIO_CHANNEL_POSITION_REAR_CENTER,
-  [PA_CHANNEL_POSITION_REAR_LEFT + 1] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
-  [PA_CHANNEL_POSITION_REAR_RIGHT + 1] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
-  [PA_CHANNEL_POSITION_LFE + 1] = GST_AUDIO_CHANNEL_POSITION_LFE,
-  [PA_CHANNEL_POSITION_FRONT_CENTER + 1] =
-      GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
-  [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER + 1] =
-      GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
-  [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER + 1] =
-      GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
-  [PA_CHANNEL_POSITION_SIDE_LEFT + 1] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
-  [PA_CHANNEL_POSITION_SIDE_RIGHT + 1] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT,
-  [PA_CHANNEL_POSITION_INVALID + 1] = GST_AUDIO_CHANNEL_POSITION_NONE,
+static const struct
+{
+  GstAudioChannelPosition gst_pos;
+  pa_channel_position_t pa_pos;
+} gst_pa_pos_table[] = {
+  {
+  GST_AUDIO_CHANNEL_POSITION_MONO, PA_CHANNEL_POSITION_MONO}, {
+  GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_LEFT}, {
+  GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_FRONT_RIGHT}, {
+  GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, PA_CHANNEL_POSITION_REAR_CENTER}, {
+  GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_LEFT}, {
+  GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_REAR_RIGHT}, {
+  GST_AUDIO_CHANNEL_POSITION_LFE1, PA_CHANNEL_POSITION_LFE}, {
+  GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_FRONT_CENTER}, {
+  GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
+        PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {
+  GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
+        PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
+  GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_LEFT}, {
+  GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, PA_CHANNEL_POSITION_SIDE_RIGHT}, {
+  GST_AUDIO_CHANNEL_POSITION_TOP_CENTER, PA_CHANNEL_POSITION_TOP_CENTER}, {
+  GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT,
+        PA_CHANNEL_POSITION_TOP_FRONT_LEFT}, {
+  GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT,
+        PA_CHANNEL_POSITION_TOP_FRONT_RIGHT}, {
+  GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER,
+        PA_CHANNEL_POSITION_TOP_FRONT_CENTER}, {
+  GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT, PA_CHANNEL_POSITION_TOP_REAR_LEFT}, {
+  GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT,
+        PA_CHANNEL_POSITION_TOP_REAR_RIGHT}, {
+  GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER,
+        PA_CHANNEL_POSITION_TOP_REAR_CENTER}, {
+  GST_AUDIO_CHANNEL_POSITION_NONE, PA_CHANNEL_POSITION_INVALID}
 };
 
 static gboolean
@@ -235,29 +213,30 @@ pa_channel_map *
 gst_pulse_gst_to_channel_map (pa_channel_map * map,
     const GstAudioRingBufferSpec * spec)
 {
-  int i;
-  GstAudioChannelPosition *pos;
+  gint i, j;
+  gint channels;
+  const GstAudioChannelPosition *pos;
 
   pa_channel_map_init (map);
 
-  if (!(pos =
-          gst_audio_get_channel_positions (gst_caps_get_structure (spec->caps,
-                  0)))) {
-    return NULL;
+  channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
+  pos = spec->info.position;
+
+  for (j = 0; j < channels; j++) {
+    for (i = 0; i < G_N_ELEMENTS (gst_pa_pos_table); i++) {
+      if (pos[j] == gst_pa_pos_table[i].gst_pos) {
+        map->map[j] = gst_pa_pos_table[i].pa_pos;
+        break;
+      }
+    }
+    if (i == G_N_ELEMENTS (gst_pa_pos_table))
+      return NULL;
   }
 
-  for (i = 0; i < spec->info.channels; i++) {
-    if (pos[i] == GST_AUDIO_CHANNEL_POSITION_NONE) {
-      /* no valid mappings for these channels */
-      g_free (pos);
-      return NULL;
-    } else if (pos[i] < GST_AUDIO_CHANNEL_POSITION_NUM)
-      map->map[i] = gst_pos_to_pa[pos[i]];
-    else
-      map->map[i] = PA_CHANNEL_POSITION_INVALID;
+  if (j != spec->info.channels) {
+    return NULL;
   }
 
-  g_free (pos);
   map->channels = spec->info.channels;
 
   if (!pa_channel_map_valid (map)) {
@@ -271,30 +250,30 @@ GstAudioRingBufferSpec *
 gst_pulse_channel_map_to_gst (const pa_channel_map * map,
     GstAudioRingBufferSpec * spec)
 {
-  int i;
-  GstAudioChannelPosition *pos;
+  gint i, j;
   gboolean invalid = FALSE;
   gint channels;
+  GstAudioChannelPosition *pos;
 
   channels = GST_AUDIO_INFO_CHANNELS (&spec->info);
 
   g_return_val_if_fail (map->channels == channels, NULL);
 
-  pos = g_new0 (GstAudioChannelPosition, channels + 1);
+  pos = spec->info.position;
 
-  for (i = 0; i < channels; i++) {
-    if (map->map[i] == PA_CHANNEL_POSITION_INVALID) {
-      invalid = TRUE;
-      break;
-    } else if ((int) map->map[i] < (int) GST_AUDIO_CHANNEL_POSITION_NUM) {
-      pos[i] = pa_to_gst_pos[map->map[i] + 1];
-    } else {
-      invalid = TRUE;
-      break;
+  for (j = 0; j < channels; j++) {
+    for (i = 0; j < channels && i < G_N_ELEMENTS (gst_pa_pos_table); i++) {
+      if (map->map[j] == gst_pa_pos_table[i].pa_pos) {
+        pos[j] = gst_pa_pos_table[i].gst_pos;
+        break;
+      }
     }
+    if (i == G_N_ELEMENTS (gst_pa_pos_table))
+      return NULL;
   }
 
-  if (!invalid && !gst_audio_check_channel_positions (pos, channels))
+  if (!invalid
+      && !gst_audio_check_valid_channel_positions (pos, channels, FALSE))
     invalid = TRUE;
 
   if (invalid) {
@@ -302,10 +281,6 @@ gst_pulse_channel_map_to_gst (const pa_channel_map * map,
       pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
   }
 
-  gst_audio_set_channel_positions (gst_caps_get_structure (spec->caps, 0), pos);
-
-  g_free (pos);
-
   return spec;
 }