Update plugin parameter instances to use shared pointers and add new parameter creation logic

This commit is contained in:
Mike Solar
2025-12-24 17:51:56 +08:00
parent ef3efce2a8
commit 88ba0e4841
10 changed files with 188 additions and 63 deletions
+15 -3
View File
@@ -1126,11 +1126,23 @@ public:
static const QString kEnabledInput;
OFX::Host::ImageEffect::ImageEffectPlugin* getPlugin();
OFX::Host::ImageEffect::Instance* getPluginInstance() const
{
return plugin_instance_;
}
OFX::Host::ImageEffect::ImageEffectPlugin* getPlugin() const
{
return plugin_instance_ ? plugin_instance_->getPlugin() : nullptr;
}
protected:
// If is set, this is a plugin node.
OFX::Host::ImageEffect::ImageEffectPlugin* plugin= nullptr;
// If set, this node owns a plugin instance.
OFX::Host::ImageEffect::Instance* plugin_instance_ = nullptr;
void setPluginInstance(OFX::Host::ImageEffect::Instance* instance)
{
plugin_instance_ = instance;
}
void InsertInput(const QString &id, NodeValue::Type type,
const QVariant &default_value, InputFlags flags,
+33 -7
View File
@@ -21,14 +21,14 @@
#include "render/rendermanager.h"
#include "render/job/pluginjob.h"
olive::plugin::PluginNode::PluginNode(
OFX::Host::ImageEffect::ImageEffectPlugin *plugin)
OFX::Host::ImageEffect::Instance *plugin)
{
this->plugin = plugin;
auto params = plugin->getDescriptor().getParams();
plugin_instance_=plugin;
auto params=plugin_instance_->getParams();
for (auto param: params) {
NodeValue::Type type;
NodeValue::Type type = NodeValue::kNone;
const std::string &ofxType = param.second->getType();
if (ofxType == kOfxParamTypeInteger) {
@@ -73,6 +73,7 @@ olive::plugin::PluginNode::PluginNode(
}
QString olive::plugin::PluginNode::Name() const
{
const auto *plugin = plugin_instance_->getPlugin();
return plugin->getDescriptor()
.getProps()
.getStringProperty(kOfxPropLabel)
@@ -82,7 +83,11 @@ QString olive::plugin::PluginNode::Name() const
QString olive::plugin::PluginNode::Description() const
{
return plugin->getDescriptor().getProps().getStringProperty(kOfxPropPluginDescription).data();
const auto *plugin = plugin_instance_->getPlugin();
return plugin->getDescriptor()
.getProps()
.getStringProperty(kOfxPropPluginDescription)
.data();
}
void olive::plugin::PluginNode::Value(const NodeValueRow &value,
@@ -90,8 +95,8 @@ void olive::plugin::PluginNode::Value(const NodeValueRow &value,
NodeValueTable *table) const
{
TexturePtr tex = value[kTextureInput].toTexture();
if (tex) {
PluginJob job(plugin, value);
if (tex && plugin_instance_) {
PluginJob job(plugin_instance_, value);
table->Push(NodeValue::kTexture, tex->toJob(job), this);
}
}
@@ -101,5 +106,26 @@ void olive::plugin::PluginNode::pushButtonClicked(QString name)
QString olive::plugin::PluginNode::id() const
{
const auto *plugin = plugin_instance_->getPlugin();
return plugin->getIdentifier().data();
}
olive::Node *olive::plugin::PluginNode::copy() const
{
auto *node = new PluginNode(new OlivePluginInstance(*plugin_instance_));
if (!plugin_instance_) {
return node;
}
const auto &contexts = plugin_instance_->getPlugin()->getContexts();
std::string context = kOfxImageEffectContextFilter;
if (!contexts.empty()) {
if (contexts.find(kOfxImageEffectContextFilter) == contexts.end()) {
context = *contexts.begin();
}
}
node->setPluginInstance(
plugin_instance_->getPlugin()->createInstance(context, node));
return node;
}
+2 -1
View File
@@ -30,7 +30,8 @@ const QString kTextureInput = QStringLiteral("tex_in");
class PluginNode : public olive::Node{
public:
PluginNode(OFX::Host::ImageEffect::ImageEffectPlugin* plugin) ;
PluginNode(OFX::Host::ImageEffect::Instance* plugin) ;
~PluginNode() override;
QString Name() const override;
+28 -2
View File
@@ -31,9 +31,19 @@
using namespace OFX::Host;
using namespace olive::plugin;
namespace olive {
namespace plugin {
class PluginNode;
}
}
void olive::plugin::loadPlugins(QString path)
{
OFX::Host::ImageEffect::PluginCache imageEffectPluginCache(myHost);
std::shared_ptr<OliveHost> host=std::make_shared<OliveHost>();
Current::getInstance().setPluginHost(host);
std::shared_ptr<ImageEffect::PluginCache> imageEffectPluginCache
=std::make_shared<ImageEffect::PluginCache>(*host);
}
OliveHost::~OliveHost()
{
@@ -47,6 +57,18 @@ OliveHost::~OliveHost()
}
}
void OliveHost::destroyInstance(OFX::Host::ImageEffect::Instance* instance)
{
if (!instance) {
return;
}
if (instances_.contains(instance))
{
instances_.removeOne(instance);
delete instance;
}
}
ImageEffect::Descriptor *
OliveHost::makeDescriptor(ImageEffect::ImageEffectPlugin* plugin)
{
@@ -75,7 +97,11 @@ OFX::Host::ImageEffect::Instance* OliveHost::newInstance(void* clientData,
OFX::Host::ImageEffect::ImageEffectPlugin* plugin,
OFX::Host::ImageEffect::Descriptor& desc,
const std::string& context){
ImageEffect::Instance* instance=new OlivePluginInstance(plugin,desc,context,Current::getInstance().interactive());
auto* instance = new OlivePluginInstance(
plugin, desc, context, Current::getInstance().interactive());
if (clientData) {
instance->setNode(static_cast<olive::plugin::PluginNode*>(clientData));
}
instances_.append(instance);
return instance;
};
+1
View File
@@ -39,6 +39,7 @@ class OliveHost: public OFX::Host::ImageEffect::Host{
public:
OliveHost()=default;
~OliveHost() override;
void destroyInstance(OFX::Host::ImageEffect::Instance *instance);
bool pluginSupported(OFX::Host::ImageEffect::ImageEffectPlugin *plugin,
std::string &reason) const override
+29 -1
View File
@@ -150,9 +150,37 @@ void OlivePluginInstance::getRenderScaleRecursive(double &x, double &y) const
}
OFX::Host::Param::Instance *
OlivePluginInstance::newParam(const std::string &name,
OFX::Host::Param::Descriptor &Descriptor)
OFX::Host::Param::Descriptor &desc)
{
if (!node_) {
return nullptr;
}
const std::string &type = desc.getType();
if (type == kOfxParamTypeInteger) {
return new IntegerInstance(node_, desc);
} else if (type == kOfxParamTypeDouble) {
return new DoubleInstance(node_, name, desc);
} else if (type == kOfxParamTypeBoolean) {
return new BooleanInstance(node_, name, desc);
} else if (type == kOfxParamTypeChoice) {
return new ChoiceInstance(node_, name, desc);
} else if (type == kOfxParamTypeRGBA) {
return new RGBAInstance(node_, name, desc);
} else if (type == kOfxParamTypeRGB) {
return new RGBInstance(node_, name, desc);
} else if (type == kOfxParamTypeDouble2D) {
return new Double2DInstance(node_, name, desc);
} else if (type == kOfxParamTypeInteger2D) {
return new Integer2DInstance(node_, name, desc);
} else if (type == kOfxParamTypePushButton) {
return new PushbuttonInstance(node_, name, desc);
}
return nullptr; // 未实现的类型
}
OfxStatus OlivePluginInstance::editBegin(const std::string &name)
{
}
OFX::Host::ImageEffect::ClipInstance *OlivePluginInstance::newClipInstance(
+21 -1
View File
@@ -28,6 +28,7 @@
#include <qlist.h>
namespace olive {
namespace plugin{
class PluginNode;
enum class ErrorType{
Error,
Warning,
@@ -47,6 +48,20 @@ public:
: OFX::Host::ImageEffect::Instance(plugin, desc, context, interactive)
{
}
OlivePluginInstance(OlivePluginInstance& instance)
: Instance(_plugin, *_descriptor, _context, _interactive)
{
_clips=instance._clips;
_created=instance._created;
_clipPrefsDirty=instance._clipPrefsDirty;
_continuousSamples=instance._continuousSamples;
_frameVarying=instance._frameVarying;
_outputPreMultiplication=instance._outputPreMultiplication;
_outputFielding=instance._outputFielding;
_outputFrameRate=instance._outputFrameRate;
}
explicit OlivePluginInstance(Instance & instance):Instance(instance){};
~OlivePluginInstance() override = default;
const std::string &getDefaultOutputFielding() const{
return kOfxImageFieldNone;
@@ -56,6 +71,10 @@ public:
{
this->params_=params;
}
void setNode(PluginNode* node)
{
node_ = node;
}
OFX::Host::ImageEffect::ClipInstance *newClipInstance(
OFX::Host::ImageEffect::Instance *plugin,
OFX::Host::ImageEffect::ClipDescriptor *descriptor,
@@ -102,7 +121,7 @@ public:
/// make a parameter instance
///
/// Client host code needs to implement this
virtual OFX::Host::Param::Instance* newParam(const std::string& name, OFX::Host::Param::Descriptor& Descriptor);
OFX::Host::Param::Instance* newParam(const std::string& name, OFX::Host::Param::Descriptor& Descriptor) override;
/// Triggered when the plug-in calls OfxParameterSuiteV1::paramEditBegin
///
@@ -150,6 +169,7 @@ public:
private:
QList<PersistentErrors> persistentErrors_;
VideoParams params_;
std::shared_ptr<PluginNode> node_ = nullptr;
};
}
}
+42 -42
View File
@@ -23,7 +23,7 @@
#include <QString>
#include <QVector2D>
#include <QVariant>
#include "ofxhParam.h"
#include "node/nodeundo.h"
#include "node/plugins/Plugin.h"
@@ -41,10 +41,10 @@ inline QString ParamChangeLabel(const OFX::Host::Param::Descriptor &descriptor)
class PushbuttonInstance : public OFX::Host::Param::PushbuttonInstance {
protected:
PluginNode* node;
std::shared_ptr<PluginNode> node;
OFX::Host::Param::Descriptor *_descriptor;
public:
PushbuttonInstance(PluginNode *effect, const std::string &name,
PushbuttonInstance(std::shared_ptr<PluginNode> effect, const std::string &name,
OFX::Host::Param::Descriptor &descriptor)
: OFX::Host::Param::PushbuttonInstance(descriptor)
, node(effect)
@@ -55,11 +55,11 @@ public:
class IntegerInstance : public OFX::Host::Param::IntegerInstance {
protected:
PluginNode* _node;
std::shared_ptr<PluginNode> _node;
OFX::Host::Param::Descriptor& _descriptor;
QString id;
public:
IntegerInstance(PluginNode *node, OFX::Host::Param::Descriptor &descriptor)
IntegerInstance(std::shared_ptr<PluginNode>node, OFX::Host::Param::Descriptor &descriptor)
: _node(node), _descriptor(descriptor),
OFX::Host::Param::IntegerInstance(_descriptor){}
OfxStatus get(int &a)
@@ -95,7 +95,7 @@ public:
NodeValue::kInt, data);
auto command = new NodeParamSetSplitStandardValueCommand(
NodeInput(_node, _descriptor.getName().c_str()), split);
NodeInput(_node.get(), _descriptor.getName().c_str()), split);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
id=_descriptor.getName().c_str();
@@ -105,7 +105,7 @@ public:
{
auto command = new MultiUndoCommand();
Node::SetValueAtTime(
NodeInput(_node, _descriptor.getName().c_str()),
NodeInput(_node.get(), _descriptor.getName().c_str()),
rational::fromDouble(time), data, 0, command, true);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
@@ -116,10 +116,10 @@ public:
class DoubleInstance : public OFX::Host::Param::DoubleInstance {
protected:
PluginNode* node;
std::shared_ptr<PluginNode> node;
OFX::Host::Param::Descriptor& _descriptor;
public:
DoubleInstance(PluginNode* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
DoubleInstance(std::shared_ptr<PluginNode> effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
: OFX::Host::Param::DoubleInstance(descriptor)
, node(effect)
, _descriptor(descriptor)
@@ -153,7 +153,7 @@ public:
SplitValue split = NodeValue::split_normal_value_into_track_values(
NodeValue::kFloat, data);
auto command = new NodeParamSetSplitStandardValueCommand(
NodeInput(node, _descriptor.getName().c_str()), split);
NodeInput(node.get(), _descriptor.getName().c_str()), split);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
return kOfxStatOK;
@@ -162,7 +162,7 @@ public:
{
auto command = new MultiUndoCommand();
Node::SetValueAtTime(
NodeInput(node, _descriptor.getName().c_str()),
NodeInput(node.get(), _descriptor.getName().c_str()),
rational::fromDouble(time), data, 0, command, true);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
@@ -180,10 +180,10 @@ public:
class BooleanInstance : public OFX::Host::Param::BooleanInstance {
protected:
PluginNode* node;
std::shared_ptr<PluginNode> node;
OFX::Host::Param::Descriptor& _descriptor;
public:
BooleanInstance(PluginNode* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
BooleanInstance(std::shared_ptr<PluginNode> effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
: OFX::Host::Param::BooleanInstance(descriptor)
, node(effect)
, _descriptor(descriptor)
@@ -217,7 +217,7 @@ public:
SplitValue split = NodeValue::split_normal_value_into_track_values(
NodeValue::kBoolean, data);
auto command = new NodeParamSetSplitStandardValueCommand(
NodeInput(node, _descriptor.getName().c_str()), split);
NodeInput(node.get(), _descriptor.getName().c_str()), split);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
return kOfxStatOK;
@@ -226,7 +226,7 @@ public:
{
auto command = new MultiUndoCommand();
Node::SetValueAtTime(
NodeInput(node, _descriptor.getName().c_str()),
NodeInput(node.get(), _descriptor.getName().c_str()),
rational::fromDouble(time), data, 0, command, true);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
@@ -236,10 +236,10 @@ public:
class ChoiceInstance : public OFX::Host::Param::ChoiceInstance {
protected:
PluginNode* node;
std::shared_ptr<PluginNode> node;
OFX::Host::Param::Descriptor& _descriptor;
public:
ChoiceInstance(PluginNode* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
ChoiceInstance(std::shared_ptr<PluginNode> effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
: OFX::Host::Param::ChoiceInstance(descriptor)
, node(effect)
, _descriptor(descriptor)
@@ -273,7 +273,7 @@ public:
SplitValue split = NodeValue::split_normal_value_into_track_values(
NodeValue::kCombo, data);
auto command = new NodeParamSetSplitStandardValueCommand(
NodeInput(node, _descriptor.getName().c_str()), split);
NodeInput(node.get(), _descriptor.getName().c_str()), split);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
return kOfxStatOK;
@@ -282,7 +282,7 @@ public:
{
auto command = new MultiUndoCommand();
Node::SetValueAtTime(
NodeInput(node, _descriptor.getName().c_str()),
NodeInput(node.get(), _descriptor.getName().c_str()),
rational::fromDouble(time), data, 0, command, true);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
@@ -292,10 +292,10 @@ public:
class RGBAInstance : public OFX::Host::Param::RGBAInstance {
protected:
PluginNode* node;
std::shared_ptr<PluginNode> node;
OFX::Host::Param::Descriptor& _descriptor;
public:
RGBAInstance(PluginNode* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
RGBAInstance(std::shared_ptr<PluginNode> effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
: OFX::Host::Param::RGBAInstance(descriptor)
, node(effect)
, _descriptor(descriptor)
@@ -333,7 +333,7 @@ public:
NodeValue::kColor,
QVariant::fromValue(olive::core::Color(r, g, b, a)));
auto command = new NodeParamSetSplitStandardValueCommand(
NodeInput(node, _descriptor.getName().c_str()), split);
NodeInput(node.get(), _descriptor.getName().c_str()), split);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
return kOfxStatOK;
@@ -342,13 +342,13 @@ public:
{
auto command = new MultiUndoCommand();
const QString name = _descriptor.getName().c_str();
Node::SetValueAtTime(NodeInput(node, name), rational::fromDouble(time),
Node::SetValueAtTime(NodeInput(node.get(), name), rational::fromDouble(time),
r, 0, command, true);
Node::SetValueAtTime(NodeInput(node, name), rational::fromDouble(time),
Node::SetValueAtTime(NodeInput(node.get(), name), rational::fromDouble(time),
g, 1, command, true);
Node::SetValueAtTime(NodeInput(node, name), rational::fromDouble(time),
Node::SetValueAtTime(NodeInput(node.get(), name), rational::fromDouble(time),
b, 2, command, true);
Node::SetValueAtTime(NodeInput(node, name), rational::fromDouble(time),
Node::SetValueAtTime(NodeInput(node.get(), name), rational::fromDouble(time),
a, 3, command, true);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
@@ -359,10 +359,10 @@ public:
class RGBInstance : public OFX::Host::Param::RGBInstance {
protected:
PluginNode* node;
std::shared_ptr<PluginNode> node;
OFX::Host::Param::Descriptor& _descriptor;
public:
RGBInstance(PluginNode* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
RGBInstance(std::shared_ptr<PluginNode> effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
: OFX::Host::Param::RGBInstance(descriptor)
, node(effect)
, _descriptor(descriptor)
@@ -398,7 +398,7 @@ public:
NodeValue::kColor,
QVariant::fromValue(olive::core::Color(r, g, b)));
auto command = new NodeParamSetSplitStandardValueCommand(
NodeInput(node, _descriptor.getName().c_str()), split);
NodeInput(node.get(), _descriptor.getName().c_str()), split);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
return kOfxStatOK;
@@ -407,11 +407,11 @@ public:
{
auto command = new MultiUndoCommand();
const QString name = _descriptor.getName().c_str();
Node::SetValueAtTime(NodeInput(node, name), rational::fromDouble(time),
Node::SetValueAtTime(NodeInput(node.get(), name), rational::fromDouble(time),
r, 0, command, true);
Node::SetValueAtTime(NodeInput(node, name), rational::fromDouble(time),
Node::SetValueAtTime(NodeInput(node.get(), name), rational::fromDouble(time),
g, 1, command, true);
Node::SetValueAtTime(NodeInput(node, name), rational::fromDouble(time),
Node::SetValueAtTime(NodeInput(node.get(), name), rational::fromDouble(time),
b, 2, command, true);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
@@ -421,10 +421,10 @@ public:
class Double2DInstance : public OFX::Host::Param::Double2DInstance {
protected:
PluginNode* node;
std::shared_ptr<PluginNode> node;
OFX::Host::Param::Descriptor& _descriptor;
public:
Double2DInstance(PluginNode* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
Double2DInstance(std::shared_ptr<PluginNode> effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
: OFX::Host::Param::Double2DInstance(descriptor)
, node(effect)
, _descriptor(descriptor)
@@ -455,7 +455,7 @@ public:
SplitValue split = NodeValue::split_normal_value_into_track_values(
NodeValue::kVec2, QVector2D(x, y));
auto command = new NodeParamSetSplitStandardValueCommand(
NodeInput(node, _descriptor.getName().c_str()), split);
NodeInput(node.get(), _descriptor.getName().c_str()), split);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
return kOfxStatOK;
@@ -464,9 +464,9 @@ public:
{
auto command = new MultiUndoCommand();
const QString name = _descriptor.getName().c_str();
Node::SetValueAtTime(NodeInput(node, name), rational::fromDouble(time),
Node::SetValueAtTime(NodeInput(node.get(), name), rational::fromDouble(time),
x, 0, command, true);
Node::SetValueAtTime(NodeInput(node, name), rational::fromDouble(time),
Node::SetValueAtTime(NodeInput(node.get(), name), rational::fromDouble(time),
y, 1, command, true);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
@@ -476,10 +476,10 @@ public:
class Integer2DInstance : public OFX::Host::Param::Integer2DInstance {
protected:
PluginNode* node;
std::shared_ptr<PluginNode> node;
OFX::Host::Param::Descriptor& _descriptor;
public:
Integer2DInstance(PluginNode* effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
Integer2DInstance(std::shared_ptr<PluginNode> effect, const std::string& name, OFX::Host::Param::Descriptor& descriptor)
: OFX::Host::Param::Integer2DInstance(descriptor)
, node(effect)
, _descriptor(descriptor)
@@ -510,7 +510,7 @@ public:
SplitValue split = NodeValue::split_normal_value_into_track_values(
NodeValue::kVec2, QVector2D(x, y));
auto command = new NodeParamSetSplitStandardValueCommand(
NodeInput(node, _descriptor.getName().c_str()), split);
NodeInput(node.get(), _descriptor.getName().c_str()), split);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
return kOfxStatOK;
@@ -519,9 +519,9 @@ public:
{
auto command = new MultiUndoCommand();
const QString name = _descriptor.getName().c_str();
Node::SetValueAtTime(NodeInput(node, name), rational::fromDouble(time),
Node::SetValueAtTime(NodeInput(node.get(), name), rational::fromDouble(time),
x, 0, command, true);
Node::SetValueAtTime(NodeInput(node, name), rational::fromDouble(time),
Node::SetValueAtTime(NodeInput(node.get(), name), rational::fromDouble(time),
y, 1, command, true);
Core::instance()->undo_stack()->push(command,
ParamChangeLabel(_descriptor));
+2 -2
View File
@@ -30,13 +30,13 @@ namespace plugin {
class PluginJob :public AcceleratedJob{
public:
explicit PluginJob(OFX::Host::ImageEffect::ImageEffectPlugin* pluginInstance, NodeValueRow row): AcceleratedJob()
explicit PluginJob(OFX::Host::ImageEffect::Instance* pluginInstance, NodeValueRow row): AcceleratedJob()
{
this->pluginInstance = pluginInstance;
}
private:
OFX::Host::ImageEffect::ImageEffectPlugin *pluginInstance=nullptr;
OFX::Host::ImageEffect::Instance *pluginInstance=nullptr;
QHash<OfxTime, QHash<QString, std::any>> paramsOnTime;
+12 -1
View File
@@ -303,7 +303,18 @@ namespace OFX {
Descriptor &other,
const std::string &context,
bool interactive);
Instance(Instance& instance)
: Base(_properties)
{
_clips = instance._clips;
_created = instance._created;
_clipPrefsDirty = instance._clipPrefsDirty;
_continuousSamples = instance._continuousSamples;
_frameVarying = instance._frameVarying;
_outputPreMultiplication = instance._outputPreMultiplication;
_outputFielding = instance._outputFielding;
_outputFrameRate = instance._outputFrameRate;
}
virtual ~Instance();
/// implemented for Param::SetInstance