changeset 1211:5a1198083d9a piper

Pull out model creation into the transformer thread run(), so that all communications with the plugin server happen on a single thread. Then make the model accessor wait for them to be created (which still happens right at the start of processing) before returning.
author Chris Cannam
date Mon, 17 Oct 2016 14:18:23 +0100 (2016-10-17)
parents 584b2d7d7cd9
children f80773b5ec96
files transform/FeatureExtractionModelTransformer.cpp transform/FeatureExtractionModelTransformer.h transform/ModelTransformer.h transform/RealTimeEffectModelTransformer.h
diffstat 4 files changed, 48 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/transform/FeatureExtractionModelTransformer.cpp	Fri Oct 14 16:23:04 2016 +0100
+++ b/transform/FeatureExtractionModelTransformer.cpp	Mon Oct 17 14:18:23 2016 +0100
@@ -42,17 +42,19 @@
 FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Input in,
                                                                      const Transform &transform) :
     ModelTransformer(in, transform),
-    m_plugin(0)
+    m_plugin(0),
+    m_haveOutputs(false)
 {
     SVDEBUG << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: plugin " << m_transforms.begin()->getPluginIdentifier() << ", outputName " << m_transforms.begin()->getOutput() << endl;
 
-    initialise();
+//    initialise();
 }
 
 FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Input in,
                                                                      const Transforms &transforms) :
     ModelTransformer(in, transforms),
-    m_plugin(0)
+    m_plugin(0),
+    m_haveOutputs(false)
 {
     if (m_transforms.empty()) {
         SVDEBUG << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: " << transforms.size() << " transform(s)" << endl;
@@ -60,7 +62,7 @@
         SVDEBUG << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: " << transforms.size() << " transform(s), first has plugin " << m_transforms.begin()->getPluginIdentifier() << ", outputName " << m_transforms.begin()->getOutput() << endl;
     }
     
-    initialise();
+//    initialise();
 }
 
 static bool
@@ -104,6 +106,9 @@
         return false;
     }
 
+    cerr << "instantiating plugin for transform in thread "
+         << QThread::currentThreadId() << endl;
+    
     m_plugin = factory->instantiatePlugin(pluginId, input->getSampleRate());
     if (!m_plugin) {
         m_message = tr("Failed to instantiate plugin \"%1\"").arg(pluginId);
@@ -220,6 +225,11 @@
         createOutputModels(j);
     }
 
+    m_outputMutex.lock();
+    m_haveOutputs = true;
+    m_outputsCondition.wakeAll();
+    m_outputMutex.unlock();
+
     return true;
 }
 
@@ -479,6 +489,16 @@
     }
 }
 
+void
+FeatureExtractionModelTransformer::awaitOutputModels()
+{
+    m_outputMutex.lock();
+    while (!m_haveOutputs) {
+        m_outputsCondition.wait(&m_outputMutex);
+    }
+    m_outputMutex.unlock();
+}
+
 FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer()
 {
 //    SVDEBUG << "FeatureExtractionModelTransformer::~FeatureExtractionModelTransformer()" << endl;
@@ -566,6 +586,8 @@
 void
 FeatureExtractionModelTransformer::run()
 {
+    initialise();
+    
     DenseTimeValueModel *input = getConformingInput();
     if (!input) return;
 
@@ -709,6 +731,9 @@
 
         if (m_abandoned) break;
 
+    cerr << "calling process() from thread "
+         << QThread::currentThreadId() << endl;
+    
 	Vamp::Plugin::FeatureSet features = m_plugin->process
 	    (buffers, RealTime::frame2RealTime(blockFrame, sampleRate).toVampRealTime());
 
--- a/transform/FeatureExtractionModelTransformer.h	Fri Oct 14 16:23:04 2016 +0100
+++ b/transform/FeatureExtractionModelTransformer.h	Mon Oct 17 14:18:23 2016 +0100
@@ -19,6 +19,8 @@
 #include "ModelTransformer.h"
 
 #include <QString>
+#include <QMutex>
+#include <QWaitCondition>
 
 #include <vamp-hostsdk/Plugin.h>
 
@@ -74,7 +76,12 @@
     void getFrames(int channelCount, sv_frame_t startFrame, sv_frame_t size,
                    float **buffer);
 
-    // just casts
+    bool m_haveOutputs;
+    QMutex m_outputMutex;
+    QWaitCondition m_outputsCondition;
+    void awaitOutputModels();
+    
+    // just casts:
 
     DenseTimeValueModel *getConformingInput();
 
--- a/transform/ModelTransformer.h	Fri Oct 14 16:23:04 2016 +0100
+++ b/transform/ModelTransformer.h	Mon Oct 17 14:18:23 2016 +0100
@@ -89,16 +89,20 @@
      * be initialised; an error message may be available via
      * getMessage() in this situation.
      */
-    Models getOutputModels() { return m_outputs; }
+    Models getOutputModels() {
+        awaitOutputModels();
+        return m_outputs;
+    }
 
     /**
      * Return the set of output models, also detaching them from the
      * transformer so that they will not be deleted when the
      * transformer is.  The caller takes ownership of the models.
      */
-    Models detachOutputModels() { 
+    Models detachOutputModels() {
+        awaitOutputModels();
         m_detached = true; 
-        return getOutputModels(); 
+        return m_outputs;
     }
 
     /**
@@ -138,6 +142,8 @@
     ModelTransformer(Input input, const Transform &transform);
     ModelTransformer(Input input, const Transforms &transforms);
 
+    virtual void awaitOutputModels() = 0;
+    
     Transforms m_transforms;
     Input m_input; // I don't own the model in this
     Models m_outputs; // I own this, unless...
--- a/transform/RealTimeEffectModelTransformer.h	Fri Oct 14 16:23:04 2016 +0100
+++ b/transform/RealTimeEffectModelTransformer.h	Mon Oct 17 14:18:23 2016 +0100
@@ -31,6 +31,8 @@
 protected:
     virtual void run();
 
+    virtual void awaitOutputModels() { } // they're created synchronously
+    
     QString m_units;
     RealTimePluginInstance *m_plugin;
     int m_outputNo;