osxaudiosrc: Probe channel layout too
authorArun Raghavan <git@arunraghavan.net>
Mon, 1 Dec 2014 15:36:27 +0000 (21:06 +0530)
committerArun Raghavan <git@arunraghavan.net>
Mon, 15 Dec 2014 05:49:52 +0000 (11:19 +0530)
https://bugzilla.gnome.org/show_bug.cgi?id=740987

sys/osxaudio/gstosxaudiosink.c
sys/osxaudio/gstosxaudiosink.h
sys/osxaudio/gstosxaudiosrc.c
sys/osxaudio/gstosxcoreaudio.c
sys/osxaudio/gstosxcoreaudio.h
sys/osxaudio/gstosxcoreaudioremoteio.c

index 5ab648a..fd8be0c 100644 (file)
@@ -618,60 +618,11 @@ gst_osx_audio_sink_probe_caps (GstOsxAudioSink * osxsink)
     channels = 2;
   }
 
-  switch (channels) {
-    case 0:
-      pos[0] = GST_AUDIO_CHANNEL_POSITION_NONE;
-      break;
-    case 1:
-      pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
-      break;
-    case 2:
-      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
-      pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
-      channel_mask |= GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT);
-      channel_mask |= GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT);
-      break;
-    default:
-      channels = MIN (layout->mNumberChannelDescriptions,
-          GST_OSX_AUDIO_MAX_CHANNEL);
-      for (i = 0; i < channels; i++) {
-        switch (layout->mChannelDescriptions[i].mChannelLabel) {
-          case kAudioChannelLabel_Left:
-            pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
-            break;
-          case kAudioChannelLabel_Right:
-            pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
-            break;
-          case kAudioChannelLabel_Center:
-            pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
-            break;
-          case kAudioChannelLabel_LFEScreen:
-            pos[i] = GST_AUDIO_CHANNEL_POSITION_LFE1;
-            break;
-          case kAudioChannelLabel_LeftSurround:
-            pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
-            break;
-          case kAudioChannelLabel_RightSurround:
-            pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
-            break;
-          case kAudioChannelLabel_RearSurroundLeft:
-            pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT;
-            break;
-          case kAudioChannelLabel_RearSurroundRight:
-            pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT;
-            break;
-          case kAudioChannelLabel_CenterSurround:
-            pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
-            break;
-          default:
-            GST_WARNING_OBJECT (osxsink, "unrecognized channel: %d",
-                (int) layout->mChannelDescriptions[i].mChannelLabel);
-            channel_mask = 0;
-            channels = 2;
-            break;
-        }
-      }
+  if (!gst_core_audio_parse_channel_layout (layout, channels, &channel_mask,
+          pos)) {
+    GST_WARNING_OBJECT (osxsink, "Failed to parse channel layout");
   }
+
   g_free (layout);
 
   /* Recover the template caps */
index 84949b7..01d9966 100644 (file)
@@ -66,8 +66,6 @@ G_BEGIN_DECLS
 #define GST_IS_OSX_AUDIO_SINK(obj) \
   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OSX_AUDIO_SINK))
 
-#define GST_OSX_AUDIO_MAX_CHANNEL (9)
-
 typedef struct _GstOsxAudioSink GstOsxAudioSink;
 typedef struct _GstOsxAudioSinkClass GstOsxAudioSinkClass;
 
index a32ccca..99f48b8 100644 (file)
@@ -251,6 +251,8 @@ gst_osx_audio_src_probe_caps (GstOsxAudioSrc * osxsrc)
       GST_OSX_AUDIO_RING_BUFFER (GST_AUDIO_BASE_SRC (osxsrc)->ringbuffer);
   GstCoreAudio *core_audio = ringbuffer->core_audio;
   GstCaps *caps;
+  gint channels;
+  AudioChannelLayout *layout;
   AudioStreamBasicDescription asbd_in;
   UInt32 propertySize;
   OSStatus status;
@@ -262,11 +264,28 @@ gst_osx_audio_src_probe_caps (GstOsxAudioSrc * osxsrc)
   if (status)
     goto fail;
 
-  caps = gst_core_audio_asbd_to_caps (&asbd_in);
-  if (!caps)
+  layout = gst_core_audio_audio_device_get_channel_layout (osxsrc->device_id,
+      FALSE);
+
+  if (layout) {
+    channels = MIN (layout->mNumberChannelDescriptions,
+        GST_OSX_AUDIO_MAX_CHANNEL);
+  } else {
+    GST_WARNING_OBJECT (osxsrc, "This driver does not support "
+        "kAudioDevicePropertyPreferredChannelLayout.");
+    channels = 2;
+  }
+
+  caps = gst_core_audio_asbd_to_caps (&asbd_in, layout);
+  if (!caps) {
     GST_WARNING_OBJECT (osxsrc, "Could not get caps from stream description");
-  else
+    g_free (layout);
+    goto fail;
+  } else {
     GST_DEBUG_OBJECT (osxsrc, "Got caps on device: %p", caps);
+  }
+
+  g_free (layout);
 
   if (osxsrc->cached_caps)
     gst_caps_unref (osxsrc->cached_caps);
index d99ff29..c2dcd17 100644 (file)
@@ -185,12 +185,80 @@ gst_core_audio_audio_device_is_spdif_avail (AudioDeviceID device_id)
   return gst_core_audio_audio_device_is_spdif_avail_impl (device_id);
 }
 
+gboolean
+gst_core_audio_parse_channel_layout (AudioChannelLayout * layout,
+    gint channels, guint64 * channel_mask, GstAudioChannelPosition * pos)
+{
+  gint i;
+  gboolean ret = TRUE;
+
+  g_return_val_if_fail (channels <= GST_OSX_AUDIO_MAX_CHANNEL, FALSE);
+
+  switch (channels) {
+    case 0:
+      pos[0] = GST_AUDIO_CHANNEL_POSITION_NONE;
+      break;
+    case 1:
+      pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
+      break;
+    case 2:
+      pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+      pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+      *channel_mask |= GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_LEFT);
+      *channel_mask |= GST_AUDIO_CHANNEL_POSITION_MASK (FRONT_RIGHT);
+      break;
+    default:
+      for (i = 0; i < channels; i++) {
+        switch (layout->mChannelDescriptions[i].mChannelLabel) {
+          case kAudioChannelLabel_Left:
+            pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
+            break;
+          case kAudioChannelLabel_Right:
+            pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
+            break;
+          case kAudioChannelLabel_Center:
+            pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
+            break;
+          case kAudioChannelLabel_LFEScreen:
+            pos[i] = GST_AUDIO_CHANNEL_POSITION_LFE1;
+            break;
+          case kAudioChannelLabel_LeftSurround:
+            pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
+            break;
+          case kAudioChannelLabel_RightSurround:
+            pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
+            break;
+          case kAudioChannelLabel_RearSurroundLeft:
+            pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT;
+            break;
+          case kAudioChannelLabel_RearSurroundRight:
+            pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT;
+            break;
+          case kAudioChannelLabel_CenterSurround:
+            pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
+            break;
+          default:
+            GST_WARNING ("unrecognized channel: %d",
+                (int) layout->mChannelDescriptions[i].mChannelLabel);
+            *channel_mask = 0;
+            ret = FALSE;
+            break;
+        }
+      }
+  }
+
+  return ret;
+}
+
 GstCaps *
-gst_core_audio_asbd_to_caps (AudioStreamBasicDescription * asbd)
+gst_core_audio_asbd_to_caps (AudioStreamBasicDescription * asbd,
+    AudioChannelLayout * layout)
 {
   GstAudioInfo info;
   GstAudioFormat format = GST_AUDIO_FORMAT_UNKNOWN;
-  int rate, channels, bps, endianness;
+  GstAudioChannelPosition pos[64] = { GST_AUDIO_CHANNEL_POSITION_INVALID, };
+  gint rate, channels, bps, endianness;
+  guint64 channel_mask;
   gboolean sign, interleaved;
 
   if (asbd->mFormatID != kAudioFormatLinearPCM) {
@@ -247,7 +315,13 @@ gst_core_audio_asbd_to_caps (AudioStreamBasicDescription * asbd)
     goto error;
   }
 
-  gst_audio_info_set_format (&info, format, rate, channels, NULL);
+  if (!gst_core_audio_parse_channel_layout (layout, channels, &channel_mask,
+          pos)) {
+    GST_WARNING ("Failed to parse channel layout");
+    goto error;
+  }
+
+  gst_audio_info_set_format (&info, format, rate, channels, pos);
 
   return gst_audio_info_to_caps (&info);
 
index 39670f4..a9d701c 100644 (file)
@@ -27,6 +27,7 @@
 #endif
 
 #include <gst/gst.h>
+#include <gst/audio/audio-channels.h>
 #ifdef HAVE_IOS
   #include <CoreAudio/CoreAudioTypes.h>
   #define AudioDeviceID gint
@@ -62,6 +63,8 @@ G_BEGIN_DECLS
 #define GST_IS_CORE_AUDIO_CLASS(klass) \
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CORE_AUDIO))
 
+#define GST_OSX_AUDIO_MAX_CHANNEL (9)
+
 #define CORE_AUDIO_FORMAT_IS_SPDIF(f) ((f).mFormat.mFormatID == 'IAC3' || (f).mFormat.mFormatID == 'iac3' || (f).mFormat.mFormatID == kAudioFormat60958AC3 || (f).mFormat.mFormatID == kAudioFormatAC3)
 
 #define CORE_AUDIO_FORMAT "FormatID: %" GST_FOURCC_FORMAT " rate: %f flags: 0x%x BytesPerPacket: %u FramesPerPacket: %u BytesPerFrame: %u ChannelsPerFrame: %u BitsPerChannel: %u"
@@ -143,7 +146,10 @@ gboolean gst_core_audio_select_device                        (GstCoreAudio * cor
 
 AudioChannelLayout * gst_core_audio_audio_device_get_channel_layout (AudioDeviceID device_id, gboolean output);
 
-GstCaps * gst_core_audio_asbd_to_caps (AudioStreamBasicDescription * asbd);
+gboolean gst_core_audio_parse_channel_layout (AudioChannelLayout * layout,
+    gint channels, guint64 * channel_mask, GstAudioChannelPosition * pos);
+GstCaps * gst_core_audio_asbd_to_caps (AudioStreamBasicDescription * asbd,
+    AudioChannelLayout * layout);
 
 G_END_DECLS
 
index 238617b..1d3c843 100644 (file)
@@ -100,7 +100,8 @@ gst_core_audio_initialize_impl (GstCoreAudio * core_audio,
 }
 
 AudioChannelLayout *
-gst_core_audio_audio_device_get_channel_layout (AudioDeviceID device_id)
+gst_core_audio_audio_device_get_channel_layout (AudioDeviceID device_id,
+    gboolean output)
 {
   return NULL;
 }