Ensure render path sets per-frame output data and handles ROD/bounds correctly.

This commit is contained in:
2026-01-04 22:40:05 +08:00
parent f191486375
commit 3b16824f34
4 changed files with 48 additions and 10 deletions
+28 -1
View File
@@ -20,6 +20,30 @@
#include "render/rendermanager.h"
#include "render/job/pluginjob.h"
static QString ClipLabelForName(const std::string &name,
const OFX::Host::ImageEffect::ClipDescriptor *desc)
{
if (name == kOfxImageEffectSimpleSourceClipName) {
return olive::plugin::PluginNode::tr("Source");
}
if (name == kOfxImageEffectTransitionSourceFromClipName) {
return olive::plugin::PluginNode::tr("From");
}
if (name == kOfxImageEffectTransitionSourceToClipName) {
return olive::plugin::PluginNode::tr("To");
}
if (desc) {
const std::string &label =
desc->getProps().getStringProperty(kOfxPropLabel);
if (!label.empty()) {
return QString::fromStdString(label);
}
}
return QString::fromStdString(name);
}
olive::plugin::PluginNode::PluginNode(
OFX::Host::ImageEffect::Instance *plugin)
{
@@ -76,11 +100,14 @@ olive::plugin::PluginNode::PluginNode(
if (entry.first == kOfxImageEffectOutputClipName) {
continue;
}
AddInput(entry.first.data(), NodeValue::kTexture);
QString input_id = QString::fromStdString(entry.first);
AddInput(input_id, NodeValue::kTexture);
SetInputName(input_id, ClipLabelForName(entry.first, entry.second));
has_texture_input = true;
}
if (!has_texture_input) {
AddInput(kTextureInput, NodeValue::kTexture);
SetInputName(kTextureInput, tr("Texture"));
}
}
QString olive::plugin::PluginNode::Name() const
+11 -7
View File
@@ -123,19 +123,23 @@ OFX::Host::ImageEffect::Image *
olive::plugin::OliveClipInstance::getImage(OfxTime time,
const OfxRectD *optionalBounds)
{
OfxRectI bounds = {0, 0, params_.width(), params_.height()};
OfxRectD rod_d = getRegionOfDefinition(time);
OfxRectI rod = { static_cast<int>(std::floor(rod_d.x1)),
static_cast<int>(std::floor(rod_d.y1)),
static_cast<int>(std::ceil(rod_d.x2)),
static_cast<int>(std::ceil(rod_d.y2)) };
OfxRectI bounds = rod;
if (optionalBounds) {
bounds.x1 = static_cast<int>(std::floor(optionalBounds->x1));
bounds.y1 = static_cast<int>(std::floor(optionalBounds->y1));
bounds.x2 = static_cast<int>(std::ceil(optionalBounds->x2));
bounds.y2 = static_cast<int>(std::ceil(optionalBounds->y2));
}
OfxRectD rod_d = getRegionOfDefinition(time);
OfxRectI rod = { static_cast<int>(std::floor(rod_d.x1)),
static_cast<int>(std::floor(rod_d.y1)),
static_cast<int>(std::ceil(rod_d.x2)),
static_cast<int>(std::ceil(rod_d.y2)) };
// Clamp bounds to ROD to keep host/plugin coords consistent.
bounds.x1 = std::max(bounds.x1, rod.x1);
bounds.y1 = std::max(bounds.y1, rod.y1);
bounds.x2 = std::min(bounds.x2, rod.x2);
bounds.y2 = std::min(bounds.y2, rod.y2);
if (name_ == "Output") {
if (!images_.contains(time)) {
+4
View File
@@ -65,6 +65,10 @@ public:
void setRegionOfDefinition(OfxRectD regionOfDefinition, OfxTime time);
void setDefaultRegionOfDefinition(OfxRectD regionOfDefinition);
void setParams(const VideoParams &params)
{
params_ = params;
}
# ifdef OFX_SUPPORTS_OPENGLRENDER
OFX::Host::ImageEffect::Texture* loadTexture(OfxTime time, const char *format, const OfxRectD *optionalBounds) { return NULL; };
# endif
+5 -2
View File
@@ -220,8 +220,8 @@ void olive::plugin::PluginRenderer::RenderPlugin(TexturePtr src, olive::plugin::
renderWindow.x1 = renderWindow.y1 = 0;
renderWindow.x2 = src->params().width();
renderWindow.y2 = src->params().height();
renderWindow.x2 = destination_params.width();
renderWindow.y2 = destination_params.height();
/// RoI is in canonical coords,
OfxRectD regionOfInterest;
@@ -253,6 +253,9 @@ void olive::plugin::PluginRenderer::RenderPlugin(TexturePtr src, olive::plugin::
// call get region of interest on each of the inputs
OfxTime frame = 0;
clip->setParams(destination_params);
clip->setRegionOfDefinition(regionOfDefinition, frame);
const NodeValueRow &values = job.GetValues();
const auto &clips = instance->getDescriptor().getClips();
for (const auto &entry : clips) {