Tidy up locking usage around FFTW.

* Move QMutex into the class instead of static.
* Use QMutexLocker
* Only lock around FFTW plan & destroy functions.
This commit is contained in:
John Maguire 2014-12-10 18:53:10 +01:00
parent fdd669360f
commit fb5181a6e9
2 changed files with 29 additions and 22 deletions

View File

@ -19,10 +19,12 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
#include <QMutex>
#include <cstring> #include <cstring>
#include <cmath> #include <cmath>
#include <QMutex>
#include <QMutexLocker>
#include "gstfastspectrum.h" #include "gstfastspectrum.h"
GST_DEBUG_CATEGORY_STATIC (gst_fastspectrum_debug); GST_DEBUG_CATEGORY_STATIC (gst_fastspectrum_debug);
@ -50,8 +52,6 @@ enum {
PROP_BANDS PROP_BANDS
}; };
static QMutex fftw_mutex;
#define gst_fastspectrum_parent_class parent_class #define gst_fastspectrum_parent_class parent_class
G_DEFINE_TYPE (GstFastSpectrum, gst_fastspectrum, GST_TYPE_AUDIO_FILTER); G_DEFINE_TYPE (GstFastSpectrum, gst_fastspectrum, GST_TYPE_AUDIO_FILTER);
@ -111,6 +111,8 @@ gst_fastspectrum_class_init (GstFastSpectrumClass * klass)
caps = gst_caps_from_string (ALLOWED_CAPS); caps = gst_caps_from_string (ALLOWED_CAPS);
gst_audio_filter_class_add_pad_templates (filter_class, caps); gst_audio_filter_class_add_pad_templates (filter_class, caps);
gst_caps_unref (caps); gst_caps_unref (caps);
klass->fftw_lock = new QMutex;
} }
static void static void
@ -127,8 +129,6 @@ gst_fastspectrum_init (GstFastSpectrum * spectrum)
static void static void
gst_fastspectrum_alloc_channel_data (GstFastSpectrum * spectrum) gst_fastspectrum_alloc_channel_data (GstFastSpectrum * spectrum)
{ {
fftw_mutex.lock();
guint bands = spectrum->bands; guint bands = spectrum->bands;
guint nfft = 2 * bands - 2; guint nfft = 2 * bands - 2;
@ -139,31 +139,36 @@ gst_fastspectrum_alloc_channel_data (GstFastSpectrum * spectrum)
fftw_malloc(sizeof(fftw_complex) * (nfft/2+1))); fftw_malloc(sizeof(fftw_complex) * (nfft/2+1)));
spectrum->spect_magnitude = new double[bands]; spectrum->spect_magnitude = new double[bands];
spectrum->plan = fftw_plan_dft_r2c_1d(
nfft,
spectrum->fft_input,
spectrum->fft_output,
FFTW_ESTIMATE);
spectrum->channel_data_initialised = true;
fftw_mutex.unlock(); GstFastSpectrumClass* klass = reinterpret_cast<GstFastSpectrumClass*>(
G_OBJECT_GET_CLASS(spectrum));
{
QMutexLocker l(klass->fftw_lock);
spectrum->plan = fftw_plan_dft_r2c_1d(
nfft,
spectrum->fft_input,
spectrum->fft_output,
FFTW_ESTIMATE);
}
spectrum->channel_data_initialised = true;
} }
static void static void
gst_fastspectrum_free_channel_data (GstFastSpectrum * spectrum) gst_fastspectrum_free_channel_data (GstFastSpectrum * spectrum)
{ {
GstFastSpectrumClass* klass = reinterpret_cast<GstFastSpectrumClass*>(
G_OBJECT_GET_CLASS(spectrum));
if (spectrum->channel_data_initialised) { if (spectrum->channel_data_initialised) {
fftw_mutex.lock(); {
QMutexLocker l(klass->fftw_lock);
fftw_destroy_plan(spectrum->plan); fftw_destroy_plan(spectrum->plan);
}
fftw_free(spectrum->fft_input); fftw_free(spectrum->fft_input);
fftw_free(spectrum->fft_output); fftw_free(spectrum->fft_output);
delete[] spectrum->input_ring_buffer; delete[] spectrum->input_ring_buffer;
delete[] spectrum->spect_magnitude; delete[] spectrum->spect_magnitude;
spectrum->channel_data_initialised = false; spectrum->channel_data_initialised = false;
fftw_mutex.unlock();
} }
} }
@ -385,12 +390,11 @@ gst_fastspectrum_run_fft (GstFastSpectrum * spectrum, guint input_pos)
guint bands = spectrum->bands; guint bands = spectrum->bands;
guint nfft = 2 * bands - 2; guint nfft = 2 * bands - 2;
fftw_mutex.lock();
for (i = 0; i < nfft; i++) for (i = 0; i < nfft; i++)
spectrum->fft_input[i] = spectrum->fft_input[i] =
spectrum->input_ring_buffer[(input_pos + i) % nfft]; spectrum->input_ring_buffer[(input_pos + i) % nfft];
// Should be safe to execute the same plan multiple times in parallel.
fftw_execute(spectrum->plan); fftw_execute(spectrum->plan);
gdouble val; gdouble val;
@ -401,8 +405,6 @@ gst_fastspectrum_run_fft (GstFastSpectrum * spectrum, guint input_pos)
val /= nfft * nfft; val /= nfft * nfft;
spectrum->spect_magnitude[i] += val; spectrum->spect_magnitude[i] += val;
} }
fftw_mutex.unlock();
} }
static GstFlowReturn static GstFlowReturn

View File

@ -43,6 +43,8 @@ G_BEGIN_DECLS
#define GST_FASTSPECTRUM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_FASTSPECTRUM,GstFastSpectrumClass)) #define GST_FASTSPECTRUM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_FASTSPECTRUM,GstFastSpectrumClass))
#define GST_IS_FASTSPECTRUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_FASTSPECTRUM)) #define GST_IS_FASTSPECTRUM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_FASTSPECTRUM))
class QMutex;
typedef void (*GstFastSpectrumInputData)(const guint8* in, double* out, typedef void (*GstFastSpectrumInputData)(const guint8* in, double* out,
guint len, double max_value, guint op, guint nfft); guint len, double max_value, guint op, guint nfft);
@ -84,6 +86,9 @@ struct GstFastSpectrum {
struct GstFastSpectrumClass { struct GstFastSpectrumClass {
GstAudioFilterClass parent_class; GstAudioFilterClass parent_class;
// Static lock for creating & destroying FFTW plans.
QMutex* fftw_lock;
}; };
GType gst_fastspectrum_get_type (void); GType gst_fastspectrum_get_type (void);