solve some bugs
This commit is contained in:
@@ -140,6 +140,11 @@ Decoder::RetrieveAudio(SampleBuffer &dest, const TimeRange &range,
|
||||
return kInvalid;
|
||||
}
|
||||
|
||||
if (params.sample_rate() <= 0 || params.channel_count() <= 0) {
|
||||
qWarning() << "Invalid audio parameters, skipping audio retrieve";
|
||||
return kInvalid;
|
||||
}
|
||||
|
||||
// Get conform state from ConformManager
|
||||
ConformManager::Conform conform =
|
||||
ConformManager::instance()->GetConformState(
|
||||
|
||||
+5
-3
@@ -287,9 +287,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (!no_plugin->IsSet()) {
|
||||
olive::plugin::loadPlugins("plugins");
|
||||
}
|
||||
const bool load_plugins = !no_plugin->IsSet();
|
||||
|
||||
if (crash_option->IsSet()) {
|
||||
startup_params.set_crash_on_startup(true);
|
||||
@@ -341,6 +339,10 @@ int main(int argc, char *argv[])
|
||||
gui_app->setWindowIcon(QIcon(QStringLiteral(":/graphics/oak-logo.png")));
|
||||
}
|
||||
|
||||
if (load_plugins) {
|
||||
olive::plugin::loadPlugins("plugins");
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// On Windows, users seem to frequently run into a crash caused by their graphics driver not
|
||||
// supporting framebuffers, which we require. I personally have only been able to recreate this
|
||||
|
||||
@@ -88,7 +88,6 @@ void NodeFactory::Initialize()
|
||||
library_.append(created_node);
|
||||
}
|
||||
|
||||
olive::plugin::loadPlugins(QString());
|
||||
RegisterPluginNodes();
|
||||
|
||||
}
|
||||
@@ -237,9 +236,13 @@ void NodeFactory::RegisterPluginNodes()
|
||||
}
|
||||
|
||||
const auto &contexts = image_effect->getContexts();
|
||||
if (contexts.empty()) {
|
||||
qWarning() << "Skipping OFX plugin with no contexts:"
|
||||
<< plugin_id;
|
||||
continue;
|
||||
}
|
||||
std::string context = kOfxImageEffectContextFilter;
|
||||
if (!contexts.empty() &&
|
||||
contexts.find(kOfxImageEffectContextFilter) == contexts.end()) {
|
||||
if (contexts.find(kOfxImageEffectContextFilter) == contexts.end()) {
|
||||
context = *contexts.begin();
|
||||
}
|
||||
|
||||
|
||||
+24
-15
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "render/rendermanager.h"
|
||||
#include "render/job/pluginjob.h"
|
||||
#include "pluginSupport/OlivePluginInstance.h"
|
||||
static QString ClipLabelForName(const std::string &name,
|
||||
const OFX::Host::ImageEffect::ClipDescriptor *desc)
|
||||
{
|
||||
@@ -222,22 +223,30 @@ QString olive::plugin::PluginNode::id() const
|
||||
return plugin->getIdentifier().data();
|
||||
}
|
||||
|
||||
olive::Node *olive::plugin::PluginNode::copy() const
|
||||
{
|
||||
auto *node = new PluginNode(new OlivePluginInstance(*plugin_instance_));
|
||||
if (!plugin_instance_) {
|
||||
return node;
|
||||
}
|
||||
olive::Node *olive::plugin::PluginNode::copy() const
|
||||
{
|
||||
if (!plugin_instance_) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto &contexts = plugin_instance_->getPlugin()->getContexts();
|
||||
std::string context = kOfxImageEffectContextFilter;
|
||||
if (!contexts.empty()) {
|
||||
if (contexts.find(kOfxImageEffectContextFilter) == contexts.end()) {
|
||||
const auto &contexts = plugin_instance_->getPlugin()->getContexts();
|
||||
std::string context = kOfxImageEffectContextFilter;
|
||||
if (!contexts.empty() &&
|
||||
contexts.find(kOfxImageEffectContextFilter) == contexts.end()) {
|
||||
context = *contexts.begin();
|
||||
}
|
||||
}
|
||||
|
||||
node->setPluginInstance(
|
||||
plugin_instance_->getPlugin()->createInstance(context, node));
|
||||
return node;
|
||||
}
|
||||
auto *instance =
|
||||
plugin_instance_->getPlugin()->createInstance(context, nullptr);
|
||||
if (!instance) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto *node = new PluginNode(instance);
|
||||
if (auto *olive_instance =
|
||||
dynamic_cast<OlivePluginInstance *>(instance)) {
|
||||
olive_instance->setNode(
|
||||
std::shared_ptr<PluginNode>(node, [](PluginNode *) {}));
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -124,7 +124,15 @@ const std::string &olive::plugin::OliveClipInstance::getFieldOrder() const
|
||||
}
|
||||
bool olive::plugin::OliveClipInstance::getConnected() const
|
||||
{
|
||||
return params_.format() == PixelFormat::INVALID;
|
||||
if (name_ == kOfxImageEffectOutputClipName) {
|
||||
return true;
|
||||
}
|
||||
#ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
if (!input_textures_.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return !images_.isEmpty();
|
||||
}
|
||||
double olive::plugin::OliveClipInstance::getUnmappedFrameRate() const
|
||||
{
|
||||
|
||||
@@ -71,15 +71,20 @@ void AddPluginPathsFromEnv(OFX::Host::PluginCache *cache, const char *env_var)
|
||||
|
||||
void olive::plugin::loadPlugins(QString path)
|
||||
{
|
||||
std::shared_ptr<OliveHost> host = std::make_shared<OliveHost>();
|
||||
Current::getInstance().setPluginHost(host);
|
||||
|
||||
std::shared_ptr<OliveHost> host = Current::getInstance().pluginHost();
|
||||
std::shared_ptr<ImageEffect::PluginCache> imageEffectPluginCache =
|
||||
std::make_shared<ImageEffect::PluginCache>(*host);
|
||||
Current::getInstance().setPluginCache(imageEffectPluginCache);
|
||||
Current::getInstance().pluginCache();
|
||||
|
||||
imageEffectPluginCache->registerInCache(
|
||||
*OFX::Host::PluginCache::getPluginCache());
|
||||
if (!host || !imageEffectPluginCache) {
|
||||
host = std::make_shared<OliveHost>();
|
||||
Current::getInstance().setPluginHost(host);
|
||||
|
||||
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");
|
||||
|
||||
|
||||
@@ -53,6 +53,14 @@ public:
|
||||
bool pluginSupported(OFX::Host::ImageEffect::ImageEffectPlugin *plugin,
|
||||
std::string &reason) const override
|
||||
{
|
||||
if (!plugin) {
|
||||
reason = "null plugin";
|
||||
return false;
|
||||
}
|
||||
if (plugin->getContexts().empty()) {
|
||||
reason = "no supported contexts (describe failed)";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@ public:
|
||||
{
|
||||
}
|
||||
OlivePluginInstance(OlivePluginInstance& instance)
|
||||
: Instance(_plugin, *_descriptor, _context, _interactive)
|
||||
: Instance(instance._plugin, *instance._descriptor, instance._context,
|
||||
instance._interactive)
|
||||
{
|
||||
_clips=instance._clips;
|
||||
_created=instance._created;
|
||||
|
||||
@@ -68,6 +68,11 @@ public:
|
||||
virtual Color GetPixelFromTexture(olive::Texture *texture,
|
||||
const QPointF &pt) override;
|
||||
|
||||
QOpenGLContext *context() const
|
||||
{
|
||||
return context_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void Blit(QVariant shader, olive::AcceleratedJob& job,
|
||||
olive::Texture *destination,
|
||||
|
||||
@@ -296,17 +296,6 @@ void olive::plugin::PluginRenderer::RenderPlugin(TexturePtr src, olive::plugin::
|
||||
if (olive_instance) {
|
||||
olive_instance->setOpenGLEnabled(use_opengl);
|
||||
}
|
||||
OfxStatus stat;
|
||||
stat = instance->createInstanceAction();
|
||||
if(stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
|
||||
return;
|
||||
}
|
||||
// now we need to to call getClipPreferences on the instance so that it does the clip component/depth
|
||||
// logic and caches away the components and depth on each clip.
|
||||
bool ok = instance->getClipPreferences();
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
// current render scale of 1
|
||||
OfxPointD renderScale;
|
||||
@@ -334,37 +323,22 @@ void olive::plugin::PluginRenderer::RenderPlugin(TexturePtr src, olive::plugin::
|
||||
|
||||
|
||||
int numFramesToRender=1;
|
||||
stat = instance->beginRenderAction(0, numFramesToRender,
|
||||
1.0, false, renderScale, true,
|
||||
interactive);
|
||||
if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
if (use_opengl) {
|
||||
instance->contextAttachedAction();
|
||||
AttachOutputTexture(destination);
|
||||
}
|
||||
#endif
|
||||
|
||||
OliveClipInstance *clip=dynamic_cast<plugin::OliveClipInstance *>(instance->getClip("Output"));
|
||||
if (!clip) {
|
||||
#ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
if (use_opengl) {
|
||||
DetachOutputTexture();
|
||||
instance->contextDetachedAction();
|
||||
}
|
||||
#endif
|
||||
instance->endRenderAction(0, numFramesToRender, 1.0, interactive, renderScale, true,interactive
|
||||
);
|
||||
return;
|
||||
}
|
||||
clip->setParams(destination_params);
|
||||
|
||||
OfxStatus stat;
|
||||
stat = instance->createInstanceAction();
|
||||
if(stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
|
||||
return;
|
||||
}
|
||||
|
||||
// call get region of interest on each of the inputs
|
||||
OfxTime frame = 0;
|
||||
|
||||
clip->setParams(destination_params);
|
||||
clip->setRegionOfDefinition(regionOfDefinition, frame);
|
||||
clip->setOutputTexture(destination, frame);
|
||||
|
||||
@@ -388,6 +362,27 @@ void olive::plugin::PluginRenderer::RenderPlugin(TexturePtr src, olive::plugin::
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now we need to call getClipPreferences on the instance so that it does
|
||||
// the clip component/depth logic and caches away the components and depth.
|
||||
bool ok = instance->getClipPreferences();
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
stat = instance->beginRenderAction(0, numFramesToRender,
|
||||
1.0, false, renderScale, true,
|
||||
interactive);
|
||||
if (stat != kOfxStatOK && stat != kOfxStatReplyDefault) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef OFX_SUPPORTS_OPENGLRENDER
|
||||
if (use_opengl) {
|
||||
instance->contextAttachedAction();
|
||||
AttachOutputTexture(destination);
|
||||
}
|
||||
#endif
|
||||
// get the RoI for each input clip
|
||||
// the regions of interest for each input clip are returned in a std::map
|
||||
// on a real host, these will be the regions of each input clip that the
|
||||
|
||||
@@ -44,8 +44,7 @@ public:
|
||||
virtual ~PluginRenderer() override{};
|
||||
void AttachOutputTexture(olive::Texture *texture);
|
||||
void DetachOutputTexture();
|
||||
protected:
|
||||
virtual void RenderPlugin(TexturePtr src, olive::plugin::PluginJob& job,
|
||||
void RenderPlugin(TexturePtr src, olive::plugin::PluginJob& job,
|
||||
olive::Texture *destination,
|
||||
olive::VideoParams destination_params,
|
||||
bool clear_destination, bool interactive);
|
||||
|
||||
@@ -393,8 +393,9 @@ void PreviewAutoCacher::StartCachingAudioRange(ViewerOutput *context,
|
||||
cache->ClearRequestRange(range);
|
||||
|
||||
pending_audio_jobs_.push_back({ node, context, cache, range });
|
||||
audio_cache_data_[cache].job_tracker.insert(range,
|
||||
copier_->GetGraphChangeTime());
|
||||
AudioCacheData &data = audio_cache_data_[cache];
|
||||
data.context = context;
|
||||
data.job_tracker.insert(range, copier_->GetGraphChangeTime());
|
||||
TryRender();
|
||||
}
|
||||
|
||||
@@ -675,6 +676,15 @@ RenderTicketPtr PreviewAutoCacher::RenderAudio(Node *node,
|
||||
running_audio_tasks_.append(watcher);
|
||||
|
||||
AudioParams p = context->GetAudioParams();
|
||||
const bool invalid_params =
|
||||
(p.sample_rate() <= 0 || p.channel_count() <= 0);
|
||||
if (invalid_params) {
|
||||
AudioParams fallback(
|
||||
OLIVE_CONFIG("DefaultSequenceAudioFrequency").toInt(),
|
||||
OLIVE_CONFIG("DefaultSequenceAudioLayout").toULongLong(),
|
||||
ViewerOutput::kDefaultSampleFormat);
|
||||
p = fallback;
|
||||
}
|
||||
p.set_format(ViewerOutput::kDefaultSampleFormat);
|
||||
|
||||
RenderManager::RenderAudioParams rap(node, r, p, RenderMode::kOffline);
|
||||
@@ -692,13 +702,17 @@ void PreviewAutoCacher::ConformFinished()
|
||||
// Got an audio conform, requeue all the audio currently needing a conform
|
||||
last_conform_task_.Acquire();
|
||||
|
||||
qDebug() << "CONFORM RESPONSE TEMPORARILY DISABLED";
|
||||
/*for (auto it=audio_cache_data_.begin(); it!=audio_cache_data_.end(); it++) {
|
||||
foreach (const TimeRange &range, it.value().needs_conform) {
|
||||
it.key()->Request(range);
|
||||
}
|
||||
it.value().needs_conform.clear();
|
||||
}*/
|
||||
for (auto it = audio_cache_data_.begin(); it != audio_cache_data_.end();
|
||||
it++) {
|
||||
if (!it.key() || !it.value().context) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const TimeRange &range : it.value().needs_conform) {
|
||||
it.key()->Request(it.value().context, range);
|
||||
}
|
||||
it.value().needs_conform.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::CacheProxyTaskCancelled()
|
||||
|
||||
@@ -186,6 +186,7 @@ private:
|
||||
struct AudioCacheData {
|
||||
RenderJobTracker job_tracker;
|
||||
TimeRangeList needs_conform;
|
||||
ViewerOutput *context = nullptr;
|
||||
};
|
||||
|
||||
std::list<VideoJob> pending_video_jobs_;
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "node/block/transition/transition.h"
|
||||
#include "node/project.h"
|
||||
#include "rendermanager.h"
|
||||
#include "render/opengl/openglrenderer.h"
|
||||
#include "render/plugin/pluginrenderer.h"
|
||||
#include "pluginSupport/OliveClip.h"
|
||||
#include "pluginSupport/OliveHost.h"
|
||||
|
||||
@@ -606,6 +608,44 @@ void RenderProcessor::ProcessFrameGeneration(TexturePtr destination,
|
||||
destination->Upload(frame->data(), frame->linesize_pixels());
|
||||
}
|
||||
|
||||
TexturePtr RenderProcessor::ProcessPluginJob(TexturePtr texture,
|
||||
TexturePtr destination,
|
||||
const Node *node)
|
||||
{
|
||||
(void)node;
|
||||
|
||||
if (!render_ctx_ || !texture || !destination) {
|
||||
return destination;
|
||||
}
|
||||
|
||||
auto *plugin_job =
|
||||
dynamic_cast<plugin::PluginJob *>(texture->job());
|
||||
if (!plugin_job) {
|
||||
return destination;
|
||||
}
|
||||
|
||||
if (!plugin_renderer_) {
|
||||
auto *gl = dynamic_cast<OpenGLRenderer *>(render_ctx_);
|
||||
if (!gl || !gl->context()) {
|
||||
return destination;
|
||||
}
|
||||
|
||||
plugin_renderer_ = std::make_unique<plugin::PluginRenderer>();
|
||||
plugin_renderer_->Init(gl->context());
|
||||
plugin_renderer_->PostInit();
|
||||
}
|
||||
|
||||
plugin_renderer_->RenderPlugin(
|
||||
texture,
|
||||
*plugin_job,
|
||||
destination.get(),
|
||||
destination->params(),
|
||||
true,
|
||||
false);
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
TexturePtr RenderProcessor::ProcessVideoCacheJob(const CacheJob *val)
|
||||
{
|
||||
FramePtr frame = FrameHashCache::LoadCacheFrame(val->GetFilename());
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#define RENDERPROCESSOR_H
|
||||
|
||||
#include "node/block/clip/clip.h"
|
||||
#include <memory>
|
||||
#include "node/traverser.h"
|
||||
#include "render/renderer.h"
|
||||
#include "rendercache.h"
|
||||
@@ -28,6 +29,10 @@
|
||||
namespace olive
|
||||
{
|
||||
|
||||
namespace plugin {
|
||||
class PluginRenderer;
|
||||
}
|
||||
|
||||
class RenderProcessor : public NodeTraverser {
|
||||
public:
|
||||
virtual NodeValueDatabase GenerateDatabase(const Node *node,
|
||||
@@ -66,6 +71,10 @@ protected:
|
||||
const Node *node,
|
||||
const GenerateJob *job) override;
|
||||
|
||||
virtual TexturePtr ProcessPluginJob(TexturePtr texture,
|
||||
TexturePtr destination,
|
||||
const Node *node) override;
|
||||
|
||||
virtual TexturePtr ProcessVideoCacheJob(const CacheJob *val) override;
|
||||
|
||||
virtual TexturePtr CreateTexture(const VideoParams &p) override;
|
||||
@@ -100,6 +109,8 @@ private:
|
||||
|
||||
Renderer *render_ctx_;
|
||||
|
||||
std::unique_ptr<olive::plugin::PluginRenderer> plugin_renderer_;
|
||||
|
||||
DecoderCache *decoder_cache_;
|
||||
|
||||
ShaderCache *shader_cache_;
|
||||
|
||||
@@ -571,10 +571,14 @@ void ViewerWidget::UpdateAudioProcessor()
|
||||
CloseAudioProcessor();
|
||||
|
||||
AudioParams ap = GetConnectedNode()->GetAudioParams();
|
||||
if (ap.sample_rate() <= 0 || ap.channel_count() <= 0) {
|
||||
ap = AudioParams(
|
||||
OLIVE_CONFIG("DefaultSequenceAudioFrequency").toInt(),
|
||||
OLIVE_CONFIG("DefaultSequenceAudioLayout").toULongLong(),
|
||||
ViewerOutput::kDefaultSampleFormat);
|
||||
}
|
||||
ap.set_format(ViewerOutput::kDefaultSampleFormat);
|
||||
|
||||
uint64_t layout =
|
||||
OLIVE_CONFIG("AudioOutputChannelLayout").toULongLong();
|
||||
AudioParams packed(
|
||||
OLIVE_CONFIG("AudioOutputSampleRate").toInt(),
|
||||
OLIVE_CONFIG("AudioOutputChannelLayout").toULongLong(),
|
||||
|
||||
+17
-3
@@ -211,6 +211,9 @@ namespace OFX {
|
||||
OFX::Host::Property::Set inarg(inargspec);
|
||||
|
||||
PluginHandle *ph = getPluginHandle();
|
||||
if (!ph) {
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<ImageEffect::Descriptor> newContext( gImageEffectHost->makeDescriptor(getDescriptor(), this));
|
||||
|
||||
OfxStatus stat;
|
||||
@@ -238,7 +241,10 @@ namespace OFX {
|
||||
/// (not because we are expecting the results to change, but because plugin
|
||||
/// might get confused otherwise), then a describe_in_context
|
||||
|
||||
getPluginHandle();
|
||||
PluginHandle *ph = getPluginHandle();
|
||||
if (!ph) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Descriptor *desc = getContext(context);
|
||||
|
||||
@@ -322,7 +328,16 @@ namespace OFX {
|
||||
|
||||
/// whether we support this plugin.
|
||||
bool PluginCache::pluginSupported(OFX::Host::Plugin *p, std::string &reason) const {
|
||||
return gImageEffectHost->pluginSupported(dynamic_cast<OFX::Host::ImageEffect::ImageEffectPlugin *>(p), reason);
|
||||
if (!gImageEffectHost) {
|
||||
reason = "host not initialized";
|
||||
return false;
|
||||
}
|
||||
auto *plugin = dynamic_cast<OFX::Host::ImageEffect::ImageEffectPlugin *>(p);
|
||||
if (!plugin) {
|
||||
reason = "not an image effect plugin";
|
||||
return false;
|
||||
}
|
||||
return gImageEffectHost->pluginSupported(plugin, reason);
|
||||
}
|
||||
|
||||
/// get the plugin by label. vermaj and vermin can be specified. if they are not it will
|
||||
@@ -589,4 +604,3 @@ namespace OFX {
|
||||
} // Host
|
||||
|
||||
} // OFX
|
||||
|
||||
|
||||
Reference in New Issue
Block a user