diff --git a/sys/osxaudio/gstosxaudiosrc.c b/sys/osxaudio/gstosxaudiosrc.c index b0be5f1111..a32ccca05d 100644 --- a/sys/osxaudio/gstosxaudiosrc.c +++ b/sys/osxaudio/gstosxaudiosrc.c @@ -177,7 +177,7 @@ gst_osx_audio_src_init (GstOsxAudioSrc * src) gst_base_src_set_live (GST_BASE_SRC (src), TRUE); src->device_id = kAudioDeviceUnknown; - src->deviceChannels = -1; + src->cached_caps = NULL; } static void @@ -250,6 +250,7 @@ gst_osx_audio_src_probe_caps (GstOsxAudioSrc * osxsrc) GstOsxAudioRingBuffer *ringbuffer = GST_OSX_AUDIO_RING_BUFFER (GST_AUDIO_BASE_SRC (osxsrc)->ringbuffer); GstCoreAudio *core_audio = ringbuffer->core_audio; + GstCaps *caps; AudioStreamBasicDescription asbd_in; UInt32 propertySize; OSStatus status; @@ -258,15 +259,27 @@ gst_osx_audio_src_probe_caps (GstOsxAudioSrc * osxsrc) status = AudioUnitGetProperty (core_audio->audiounit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &asbd_in, &propertySize); + if (status) + goto fail; - if (status) { - AudioComponentInstanceDispose (core_audio->audiounit); - core_audio->audiounit = NULL; - GST_WARNING_OBJECT (core_audio, - "Unable to obtain device properties: %d", (int) status); - } else { - osxsrc->deviceChannels = asbd_in.mChannelsPerFrame; - } + caps = gst_core_audio_asbd_to_caps (&asbd_in); + if (!caps) + GST_WARNING_OBJECT (osxsrc, "Could not get caps from stream description"); + else + GST_DEBUG_OBJECT (osxsrc, "Got caps on device: %p", caps); + + if (osxsrc->cached_caps) + gst_caps_unref (osxsrc->cached_caps); + + osxsrc->cached_caps = caps; + + return; + +fail: + AudioComponentInstanceDispose (core_audio->audiounit); + core_audio->audiounit = NULL; + GST_WARNING_OBJECT (osxsrc, + "Unable to obtain device properties: %d", (int) status); } static GstCaps * @@ -275,9 +288,7 @@ gst_osx_audio_src_get_caps (GstBaseSrc * src, GstCaps * filter) GstElementClass *gstelement_class; GstOsxAudioSrc *osxsrc; GstAudioRingBuffer *buf; - GstPadTemplate *pad_template; - GstCaps *caps; - gint min, max; + GstCaps *ret = NULL; gstelement_class = GST_ELEMENT_GET_CLASS (src); osxsrc = GST_OSX_AUDIO_SRC (src); @@ -285,38 +296,34 @@ gst_osx_audio_src_get_caps (GstBaseSrc * src, GstCaps * filter) if (buf) { GST_OBJECT_LOCK (buf); - if (buf->open && osxsrc->deviceChannels == -1) { + + if (buf->acquired) { + /* Caps are fixed, use what we have */ + ret = gst_pad_get_current_caps (GST_BASE_SINK_PAD (src)); + if (!ret) { + GST_OBJECT_UNLOCK (buf); + g_return_val_if_reached (NULL); + } + + } else if (buf->open && !osxsrc->cached_caps) { /* Device is open, let's probe its caps */ gst_osx_audio_src_probe_caps (osxsrc); } + GST_OBJECT_UNLOCK (buf); } - if (osxsrc->deviceChannels == -1) { - /* -1 means we don't know the number of channels yet. for now, return - * template caps. - */ - return NULL; + if (!ret && osxsrc->cached_caps) + ret = gst_caps_ref (osxsrc->cached_caps); + + if (filter) { + GstCaps *tmp; + tmp = gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (ret); + ret = tmp; } - max = osxsrc->deviceChannels; - if (max < 1) - max = 1; /* 0 channels means 1 channel? */ - - min = MIN (1, max); - - pad_template = gst_element_class_get_pad_template (gstelement_class, "src"); - g_return_val_if_fail (pad_template != NULL, NULL); - - caps = gst_caps_copy (gst_pad_template_get_caps (pad_template)); - - if (min == max) { - gst_caps_set_simple (caps, "channels", G_TYPE_INT, max, NULL); - } else { - gst_caps_set_simple (caps, "channels", GST_TYPE_INT_RANGE, min, max, NULL); - } - - return caps; + return ret; } static GstAudioRingBuffer * diff --git a/sys/osxaudio/gstosxaudiosrc.h b/sys/osxaudio/gstosxaudiosrc.h index a5f5d84117..163303c464 100644 --- a/sys/osxaudio/gstosxaudiosrc.h +++ b/sys/osxaudio/gstosxaudiosrc.h @@ -67,8 +67,7 @@ struct _GstOsxAudioSrc AudioDeviceID device_id; - /* actual number of channels reported by input device */ - int deviceChannels; + GstCaps *cached_caps; }; struct _GstOsxAudioSrcClass diff --git a/sys/osxaudio/gstosxcoreaudio.c b/sys/osxaudio/gstosxcoreaudio.c index 19c0d44765..d99ff291ef 100644 --- a/sys/osxaudio/gstosxcoreaudio.c +++ b/sys/osxaudio/gstosxcoreaudio.c @@ -184,3 +184,73 @@ gst_core_audio_audio_device_is_spdif_avail (AudioDeviceID device_id) { return gst_core_audio_audio_device_is_spdif_avail_impl (device_id); } + +GstCaps * +gst_core_audio_asbd_to_caps (AudioStreamBasicDescription * asbd) +{ + GstAudioInfo info; + GstAudioFormat format = GST_AUDIO_FORMAT_UNKNOWN; + int rate, channels, bps, endianness; + gboolean sign, interleaved; + + if (asbd->mFormatID != kAudioFormatLinearPCM) { + GST_WARNING ("Only linear PCM is supported"); + goto error; + } + + if (!(asbd->mFormatFlags & kAudioFormatFlagIsPacked)) { + GST_WARNING ("Only packed formats supported"); + goto error; + } + + if (asbd->mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask) { + GST_WARNING ("Fixed point audio is unsupported"); + goto error; + } + + rate = asbd->mSampleRate; + if (rate == kAudioStreamAnyRate) + rate = GST_AUDIO_DEF_RATE; + + channels = asbd->mChannelsPerFrame; + if (channels == 0) { + /* The documentation says this should not happen! */ + channels = 1; + } + + bps = asbd->mBitsPerChannel; + endianness = asbd->mFormatFlags & kAudioFormatFlagIsBigEndian ? + G_BIG_ENDIAN : G_LITTLE_ENDIAN; + sign = asbd->mFormatID & kAudioFormatFlagIsSignedInteger ? TRUE : FALSE; + interleaved = asbd->mFormatFlags & kAudioFormatFlagIsNonInterleaved ? + TRUE : FALSE; + + if (asbd->mFormatFlags & kAudioFormatFlagIsFloat) { + if (bps == 32) { + if (endianness == G_LITTLE_ENDIAN) + format = GST_AUDIO_FORMAT_F32LE; + else + format = GST_AUDIO_FORMAT_F32BE; + + } else if (bps == 64) { + if (endianness == G_LITTLE_ENDIAN) + format = GST_AUDIO_FORMAT_F64LE; + else + format = GST_AUDIO_FORMAT_F64BE; + } + } else { + format = gst_audio_format_build_integer (sign, endianness, bps, bps); + } + + if (format == GST_AUDIO_FORMAT_UNKNOWN) { + GST_WARNING ("Unsupported sample format"); + goto error; + } + + gst_audio_info_set_format (&info, format, rate, channels, NULL); + + return gst_audio_info_to_caps (&info); + +error: + return NULL; +} diff --git a/sys/osxaudio/gstosxcoreaudio.h b/sys/osxaudio/gstosxcoreaudio.h index b1f7a285b0..39670f49e9 100644 --- a/sys/osxaudio/gstosxcoreaudio.h +++ b/sys/osxaudio/gstosxcoreaudio.h @@ -143,6 +143,7 @@ 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); G_END_DECLS