mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-05 10:12:20 +00:00
osxaudiosrc: Implement caps probing
https://bugzilla.gnome.org/show_bug.cgi?id=740987
This commit is contained in:
parent
48872dbc56
commit
bd1502862c
4 changed files with 115 additions and 38 deletions
|
@ -177,7 +177,7 @@ gst_osx_audio_src_init (GstOsxAudioSrc * src)
|
||||||
gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
|
gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
|
||||||
|
|
||||||
src->device_id = kAudioDeviceUnknown;
|
src->device_id = kAudioDeviceUnknown;
|
||||||
src->deviceChannels = -1;
|
src->cached_caps = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -250,6 +250,7 @@ gst_osx_audio_src_probe_caps (GstOsxAudioSrc * osxsrc)
|
||||||
GstOsxAudioRingBuffer *ringbuffer =
|
GstOsxAudioRingBuffer *ringbuffer =
|
||||||
GST_OSX_AUDIO_RING_BUFFER (GST_AUDIO_BASE_SRC (osxsrc)->ringbuffer);
|
GST_OSX_AUDIO_RING_BUFFER (GST_AUDIO_BASE_SRC (osxsrc)->ringbuffer);
|
||||||
GstCoreAudio *core_audio = ringbuffer->core_audio;
|
GstCoreAudio *core_audio = ringbuffer->core_audio;
|
||||||
|
GstCaps *caps;
|
||||||
AudioStreamBasicDescription asbd_in;
|
AudioStreamBasicDescription asbd_in;
|
||||||
UInt32 propertySize;
|
UInt32 propertySize;
|
||||||
OSStatus status;
|
OSStatus status;
|
||||||
|
@ -258,15 +259,27 @@ gst_osx_audio_src_probe_caps (GstOsxAudioSrc * osxsrc)
|
||||||
status = AudioUnitGetProperty (core_audio->audiounit,
|
status = AudioUnitGetProperty (core_audio->audiounit,
|
||||||
kAudioUnitProperty_StreamFormat,
|
kAudioUnitProperty_StreamFormat,
|
||||||
kAudioUnitScope_Input, 1, &asbd_in, &propertySize);
|
kAudioUnitScope_Input, 1, &asbd_in, &propertySize);
|
||||||
|
if (status)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
if (status) {
|
caps = gst_core_audio_asbd_to_caps (&asbd_in);
|
||||||
AudioComponentInstanceDispose (core_audio->audiounit);
|
if (!caps)
|
||||||
core_audio->audiounit = NULL;
|
GST_WARNING_OBJECT (osxsrc, "Could not get caps from stream description");
|
||||||
GST_WARNING_OBJECT (core_audio,
|
else
|
||||||
"Unable to obtain device properties: %d", (int) status);
|
GST_DEBUG_OBJECT (osxsrc, "Got caps on device: %p", caps);
|
||||||
} else {
|
|
||||||
osxsrc->deviceChannels = asbd_in.mChannelsPerFrame;
|
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 *
|
static GstCaps *
|
||||||
|
@ -275,9 +288,7 @@ gst_osx_audio_src_get_caps (GstBaseSrc * src, GstCaps * filter)
|
||||||
GstElementClass *gstelement_class;
|
GstElementClass *gstelement_class;
|
||||||
GstOsxAudioSrc *osxsrc;
|
GstOsxAudioSrc *osxsrc;
|
||||||
GstAudioRingBuffer *buf;
|
GstAudioRingBuffer *buf;
|
||||||
GstPadTemplate *pad_template;
|
GstCaps *ret = NULL;
|
||||||
GstCaps *caps;
|
|
||||||
gint min, max;
|
|
||||||
|
|
||||||
gstelement_class = GST_ELEMENT_GET_CLASS (src);
|
gstelement_class = GST_ELEMENT_GET_CLASS (src);
|
||||||
osxsrc = GST_OSX_AUDIO_SRC (src);
|
osxsrc = GST_OSX_AUDIO_SRC (src);
|
||||||
|
@ -285,38 +296,34 @@ gst_osx_audio_src_get_caps (GstBaseSrc * src, GstCaps * filter)
|
||||||
|
|
||||||
if (buf) {
|
if (buf) {
|
||||||
GST_OBJECT_LOCK (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 */
|
/* Device is open, let's probe its caps */
|
||||||
gst_osx_audio_src_probe_caps (osxsrc);
|
gst_osx_audio_src_probe_caps (osxsrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_OBJECT_UNLOCK (buf);
|
GST_OBJECT_UNLOCK (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (osxsrc->deviceChannels == -1) {
|
if (!ret && osxsrc->cached_caps)
|
||||||
/* -1 means we don't know the number of channels yet. for now, return
|
ret = gst_caps_ref (osxsrc->cached_caps);
|
||||||
* template caps.
|
|
||||||
*/
|
if (filter) {
|
||||||
return NULL;
|
GstCaps *tmp;
|
||||||
|
tmp = gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
|
||||||
|
gst_caps_unref (ret);
|
||||||
|
ret = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
max = osxsrc->deviceChannels;
|
return ret;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstAudioRingBuffer *
|
static GstAudioRingBuffer *
|
||||||
|
|
|
@ -67,8 +67,7 @@ struct _GstOsxAudioSrc
|
||||||
|
|
||||||
AudioDeviceID device_id;
|
AudioDeviceID device_id;
|
||||||
|
|
||||||
/* actual number of channels reported by input device */
|
GstCaps *cached_caps;
|
||||||
int deviceChannels;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstOsxAudioSrcClass
|
struct _GstOsxAudioSrcClass
|
||||||
|
|
|
@ -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);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue