[PATCH] alsa: Add channel map API support

Takashi Iwai tiwai at suse.de
Wed Oct 9 17:41:23 CEST 2013


The initial support for the new ALSA chmap API.
Just translate the current chmap to GstAudioChannelPosition during the
setup.  No function to specify the channel map manually yet, so still
impossible to assign any non-standard positions or to configure in a
different order even if the hardware allows.
---
 ext/alsa/gstalsa.c     | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
 ext/alsa/gstalsa.h     |  4 ++++
 ext/alsa/gstalsasink.c | 12 ++++++++++++
 ext/alsa/gstalsasrc.c  | 12 ++++++++++++
 4 files changed, 80 insertions(+)

diff --git a/ext/alsa/gstalsa.c b/ext/alsa/gstalsa.c
index 0828110..d702a23 100644
--- a/ext/alsa/gstalsa.c
+++ b/ext/alsa/gstalsa.c
@@ -707,3 +707,55 @@ const GstAudioChannelPosition alsa_position[][8] = {
         GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
       GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}
 };
+
+#ifdef SND_CHMAP_API_VERSION
+/* +1 is to make zero as holes */
+#define ITEM(x, y) \
+  [SND_CHMAP_ ## x] = GST_AUDIO_CHANNEL_POSITION_ ## y + 1
+
+static GstAudioChannelPosition gst_pos[SND_CHMAP_LAST + 1] = {
+  ITEM(MONO, MONO),
+  ITEM(FL, FRONT_LEFT),
+  ITEM(FR, FRONT_RIGHT),
+  ITEM(FC, FRONT_CENTER),
+  ITEM(RL, REAR_LEFT),
+  ITEM(RR, REAR_RIGHT),
+  ITEM(RC, REAR_CENTER),
+  ITEM(LFE, LFE1),
+  ITEM(SL, SIDE_LEFT),
+  ITEM(SR, SIDE_RIGHT),
+  ITEM(FLC, FRONT_LEFT_OF_CENTER),
+  ITEM(FRC, FRONT_RIGHT_OF_CENTER),
+  ITEM(FLW, WIDE_LEFT),
+  ITEM(FRW, WIDE_RIGHT),
+  ITEM(TC, TOP_CENTER),
+  ITEM(TFL, TOP_FRONT_LEFT),
+  ITEM(TFR, TOP_FRONT_RIGHT),
+  ITEM(TFC, TOP_FRONT_CENTER),
+  ITEM(TRL, TOP_REAR_LEFT),
+  ITEM(TRR, TOP_REAR_RIGHT),
+  ITEM(TRC, TOP_REAR_CENTER),
+  ITEM(LLFE, LFE1),
+  ITEM(RLFE, LFE2),
+  ITEM(BC, BOTTOM_FRONT_CENTER),
+  ITEM(BLC, BOTTOM_FRONT_LEFT),
+  ITEM(BRC, BOTTOM_FRONT_LEFT),
+};
+#undef ITEM
+
+gboolean alsa_chmap_to_channel_positions (const snd_pcm_chmap_t *chmap,
+					  GstAudioChannelPosition *pos)
+{
+  int c;
+
+  for (c = 0; c < chmap->channels; c++) {
+    if (chmap->pos[c] > SND_CHMAP_LAST)
+      return FALSE;
+    pos[c] = gst_pos[chmap->pos[c]];
+    if (!pos[c])
+      return FALSE;
+    pos[c]--;
+  }
+  return TRUE;
+}
+#endif /* SND_CHMAP_API_VERSION */
diff --git a/ext/alsa/gstalsa.h b/ext/alsa/gstalsa.h
index b9000de..8026619 100644
--- a/ext/alsa/gstalsa.h
+++ b/ext/alsa/gstalsa.h
@@ -71,5 +71,9 @@ void      gst_alsa_add_channel_reorder_map (GstObject * obj,
                                             GstCaps   * caps);
 
 extern const GstAudioChannelPosition alsa_position[][8];
+#ifdef SND_CHMAP_API_VERSION
+gboolean alsa_chmap_to_channel_positions (const snd_pcm_chmap_t *chmap,
+					  GstAudioChannelPosition *pos);
+#endif
 
 #endif /* __GST_ALSA_H__ */
diff --git a/ext/alsa/gstalsasink.c b/ext/alsa/gstalsasink.c
index 19dbd8b..3895749 100644
--- a/ext/alsa/gstalsasink.c
+++ b/ext/alsa/gstalsasink.c
@@ -896,6 +896,18 @@ gst_alsasink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec)
     snd_output_close (out_buf);
   }
 
+#ifdef SND_CHMAP_API_VERSION
+  if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9) {
+    snd_pcm_chmap_t *chmap = snd_pcm_get_chmap (alsa->handle);
+    if (chmap && chmap->channels == alsa->channels) {
+      GstAudioChannelPosition pos[8];
+      if (alsa_chmap_to_channel_positions (chmap, pos))
+	gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SINK (alsa)->ringbuffer, pos);
+    }
+    free (chmap);
+  }
+#endif /* SND_CHMAP_API_VERSION */
+
   return TRUE;
 
   /* ERRORS */
diff --git a/ext/alsa/gstalsasrc.c b/ext/alsa/gstalsasrc.c
index fa4b555..741f9f9 100644
--- a/ext/alsa/gstalsasrc.c
+++ b/ext/alsa/gstalsasrc.c
@@ -783,6 +783,18 @@ gst_alsasrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
     snd_output_close (out_buf);
   }
 
+#ifdef SND_CHMAP_API_VERSION
+  if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9) {
+    snd_pcm_chmap_t *chmap = snd_pcm_get_chmap (alsa->handle);
+    if (chmap && chmap->channels == alsa->channels) {
+      GstAudioChannelPosition pos[8];
+      if (alsa_chmap_to_channel_positions (chmap, pos))
+	gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC (alsa)->ringbuffer, pos);
+    }
+    free (chmap);
+  }
+#endif /* SND_CHMAP_API_VERSION */
+
   return TRUE;
 
   /* ERRORS */
-- 
1.8.4



More information about the gstreamer-devel mailing list