diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index b9cac208b7..2583e15760 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -47,40 +47,54 @@ static const QString AUDIO_THREADING_GROUP_KEY = "audio_threading"; int AudioMixer::_numStaticJitterFrames{ -1 }; float AudioMixer::_noiseMutingThreshold{ DEFAULT_NOISE_MUTING_THRESHOLD }; float AudioMixer::_attenuationPerDoublingInDistance{ DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE }; +std::map> AudioMixer::_availableCodecs{ }; +QStringList AudioMixer::_codecPreferenceOrder{}; QHash AudioMixer::_audioZones; QVector AudioMixer::_zoneSettings; QVector AudioMixer::_zoneReverbSettings; AudioMixer::AudioMixer(ReceivedMessage& message) : ThreadedAssignment(message) { + + // hash the available codecs (on the mixer) + auto codecPlugins = PluginManager::getInstance()->getCodecPlugins(); + std::for_each(codecPlugins.cbegin(), codecPlugins.cend(), + [&](const CodecPluginPointer& codec) { + _availableCodecs[codec->getName()] = codec; + }); + auto nodeList = DependencyManager::get(); auto& packetReceiver = nodeList->getPacketReceiver(); - packetReceiver.registerListenerForTypes({ PacketType::MicrophoneAudioNoEcho, PacketType::MicrophoneAudioWithEcho, - PacketType::InjectAudio, PacketType::AudioStreamStats }, - this, "handleAudioPacket"); - packetReceiver.registerListenerForTypes({ PacketType::SilentAudioFrame }, this, "handleSilentAudioPacket"); - packetReceiver.registerListener(PacketType::NegotiateAudioFormat, this, "handleNegotiateAudioFormat"); + // packets whose consequences are limited to their own node can be parallelized + packetReceiver.registerListenerForTypes({ + PacketType::MicrophoneAudioNoEcho, + PacketType::MicrophoneAudioWithEcho, + PacketType::InjectAudio, + PacketType::AudioStreamStats, + PacketType::SilentAudioFrame, + PacketType::NegotiateAudioFormat, + PacketType::MuteEnvironment, + PacketType::NodeIgnoreRequest, + PacketType::RadiusIgnoreRequest, + PacketType::RequestsDomainListData, + PacketType::PerAvatarGainSet }, + this, "queueAudioPacket"); + + // packets whose consequences are global should be processed on the main thread packetReceiver.registerListener(PacketType::MuteEnvironment, this, "handleMuteEnvironmentPacket"); - packetReceiver.registerListener(PacketType::NodeIgnoreRequest, this, "handleNodeIgnoreRequestPacket"); - packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket"); packetReceiver.registerListener(PacketType::NodeMuteRequest, this, "handleNodeMuteRequestPacket"); - packetReceiver.registerListener(PacketType::RadiusIgnoreRequest, this, "handleRadiusIgnoreRequestPacket"); - packetReceiver.registerListener(PacketType::RequestsDomainListData, this, "handleRequestsDomainListDataPacket"); - packetReceiver.registerListener(PacketType::PerAvatarGainSet, this, "handlePerAvatarGainSetDataPacket"); + packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket"); connect(nodeList.data(), &NodeList::nodeKilled, this, &AudioMixer::handleNodeKilled); } -void AudioMixer::handleAudioPacket(QSharedPointer message, SharedNodePointer sendingNode) { - getOrCreateClientData(sendingNode.data()); - DependencyManager::get()->updateNodeWithDataFromPacket(message, sendingNode); -} +void AudioMixer::queueAudioPacket(QSharedPointer message, SharedNodePointer node) { + if (message->getType() == PacketType::SilentAudioFrame) { + _numSilentPackets++; + } -void AudioMixer::handleSilentAudioPacket(QSharedPointer message, SharedNodePointer sendingNode) { - _numSilentPackets++; - getOrCreateClientData(sendingNode.data()); - DependencyManager::get()->updateNodeWithDataFromPacket(message, sendingNode); + getOrCreateClientData(node.data())->queuePacket(message, node); } void AudioMixer::handleMuteEnvironmentPacket(QSharedPointer message, SharedNodePointer sendingNode) { @@ -119,69 +133,28 @@ InputPluginList getInputPlugins() { return result; } -void saveInputPluginSettings(const InputPluginList& plugins) { -} +// must be here to satisfy a reference in PluginManager::saveSettings() +void saveInputPluginSettings(const InputPluginList& plugins) {} - -void AudioMixer::handleNegotiateAudioFormat(QSharedPointer message, SharedNodePointer sendingNode) { - QStringList availableCodecs; - auto codecPlugins = PluginManager::getInstance()->getCodecPlugins(); - if (codecPlugins.size() > 0) { - for (auto& plugin : codecPlugins) { - auto codecName = plugin->getName(); - qDebug() << "Codec available:" << codecName; - availableCodecs.append(codecName); - } - } else { - qDebug() << "No Codecs available..."; - } - - CodecPluginPointer selectedCodec; +const std::pair AudioMixer::negotiateCodec(std::vector codecs) { QString selectedCodecName; + CodecPluginPointer selectedCodec; - QStringList codecPreferenceList = _codecPreferenceOrder.split(","); + // read the codecs requested (by the client) + int minPreference = std::numeric_limits::max(); + for (auto& codec : codecs) { + if (_availableCodecs.count(codec) > 0) { + int preference = _codecPreferenceOrder.indexOf(codec); - // read the codecs requested by the client - const int MAX_PREFERENCE = 99999; - int preferredCodecIndex = MAX_PREFERENCE; - QString preferredCodec; - quint8 numberOfCodecs = 0; - message->readPrimitive(&numberOfCodecs); - qDebug() << "numberOfCodecs:" << numberOfCodecs; - QStringList codecList; - for (quint16 i = 0; i < numberOfCodecs; i++) { - QString requestedCodec = message->readString(); - int preferenceOfThisCodec = codecPreferenceList.indexOf(requestedCodec); - bool codecAvailable = availableCodecs.contains(requestedCodec); - qDebug() << "requestedCodec:" << requestedCodec << "preference:" << preferenceOfThisCodec << "available:" << codecAvailable; - if (codecAvailable) { - codecList.append(requestedCodec); - if (preferenceOfThisCodec >= 0 && preferenceOfThisCodec < preferredCodecIndex) { - qDebug() << "This codec is preferred..."; - selectedCodecName = requestedCodec; - preferredCodecIndex = preferenceOfThisCodec; - } - } - } - qDebug() << "all requested and available codecs:" << codecList; - - // choose first codec - if (!selectedCodecName.isEmpty()) { - if (codecPlugins.size() > 0) { - for (auto& plugin : codecPlugins) { - if (selectedCodecName == plugin->getName()) { - qDebug() << "Selecting codec:" << selectedCodecName; - selectedCodec = plugin; - break; - } + // choose the preferred, available codec + if (preference >= 0 && preference < minPreference) { + minPreference = preference; + selectedCodecName = codec; } } } - auto clientData = getOrCreateClientData(sendingNode.data()); - clientData->setupCodec(selectedCodec, selectedCodecName); - qDebug() << "selectedCodecName:" << selectedCodecName; - clientData->sendSelectAudioFormat(sendingNode, selectedCodecName); + return std::make_pair(selectedCodecName, _availableCodecs[selectedCodecName]); } void AudioMixer::handleNodeKilled(SharedNodePointer killedNode) { @@ -227,42 +200,6 @@ void AudioMixer::handleKillAvatarPacket(QSharedPointer packet, } } -void AudioMixer::handleRequestsDomainListDataPacket(QSharedPointer message, SharedNodePointer senderNode) { - auto nodeList = DependencyManager::get(); - nodeList->getOrCreateLinkedData(senderNode); - - if (senderNode->getLinkedData()) { - AudioMixerClientData* nodeData = dynamic_cast(senderNode->getLinkedData()); - if (nodeData != nullptr) { - bool isRequesting; - message->readPrimitive(&isRequesting); - nodeData->setRequestsDomainListData(isRequesting); - } - } -} - -void AudioMixer::handleNodeIgnoreRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode) { - sendingNode->parseIgnoreRequestMessage(packet); -} - -void AudioMixer::handlePerAvatarGainSetDataPacket(QSharedPointer packet, SharedNodePointer sendingNode) { - auto clientData = dynamic_cast(sendingNode->getLinkedData()); - if (clientData) { - QUuid listeningNodeUUID = sendingNode->getUUID(); - // parse the UUID from the packet - QUuid audioSourceUUID = QUuid::fromRfc4122(packet->readWithoutCopy(NUM_BYTES_RFC4122_UUID)); - uint8_t packedGain; - packet->readPrimitive(&packedGain); - float gain = unpackFloatGainFromByte(packedGain); - clientData->hrtfForStream(audioSourceUUID, QUuid()).setGainAdjustment(gain); - qDebug() << "Setting gain adjustment for hrtf[" << listeningNodeUUID << "][" << audioSourceUUID << "] to " << gain; - } -} - -void AudioMixer::handleRadiusIgnoreRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode) { - sendingNode->parseIgnoreRadiusRequestMessage(packet); -} - void AudioMixer::removeHRTFsForFinishedInjector(const QUuid& streamID) { auto injectorClientData = qobject_cast(sender()); if (injectorClientData) { @@ -323,6 +260,7 @@ void AudioMixer::sendStatsPacket() { addTiming(_prepareTiming, "prepare"); addTiming(_mixTiming, "mix"); addTiming(_eventsTiming, "events"); + addTiming(_packetsTiming, "packets"); #ifdef HIFI_AUDIO_MIXER_DEBUG timingStats["ns_per_mix"] = (_stats.totalMixes > 0) ? (float)(_stats.mixTime / _stats.totalMixes) : 0; @@ -452,19 +390,27 @@ void AudioMixer::start() { ++frame; ++_numStatFrames; - // play nice with qt event-looping + // process queued events (networking, global audio packets, &c.) { auto eventsTimer = _eventsTiming.timer(); // since we're a while loop we need to yield to qt's event processing QCoreApplication::processEvents(); - if (_isFinished) { - // alert qt eventing that this is finished - QCoreApplication::sendPostedEvents(this, QEvent::DeferredDelete); - break; + // process (node-isolated) audio packets across slave threads + { + nodeList->nestedEach([&](NodeList::const_iterator cbegin, NodeList::const_iterator cend) { + auto packetsTimer = _packetsTiming.timer(); + _slavePool.processPackets(cbegin, cend); + }); } } + + if (_isFinished) { + // alert qt eventing that this is finished + QCoreApplication::sendPostedEvents(this, QEvent::DeferredDelete); + break; + } } } @@ -629,7 +575,8 @@ void AudioMixer::parseSettingsObject(const QJsonObject &settingsObject) { const QString CODEC_PREFERENCE_ORDER = "codec_preference_order"; if (audioEnvGroupObject[CODEC_PREFERENCE_ORDER].isString()) { - _codecPreferenceOrder = audioEnvGroupObject[CODEC_PREFERENCE_ORDER].toString(); + QString codecPreferenceOrder = audioEnvGroupObject[CODEC_PREFERENCE_ORDER].toString(); + _codecPreferenceOrder = codecPreferenceOrder.split(","); qDebug() << "Codec preference order changed to" << _codecPreferenceOrder; } diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 07359f4aef..0641c04a6c 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -49,6 +49,7 @@ public: static const QHash& getAudioZones() { return _audioZones; } static const QVector& getZoneSettings() { return _zoneSettings; } static const QVector& getReverbSettings() { return _zoneReverbSettings; } + static const std::pair negotiateCodec(std::vector codecs); public slots: void run() override; @@ -56,20 +57,14 @@ public slots: private slots: // packet handlers - void handleAudioPacket(QSharedPointer packet, SharedNodePointer sendingNode); - void handleSilentAudioPacket(QSharedPointer packet, SharedNodePointer sendingNode); void handleMuteEnvironmentPacket(QSharedPointer packet, SharedNodePointer sendingNode); - void handleNegotiateAudioFormat(QSharedPointer message, SharedNodePointer sendingNode); - void handleNodeKilled(SharedNodePointer killedNode); - void handleRequestsDomainListDataPacket(QSharedPointer message, SharedNodePointer senderNode); - void handleNodeIgnoreRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); - void handleRadiusIgnoreRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); - void handleKillAvatarPacket(QSharedPointer packet, SharedNodePointer sendingNode); void handleNodeMuteRequestPacket(QSharedPointer packet, SharedNodePointer sendingNode); - void handlePerAvatarGainSetDataPacket(QSharedPointer packet, SharedNodePointer sendingNode); + void handleNodeKilled(SharedNodePointer killedNode); + void handleKillAvatarPacket(QSharedPointer packet, SharedNodePointer sendingNode); - void start(); + void queueAudioPacket(QSharedPointer packet, SharedNodePointer sendingNode); void removeHRTFsForFinishedInjector(const QUuid& streamID); + void start(); private: // mixing helpers @@ -93,8 +88,6 @@ private: int _numStatFrames { 0 }; AudioMixerStats _stats; - QString _codecPreferenceOrder; - AudioMixerSlavePool _slavePool; class Timer { @@ -124,13 +117,17 @@ private: Timer _prepareTiming; Timer _mixTiming; Timer _eventsTiming; + Timer _packetsTiming; static int _numStaticJitterFrames; // -1 denotes dynamic jitter buffering static float _noiseMutingThreshold; static float _attenuationPerDoublingInDistance; + static std::map _availableCodecs; + static QStringList _codecPreferenceOrder; static QHash _audioZones; static QVector _zoneSettings; static QVector _zoneReverbSettings; + }; #endif // hifi_AudioMixer_h diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 791ccb8b03..87eb5ee1ab 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -19,6 +19,7 @@ #include "InjectedAudioStream.h" +#include "AudioHelpers.h" #include "AudioMixer.h" #include "AudioMixerClientData.h" @@ -47,6 +48,92 @@ AudioMixerClientData::~AudioMixerClientData() { } } +void AudioMixerClientData::queuePacket(QSharedPointer message, SharedNodePointer node) { + if (!_packetQueue.node) { + _packetQueue.node = node; + } + _packetQueue.push(message); +} + +void AudioMixerClientData::processPackets() { + SharedNodePointer node = _packetQueue.node; + assert(_packetQueue.empty() || node); + _packetQueue.node.clear(); + + while (!_packetQueue.empty()) { + auto& packet = _packetQueue.back(); + + switch (packet->getType()) { + case PacketType::MicrophoneAudioNoEcho: + case PacketType::MicrophoneAudioWithEcho: + case PacketType::InjectAudio: + case PacketType::AudioStreamStats: + case PacketType::SilentAudioFrame: { + QMutexLocker lock(&getMutex()); + parseData(*packet); + break; + } + case PacketType::NegotiateAudioFormat: + negotiateAudioFormat(*packet, node); + break; + case PacketType::RequestsDomainListData: + parseRequestsDomainListData(*packet); + break; + case PacketType::PerAvatarGainSet: + parsePerAvatarGainSet(*packet, node); + break; + case PacketType::NodeIgnoreRequest: + parseNodeIgnoreRequest(packet, node); + break; + case PacketType::RadiusIgnoreRequest: + parseRadiusIgnoreRequest(packet, node); + break; + default: + Q_UNREACHABLE(); + } + + _packetQueue.pop(); + } + assert(_packetQueue.empty()); +} + +void AudioMixerClientData::negotiateAudioFormat(ReceivedMessage& message, const SharedNodePointer& node) { + quint8 numberOfCodecs; + message.readPrimitive(&numberOfCodecs); + std::vector codecs; + for (auto i = 0; i < numberOfCodecs; i++) { + codecs.push_back(message.readString()); + } + const std::pair codec = AudioMixer::negotiateCodec(codecs); + + setupCodec(codec.second, codec.first); + sendSelectAudioFormat(node, codec.first); +} + +void AudioMixerClientData::parseRequestsDomainListData(ReceivedMessage& message) { + bool isRequesting; + message.readPrimitive(&isRequesting); + setRequestsDomainListData(isRequesting); +} + +void AudioMixerClientData::parsePerAvatarGainSet(ReceivedMessage& message, const SharedNodePointer& node) { + QUuid uuid = node->getUUID(); + // parse the UUID from the packet + QUuid avatarUuid = QUuid::fromRfc4122(message.readWithoutCopy(NUM_BYTES_RFC4122_UUID)); + uint8_t packedGain; + message.readPrimitive(&packedGain); + float gain = unpackFloatGainFromByte(packedGain); + hrtfForStream(avatarUuid, QUuid()).setGainAdjustment(gain); + qDebug() << "Setting gain adjustment for hrtf[" << uuid << "][" << avatarUuid << "] to " << gain; +} + +void AudioMixerClientData::parseNodeIgnoreRequest(QSharedPointer message, const SharedNodePointer& node) { + node->parseIgnoreRequestMessage(message); +} + +void AudioMixerClientData::parseRadiusIgnoreRequest(QSharedPointer message, const SharedNodePointer& node) { + node->parseIgnoreRadiusRequestMessage(message); +} AvatarAudioStream* AudioMixerClientData::getAvatarAudioStream() { QReadLocker readLocker { &_streamsLock }; diff --git a/assignment-client/src/audio/AudioMixerClientData.h b/assignment-client/src/audio/AudioMixerClientData.h index c30923f411..1047e10570 100644 --- a/assignment-client/src/audio/AudioMixerClientData.h +++ b/assignment-client/src/audio/AudioMixerClientData.h @@ -12,6 +12,8 @@ #ifndef hifi_AudioMixerClientData_h #define hifi_AudioMixerClientData_h +#include + #include #include @@ -34,6 +36,9 @@ public: using SharedStreamPointer = std::shared_ptr; using AudioStreamMap = std::unordered_map; + void queuePacket(QSharedPointer packet, SharedNodePointer node); + void processPackets(); + // locks the mutex to make a copy AudioStreamMap getAudioStreams() { QReadLocker readLock { &_streamsLock }; return _audioStreams; } AvatarAudioStream* getAvatarAudioStream(); @@ -56,7 +61,13 @@ public: void removeAgentAvatarAudioStream(); + // packet parsers int parseData(ReceivedMessage& message) override; + void negotiateAudioFormat(ReceivedMessage& message, const SharedNodePointer& node); + void parseRequestsDomainListData(ReceivedMessage& message); + void parsePerAvatarGainSet(ReceivedMessage& message, const SharedNodePointer& node); + void parseNodeIgnoreRequest(QSharedPointer message, const SharedNodePointer& node); + void parseRadiusIgnoreRequest(QSharedPointer message, const SharedNodePointer& node); // attempt to pop a frame from each audio stream, and return the number of streams from this client int checkBuffersBeforeFrameSend(); @@ -105,11 +116,15 @@ public slots: void sendSelectAudioFormat(SharedNodePointer node, const QString& selectedCodecName); private: - using IgnoreZone = AABox; + struct PacketQueue : public std::queue> { + QWeakPointer node; + }; + PacketQueue _packetQueue; QReadWriteLock _streamsLock; AudioStreamMap _audioStreams; // microphone stream from avatar is stored under key of null UUID + using IgnoreZone = AABox; class IgnoreZoneMemo { public: IgnoreZoneMemo(AudioMixerClientData& data) : _data(data) {} diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index 370df60ec5..6b53de89c2 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -53,7 +53,14 @@ inline float computeGain(const AvatarAudioStream& listeningNodeStream, const Pos inline float computeAzimuth(const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd, const glm::vec3& relativePosition); -void AudioMixerSlave::configure(ConstIter begin, ConstIter end, unsigned int frame, float throttlingRatio) { +void AudioMixerSlave::processPackets(const SharedNodePointer& node) { + AudioMixerClientData* data = (AudioMixerClientData*)node->getLinkedData(); + if (data) { + data->processPackets(); + } +} + +void AudioMixerSlave::configureMix(ConstIter begin, ConstIter end, unsigned int frame, float throttlingRatio) { _begin = begin; _end = end; _frame = frame; diff --git a/assignment-client/src/audio/AudioMixerSlave.h b/assignment-client/src/audio/AudioMixerSlave.h index 7b59500629..074d10ff40 100644 --- a/assignment-client/src/audio/AudioMixerSlave.h +++ b/assignment-client/src/audio/AudioMixerSlave.h @@ -30,9 +30,13 @@ class AudioMixerSlave { public: using ConstIter = NodeList::const_iterator; - void configure(ConstIter begin, ConstIter end, unsigned int frame, float throttlingRatio); + // process packets for a given node (requires no configuration) + void processPackets(const SharedNodePointer& node); - // mix and broadcast non-ignored streams to the node + // configure a round of mixing + void configureMix(ConstIter begin, ConstIter end, unsigned int frame, float throttlingRatio); + + // mix and broadcast non-ignored streams to the node (requires configuration using configureMix, above) // returns true if a mixed packet was sent to the node void mix(const SharedNodePointer& node); diff --git a/assignment-client/src/audio/AudioMixerSlavePool.cpp b/assignment-client/src/audio/AudioMixerSlavePool.cpp index 9b20572b84..643361ac5d 100644 --- a/assignment-client/src/audio/AudioMixerSlavePool.cpp +++ b/assignment-client/src/audio/AudioMixerSlavePool.cpp @@ -21,7 +21,7 @@ void AudioMixerSlaveThread::run() { // iterate over all available nodes SharedNodePointer node; while (try_pop(node)) { - mix(node); + (this->*_function)(node); } bool stopping = _stop; @@ -41,7 +41,11 @@ void AudioMixerSlaveThread::wait() { }); ++_pool._numStarted; } - configure(_pool._begin, _pool._end, _pool._frame, _pool._throttlingRatio); + + if (_pool._configure) { + _pool._configure(*this); + } + _function = _pool._function; } void AudioMixerSlaveThread::notify(bool stopping) { @@ -64,16 +68,31 @@ bool AudioMixerSlaveThread::try_pop(SharedNodePointer& node) { static AudioMixerSlave slave; #endif +void AudioMixerSlavePool::processPackets(ConstIter begin, ConstIter end) { + _function = &AudioMixerSlave::processPackets; + _configure = [](AudioMixerSlave& slave) {}; + run(begin, end); +} + void AudioMixerSlavePool::mix(ConstIter begin, ConstIter end, unsigned int frame, float throttlingRatio) { - _begin = begin; - _end = end; + _function = &AudioMixerSlave::mix; + _configure = [&](AudioMixerSlave& slave) { + slave.configureMix(_begin, _end, _frame, _throttlingRatio); + }; _frame = frame; _throttlingRatio = throttlingRatio; + run(begin, end); +} + +void AudioMixerSlavePool::run(ConstIter begin, ConstIter end) { + _begin = begin; + _end = end; + #ifdef AUDIO_SINGLE_THREADED - slave.configure(_begin, _end, frame, throttlingRatio); + _configure(slave); std::for_each(begin, end, [&](const SharedNodePointer& node) { - slave.mix(node); + _function(slave, node); }); #else // fill the queue @@ -84,7 +103,7 @@ void AudioMixerSlavePool::mix(ConstIter begin, ConstIter end, unsigned int frame { Lock lock(_mutex); - // mix + // run _numStarted = _numFinished = 0; _slaveCondition.notify_all(); diff --git a/assignment-client/src/audio/AudioMixerSlavePool.h b/assignment-client/src/audio/AudioMixerSlavePool.h index 19d2315d12..4082ea18d9 100644 --- a/assignment-client/src/audio/AudioMixerSlavePool.h +++ b/assignment-client/src/audio/AudioMixerSlavePool.h @@ -43,6 +43,7 @@ private: bool try_pop(SharedNodePointer& node); AudioMixerSlavePool& _pool; + void (AudioMixerSlave::*_function)(const SharedNodePointer& node) { nullptr }; bool _stop { false }; }; @@ -60,6 +61,9 @@ public: AudioMixerSlavePool(int numThreads = QThread::idealThreadCount()) { setNumThreads(numThreads); } ~AudioMixerSlavePool() { resize(0); } + // process packets on slave threads + void processPackets(ConstIter begin, ConstIter end); + // mix on slave threads void mix(ConstIter begin, ConstIter end, unsigned int frame, float throttlingRatio); @@ -70,6 +74,7 @@ public: int numThreads() { return _numThreads; } private: + void run(ConstIter begin, ConstIter end); void resize(int numThreads); std::vector> _slaves; @@ -82,6 +87,8 @@ private: Mutex _mutex; ConditionVariable _slaveCondition; ConditionVariable _poolCondition; + void (AudioMixerSlave::*_function)(const SharedNodePointer& node); + std::function _configure; int _numThreads { 0 }; int _numStarted { 0 }; // guarded by _mutex int _numFinished { 0 }; // guarded by _mutex diff --git a/libraries/plugins/src/plugins/PluginManager.cpp b/libraries/plugins/src/plugins/PluginManager.cpp index 75b0f1e3bc..8471dbc7e8 100644 --- a/libraries/plugins/src/plugins/PluginManager.cpp +++ b/libraries/plugins/src/plugins/PluginManager.cpp @@ -123,8 +123,6 @@ const CodecPluginList& PluginManager::getCodecPlugins() { static CodecPluginList codecPlugins; static std::once_flag once; std::call_once(once, [&] { - //codecPlugins = ::getCodecPlugins(); - // Now grab the dynamic plugins for (auto loader : getLoadedPlugins()) { CodecProvider* codecProvider = qobject_cast(loader->instance()); diff --git a/libraries/recording/src/recording/Deck.cpp b/libraries/recording/src/recording/Deck.cpp index 6f624db191..61eb86c91f 100644 --- a/libraries/recording/src/recording/Deck.cpp +++ b/libraries/recording/src/recording/Deck.cpp @@ -145,10 +145,8 @@ void Deck::processFrames() { } if (!nextClip) { - qCDebug(recordingLog) << "No more frames available"; // No more frames available, so handle the end of playback if (_loop) { - qCDebug(recordingLog) << "Looping enabled, seeking back to beginning"; // If we have looping enabled, start the playback over seek(0); // FIXME configure the recording scripting interface to reset the avatar basis on a loop