From be37921845d760e9052f68ec04891bf6d2dee237 Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Thu, 9 Jun 2016 15:49:07 -0700 Subject: [PATCH] first cut at codec plugins --- interface/src/Application.cpp | 7 +++ libraries/audio-client/src/AudioClient.cpp | 20 ++++++--- libraries/plugins/src/plugins/CodecPlugin.h | 19 ++++++++ libraries/plugins/src/plugins/Forward.h | 4 ++ .../plugins/src/plugins/PluginManager.cpp | 30 +++++++++++++ libraries/plugins/src/plugins/PluginManager.h | 1 + libraries/plugins/src/plugins/RuntimePlugin.h | 9 ++++ plugins/pcmCodec/CMakeLists.txt | 11 +++++ plugins/pcmCodec/src/PCMCodecManager.cpp | 45 +++++++++++++++++++ plugins/pcmCodec/src/PCMCodecManager.h | 40 +++++++++++++++++ plugins/pcmCodec/src/PCMCodecProvider.cpp | 44 ++++++++++++++++++ plugins/pcmCodec/src/plugin.json | 1 + 12 files changed, 224 insertions(+), 7 deletions(-) create mode 100644 libraries/plugins/src/plugins/CodecPlugin.h create mode 100644 plugins/pcmCodec/CMakeLists.txt create mode 100644 plugins/pcmCodec/src/PCMCodecManager.cpp create mode 100644 plugins/pcmCodec/src/PCMCodecManager.h create mode 100644 plugins/pcmCodec/src/PCMCodecProvider.cpp create mode 100644 plugins/pcmCodec/src/plugin.json diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 37c3b361bf..855cf2f313 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -85,6 +85,7 @@ #include #include #include +#include #include #include #include @@ -1236,7 +1237,13 @@ QString Application::getUserAgent() { userAgent += " " + formatPluginName(ip->getName()); } } + // for codecs, we include all of them, even if not active + auto codecPlugins = PluginManager::getInstance()->getCodecPlugins(); + for (auto& cp : codecPlugins) { + userAgent += " " + formatPluginName(cp->getName()); + } + qDebug() << __FUNCTION__ << ":" << userAgent; return userAgent; } diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 0c7a79e2a3..2569f27aaa 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -813,19 +813,25 @@ void AudioClient::handleRecordedAudioInput(const QByteArray& audio) { emitAudioPacket(audio.data(), audio.size(), _outgoingAvatarAudioSequenceNumber, audioTransform, PacketType::MicrophoneAudioWithEcho); } -void AudioClient::processReceivedSamples(const QByteArray& inputBuffer, QByteArray& outputBuffer) { - const int numNetworkOutputSamples = inputBuffer.size() / sizeof(int16_t); - const int numDeviceOutputSamples = numNetworkOutputSamples * (_outputFormat.sampleRate() * _outputFormat.channelCount()) - / (_desiredOutputFormat.sampleRate() * _desiredOutputFormat.channelCount()); +void AudioClient::processReceivedSamples(const QByteArray& networkBuffer, QByteArray& outputBuffer) { + + // TODO - codec decode goes here + QByteArray decodedBuffer = networkBuffer; + + const int numDecodecSamples = decodedBuffer.size() / sizeof(int16_t); + const int numDeviceOutputSamples = _outputFrameSize; + + Q_ASSERT(_outputFrameSize == numDecodecSamples * (_outputFormat.sampleRate() * _outputFormat.channelCount()) + / (_desiredOutputFormat.sampleRate() * _desiredOutputFormat.channelCount())); outputBuffer.resize(numDeviceOutputSamples * sizeof(int16_t)); - const int16_t* receivedSamples = reinterpret_cast(inputBuffer.data()); + const int16_t* decodedSamples = reinterpret_cast(decodedBuffer.data()); int16_t* outputSamples = reinterpret_cast(outputBuffer.data()); // copy the packet from the RB to the output - possibleResampling(_networkToOutputResampler, receivedSamples, outputSamples, - numNetworkOutputSamples, numDeviceOutputSamples, + possibleResampling(_networkToOutputResampler, decodedSamples, outputSamples, + numDecodecSamples, numDeviceOutputSamples, _desiredOutputFormat, _outputFormat); // apply stereo reverb at the listener, to the received audio diff --git a/libraries/plugins/src/plugins/CodecPlugin.h b/libraries/plugins/src/plugins/CodecPlugin.h new file mode 100644 index 0000000000..d9e1b947fe --- /dev/null +++ b/libraries/plugins/src/plugins/CodecPlugin.h @@ -0,0 +1,19 @@ +// +// CodecPlugin.h +// plugins/src/plugins +// +// Created by Brad Hefta-Gaub on 6/9/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#pragma once + +#include "Plugin.h" + +class CodecPlugin : public Plugin { +public: + virtual void decode(const QByteArray& encodedBuffer, QByteArray& decodedBuffer) = 0; +}; + diff --git a/libraries/plugins/src/plugins/Forward.h b/libraries/plugins/src/plugins/Forward.h index 036b42f7d7..723c4f321e 100644 --- a/libraries/plugins/src/plugins/Forward.h +++ b/libraries/plugins/src/plugins/Forward.h @@ -13,10 +13,12 @@ enum class PluginType { DISPLAY_PLUGIN, INPUT_PLUGIN, + CODEC_PLUGIN, }; class DisplayPlugin; class InputPlugin; +class CodecPlugin; class Plugin; class PluginContainer; class PluginManager; @@ -25,4 +27,6 @@ using DisplayPluginPointer = std::shared_ptr; using DisplayPluginList = std::vector; using InputPluginPointer = std::shared_ptr; using InputPluginList = std::vector; +using CodecPluginPointer = std::shared_ptr; +using CodecPluginList = std::vector; diff --git a/libraries/plugins/src/plugins/PluginManager.cpp b/libraries/plugins/src/plugins/PluginManager.cpp index 29658eeb6b..fe34d2dbee 100644 --- a/libraries/plugins/src/plugins/PluginManager.cpp +++ b/libraries/plugins/src/plugins/PluginManager.cpp @@ -18,6 +18,7 @@ #include #include "RuntimePlugin.h" +#include "CodecPlugin.h" #include "DisplayPlugin.h" #include "InputPlugin.h" @@ -117,6 +118,7 @@ PluginManager::PluginManager() { // TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class extern DisplayPluginList getDisplayPlugins(); extern InputPluginList getInputPlugins(); +extern CodecPluginList getCodecPlugins(); extern void saveInputPluginSettings(const InputPluginList& plugins); static DisplayPluginList displayPlugins; @@ -202,6 +204,34 @@ const InputPluginList& PluginManager::getInputPlugins() { return inputPlugins; } +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()); + if (codecProvider) { + for (auto codecPlugin : codecProvider->getCodecPlugins()) { + if (codecPlugin->isSupported()) { + codecPlugins.push_back(codecPlugin); + } + } + } + } + + auto& container = PluginContainer::getInstance(); + for (auto plugin : codecPlugins) { + plugin->setContainer(&container); + plugin->init(); + } + }); + return codecPlugins; +} + + void PluginManager::setPreferredDisplayPlugins(const QStringList& displays) { preferredDisplayPlugins = displays; } diff --git a/libraries/plugins/src/plugins/PluginManager.h b/libraries/plugins/src/plugins/PluginManager.h index 7903bdd724..30d52298da 100644 --- a/libraries/plugins/src/plugins/PluginManager.h +++ b/libraries/plugins/src/plugins/PluginManager.h @@ -18,6 +18,7 @@ public: const DisplayPluginList& getDisplayPlugins(); const InputPluginList& getInputPlugins(); + const CodecPluginList& getCodecPlugins(); DisplayPluginList getPreferredDisplayPlugins(); void setPreferredDisplayPlugins(const QStringList& displays); diff --git a/libraries/plugins/src/plugins/RuntimePlugin.h b/libraries/plugins/src/plugins/RuntimePlugin.h index d7bf31ea28..9bf15f344d 100644 --- a/libraries/plugins/src/plugins/RuntimePlugin.h +++ b/libraries/plugins/src/plugins/RuntimePlugin.h @@ -34,3 +34,12 @@ public: #define InputProvider_iid "com.highfidelity.plugins.input" Q_DECLARE_INTERFACE(InputProvider, InputProvider_iid) +class CodecProvider { +public: + virtual ~CodecProvider() {} + virtual CodecPluginList getCodecPlugins() = 0; +}; + +#define CodecProvider_iid "com.highfidelity.plugins.codec" +Q_DECLARE_INTERFACE(CodecProvider, CodecProvider_iid) + diff --git a/plugins/pcmCodec/CMakeLists.txt b/plugins/pcmCodec/CMakeLists.txt new file mode 100644 index 0000000000..162fe557cc --- /dev/null +++ b/plugins/pcmCodec/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# Created by Brad Hefta-Gaub on 6/9/2016 +# Copyright 2016 High Fidelity, Inc. +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html +# + +set(TARGET_NAME pcmCodec) +setup_hifi_plugin() +link_hifi_libraries(shared plugins) diff --git a/plugins/pcmCodec/src/PCMCodecManager.cpp b/plugins/pcmCodec/src/PCMCodecManager.cpp new file mode 100644 index 0000000000..264c139ac6 --- /dev/null +++ b/plugins/pcmCodec/src/PCMCodecManager.cpp @@ -0,0 +1,45 @@ +// +// PCMCodecManager.cpp +// plugins/pcmCodec/src +// +// Created by Brad Hefta-Gaub on 6/9/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include + +#include "PCMCodecManager.h" + +const QString PCMCodecManager::NAME = "PCM Codec"; + +void PCMCodecManager::init() { +} + +void PCMCodecManager::deinit() { +} + +bool PCMCodecManager::activate() { + CodecPlugin::activate(); + return true; +} + +void PCMCodecManager::deactivate() { + CodecPlugin::deactivate(); +} + + +bool PCMCodecManager::isSupported() const { + return true; +} + + +void PCMCodecManager::decode(const QByteArray& encodedBuffer, QByteArray& decodedBuffer) { + // this codec doesn't actually do anything.... + decodedBuffer = encodedBuffer; +} + diff --git a/plugins/pcmCodec/src/PCMCodecManager.h b/plugins/pcmCodec/src/PCMCodecManager.h new file mode 100644 index 0000000000..a8b3e49a2c --- /dev/null +++ b/plugins/pcmCodec/src/PCMCodecManager.h @@ -0,0 +1,40 @@ +// +// PCMCodecManager.h +// plugins/pcmCodec/src +// +// Created by Brad Hefta-Gaub on 6/9/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi__PCMCodecManager_h +#define hifi__PCMCodecManager_h + + +#include + +class PCMCodecManager : public CodecPlugin { + Q_OBJECT + +public: + // Plugin functions + bool isSupported() const override; + const QString& getName() const override { return NAME; } + + void init() override; + void deinit() override; + + /// Called when a plugin is being activated for use. May be called multiple times. + bool activate() override; + /// Called when a plugin is no longer being used. May be called multiple times. + void deactivate() override; + + virtual void decode(const QByteArray& encodedBuffer, QByteArray& decodedBuffer) override; + +private: + static const QString NAME; +}; + +#endif // hifi__PCMCodecManager_h diff --git a/plugins/pcmCodec/src/PCMCodecProvider.cpp b/plugins/pcmCodec/src/PCMCodecProvider.cpp new file mode 100644 index 0000000000..732ed2d57d --- /dev/null +++ b/plugins/pcmCodec/src/PCMCodecProvider.cpp @@ -0,0 +1,44 @@ +// +// Created by Brad Hefta-Gaub on 6/9/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include +#include +#include + +#include +#include + +#include "PCMCodecManager.h" + +class PCMCodecProvider : public QObject, public CodecProvider { + Q_OBJECT + Q_PLUGIN_METADATA(IID CodecProvider_iid FILE "plugin.json") + Q_INTERFACES(CodecProvider) + +public: + PCMCodecProvider(QObject* parent = nullptr) : QObject(parent) {} + virtual ~PCMCodecProvider() {} + + virtual CodecPluginList getCodecPlugins() override { + static std::once_flag once; + std::call_once(once, [&] { + CodecPluginPointer plugin(new PCMCodecManager()); + if (plugin->isSupported()) { + _codecPlugins.push_back(plugin); + } + }); + return _codecPlugins; + } + +private: + CodecPluginList _codecPlugins; +}; + +#include "PCMCodecProvider.moc" diff --git a/plugins/pcmCodec/src/plugin.json b/plugins/pcmCodec/src/plugin.json new file mode 100644 index 0000000000..2d86251845 --- /dev/null +++ b/plugins/pcmCodec/src/plugin.json @@ -0,0 +1 @@ +{"name":"PCM Codec"}