Skip to content

Commit

Permalink
Reduce locking in VampPluginAdapter
Browse files Browse the repository at this point in the history
  • Loading branch information
uklotzde committed Jan 9, 2018
1 parent 2990add commit 18a67f4
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 100 deletions.
16 changes: 8 additions & 8 deletions src/analyzer/vamp/vampanalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ bool VampAnalyzer::Init(const QString pluginlibrary, const QString pluginId,
mixxx::VampPluginAdapter::composePluginKey(
pluginlibrary.toStdString(),
pluginList.at(0).toStdString());
m_pluginAdapter.reload(
m_pluginAdapter.loadPlugin(
pluginKey,
samplerate,
Vamp::HostExt::PluginLoader::ADAPT_ALL_SAFE);
Expand All @@ -64,7 +64,7 @@ bool VampAnalyzer::Init(const QString pluginlibrary, const QString pluginId,
return false;
}

const auto outputs = m_pluginAdapter.getOutputDescriptors();
const auto outputs = m_pluginAdapter->getOutputDescriptors();
if (outputs.empty()) {
qWarning() << "VampAnalyzer: Plugin has no outputs!";
return false;
Expand All @@ -76,7 +76,7 @@ bool VampAnalyzer::Init(const QString pluginlibrary, const QString pluginId,
return false;
}

m_iBlockSize = m_pluginAdapter.getPreferredBlockSize();
m_iBlockSize = m_pluginAdapter->getPreferredBlockSize();
qDebug() << "VampAnalyzer BlockSize: " << m_iBlockSize;
if (m_iBlockSize == 0) {
// A plugin that can handle any block size may return 0. The final block
Expand All @@ -86,7 +86,7 @@ bool VampAnalyzer::Init(const QString pluginlibrary, const QString pluginId,
qDebug() << "VampAnalyzer: setting block size to" << m_iBlockSize;
}

m_iStepSize = m_pluginAdapter.getPreferredStepSize();
m_iStepSize = m_pluginAdapter->getPreferredStepSize();
qDebug() << "VampAnalyzer StepSize: " << m_iStepSize;
if (m_iStepSize == 0 || m_iStepSize > m_iBlockSize) {
// A plugin may return 0 if it has no particular interest in the step
Expand All @@ -99,7 +99,7 @@ bool VampAnalyzer::Init(const QString pluginlibrary, const QString pluginId,
qDebug() << "VampAnalyzer: setting step size to" << m_iStepSize;
}

if (!m_pluginAdapter.initialise(2, m_iStepSize, m_iBlockSize)) {
if (!m_pluginAdapter->initialise(2, m_iStepSize, m_iBlockSize)) {
qWarning() << "VampAnalyzer: Cannot initialize plugin";
return false;
}
Expand Down Expand Up @@ -175,14 +175,14 @@ bool VampAnalyzer::Process(const CSAMPLE *pIn, const int iLen) {
Vamp::RealTime::frame2RealTime(m_iSampleCount, m_rate);

Vamp::Plugin::FeatureSet features =
m_pluginAdapter.process(m_pluginbuf, timestamp);
m_pluginAdapter->process(m_pluginbuf, timestamp);

m_results.insert(m_results.end(), features[m_iOutput].begin(),
features[m_iOutput].end());

if (lastsamples) {
Vamp::Plugin::FeatureSet features =
m_pluginAdapter.getRemainingFeatures();
m_pluginAdapter->getRemainingFeatures();
m_results.insert(m_results.end(), features[m_iOutput].begin(),
features[m_iOutput].end());
}
Expand Down Expand Up @@ -217,7 +217,7 @@ bool VampAnalyzer::End() {
// If the total number of samples has been estimated incorrectly
if (m_iRemainingSamples > 0) {
Vamp::Plugin::FeatureSet features =
m_pluginAdapter.getRemainingFeatures();
m_pluginAdapter->getRemainingFeatures();
m_results.insert(m_results.end(), features[m_iOutput].begin(),
features[m_iOutput].end());
}
Expand Down
61 changes: 13 additions & 48 deletions src/analyzer/vamp/vamppluginadapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,69 +198,34 @@ Vamp::HostExt::PluginLoader::PluginKey VampPluginAdapter::composePluginKey(
}
}

VampPluginAdapter::VampPluginAdapter()
: m_plugin(nullptr),
m_preferredBlockSize(0),
m_preferredStepSize(0) {
}

VampPluginAdapter::VampPluginAdapter(
Vamp::HostExt::PluginLoader::PluginKey key,
float inputSampleRate,
int adapterFlags)
: m_plugin(nullptr),
m_preferredBlockSize(0),
m_preferredStepSize(0) {
reload(key, inputSampleRate, adapterFlags);
int adapterFlags) {
std::lock_guard<std::mutex> locked(s_mutex);
m_plugin.reset(mixxx::loadPlugin(
locked,
key,
inputSampleRate,
adapterFlags));
}

VampPluginAdapter::~VampPluginAdapter() {
std::lock_guard<std::mutex> locked(s_mutex);
m_plugin.reset();
}

void VampPluginAdapter::reload(
void VampPluginAdapter::loadPlugin(
Vamp::HostExt::PluginLoader::PluginKey key,
float inputSampleRate,
int adapterFlags) {
std::lock_guard<std::mutex> locked(s_mutex);
m_plugin.reset();
m_plugin.reset(loadPlugin(locked, key, inputSampleRate, adapterFlags));
if (m_plugin) {
m_identifier = m_plugin->getIdentifier();
m_name = m_plugin->getName();
m_outputDescriptors = m_plugin->getOutputDescriptors();
m_preferredBlockSize = m_plugin->getPreferredBlockSize();
m_preferredStepSize = m_plugin->getPreferredStepSize();
}
}

bool VampPluginAdapter::initialise(
size_t inputChannels,
size_t stepSize,
size_t blockSize) {
DEBUG_ASSERT(m_plugin);
std::lock_guard<std::mutex> locked(s_mutex);
return m_plugin->initialise(
inputChannels,
stepSize,
blockSize);
}

Vamp::Plugin::FeatureSet VampPluginAdapter::process(
const float* const* inputBuffers,
Vamp::RealTime timestamp) {
DEBUG_ASSERT(m_plugin);
std::lock_guard<std::mutex> locked(s_mutex);
return m_plugin->process(
inputBuffers,
timestamp);
}

Vamp::Plugin::FeatureSet VampPluginAdapter::getRemainingFeatures() {
DEBUG_ASSERT(m_plugin);
std::lock_guard<std::mutex> locked(s_mutex);
return m_plugin->getRemainingFeatures();
m_plugin.reset(mixxx::loadPlugin(
locked,
key,
inputSampleRate,
adapterFlags));
}

} // namespace mixxx
50 changes: 14 additions & 36 deletions src/analyzer/vamp/vamppluginadapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

namespace mixxx {

// Thread-safe adapter/decorator for the thread-unsafe Vamp plugin C++ API
// Thread-safe adapter/decorator for the partially thread-unsafe
// PluginLoader/Plugin couple
class VampPluginAdapter {
public:
static Vamp::HostExt::PluginLoader::PluginKeyList listPlugins();
Expand All @@ -17,7 +18,7 @@ class VampPluginAdapter {
std::string libraryName,
std::string identifier);

VampPluginAdapter();
VampPluginAdapter() = default;
VampPluginAdapter(
Vamp::HostExt::PluginLoader::PluginKey key,
float inputSampleRate,
Expand All @@ -28,60 +29,37 @@ class VampPluginAdapter {
VampPluginAdapter& operator=(VampPluginAdapter&&) = delete;
VampPluginAdapter& operator=(const VampPluginAdapter&) = delete;

operator bool() const {
return m_plugin != nullptr;
}

void reload(
void loadPlugin(
Vamp::HostExt::PluginLoader::PluginKey key,
float inputSampleRate,
int adapterFlags = 0);

const std::string& getIdentifier() const {
DEBUG_ASSERT(m_plugin);
return m_identifier;
operator bool() const {
return m_plugin != nullptr;
}

const std::string& getName() const {
Vamp::Plugin* operator->() {
DEBUG_ASSERT(m_plugin);
return m_name;
return m_plugin.get();
}

const Vamp::Plugin::OutputList& getOutputDescriptors() const {
const Vamp::Plugin* operator->() const {
DEBUG_ASSERT(m_plugin);
return m_outputDescriptors;
return m_plugin.get();
}

size_t getPreferredBlockSize() const {
Vamp::Plugin& operator*() {
DEBUG_ASSERT(m_plugin);
return m_preferredBlockSize;
return *m_plugin.get();
}

size_t getPreferredStepSize() const {
const Vamp::Plugin& operator*() const {
DEBUG_ASSERT(m_plugin);
return m_preferredStepSize;
return *m_plugin.get();
}

bool initialise(
size_t inputChannels,
size_t stepSize,
size_t blockSize);

Vamp::Plugin::FeatureSet process(
const float* const* inputBuffers,
Vamp::RealTime timestamp);
Vamp::Plugin::FeatureSet getRemainingFeatures();

private:
// This pointer must never be deleted implicitly to avoid race conditions!
// It is only needed for utilizing the default move constructor.
std::unique_ptr<Vamp::Plugin> m_plugin;

std::string m_identifier;
std::string m_name;
Vamp::Plugin::OutputList m_outputDescriptors;
size_t m_preferredBlockSize;
size_t m_preferredStepSize;
};

} // namespace mixxx
8 changes: 4 additions & 4 deletions src/preferences/dialog/dlgprefbeats.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,11 @@ void DlgPrefBeats::populate() {
mixxx::VampPluginAdapter pluginAdapter(plugins[iplugin], 48000);
//TODO: find a way to add beat trackers only
if (pluginAdapter) {
const Plugin::OutputList& outputs = pluginAdapter.getOutputDescriptors();
const Plugin::OutputList& outputs = pluginAdapter->getOutputDescriptors();
for (unsigned int ioutput=0; ioutput < outputs.size(); ioutput++) {
QString displayname = QString::fromStdString(pluginAdapter.getIdentifier()) + ":"
QString displayname = QString::fromStdString(pluginAdapter->getIdentifier()) + ":"
+ QString::number(ioutput);
QString displaynametext = QString::fromStdString(pluginAdapter.getName());
QString displaynametext = QString::fromStdString(pluginAdapter->getName());
qDebug() << "Plugin output displayname:" << displayname << displaynametext;
bool goodones = ((displayname.contains("mixxxbpmdetection")||
displayname.contains("qm-tempotracker:0"))||
Expand All @@ -240,7 +240,7 @@ void DlgPrefBeats::populate() {
m_listName << displaynametext;
QString pluginlibrary = QString::fromStdString(plugins[iplugin]).section(":",0,0);
m_listLibrary << pluginlibrary;
QString displayname = QString::fromStdString(pluginAdapter.getIdentifier()) + ":"
QString displayname = QString::fromStdString(pluginAdapter->getIdentifier()) + ":"
+ QString::number(ioutput);
m_listIdentifier << displayname;
plugincombo->addItem(displaynametext, displayname);
Expand Down
8 changes: 4 additions & 4 deletions src/preferences/dialog/dlgprefkey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,19 +287,19 @@ void DlgPrefKey::populate() {
mixxx::VampPluginAdapter pluginAdapter(plugins[iplugin], 48000);
//TODO(XXX): find a general way to add key detectors only
if (pluginAdapter) {
const Plugin::OutputList& outputs = pluginAdapter.getOutputDescriptors();
const Plugin::OutputList& outputs = pluginAdapter->getOutputDescriptors();
for (unsigned int ioutput=0; ioutput < outputs.size(); ioutput++) {
QString displayname = QString::fromStdString(pluginAdapter.getIdentifier()) + ":"
QString displayname = QString::fromStdString(pluginAdapter->getIdentifier()) + ":"
+ QString::number(ioutput);
QString displaynametext = QString::fromStdString(pluginAdapter.getName());
QString displaynametext = QString::fromStdString(pluginAdapter->getName());
qDebug() << "Plugin output displayname:" << displayname << displaynametext;
bool goodones = displayname.contains(VAMP_ANALYZER_KEY_DEFAULT_PLUGIN_ID);

if (goodones) {
m_listName << displaynametext;
QString pluginlibrary = QString::fromStdString(plugins[iplugin]).section(":",0,0);
m_listLibrary << pluginlibrary;
QString displayname = QString::fromStdString(pluginAdapter.getIdentifier()) + ":"
QString displayname = QString::fromStdString(pluginAdapter->getIdentifier()) + ":"
+ QString::number(ioutput);
m_listIdentifier << displayname;
plugincombo->addItem(displaynametext, displayname);
Expand Down

0 comments on commit 18a67f4

Please sign in to comment.