完成1
This commit is contained in:
+5
-3
@@ -3,9 +3,11 @@
|
||||
下面是 README 里 OpenFX TODO 的中文翻译与详细说明。每条都尽量解释“是什么、为什么需要、该往哪里改”。
|
||||
|
||||
1) 实现插件发现与加载流程
|
||||
- 现状:`app/pluginSupport/OliveHost.cpp` 里只创建了 Host 和 PluginCache,但没有扫描路径/加载 OFX 插件。
|
||||
- 为什么需要:没有完整的发现/加载,就无法让用户看到插件或实例化插件。
|
||||
- 可能改动:补全 `loadPlugins()`,遍历指定目录(如 OFX 标准路径),调用 OpenFX 的插件缓存加载逻辑,注册可用插件并让 UI/节点系统可用。
|
||||
- 现状:`app/node/factory.cpp` 自己临时创建 Host/PluginCache 并扫描,`loadPlugins()` 只是一段占位逻辑。
|
||||
- 为什么需要:没有统一的发现/加载入口,插件扫描路径和实例化流程很容易分叉,后续维护困难。
|
||||
- 已完成:
|
||||
- 在 `app/pluginSupport/OliveHost.cpp` 实现 `loadPlugins()`:创建 Host/PluginCache,注册到 OFX 全局缓存,设置 host path,按需追加路径并扫描插件文件。
|
||||
- `app/node/factory.cpp` 统一通过 `loadPlugins()` 初始化插件,再从全局缓存取插件注册到节点库。
|
||||
|
||||
2) 输出剪辑图像的缓冲区管理(Output Clip)
|
||||
- 现状:`OliveClipInstance::getImage()` 返回空的 OFX Image,没有分配像素内存,也没有设置 `kOfxImagePropData`。
|
||||
|
||||
@@ -88,12 +88,7 @@ void NodeFactory::Initialize()
|
||||
library_.append(created_node);
|
||||
}
|
||||
|
||||
std::shared_ptr<olive::plugin::OliveHost> host=std::make_shared<olive::plugin::OliveHost>();
|
||||
Current::getInstance().setPluginHost(host);
|
||||
std::shared_ptr<OFX::Host::ImageEffect::PluginCache> plugin_cache=std::make_shared<OFX::Host::ImageEffect::PluginCache>(*host);
|
||||
plugin_cache->registerInCache(*OFX::Host::PluginCache::getPluginCache());
|
||||
OFX::Host::PluginCache::getPluginCache()->scanPluginFiles();
|
||||
|
||||
olive::plugin::loadPlugins(QString());
|
||||
|
||||
for (auto plugin : OFX::Host::PluginCache::getPluginCache()->getPlugins()) {
|
||||
plugin::PluginNode *plugin_node=new plugin::PluginNode(dynamic_cast<OFX::Host::ImageEffect::ImageEffectPlugin*>(plugin));
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <ofxhBinary.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include "OliveHost.h"
|
||||
|
||||
@@ -41,13 +42,64 @@ class PluginNode;
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
void AddPluginPath(OFX::Host::PluginCache *cache, const QString &path, bool recurse = true)
|
||||
{
|
||||
if (!cache || path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
QDir dir(path);
|
||||
if (!dir.exists()) {
|
||||
return;
|
||||
}
|
||||
cache->addFileToPath(dir.canonicalPath().toStdString(), recurse);
|
||||
}
|
||||
|
||||
void AddPluginPathsFromEnv(OFX::Host::PluginCache *cache, const char *env_var)
|
||||
{
|
||||
QString raw = qEnvironmentVariable(env_var);
|
||||
if (raw.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
const QChar separator = QDir::listSeparator();
|
||||
const QStringList paths = raw.split(separator, Qt::SkipEmptyParts);
|
||||
for (const QString &path : paths) {
|
||||
AddPluginPath(cache, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void olive::plugin::loadPlugins(QString path)
|
||||
{
|
||||
std::shared_ptr<OliveHost> host=std::make_shared<OliveHost>();
|
||||
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);
|
||||
|
||||
std::shared_ptr<ImageEffect::PluginCache> imageEffectPluginCache =
|
||||
std::make_shared<ImageEffect::PluginCache>(*host);
|
||||
Current::getInstance().setPluginCache(imageEffectPluginCache);
|
||||
|
||||
imageEffectPluginCache->registerInCache(
|
||||
*OFX::Host::PluginCache::getPluginCache());
|
||||
OFX::Host::PluginCache *cache = OFX::Host::PluginCache::getPluginCache();
|
||||
cache->setPluginHostPath("Olive");
|
||||
|
||||
const QString home_path = QDir::homePath();
|
||||
AddPluginPath(cache, QDir(home_path).filePath(".OFX/Plugins"));
|
||||
AddPluginPath(cache, QDir(home_path).filePath(".local/share/OFX/Plugins"));
|
||||
AddPluginPath(cache, QDir(home_path).filePath(".local/share/olive/ofx/Plugins"));
|
||||
|
||||
const QString app_dir = QCoreApplication::applicationDirPath();
|
||||
AddPluginPath(cache, QDir(app_dir).filePath("../OFX/Plugins"));
|
||||
AddPluginPath(cache, QDir(app_dir).filePath("../share/olive/ofx/Plugins"));
|
||||
AddPluginPath(cache, QDir(app_dir).filePath("../lib/olive/ofx/Plugins"));
|
||||
|
||||
AddPluginPathsFromEnv(cache, "OLIVE_OFX_PLUGIN_PATH");
|
||||
AddPluginPathsFromEnv(cache, "OLIVE_PLUGIN_PATH");
|
||||
|
||||
if (!path.isEmpty()) {
|
||||
AddPluginPath(cache, path, true);
|
||||
}
|
||||
cache->scanPluginFiles();
|
||||
}
|
||||
OliveHost::~OliveHost()
|
||||
{
|
||||
|
||||
@@ -410,6 +410,7 @@ bool OlivePluginInstance::progressUpdate(double t)
|
||||
return !progress_cancelled_;
|
||||
}
|
||||
|
||||
#ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
OfxStatus OlivePluginInstance::contextAttachedAction()
|
||||
{
|
||||
if (!open_gl_enabled_) {
|
||||
@@ -425,6 +426,7 @@ OfxStatus OlivePluginInstance::contextDetachedAction()
|
||||
}
|
||||
return kOfxStatOK;
|
||||
}
|
||||
#endif
|
||||
|
||||
double OlivePluginInstance::timeLineGetTime()
|
||||
{
|
||||
|
||||
@@ -341,10 +341,12 @@ void olive::plugin::PluginRenderer::RenderPlugin(TexturePtr src, olive::plugin::
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
if (use_opengl) {
|
||||
instance->contextAttachedAction();
|
||||
AttachOutputTexture(destination);
|
||||
}
|
||||
#endif
|
||||
|
||||
OliveClipInstance *clip=dynamic_cast<plugin::OliveClipInstance *>(instance->getClip("Output"));
|
||||
if (!clip) {
|
||||
@@ -412,8 +414,10 @@ void olive::plugin::PluginRenderer::RenderPlugin(TexturePtr src, olive::plugin::
|
||||
}
|
||||
} else {
|
||||
if (!destination || !destination->id().isValid()) {
|
||||
#ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
DetachOutputTexture();
|
||||
instance->contextDetachedAction();
|
||||
#endif
|
||||
instance->endRenderAction(frame, numFramesToRender, 1.0, interactive,
|
||||
renderScale, true, interactive);
|
||||
return;
|
||||
@@ -432,8 +436,10 @@ void olive::plugin::PluginRenderer::RenderPlugin(TexturePtr src, olive::plugin::
|
||||
} else {
|
||||
AVFramePtr frame_ptr =
|
||||
ReadbackTextureToFrame(destination, destination_params);
|
||||
#ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
DetachOutputTexture();
|
||||
instance->contextDetachedAction();
|
||||
#endif
|
||||
if (frame_ptr) {
|
||||
AVFramePtr converted =
|
||||
ConvertFrameIfNeeded(frame_ptr, destination_params);
|
||||
|
||||
Reference in New Issue
Block a user