diff --git a/ChangeLog b/ChangeLog index 75c7634d47..faaa4f1ecc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2008-08-26 Michael Smith + + * sys/osxaudio/Makefile.am: + * sys/osxaudio/gstosxaudio.c: + * sys/osxaudio/gstosxaudiosink.c: + * sys/osxaudio/gstosxaudiosink.h: + * sys/osxaudio/gstosxaudiosrc.c: + * sys/osxaudio/gstosxaudiosrc.h: + * sys/osxaudio/gstosxringbuffer.c: + * sys/osxaudio/gstosxringbuffer.h: + Rewrite caps setting and ring buffer initialisation. + Previously we never told CoreAudio what format we were going to send it, + so it only worked due to luck, and not at all on some hardware. + Now we explicitly advertise what formats the hardware supports, and then + configure the selected one correctly. + 2008-08-26 Stefan Kost * sys/v4l2/gstv4l2object.c: diff --git a/sys/osxaudio/Makefile.am b/sys/osxaudio/Makefile.am index 1b0e487573..8882dea2b8 100644 --- a/sys/osxaudio/Makefile.am +++ b/sys/osxaudio/Makefile.am @@ -3,7 +3,8 @@ plugin_LTLIBRARIES = libgstosxaudio.la libgstosxaudio_la_SOURCES = gstosxringbuffer.c \ gstosxaudioelement.c \ gstosxaudiosink.c \ - gstosxaudiosrc.c + gstosxaudiosrc.c \ + gstosxaudio.c libgstosxaudio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \ -Wno-deprecated-declarations diff --git a/sys/osxaudio/gstosxaudio.c b/sys/osxaudio/gstosxaudio.c index 8a79bed278..8923284263 100644 --- a/sys/osxaudio/gstosxaudio.c +++ b/sys/osxaudio/gstosxaudio.c @@ -1,6 +1,7 @@ /* GStreamer * Copyright (C) <1999> Erik Walthinsen - * Copyright (C) 2007 Pioneers of the Inevitable + * Copyright (C) 2007,2008 Pioneers of the Inevitable + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either @@ -16,7 +17,8 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * - * The development of this code was made possible due to the involvement of Pioneers of the * Inevitable, the creators of the Songbird Music player + * The development of this code was made possible due to the involvement of + * Pioneers of the Inevitable, the creators of the Songbird Music player * */ @@ -49,29 +51,20 @@ #include "gstosxaudioelement.h" #include "gstosxaudiosink.h" #include "gstosxaudiosrc.h" -extern gchar *__gst_osxaudio_plugin_dir; - -GST_DEBUG_CATEGORY (osxaudio_debug); static gboolean plugin_init (GstPlugin * plugin) { - if (!gst_library_load ("gstaudio")) - return FALSE; - - if (!gst_element_register (plugin, "osxaudiosink", GST_RANK_PRIMARY, - GST_TYPE_OSXAUDIOSINK)) { + if (!gst_element_register (plugin, "fixedosxaudiosink", GST_RANK_PRIMARY + 1, + GST_TYPE_OSX_AUDIO_SINK)) { return FALSE; } - if (!gst_element_register (plugin, "osxaudiosrc", GST_RANK_PRIMARY, - GST_TYPE_OSXAUDIOSRC)) { + if (!gst_element_register (plugin, "fixedosxaudiosrc", GST_RANK_PRIMARY + 1, + GST_TYPE_OSX_AUDIO_SRC)) { return FALSE; } - GST_DEBUG_CATEGORY_INIT (osxaudio_debug, "osx", 0, "OSX audio elements"); - - return TRUE; } diff --git a/sys/osxaudio/gstosxaudiosink.c b/sys/osxaudio/gstosxaudiosink.c index 222056c8a3..5f67bb7b02 100644 --- a/sys/osxaudio/gstosxaudiosink.c +++ b/sys/osxaudio/gstosxaudiosink.c @@ -41,8 +41,8 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * - * The development of this code was made possible due to the involvement of Pioneers of i - * the Inevitable, the creators of the Songbird Music player + * The development of this code was made possible due to the involvement of + * Pioneers of the Inevitable, the creators of the Songbird Music player. * */ @@ -65,6 +65,7 @@ #include #include +#include #include "gstosxaudiosink.h" #include "gstosxaudiosrc.h" @@ -99,7 +100,8 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", "endianness = (int) {" G_STRINGIFY (G_BYTE_ORDER) " }, " "signed = (boolean) { TRUE }, " "width = (int) 32, " - "depth = (int) 32, " "rate = (int) 44100, " "channels = (int) 2") + "depth = (int) 32, " + "rate = (int) [1, MAX], " "channels = (int) [1, 2]") ); static void gst_osx_audio_sink_set_property (GObject * object, guint prop_id, @@ -108,16 +110,16 @@ static void gst_osx_audio_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static GstCaps *gst_osx_audio_sink_getcaps (GstBaseSink * sink); - static GstRingBuffer *gst_osx_audio_sink_create_ringbuffer (GstBaseAudioSink * sink); -/*static GstCaps* gst_osx_audio_sink_getcaps (GstBaseSink * bsink);*/ static void gst_osx_audio_sink_osxelement_init (gpointer g_iface, gpointer iface_data); OSStatus gst_osx_audio_sink_io_proc (AudioDeviceID inDevice, const AudioTimeStamp * inNow, const AudioBufferList * inInputData, const AudioTimeStamp * inInputTime, AudioBufferList * outOutputData, const AudioTimeStamp * inOutputTime, void *inClientData); +static void gst_osx_audio_sink_select_device (GstOsxAudioSink * osxsink); + static void gst_osx_audio_sink_osxelement_do_init (GType type) { @@ -189,10 +191,10 @@ static void gst_osx_audio_sink_init (GstOsxAudioSink * sink, GstOsxAudioSinkClass * gclass) { /* GstElementClass *klass = GST_ELEMENT_GET_CLASS (sink); */ - sink->ringbuffer = NULL; GST_DEBUG ("Initialising object"); - gst_osx_audio_sink_create_ringbuffer (GST_BASE_AUDIO_SINK (sink)); + sink->device_id = kAudioDeviceUnknown; + sink->stream_id = kAudioStreamUnknown; } static void @@ -203,8 +205,7 @@ gst_osx_audio_sink_set_property (GObject * object, guint prop_id, switch (prop_id) { case ARG_DEVICE: - if (sink->ringbuffer) - sink->ringbuffer->device_id = g_value_get_int (value); + sink->device_id = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -217,14 +218,9 @@ gst_osx_audio_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstOsxAudioSink *sink = GST_OSX_AUDIO_SINK (object); - int val = 0; - switch (prop_id) { case ARG_DEVICE: - if (sink->ringbuffer) - val = sink->ringbuffer->device_id; - - g_value_set_int (value, val); + g_value_set_int (value, sink->device_id); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -238,32 +234,93 @@ gst_osx_audio_sink_get_property (GObject * object, guint prop_id, static GstCaps * gst_osx_audio_sink_getcaps (GstBaseSink * sink) { - GstCaps *caps; + GstCaps *caps = NULL; GstOsxAudioSink *osxsink; OSStatus status; - AudioValueRange rates[10]; + AudioValueRange *rates = NULL; UInt32 propertySize; int i; + gboolean foundFixedRate = FALSE; + GstStructure *structure; + GValue rate_v = { 0 }; + GValue rates_v = { 0 }; - propertySize = sizeof (AudioValueRange) * 9; osxsink = GST_OSX_AUDIO_SINK (sink); + gst_osx_audio_sink_select_device (osxsink); + + GST_DEBUG_OBJECT (osxsink, "Using device_id %d", (int) osxsink->device_id); + + status = AudioDeviceGetPropertyInfo (osxsink->device_id, 0, /* Master channel */ + FALSE, /* isInput */ + kAudioDevicePropertyAvailableNominalSampleRates, &propertySize, NULL); + + if (status) { + GST_WARNING_OBJECT (osxsink, "Failed to get sample rates size: %ld", + status); + goto done; + } + + GST_DEBUG_OBJECT (osxsink, "Allocating %d bytes for sizes", + (int) propertySize); + rates = g_malloc (propertySize); + + status = AudioDeviceGetProperty (osxsink->device_id, 0, /* Master channel */ + FALSE, /* isInput */ + kAudioDevicePropertyAvailableNominalSampleRates, &propertySize, rates); + + if (status) { + GST_WARNING_OBJECT (osxsink, "Failed to get sample rates: %ld", status); + goto done; + } + + GST_DEBUG_OBJECT (osxsink, "Used %d bytes for sizes", (int) propertySize); + + if (propertySize < sizeof (AudioValueRange)) { + GST_WARNING_OBJECT (osxsink, "Zero sample rates available"); + goto done; + } + + /* Create base caps object, then modify to suit. */ caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (sink))); - - - status = AudioDeviceGetProperty (osxsink->ringbuffer->device_id, 0, FALSE, - kAudioDevicePropertyAvailableNominalSampleRates, &propertySize, &rates); + structure = gst_caps_get_structure (caps, 0); GST_DEBUG ("Getting available sample rates: Status: %ld number of ranges: %lu", status, propertySize / sizeof (AudioValueRange)); + g_value_init (&rates_v, GST_TYPE_LIST); + g_value_init (&rate_v, G_TYPE_INT); + for (i = 0; i < propertySize / sizeof (AudioValueRange); i++) { GST_LOG_OBJECT (osxsink, "Range from %f to %f", rates[i].mMinimum, rates[i].mMaximum); + if (rates[i].mMinimum == rates[i].mMaximum) { + /* For now, we only support these in this form. If there are none + * in this form, we use the first (only) as a range. */ + foundFixedRate = TRUE; + + g_value_set_int (&rate_v, rates[i].mMinimum); + gst_value_list_append_value (&rates_v, &rate_v); + } } + g_value_unset (&rate_v); + + if (foundFixedRate) { + gst_structure_set_value (structure, "rate", &rates_v); + } else { + gst_structure_set (structure, "rate", GST_TYPE_INT_RANGE, + rates[0].mMinimum, rates[0].mMaximum, NULL); + } + + g_value_unset (&rates_v); + +done: + if (rates) + g_free (rates); + return caps; } @@ -272,19 +329,22 @@ static GstRingBuffer * gst_osx_audio_sink_create_ringbuffer (GstBaseAudioSink * sink) { GstOsxAudioSink *osxsink; + GstOsxRingBuffer *ringbuffer; osxsink = GST_OSX_AUDIO_SINK (sink); - if (!osxsink->ringbuffer) { - GST_DEBUG ("Creating ringbuffer"); - osxsink->ringbuffer = g_object_new (GST_TYPE_OSX_RING_BUFFER, NULL); - GST_DEBUG ("osx sink 0x%p element 0x%p ioproc 0x%p", osxsink, - GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink), - (void *) gst_osx_audio_sink_io_proc); - osxsink->ringbuffer->element = - GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink); - } - return GST_RING_BUFFER (osxsink->ringbuffer); + gst_osx_audio_sink_select_device (osxsink); + + GST_DEBUG ("Creating ringbuffer"); + ringbuffer = g_object_new (GST_TYPE_OSX_RING_BUFFER, NULL); + GST_DEBUG ("osx sink 0x%p element 0x%p ioproc 0x%p", osxsink, + GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink), + (void *) gst_osx_audio_sink_io_proc); + ringbuffer->element = GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink); + ringbuffer->device_id = osxsink->device_id; + ringbuffer->stream_id = osxsink->stream_id; + + return GST_RING_BUFFER (ringbuffer); } OSStatus @@ -321,31 +381,73 @@ gst_osx_audio_sink_osxelement_init (gpointer g_iface, gpointer iface_data) iface->io_proc = gst_osx_audio_sink_io_proc; } -/* entry point to initialize the plug-in - * initialize the plug-in itself - * register the element factories and pad templates - * register the features - * - * exchange the string 'plugin' with your elemnt name - */ -static gboolean -plugin_init (GstPlugin * plugin) + +static void +gst_osx_audio_sink_select_device (GstOsxAudioSink * osxsink) { - gboolean ret; + OSStatus status; + UInt32 propertySize; - ret = gst_element_register (plugin, "osxaudiosink", - GST_RANK_PRIMARY, GST_TYPE_OSX_AUDIO_SINK); - return ret && gst_element_register (plugin, "osxaudiosrc", - GST_RANK_PRIMARY, GST_TYPE_OSX_AUDIO_SRC); + if (osxsink->device_id == kAudioDeviceUnknown) { + GST_DEBUG_OBJECT (osxsink, "Selecting device for OSXAudioSink"); + propertySize = sizeof (osxsink->device_id); + status = + AudioHardwareGetProperty (kAudioHardwarePropertyDefaultOutputDevice, + &propertySize, &osxsink->device_id); + + if (status) + GST_WARNING_OBJECT (osxsink, + "AudioHardwareGetProperty returned %d", (int) status); + else + GST_DEBUG_OBJECT (osxsink, "AudioHardwareGetProperty returned 0"); + + if (osxsink->device_id == kAudioDeviceUnknown) + GST_WARNING_OBJECT (osxsink, + "AudioHardwareGetProperty: device_id is kAudioDeviceUnknown"); + + GST_DEBUG_OBJECT (osxsink, "AudioHardwareGetProperty: device_id is %lu", + (long) osxsink->device_id); + } + + if (osxsink->stream_id == kAudioStreamUnknown) { + AudioStreamID *streams; + + GST_DEBUG_OBJECT (osxsink, "Getting streamid"); + status = AudioDeviceGetPropertyInfo (osxsink->device_id, 0, /* Master channel */ + FALSE, /* isInput */ + kAudioDevicePropertyStreams, &propertySize, NULL); + + if (status) { + GST_WARNING_OBJECT (osxsink, + "AudioDeviceGetProperty returned %d", (int) status); + return; + } + + GST_DEBUG_OBJECT (osxsink, + "Getting available streamids from %d (%d bytes)", + (int) (propertySize / sizeof (AudioStreamID)), propertySize); + streams = g_malloc (propertySize); + status = AudioDeviceGetProperty (osxsink->device_id, 0, /* Master channel */ + FALSE, /* isInput */ + kAudioDevicePropertyStreams, &propertySize, streams); + + if (status) { + GST_WARNING_OBJECT (osxsink, + "AudioDeviceGetProperty returned %d", (int) status); + g_free (streams); + return; + } + + GST_DEBUG_OBJECT (osxsink, "Getting streamid from %d (%d bytes)", + (int) (propertySize / sizeof (AudioStreamID)), propertySize); + + if (propertySize >= sizeof (AudioStreamID)) { + osxsink->stream_id = streams[0]; + GST_DEBUG_OBJECT (osxsink, "Selected stream %d of %d: %d", 0, + (int) (propertySize / sizeof (AudioStreamID)), + (int) osxsink->stream_id); + } + + g_free (streams); + } } - -/* this is the structure that gstreamer looks for to register plugins - * - * exchange the strings 'plugin' and 'Template plugin' with you plugin name and - * description - */ -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "osxaudio", - "OSX Audio plugin", - plugin_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/") diff --git a/sys/osxaudio/gstosxaudiosink.h b/sys/osxaudio/gstosxaudiosink.h index ba71c11d6a..a46d244895 100644 --- a/sys/osxaudio/gstosxaudiosink.h +++ b/sys/osxaudio/gstosxaudiosink.h @@ -71,7 +71,8 @@ struct _GstOsxAudioSink { GstBaseAudioSink sink; - GstOsxRingBuffer *ringbuffer; + AudioDeviceID device_id; + AudioStreamID stream_id; }; struct _GstOsxAudioSinkClass diff --git a/sys/osxaudio/gstosxaudiosrc.c b/sys/osxaudio/gstosxaudiosrc.c index 0a543ae5ae..359eb7a745 100644 --- a/sys/osxaudio/gstosxaudiosrc.c +++ b/sys/osxaudio/gstosxaudiosrc.c @@ -1,6 +1,7 @@ /* * GStreamer * Copyright 2005,2006 Zaheer Abbas Merali + * 2008 Pioneers of the Inevitable * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -92,7 +93,8 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", "endianness = (int) {" G_STRINGIFY (G_BYTE_ORDER) " }, " "signed = (boolean) { TRUE }, " "width = (int) 32, " - "depth = (int) 32, " "rate = (int) 44100, " "channels = (int) 2") + "depth = (int) 32, " + "rate = (int) [1, MAX], " "channels = (int) [1, 2]") ); static void gst_osx_audio_src_set_property (GObject * object, guint prop_id, @@ -103,13 +105,13 @@ static void gst_osx_audio_src_get_property (GObject * object, guint prop_id, static GstRingBuffer *gst_osx_audio_src_create_ringbuffer (GstBaseAudioSrc * src); -/*static GstCaps* gst_osx_audio_sink_getcaps (GstBaseSink * bsrc);*/ static void gst_osx_audio_src_osxelement_init (gpointer g_iface, gpointer iface_data); OSStatus gst_osx_audio_src_io_proc (AudioDeviceID inDevice, const AudioTimeStamp * inNow, const AudioBufferList * inInputData, const AudioTimeStamp * inInputTime, AudioBufferList * outOutputData, const AudioTimeStamp * inOutputTime, void *inClientData); +static void gst_osx_audio_src_select_device (GstOsxAudioSrc * osxsrc); static void gst_osx_audio_src_osxelement_do_init (GType type) @@ -178,11 +180,11 @@ gst_osx_audio_src_class_init (GstOsxAudioSrcClass * klass) static void gst_osx_audio_src_init (GstOsxAudioSrc * src, GstOsxAudioSrcClass * gclass) { -/* GstElementClass *klass = GST_ELEMENT_GET_CLASS (sink); */ +/* GstElementClass *klass = GST_ELEMENT_GET_CLASS (src); */ gst_base_src_set_live (GST_BASE_SRC (src), TRUE); - src->ringbuffer = NULL; - GST_DEBUG ("Initialising object"); - gst_osx_audio_src_create_ringbuffer (GST_BASE_AUDIO_SRC (src)); + + src->device_id = kAudioDeviceUnknown; + src->stream_id = kAudioStreamUnknown; } static void @@ -193,8 +195,7 @@ gst_osx_audio_src_set_property (GObject * object, guint prop_id, switch (prop_id) { case ARG_DEVICE: - if (src->ringbuffer) - src->ringbuffer->device_id = g_value_get_int (value); + src->device_id = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -207,14 +208,10 @@ gst_osx_audio_src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstOsxAudioSrc *src = GST_OSX_AUDIO_SRC (object); - int val = 0; switch (prop_id) { case ARG_DEVICE: - if (src->ringbuffer) - val = src->ringbuffer->device_id; - - g_value_set_int (value, val); + g_value_set_int (value, src->device_id); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -225,29 +222,32 @@ gst_osx_audio_src_get_property (GObject * object, guint prop_id, /* GstElement vmethod implementations */ -/* GstBaseAudioSink vmethod implementations */ +/* GstBaseAudioSrc vmethod implementations */ static GstRingBuffer * gst_osx_audio_src_create_ringbuffer (GstBaseAudioSrc * src) { GstOsxAudioSrc *osxsrc; OSStatus status; UInt32 propertySize; + GstOsxRingBuffer *ringbuffer; osxsrc = GST_OSX_AUDIO_SRC (src); - if (!osxsrc->ringbuffer) { - GST_DEBUG ("Creating ringbuffer"); - osxsrc->ringbuffer = g_object_new (GST_TYPE_OSX_RING_BUFFER, NULL); - /* change the device to the Default Input Device */ - propertySize = sizeof (osxsrc->ringbuffer->device_id); - status = AudioHardwareGetProperty (kAudioHardwarePropertyDefaultInputDevice, - &propertySize, &osxsrc->ringbuffer->device_id); - GST_DEBUG ("osx src 0x%p element 0x%p ioproc 0x%p", osxsrc, - GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc), - (void *) gst_osx_audio_src_io_proc); - osxsrc->ringbuffer->element = GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc); - } - return GST_RING_BUFFER (osxsrc->ringbuffer); + gst_osx_audio_src_select_device (osxsrc); + + GST_DEBUG ("Creating ringbuffer"); + ringbuffer = g_object_new (GST_TYPE_OSX_RING_BUFFER, NULL); + + /* change the device to the Default Input Device */ + GST_DEBUG ("osx src 0x%p element 0x%p ioproc 0x%p", osxsrc, + GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc), + (void *) gst_osx_audio_src_io_proc); + + ringbuffer->element = GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc); + ringbuffer->device_id = osxsrc->device_id; + ringbuffer->stream_id = osxsrc->stream_id; + + return GST_RING_BUFFER (ringbuffer); } OSStatus @@ -284,3 +284,72 @@ gst_osx_audio_src_osxelement_init (gpointer g_iface, gpointer iface_data) iface->io_proc = gst_osx_audio_src_io_proc; } + +static void +gst_osx_audio_src_select_device (GstOsxAudioSrc * osxsrc) +{ + OSStatus status; + UInt32 propertySize; + + if (osxsrc->device_id == kAudioDeviceUnknown) { + GST_DEBUG_OBJECT (osxsrc, "Selecting device for OSXAudioSrc"); + propertySize = sizeof (osxsrc->device_id); + status = AudioHardwareGetProperty (kAudioHardwarePropertyDefaultInputDevice, + &propertySize, &osxsrc->device_id); + + if (status) + GST_WARNING_OBJECT (osxsrc, + "AudioHardwareGetProperty returned %d", (int) status); + else + GST_DEBUG_OBJECT (osxsrc, "AudioHardwareGetProperty returned 0"); + + if (osxsrc->device_id == kAudioDeviceUnknown) + GST_WARNING_OBJECT (osxsrc, + "AudioHardwareGetProperty: device_id is kAudioDeviceUnknown"); + + GST_DEBUG_OBJECT (osxsrc, "AudioHardwareGetProperty: device_id is %lu", + (long) osxsrc->device_id); + } + + if (osxsrc->stream_id == kAudioStreamUnknown) { + AudioStreamID *streams; + + GST_DEBUG_OBJECT (osxsrc, "Getting streamid"); + status = AudioDeviceGetPropertyInfo (osxsrc->device_id, 0, /* Master channel */ + FALSE, /* isInput */ + kAudioDevicePropertyStreams, &propertySize, NULL); + + if (status) { + GST_WARNING_OBJECT (osxsrc, + "AudioDeviceGetProperty returned %d", (int) status); + return; + } + + GST_DEBUG_OBJECT (osxsrc, + "Getting available streamids from %d (%d bytes)", + (int) (propertySize / sizeof (AudioStreamID)), propertySize); + streams = g_malloc (propertySize); + status = AudioDeviceGetProperty (osxsrc->device_id, 0, /* Master channel */ + FALSE, /* isInput */ + kAudioDevicePropertyStreams, &propertySize, streams); + + if (status) { + GST_WARNING_OBJECT (osxsrc, + "AudioDeviceGetProperty returned %d", (int) status); + g_free (streams); + return; + } + + GST_DEBUG_OBJECT (osxsrc, "Getting streamid from %d (%d bytes)", + (int) (propertySize / sizeof (AudioStreamID)), propertySize); + + if (propertySize >= sizeof (AudioStreamID)) { + osxsrc->stream_id = streams[0]; + GST_DEBUG_OBJECT (osxsrc, "Selected stream %d of %d: %d", 0, + (int) (propertySize / sizeof (AudioStreamID)), + (int) osxsrc->stream_id); + } + + g_free (streams); + } +} diff --git a/sys/osxaudio/gstosxaudiosrc.h b/sys/osxaudio/gstosxaudiosrc.h index 93fc659f47..7336c82f19 100644 --- a/sys/osxaudio/gstosxaudiosrc.h +++ b/sys/osxaudio/gstosxaudiosrc.h @@ -65,7 +65,8 @@ struct _GstOsxAudioSrc { GstBaseAudioSrc src; - GstOsxRingBuffer *ringbuffer; + AudioDeviceID device_id; + AudioStreamID stream_id; }; struct _GstOsxAudioSrcClass diff --git a/sys/osxaudio/gstosxringbuffer.c b/sys/osxaudio/gstosxringbuffer.c index 428c3806b3..116893810d 100644 --- a/sys/osxaudio/gstosxringbuffer.c +++ b/sys/osxaudio/gstosxringbuffer.c @@ -137,37 +137,7 @@ static void gst_osx_ring_buffer_init (GstOsxRingBuffer * ringbuffer, GstOsxRingBufferClass * g_class) { - OSStatus status; - UInt32 propertySize; - - /* currently do bugger all */ - GST_DEBUG ("osx ring buffer init"); - propertySize = sizeof (ringbuffer->device_id); - status = - AudioHardwareGetProperty (kAudioHardwarePropertyDefaultOutputDevice, - &propertySize, &(ringbuffer->device_id)); - GST_DEBUG ("osx ring buffer called AudioHardwareGetProperty"); - if (status) { - GST_WARNING ("AudioHardwareGetProperty returned %d", (int) status); - } else { - GST_DEBUG ("AudioHardwareGetProperty returned 0"); - } - if (ringbuffer->device_id == kAudioDeviceUnknown) { - GST_DEBUG ("AudioHardwareGetProperty: device_id is kAudioDeviceUnknown"); - } - GST_DEBUG ("AudioHardwareGetProperty: device_id is %lu", - ringbuffer->device_id); - /* get requested buffer length */ - propertySize = sizeof (ringbuffer->buffer_len); - status = - AudioDeviceGetProperty (ringbuffer->device_id, 0, false, - kAudioDevicePropertyBufferSize, &propertySize, &ringbuffer->buffer_len); - if (status) { - GST_WARNING - ("AudioDeviceGetProperty returned %d when getting kAudioDevicePropertyBufferSize", - (int) status); - } - GST_DEBUG ("%5d ringbuffer->buffer_len", (int) ringbuffer->buffer_len); + /* Nothing to do right now */ } static void @@ -199,15 +169,65 @@ gst_osx_ring_buffer_close_device (GstRingBuffer * buf) static gboolean gst_osx_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) { - /* stub, we need to allocate ringbuffer memory */ + /* Configure the output stream and allocate ringbuffer memory */ GstOsxRingBuffer *osxbuf; + AudioStreamBasicDescription asbd; + AudioStreamBasicDescription asbd2; + OSStatus status; + UInt32 buffer_len; + UInt32 propertySize; osxbuf = GST_OSX_RING_BUFFER (buf); - spec->segsize = osxbuf->buffer_len; + /* Fill out the audio description we're going to be using */ + asbd.mFormatID = kAudioFormatLinearPCM; + asbd.mSampleRate = (double) spec->rate; + asbd.mChannelsPerFrame = spec->channels; + asbd.mFormatFlags = kAudioFormatFlagsNativeFloatPacked; + asbd.mBytesPerFrame = spec->channels * sizeof (float); + asbd.mBitsPerChannel = sizeof (float) * 8; + asbd.mBytesPerPacket = spec->channels * sizeof (float); + asbd.mFramesPerPacket = 1; + asbd.mReserved = 0; + + GST_LOG_OBJECT (osxbuf, "Format: %x, %f, %d, %x, %d, %d, %d, %d, %d", + asbd.mFormatID, + asbd.mSampleRate, + asbd.mChannelsPerFrame, + asbd.mFormatFlags, + asbd.mBytesPerFrame, + asbd.mBitsPerChannel, + asbd.mBytesPerPacket, asbd.mFramesPerPacket, asbd.mReserved); + + GST_DEBUG_OBJECT (osxbuf, "Using stream_id %d, setting output format", + (int) osxbuf->stream_id); + + propertySize = sizeof (asbd); + status = AudioStreamSetProperty (osxbuf->stream_id, NULL, /* Change immediately */ + 0, /* Master channel */ + kAudioStreamPropertyVirtualFormat, propertySize, &asbd); + + if (status) { + GST_WARNING_OBJECT (osxbuf, "Failed to set output description: %lx", + status); + return FALSE; + } + + /* get requested buffer length to use */ + propertySize = sizeof (buffer_len); + status = AudioDeviceGetProperty (osxbuf->device_id, 0, false, /* TODO, this should be true for the source element */ + kAudioDevicePropertyBufferSize, &propertySize, &buffer_len); + + if (status) { + GST_WARNING_OBJECT (osxbuf, + "AudioDeviceGetProperty returned %d when getting " + "kAudioDevicePropertyBufferSize", (int) status); + } + GST_DEBUG_OBJECT (osxbuf, "%5d osxbuf->buffer_len", (int) buffer_len); + spec->segsize = buffer_len; spec->segtotal = 16; - GST_DEBUG ("osx ring buffer acquire"); + GST_DEBUG_OBJECT (osxbuf, "osx ring buffer acquired"); buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize); memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data)); diff --git a/sys/osxaudio/gstosxringbuffer.h b/sys/osxaudio/gstosxringbuffer.h index bc8d552450..40a299ff4a 100644 --- a/sys/osxaudio/gstosxringbuffer.h +++ b/sys/osxaudio/gstosxringbuffer.h @@ -67,6 +67,7 @@ struct _GstOsxRingBuffer { GstRingBuffer object; AudioDeviceID device_id; + AudioStreamID stream_id; gboolean io_proc_active; guint buffer_len; GstOsxAudioElementInterface* element;