From e7a69bb8de5bc81658ddfefbd8122df5e8b6f1c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 26 Mar 2013 15:22:16 +0100 Subject: [PATCH] wasapi: Initial port to 1.0 This should really use GstAudioSink and GstAudioSrc. --- configure.ac | 2 +- sys/wasapi/Makefile.am | 2 +- sys/wasapi/gstwasapi.c | 2 +- sys/wasapi/gstwasapisink.c | 67 +++++++++++++++------------- sys/wasapi/gstwasapisink.h | 2 - sys/wasapi/gstwasapisrc.c | 89 +++++++++++++++----------------------- sys/wasapi/gstwasapisrc.h | 2 - sys/wasapi/gstwasapiutil.c | 9 +++- sys/wasapi/gstwasapiutil.h | 1 + 9 files changed, 83 insertions(+), 93 deletions(-) diff --git a/configure.ac b/configure.ac index 31de789d48..b4cba5feb5 100644 --- a/configure.ac +++ b/configure.ac @@ -328,7 +328,7 @@ GST_PLUGINS_NONPORTED=" aiff \ gsettings ladspa \ musepack musicbrainz nas neon ofa openal rsvg sdl sndfile timidity \ directdraw direct3d9 acm wininet \ - xvid lv2 teletextdec sndio wasapi" + xvid lv2 teletextdec sndio" AC_SUBST(GST_PLUGINS_NONPORTED) dnl these are all the gst plug-ins, compilable without additional libs diff --git a/sys/wasapi/Makefile.am b/sys/wasapi/Makefile.am index 2f5f459803..93fa3a1ebd 100644 --- a/sys/wasapi/Makefile.am +++ b/sys/wasapi/Makefile.am @@ -7,7 +7,7 @@ libgstwasapi_la_SOURCES = gstwasapi.c \ libgstwasapi_la_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS) -DCOBJMACROS=1 libgstwasapi_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ - -lgstaudio-$(GST_MAJORMINOR) -lgstinterfaces-$(GST_MAJORMINOR) \ + -lgstaudio-$(GST_API_VERSION) \ $(WASAPI_LIBS) libgstwasapi_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstwasapi_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/sys/wasapi/gstwasapi.c b/sys/wasapi/gstwasapi.c index 9c901d08cc..920e2d0d96 100644 --- a/sys/wasapi/gstwasapi.c +++ b/sys/wasapi/gstwasapi.c @@ -42,4 +42,4 @@ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, wasapi, "Windows audio session API plugin", - plugin_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/") + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/sys/wasapi/gstwasapisink.c b/sys/wasapi/gstwasapisink.c index 193a608f1a..f16e611cfd 100644 --- a/sys/wasapi/gstwasapisink.c +++ b/sys/wasapi/gstwasapisink.c @@ -26,7 +26,7 @@ * * Example pipelines * |[ - * gst-launch-0.10 -v audiotestsrc samplesperbuffer=160 ! wasapisink + * gst-launch-1.0 -v audiotestsrc samplesperbuffer=160 ! wasapisink * ]| Generate 20 ms buffers and render to the default audio device. * */ @@ -42,13 +42,10 @@ GST_DEBUG_CATEGORY_STATIC (gst_wasapi_sink_debug); static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "width = (int) 16, " - "depth = (int) 16, " - "rate = (int) 8000, " - "channels = (int) 1, " - "signed = (boolean) TRUE, " - "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER))); + GST_STATIC_CAPS ("audio/x-raw, " + "format = (string) S16LE, " + "layout = (string) interleaved, " + "rate = (int) 8000, " "channels = (int) 1")); static void gst_wasapi_sink_dispose (GObject * object); static void gst_wasapi_sink_finalize (GObject * object); @@ -60,31 +57,25 @@ static gboolean gst_wasapi_sink_stop (GstBaseSink * sink); static GstFlowReturn gst_wasapi_sink_render (GstBaseSink * sink, GstBuffer * buffer); -GST_BOILERPLATE (GstWasapiSink, gst_wasapi_sink, GstBaseSink, - GST_TYPE_BASE_SINK); - -static void -gst_wasapi_sink_base_init (gpointer gclass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_template)); - gst_element_class_set_static_metadata (element_class, "WasapiSrc", - "Sink/Audio", - "Stream audio to an audio capture device through WASAPI", - "Ole André Vadla Ravnås "); -} +G_DEFINE_TYPE (GstWasapiSink, gst_wasapi_sink, GST_TYPE_BASE_SINK); static void gst_wasapi_sink_class_init (GstWasapiSinkClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass); gobject_class->dispose = gst_wasapi_sink_dispose; gobject_class->finalize = gst_wasapi_sink_finalize; + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sink_template)); + gst_element_class_set_static_metadata (gstelement_class, "WasapiSrc", + "Sink/Audio", + "Stream audio to an audio capture device through WASAPI", + "Ole André Vadla Ravnås "); + gstbasesink_class->get_times = gst_wasapi_sink_get_times; gstbasesink_class->start = gst_wasapi_sink_start; gstbasesink_class->stop = gst_wasapi_sink_stop; @@ -95,7 +86,7 @@ gst_wasapi_sink_class_init (GstWasapiSinkClass * klass) } static void -gst_wasapi_sink_init (GstWasapiSink * self, GstWasapiSinkClass * gclass) +gst_wasapi_sink_init (GstWasapiSink * self) { self->rate = 8000; self->buffer_time = 20 * GST_MSECOND; @@ -117,17 +108,15 @@ gst_wasapi_sink_dispose (GObject * object) self->event_handle = NULL; } - G_OBJECT_CLASS (parent_class)->dispose (object); + G_OBJECT_CLASS (gst_wasapi_sink_parent_class)->dispose (object); } static void gst_wasapi_sink_finalize (GObject * object) { - GstWasapiSink *self = GST_WASAPI_SINK (object); - CoUninitialize (); - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (gst_wasapi_sink_parent_class)->finalize (object); } static void @@ -171,7 +160,7 @@ gst_wasapi_sink_start (GstBaseSink * sink) } hr = IAudioClient_GetService (client, &IID_IAudioRenderClient, - &render_client); + (void **) &render_client); if (hr != S_OK) { GST_ERROR_OBJECT (self, "IAudioClient::GetService " "(IID_IAudioRenderClient) failed"); @@ -229,11 +218,23 @@ gst_wasapi_sink_render (GstBaseSink * sink, GstBuffer * buffer) GstWasapiSink *self = GST_WASAPI_SINK (sink); GstFlowReturn ret = GST_FLOW_OK; HRESULT hr; - gint16 *src = (gint16 *) GST_BUFFER_DATA (buffer); + GstMapInfo minfo; + const gint16 *src; gint16 *dst = NULL; - guint nsamples = GST_BUFFER_SIZE (buffer) / sizeof (gint16); + guint nsamples; guint i; + memset (&minfo, 0, sizeof (minfo)); + + if (!gst_buffer_map (buffer, &minfo, GST_MAP_READ)) { + GST_ELEMENT_ERROR (self, RESOURCE, WRITE, (NULL), + ("Failed to map input buffer")); + ret = GST_FLOW_ERROR; + goto beach; + } + + nsamples = minfo.size / sizeof (gint16); + WaitForSingleObject (self->event_handle, INFINITE); hr = IAudioRenderClient_GetBuffer (self->render_client, nsamples, @@ -246,6 +247,7 @@ gst_wasapi_sink_render (GstBaseSink * sink, GstBuffer * buffer) goto beach; } + src = (const gint16 *) minfo.data; for (i = 0; i < nsamples; i++) { dst[0] = *src; dst[1] = *src; @@ -263,5 +265,8 @@ gst_wasapi_sink_render (GstBaseSink * sink, GstBuffer * buffer) } beach: + if (minfo.data) + gst_buffer_unmap (buffer, &minfo); + return ret; } diff --git a/sys/wasapi/gstwasapisink.h b/sys/wasapi/gstwasapisink.h index bbdc85dff4..2c354917b3 100644 --- a/sys/wasapi/gstwasapisink.h +++ b/sys/wasapi/gstwasapisink.h @@ -22,8 +22,6 @@ #include "gstwasapiutil.h" -#include - G_BEGIN_DECLS #define GST_TYPE_WASAPI_SINK \ diff --git a/sys/wasapi/gstwasapisrc.c b/sys/wasapi/gstwasapisrc.c index e7e24e7101..3cee9cefe2 100644 --- a/sys/wasapi/gstwasapisrc.c +++ b/sys/wasapi/gstwasapisrc.c @@ -26,7 +26,7 @@ * * Example pipelines * |[ - * gst-launch-0.10 -v wasapisrc ! fakesink + * gst-launch-1.0 -v wasapisrc ! fakesink * ]| Capture from the default audio device and render to fakesink. * */ @@ -43,13 +43,10 @@ GST_DEBUG_CATEGORY_STATIC (gst_wasapi_src_debug); static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "width = (int) 16, " - "depth = (int) 16, " - "rate = (int) 8000, " - "channels = (int) 1, " - "signed = (boolean) TRUE, " - "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER))); + GST_STATIC_CAPS ("audio/x-raw, " + "format = (string) S16LE, " + "layout = (string) interleaved, " + "rate = (int) 8000, " "channels = (int) 1")); static void gst_wasapi_src_dispose (GObject * object); static void gst_wasapi_src_finalize (GObject * object); @@ -65,20 +62,7 @@ static GstFlowReturn gst_wasapi_src_create (GstPushSrc * src, GstBuffer ** buf); static GstClockTime gst_wasapi_src_get_time (GstClock * clock, gpointer user_data); -GST_BOILERPLATE (GstWasapiSrc, gst_wasapi_src, GstPushSrc, GST_TYPE_PUSH_SRC); - -static void -gst_wasapi_src_base_init (gpointer gclass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&src_template)); - gst_element_class_set_static_metadata (element_class, "WasapiSrc", - "Source/Audio", - "Stream audio from an audio capture device through WASAPI", - "Ole André Vadla Ravnås "); -} +G_DEFINE_TYPE (GstWasapiSrc, gst_wasapi_src, GST_TYPE_PUSH_SRC); static void gst_wasapi_src_class_init (GstWasapiSrcClass * klass) @@ -93,6 +77,13 @@ gst_wasapi_src_class_init (GstWasapiSrcClass * klass) gstelement_class->provide_clock = gst_wasapi_src_provide_clock; + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&src_template)); + gst_element_class_set_static_metadata (gstelement_class, "WasapiSrc", + "Source/Audio", + "Stream audio from an audio capture device through WASAPI", + "Ole André Vadla Ravnås "); + gstbasesrc_class->start = gst_wasapi_src_start; gstbasesrc_class->stop = gst_wasapi_src_stop; gstbasesrc_class->query = gst_wasapi_src_query; @@ -104,7 +95,7 @@ gst_wasapi_src_class_init (GstWasapiSrcClass * klass) } static void -gst_wasapi_src_init (GstWasapiSrc * self, GstWasapiSrcClass * gclass) +gst_wasapi_src_init (GstWasapiSrc * self) { GstBaseSrc *basesrc = GST_BASE_SRC (self); @@ -120,14 +111,9 @@ gst_wasapi_src_init (GstWasapiSrc * self, GstWasapiSrcClass * gclass) self->start_time = GST_CLOCK_TIME_NONE; self->next_time = GST_CLOCK_TIME_NONE; -#if GST_CHECK_VERSION(0, 10, 31) || (GST_CHECK_VERSION(0, 10, 30) && GST_VERSION_NANO > 0) - self->clock = gst_audio_clock_new_full ("GstWasapiSrcClock", + self->clock = gst_audio_clock_new ("GstWasapiSrcClock", gst_wasapi_src_get_time, gst_object_ref (self), (GDestroyNotify) gst_object_unref); -#else - self->clock = gst_audio_clock_new ("GstWasapiSrcClock", - gst_wasapi_src_get_time, self); -#endif CoInitialize (NULL); } @@ -142,17 +128,15 @@ gst_wasapi_src_dispose (GObject * object) self->clock = NULL; } - G_OBJECT_CLASS (parent_class)->dispose (object); + G_OBJECT_CLASS (gst_wasapi_src_parent_class)->dispose (object); } static void gst_wasapi_src_finalize (GObject * object) { - GstWasapiSrc *self = GST_WASAPI_SRC (object); - CoUninitialize (); - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (gst_wasapi_src_parent_class)->finalize (object); } static GstClock * @@ -196,7 +180,7 @@ gst_wasapi_src_start (GstBaseSrc * src) &self->latency)) goto beach; - hr = IAudioClient_GetService (client, &IID_IAudioClock, &client_clock); + hr = IAudioClient_GetService (client, &IID_IAudioClock, (void**) &client_clock); if (hr != S_OK) { GST_ERROR_OBJECT (self, "IAudioClient::GetService (IID_IAudioClock) " "failed"); @@ -210,7 +194,7 @@ gst_wasapi_src_start (GstBaseSrc * src) } hr = IAudioClient_GetService (client, &IID_IAudioCaptureClient, - &capture_client); + (void**) &capture_client); if (hr != S_OK) { GST_ERROR_OBJECT (self, "IAudioClient::GetService " "(IID_IAudioCaptureClient) failed"); @@ -298,7 +282,8 @@ gst_wasapi_src_query (GstBaseSrc * src, GstQuery * query) } default: - ret = GST_BASE_SRC_CLASS (parent_class)->query (src, query); + ret = + GST_BASE_SRC_CLASS (gst_wasapi_src_parent_class)->query (src, query); break; } @@ -317,6 +302,9 @@ gst_wasapi_src_create (GstPushSrc * src, GstBuffer ** buf) guint32 nsamples_read = 0, nsamples; DWORD flags = 0; guint64 devpos; + guint i; + GstMapInfo minfo; + gint16 *dst; GST_OBJECT_LOCK (self); clock = GST_ELEMENT_CLOCK (self); @@ -347,7 +335,7 @@ gst_wasapi_src_create (GstPushSrc * src, GstBuffer ** buf) if (flags != 0) { GST_WARNING_OBJECT (self, "devpos %" G_GUINT64_FORMAT ": flags=0x%08x", - devpos, flags); + devpos, (guint) flags); } /* FIXME: Why do we get 1024 sometimes and not a multiple of @@ -384,26 +372,21 @@ gst_wasapi_src_create (GstPushSrc * src, GstBuffer ** buf) timestamp = 0; } - ret = gst_pad_alloc_buffer_and_set_caps (GST_BASE_SRC_PAD (self), - devpos, - nsamples * sizeof (gint16), GST_PAD_CAPS (GST_BASE_SRC_PAD (self)), buf); + *buf = gst_buffer_new_and_alloc (nsamples * sizeof (gint16)); - if (ret == GST_FLOW_OK) { - guint i; - gint16 *dst; + GST_BUFFER_OFFSET_END (*buf) = devpos + self->samples_per_buffer; + GST_BUFFER_TIMESTAMP (*buf) = timestamp; + GST_BUFFER_DURATION (*buf) = duration; - GST_BUFFER_OFFSET_END (*buf) = devpos + self->samples_per_buffer; - GST_BUFFER_TIMESTAMP (*buf) = timestamp; - GST_BUFFER_DURATION (*buf) = duration; + gst_buffer_map (*buf, &minfo, GST_MAP_WRITE); + dst = (gint16 *) minfo.data; + for (i = 0; i < nsamples; i++) { + *dst = *samples; - dst = (gint16 *) GST_BUFFER_DATA (*buf); - for (i = 0; i < nsamples; i++) { - *dst = *samples; - - samples += 2; - dst++; - } + samples += 2; + dst++; } + gst_buffer_unmap (*buf, &minfo); hr = IAudioCaptureClient_ReleaseBuffer (self->capture_client, nsamples_read); if (hr != S_OK) { diff --git a/sys/wasapi/gstwasapisrc.h b/sys/wasapi/gstwasapisrc.h index 5b868c7660..0158d13273 100644 --- a/sys/wasapi/gstwasapisrc.h +++ b/sys/wasapi/gstwasapisrc.h @@ -22,8 +22,6 @@ #include "gstwasapiutil.h" -#include - G_BEGIN_DECLS #define GST_TYPE_WASAPI_SRC \ diff --git a/sys/wasapi/gstwasapiutil.c b/sys/wasapi/gstwasapiutil.c index ce6b440699..fa3e39bc4a 100644 --- a/sys/wasapi/gstwasapiutil.c +++ b/sys/wasapi/gstwasapiutil.c @@ -28,18 +28,23 @@ const CLSID CLSID_MMDeviceEnumerator = { 0xbcde0395, 0xe52f, 0x467c, {0x8e, 0x3d, 0xc4, 0x57, 0x92, 0x91, 0x69, 0x2e} }; + const IID IID_IMMDeviceEnumerator = { 0xa95664d2, 0x9614, 0x4f35, {0xa7, 0x46, 0xde, 0x8d, 0xb6, 0x36, 0x17, 0xe6} }; + const IID IID_IAudioClient = { 0x1cb9ad4c, 0xdbfa, 0x4c32, {0xb1, 0x78, 0xc2, 0xf5, 0x68, 0xa7, 0x03, 0xb2} }; + const IID IID_IAudioClock = { 0xcd63314f, 0x3fba, 0x4a1b, {0x81, 0x2c, 0xef, 0x96, 0x35, 0x87, 0x28, 0xe7} }; + const IID IID_IAudioCaptureClient = { 0xc8adbd64, 0xe71e, 0x48a0, {0xa4, 0xde, 0x18, 0x5c, 0x39, 0x5c, 0xd3, 0x17} }; + const IID IID_IAudioRenderClient = { 0xf294acfc, 0x3146, 0x4483, {0xa7, 0xbf, 0xad, 0xdc, 0xa7, 0xc2, 0x60, 0xe2} }; @@ -147,7 +152,7 @@ gst_wasapi_util_get_default_device_client (GstElement * element, WAVEFORMATEXTENSIBLE format; hr = CoCreateInstance (&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, - &IID_IMMDeviceEnumerator, &enumerator); + &IID_IMMDeviceEnumerator, (void **) &enumerator); if (hr != S_OK) { GST_ERROR_OBJECT (element, "CoCreateInstance (MMDeviceEnumerator) failed"); goto beach; @@ -162,7 +167,7 @@ gst_wasapi_util_get_default_device_client (GstElement * element, } hr = IMMDevice_Activate (device, &IID_IAudioClient, CLSCTX_ALL, NULL, - &client); + (void **) &client); if (hr != S_OK) { GST_ERROR_OBJECT (element, "IMMDevice::Activate (IID_IAudioClient) failed"); goto beach; diff --git a/sys/wasapi/gstwasapiutil.h b/sys/wasapi/gstwasapiutil.h index 7ddd81a5dd..b32b05cc73 100644 --- a/sys/wasapi/gstwasapiutil.h +++ b/sys/wasapi/gstwasapiutil.h @@ -21,6 +21,7 @@ #define __GST_WASAPI_UTIL_H__ #include +#include #include