osxaudiosrc: Probe channel layout too

https://bugzilla.gnome.org/show_bug.cgi?id=740987
This commit is contained in:
Arun Raghavan 2014-12-01 21:06:27 +05:30
parent df610a7c18
commit 4a58ebf487
6 changed files with 112 additions and 63 deletions

View 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 */

View 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;

View 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);

View 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);

View 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

View 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;
}