diff --git a/app/node/input.cpp b/app/node/input.cpp index b86dea364..eb9c79ee1 100644 --- a/app/node/input.cpp +++ b/app/node/input.cpp @@ -283,7 +283,7 @@ void NodeInput::set_maximum(const QVariant &max) has_maximum_ = true; } -void NodeInput::CopyValues(NodeInput *source, NodeInput *dest, bool include_connections) +void NodeInput::CopyValues(NodeInput *source, NodeInput *dest, bool include_connections, bool lock_connections) { Q_ASSERT(source->id() == dest->id()); @@ -295,7 +295,7 @@ void NodeInput::CopyValues(NodeInput *source, NodeInput *dest, bool include_conn // Copy connections if (include_connections && source->get_connected_output() != nullptr) { - ConnectEdge(source->get_connected_output(), dest); + ConnectEdge(source->get_connected_output(), dest, lock_connections); } // If these inputs are an array, copy the subparams too diff --git a/app/node/input.h b/app/node/input.h index a9db08aa6..4885833a4 100644 --- a/app/node/input.h +++ b/app/node/input.h @@ -121,7 +121,7 @@ public: /** * @brief Copy all values including keyframe information and connections from another NodeInput */ - static void CopyValues(NodeInput* source, NodeInput* dest, bool include_connections = true); + static void CopyValues(NodeInput* source, NodeInput* dest, bool include_connections = true, bool lock_connections = true); signals: void ValueChanged(const rational& start, const rational& end); diff --git a/app/node/node.cpp b/app/node/node.cpp index 527e5f2e1..cec2712fa 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -182,7 +182,7 @@ void Node::CopyInputs(Node *source, Node *destination, bool include_connections) if (src->dependent()) { NodeInput* dst = static_cast(dst_param.at(i)); - NodeInput::CopyValues(src, dst, include_connections); + NodeInput::CopyValues(src, dst, include_connections, false); } } } diff --git a/app/node/param.cpp b/app/node/param.cpp index 359d29bf9..09a9d07d0 100644 --- a/app/node/param.cpp +++ b/app/node/param.cpp @@ -103,7 +103,7 @@ void NodeParam::DisconnectAll() } } -NodeEdgePtr NodeParam::ConnectEdge(NodeOutput *output, NodeInput *input) +NodeEdgePtr NodeParam::ConnectEdge(NodeOutput *output, NodeInput *input, bool lock) { // If the input can only accept one input (the default) and has one already, disconnect it DisconnectForNewOutput(input); @@ -127,14 +127,18 @@ NodeEdgePtr NodeParam::ConnectEdge(NodeOutput *output, NodeInput *input) // that's difficult to diagnose. This makes that issue very clear. Q_ASSERT(output->parentNode() != input->parentNode()); - output->parentNode()->LockUserInput(); - input->parentNode()->LockUserInput(); + if (lock) { + output->parentNode()->LockUserInput(); + input->parentNode()->LockUserInput(); + } output->edges_.append(edge); input->edges_.append(edge); - output->parentNode()->UnlockUserInput(); - input->parentNode()->UnlockUserInput(); + if (lock) { + output->parentNode()->UnlockUserInput(); + input->parentNode()->UnlockUserInput(); + } // Emit a signal than an edge was added (only one signal needs emitting) emit input->EdgeAdded(edge); diff --git a/app/node/param.h b/app/node/param.h index a0ca4e665..f7ac48dd4 100644 --- a/app/node/param.h +++ b/app/node/param.h @@ -292,7 +292,7 @@ public: * * This function emits EdgeAdded(). */ - static NodeEdgePtr ConnectEdge(NodeOutput *output, NodeInput *input); + static NodeEdgePtr ConnectEdge(NodeOutput *output, NodeInput *input, bool lock = true); /** * @brief Disconnect an edge diff --git a/app/render/backend/audio/audiobackend.cpp b/app/render/backend/audio/audiobackend.cpp index 82647ab66..f1c5ae55d 100644 --- a/app/render/backend/audio/audiobackend.cpp +++ b/app/render/backend/audio/audiobackend.cpp @@ -37,7 +37,7 @@ bool AudioBackend::InitInternal() // Initiate one thread per CPU core for (int i=0;iSetParameters(params()); processors_.append(processor); } @@ -67,8 +67,6 @@ void AudioBackend::ConnectWorkerToThis(RenderWorker *worker) void AudioBackend::ThreadCompletedCache(NodeDependency dep, NodeValueTable data) { - caching_ = false; - QByteArray cached_samples = data.Get(NodeParam::kSamples).toByteArray(); int offset = params().time_to_bytes(dep.in()); diff --git a/app/render/backend/audio/audioworker.cpp b/app/render/backend/audio/audioworker.cpp index f48f43f50..c012976af 100644 --- a/app/render/backend/audio/audioworker.cpp +++ b/app/render/backend/audio/audioworker.cpp @@ -1,12 +1,13 @@ #include "audioworker.h" -AudioWorker::AudioWorker(DecoderCache *decoder_cache, QObject *parent) : - AudioRenderWorker(decoder_cache, parent) +AudioWorker::AudioWorker(QObject *parent) : + AudioRenderWorker(parent) { } void AudioWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable *table) { Q_UNUSED(stream) + table->Push(NodeParam::kSamples, frame->ToByteArray()); } diff --git a/app/render/backend/audio/audioworker.h b/app/render/backend/audio/audioworker.h index 686888dee..3fdcb02ce 100644 --- a/app/render/backend/audio/audioworker.h +++ b/app/render/backend/audio/audioworker.h @@ -6,7 +6,7 @@ class AudioWorker : public AudioRenderWorker { public: - AudioWorker(DecoderCache* decoder_cache, QObject* parent = nullptr); + AudioWorker(QObject* parent = nullptr); protected: virtual void FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable* table) override; diff --git a/app/render/backend/audiorenderbackend.cpp b/app/render/backend/audiorenderbackend.cpp index 1b49e9b37..ba0b0dd07 100644 --- a/app/render/backend/audiorenderbackend.cpp +++ b/app/render/backend/audiorenderbackend.cpp @@ -29,6 +29,8 @@ void AudioRenderBackend::SetParameters(const AudioRenderingParams ¶ms) void AudioRenderBackend::InvalidateCache(const rational &start_range, const rational &end_range) { + RenderBackend::InvalidateCache(start_range, end_range); + rational start_range_adj = qMax(rational(0), start_range); rational end_range_adj = qMin(SequenceLength(), end_range); diff --git a/app/render/backend/audiorenderworker.cpp b/app/render/backend/audiorenderworker.cpp index 61196027b..438b62fd7 100644 --- a/app/render/backend/audiorenderworker.cpp +++ b/app/render/backend/audiorenderworker.cpp @@ -2,8 +2,8 @@ #include "audio/audiomanager.h" -AudioRenderWorker::AudioRenderWorker(DecoderCache *decoder_cache, QObject *parent) : - RenderWorker(decoder_cache, parent) +AudioRenderWorker::AudioRenderWorker(QObject *parent) : + RenderWorker(parent) { } diff --git a/app/render/backend/audiorenderworker.h b/app/render/backend/audiorenderworker.h index 9aea9c154..4a2fae507 100644 --- a/app/render/backend/audiorenderworker.h +++ b/app/render/backend/audiorenderworker.h @@ -7,7 +7,7 @@ class AudioRenderWorker : public RenderWorker { Q_OBJECT public: - AudioRenderWorker(DecoderCache* decoder_cache, QObject* parent = nullptr); + AudioRenderWorker(QObject* parent = nullptr); void SetParameters(const AudioRenderingParams& audio_params); diff --git a/app/render/backend/decodercache.h b/app/render/backend/decodercache.h index 6cda4c30f..c2a2adee0 100644 --- a/app/render/backend/decodercache.h +++ b/app/render/backend/decodercache.h @@ -5,6 +5,6 @@ #include "project/item/footage/stream.h" #include "rendercache.h" -using DecoderCache = RenderCache; +using DecoderCache = ThreadSafeRenderCache; #endif // DECODERCACHE_H diff --git a/app/render/backend/opengl/CMakeLists.txt b/app/render/backend/opengl/CMakeLists.txt index 631879dcf..0b292eadd 100644 --- a/app/render/backend/opengl/CMakeLists.txt +++ b/app/render/backend/opengl/CMakeLists.txt @@ -27,7 +27,6 @@ set(OLIVE_SOURCES render/backend/opengl/openglshader.h render/backend/opengl/openglshader.cpp render/backend/opengl/openglshadercache.h - render/backend/opengl/openglshadercache.cpp render/backend/opengl/opengltexture.h render/backend/opengl/opengltexture.cpp render/backend/opengl/openglworker.h diff --git a/app/render/backend/opengl/openglbackend.cpp b/app/render/backend/opengl/openglbackend.cpp index 8c2c9607f..dae35f97e 100644 --- a/app/render/backend/opengl/openglbackend.cpp +++ b/app/render/backend/opengl/openglbackend.cpp @@ -31,7 +31,7 @@ bool OpenGLBackend::InitInternal() // Initiate one thread per CPU core for (int i=0;iSetParameters(params()); processors_.append(processor); } @@ -76,14 +76,14 @@ bool OpenGLBackend::CompileInternal() foreach (Node* n, nodes) { // Check if we have a shader or not - if (!shader_cache_.HasShader(n)) { + if (!shader_cache_.Has(n->id())) { // Since we don't have a shader, compile one now QString node_code = n->Code(); // If the node has no code, it mustn't be GPU accelerated if (node_code.isEmpty()) { // We enter a null shader so we don't try to compile this again - shader_cache_.AddShader(n, nullptr); + shader_cache_.Add(n->id(), nullptr); } else { // Since we have shader code, compile it now OpenGLShaderPtr program; @@ -113,7 +113,7 @@ bool OpenGLBackend::CompileInternal() return false; } - shader_cache_.AddShader(n, program); + shader_cache_.Add(n->id(), program); //qDebug() << "Compiled" << connected_output->parent()->id() << "->" << connected_output->id(); } @@ -166,26 +166,33 @@ void OpenGLBackend::ThreadCompletedFrame(NodeDependency path, QByteArray hash, N emit CachedFrameReady(path.in(), value); } - CompletedFrame(); + // Queue up a new frame for this worker + CacheNext(); } void OpenGLBackend::ThreadCompletedDownload(NodeDependency dep, QByteArray hash) { frame_cache()->SetHash(dep.in(), hash); - emit CachedTimeReady(dep.in()); + // Emit for each frame that has this hash (some may have been added in ThreadSkippedFrame) + QList times_with_this_hash = frame_cache()->TimesWithHash(hash); + foreach (const rational& t, times_with_this_hash) { + emit CachedTimeReady(t); + } } void OpenGLBackend::ThreadSkippedFrame(NodeDependency dep, QByteArray hash) { frame_cache()->SetHash(dep.in(), hash); - CompletedFrame(); + // Queue up a new frame for this worker + CacheNext(); } void OpenGLBackend::ThreadHashAlreadyExists(NodeDependency dep, QByteArray hash) { ThreadCompletedDownload(dep, hash); - CompletedFrame(); + // Queue up a new frame for this worker + CacheNext(); } diff --git a/app/render/backend/opengl/openglshadercache.cpp b/app/render/backend/opengl/openglshadercache.cpp deleted file mode 100644 index e2f3d5cf9..000000000 --- a/app/render/backend/opengl/openglshadercache.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "openglshadercache.h" - -#include "node/node.h" - -void OpenGLShaderCache::Clear() -{ - compiled_nodes_.clear(); -} - -void OpenGLShaderCache::AddShader(Node *output, OpenGLShaderPtr shader) -{ - compiled_nodes_.insert(GenerateShaderID(output), shader); -} - -OpenGLShaderPtr OpenGLShaderCache::GetShader(Node *output) -{ - return compiled_nodes_.value(GenerateShaderID(output)); -} - -QString OpenGLShaderCache::GenerateShaderID(Node *output) -{ - return output->id(); -} - -bool OpenGLShaderCache::HasShader(Node *output) -{ - return compiled_nodes_.contains(GenerateShaderID(output)); -} diff --git a/app/render/backend/opengl/openglshadercache.h b/app/render/backend/opengl/openglshadercache.h index 8626f31b2..3ccf6e8dc 100644 --- a/app/render/backend/opengl/openglshadercache.h +++ b/app/render/backend/opengl/openglshadercache.h @@ -1,32 +1,11 @@ #ifndef OPENGLSHADERCACHE_H #define OPENGLSHADERCACHE_H -#include +#include -#include "node/output.h" #include "openglshader.h" +#include "render/backend/rendercache.h" -/** - * @brief Thread-safe cache of OpenGL shaders - */ -class OpenGLShaderCache -{ -public: - OpenGLShaderCache() = default; - - void Clear(); - - void AddShader(Node* output, OpenGLShaderPtr shader); - - OpenGLShaderPtr GetShader(Node* output); - - bool HasShader(Node* output); - -private: - QString GenerateShaderID(Node *output); - - QMap compiled_nodes_; - -}; +using OpenGLShaderCache = RenderCache; #endif // OPENGLSHADERCACHE_H diff --git a/app/render/backend/opengl/openglworker.cpp b/app/render/backend/opengl/openglworker.cpp index dda783874..82ff47595 100644 --- a/app/render/backend/opengl/openglworker.cpp +++ b/app/render/backend/opengl/openglworker.cpp @@ -7,8 +7,8 @@ #include "render/colormanager.h" #include "render/pixelservice.h" -OpenGLWorker::OpenGLWorker(QOpenGLContext *share_ctx, OpenGLShaderCache *shader_cache, DecoderCache *decoder_cache, ColorProcessorCache *color_cache, VideoRenderFrameCache *frame_cache, QObject *parent) : - VideoRenderWorker(decoder_cache, color_cache, frame_cache, parent), +OpenGLWorker::OpenGLWorker(QOpenGLContext *share_ctx, OpenGLShaderCache *shader_cache, VideoRenderFrameCache *frame_cache, QObject *parent) : + VideoRenderWorker(frame_cache, parent), share_ctx_(share_ctx), ctx_(nullptr), functions_(nullptr), @@ -143,7 +143,7 @@ void OpenGLWorker::ParametersChangedEvent() void OpenGLWorker::RunNodeAccelerated(Node *node, const NodeValueDatabase *input_params, NodeValueTable *output_params) { - OpenGLShaderPtr shader = shader_cache_->GetShader(node); + OpenGLShaderPtr shader = shader_cache_->Get(node->id()); if (!shader) { return; diff --git a/app/render/backend/opengl/openglworker.h b/app/render/backend/opengl/openglworker.h index e0dfe013f..f0bba8c76 100644 --- a/app/render/backend/opengl/openglworker.h +++ b/app/render/backend/opengl/openglworker.h @@ -13,8 +13,6 @@ class OpenGLWorker : public VideoRenderWorker { public: OpenGLWorker(QOpenGLContext* share_ctx, OpenGLShaderCache* shader_cache, - DecoderCache* decoder_cache, - ColorProcessorCache *color_cache, VideoRenderFrameCache* frame_cache, QObject* parent = nullptr); diff --git a/app/render/backend/renderbackend.cpp b/app/render/backend/renderbackend.cpp index 4ef03b849..ad4b56ac4 100644 --- a/app/render/backend/renderbackend.cpp +++ b/app/render/backend/renderbackend.cpp @@ -6,12 +6,12 @@ RenderBackend::RenderBackend(QObject *parent) : QObject(parent), compiled_(false), - caching_(false), started_(false), viewer_node_(nullptr), copied_viewer_node_(nullptr), value_update_queued_(false), - recompile_queued_(false) + recompile_queued_(false), + input_update_queued_(false) { } @@ -53,17 +53,22 @@ void RenderBackend::Close() CloseInternal(); - decoder_cache_.Clear(); + for (int i=0;iquit(); - thread->wait(); // FIXME: Maximum time in case a thread is stuck? + threads_.at(i)->quit(); } + + for (int i=0;iwait(); // FIXME: Maximum time in case a thread is stuck? + delete threads_.at(i); + delete processors_.at(i); + } + threads_.clear(); - - foreach (RenderWorker* processor, processors_) { - delete processor; - } processors_.clear(); } @@ -100,12 +105,17 @@ bool RenderBackend::IsInitiated() return started_; } +void RenderBackend::InvalidateCache(const rational &start_range, const rational &end_range) +{ + Q_UNUSED(start_range) + Q_UNUSED(end_range) + + input_update_queued_ = true; +} + bool RenderBackend::Compile() { - if (recompile_queued_) { - Decompile(); - recompile_queued_ = false; - } else if (compiled_) { + if (compiled_) { return true; } @@ -199,39 +209,48 @@ void RenderBackend::DisconnectViewer(ViewerOutput *node) void RenderBackend::CacheNext() { - if (!Init() || cache_queue_.isEmpty() || !ViewerIsConnected() || caching_) { + if (!Init() + || cache_queue_.isEmpty() + || !ViewerIsConnected()) { return; } - UpdateNodeInputs(); - - TimeRange cache_frame = cache_queue_.takeFirst(); - - //qDebug() << "Caching" << cache_frame.in(); - - caching_ = GenerateData(cache_frame); -} - -bool RenderBackend::GenerateData(const TimeRange &range) -{ - if (!Compile()) { - qDebug() << "Graph remains uncompiled, nothing to be done"; - return false; + if ((input_update_queued_ || recompile_queued_) && !AllProcessorsAreAvailable()) { + qDebug() << "Blocking render while we wait for all workers to finish..."; + return; } - NodeDependency dep = NodeDependency(GetDependentInput()->get_connected_node(), range.in(), range.out()); + if (input_update_queued_) { + UpdateNodeInputs(); + input_update_queued_ = false; + } + + if (recompile_queued_) { + Decompile(); + recompile_queued_ = false; + } + + if (!compiled_ && !Compile()) { + qDebug() << "Graph remains uncompiled, nothing to be done"; + return; + } foreach (RenderWorker* worker, processors_) { - if (worker->IsAvailable() || worker == processors_.last()) { + if (cache_queue_.isEmpty()) { + break; + } + + if (worker->IsAvailable()) { + TimeRange cache_frame = cache_queue_.takeFirst(); + + NodeDependency dep = NodeDependency(GetDependentInput()->get_connected_node(), cache_frame.in(), cache_frame.out()); + QMetaObject::invokeMethod(worker, "Render", Qt::QueuedConnection, Q_ARG(NodeDependency, dep)); - return true; } } - - return false; } ViewerOutput *RenderBackend::viewer_node() const @@ -244,11 +263,6 @@ bool RenderBackend::ViewerIsConnected() const return viewer_node_ != nullptr; } -DecoderCache *RenderBackend::decoder_cache() -{ - return &decoder_cache_; -} - const QString &RenderBackend::cache_id() const { return cache_id_; @@ -274,6 +288,17 @@ void RenderBackend::UpdateNodeInputs() } } +bool RenderBackend::AllProcessorsAreAvailable() const +{ + foreach (RenderWorker* worker, processors_) { + if (!worker->IsAvailable()) { + return false; + } + } + + return true; +} + const QVector &RenderBackend::threads() { return threads_; diff --git a/app/render/backend/renderbackend.h b/app/render/backend/renderbackend.h index 50eb5aa80..f159149db 100644 --- a/app/render/backend/renderbackend.h +++ b/app/render/backend/renderbackend.h @@ -30,7 +30,7 @@ public: bool IsInitiated(); public slots: - virtual void InvalidateCache(const rational &start_range, const rational &end_range) = 0; + virtual void InvalidateCache(const rational &start_range, const rational &end_range); bool Compile(); @@ -70,8 +70,6 @@ protected: */ void CacheNext(); - bool GenerateData(const TimeRange& range); - void InitWorkers(); virtual NodeInput* GetDependentInput() = 0; @@ -82,8 +80,6 @@ protected: bool ViewerIsConnected() const; - DecoderCache* decoder_cache(); - const QString& cache_id() const; void QueueValueUpdate(const TimeRange& range); @@ -96,9 +92,9 @@ protected: bool compiled_; - bool caching_; - private: + bool AllProcessorsAreAvailable() const; + /** * @brief Internal list of RenderProcessThreads */ @@ -124,8 +120,6 @@ private: */ QString error_; - DecoderCache decoder_cache_; - QString cache_name_; qint64 cache_time_; QString cache_id_; @@ -137,6 +131,7 @@ private: TimeRange value_update_range_; bool recompile_queued_; + bool input_update_queued_; private slots: void ThreadRequestedSibling(NodeDependency dep); diff --git a/app/render/backend/rendercache.h b/app/render/backend/rendercache.h index e38f7bf56..1a015168b 100644 --- a/app/render/backend/rendercache.h +++ b/app/render/backend/rendercache.h @@ -2,6 +2,7 @@ #define RENDERCACHE_H #include +#include template class RenderCache @@ -11,12 +12,53 @@ public: void Clear(){values_.clear();} - void Add(K stream, V shader){values_.insert(stream, shader);} + void Add(K key, V val){values_.insert(key, val);} - V Get(K stream){return values_.value(stream);} + V Get(K key) const {return values_.value(key);} + + bool Has(K key) const {return values_.contains(key);} private: QMap values_; }; +template +class ThreadSafeRenderCache +{ +public: + ThreadSafeRenderCache() = default; + + void Clear() { + lock_.lock(); + values_.clear(); + lock_.unlock(); + } + + void Add(K key, V val) { + lock_.lock(); + values_.insert(key, val); + lock_.unlock(); + } + + V Get(K key) { + lock_.lock(); + V val = values_.value(key); + lock_.unlock(); + return val; + } + + bool Has(K key) { + lock_.lock(); + bool has = values_.contains(key); + lock_.unlock(); + return has; + } + +private: + QMap values_; + + QMutex lock_; + +}; + #endif // RENDERCACHE_H diff --git a/app/render/backend/renderworker.cpp b/app/render/backend/renderworker.cpp index 43da6b949..913b2defb 100644 --- a/app/render/backend/renderworker.cpp +++ b/app/render/backend/renderworker.cpp @@ -4,17 +4,16 @@ #include "node/block/block.h" -RenderWorker::RenderWorker(DecoderCache *decoder_cache, QObject *parent) : +RenderWorker::RenderWorker(QObject *parent) : QObject(parent), working_(0), - started_(false), - decoder_cache_(decoder_cache) + started_(false) { } bool RenderWorker::IsAvailable() { - return (working_ == 0); + return !working_; } bool RenderWorker::Init() @@ -34,6 +33,8 @@ void RenderWorker::Close() { CloseInternal(); + decoder_cache_.Clear(); + started_ = false; } @@ -70,11 +71,6 @@ NodeValueTable RenderWorker::RenderAsSibling(NodeDependency dep) return value; } -DecoderCache *RenderWorker::decoder_cache() -{ - return decoder_cache_; -} - NodeValueTable RenderWorker::RenderInternal(const NodeDependency &path) { return RenderAsSibling(path); @@ -101,13 +97,13 @@ StreamPtr RenderWorker::ResolveStreamFromInput(NodeInput *input) DecoderPtr RenderWorker::ResolveDecoderFromInput(StreamPtr stream) { // Access a map of Node inputs and decoder instances and retrieve a frame! - DecoderPtr decoder = decoder_cache()->Get(stream.get()); + DecoderPtr decoder = decoder_cache_.Get(stream.get()); if (decoder == nullptr && stream != nullptr) { // Create a new Decoder here - DecoderPtr decoder = Decoder::CreateFromID(stream->footage()->decoder()); + decoder = Decoder::CreateFromID(stream->footage()->decoder()); decoder->set_stream(stream); - decoder_cache()->Add(stream.get(), decoder); + decoder_cache_.Add(stream.get(), decoder); } return decoder; diff --git a/app/render/backend/renderworker.h b/app/render/backend/renderworker.h index 1fcafe3c9..0664012d4 100644 --- a/app/render/backend/renderworker.h +++ b/app/render/backend/renderworker.h @@ -12,7 +12,7 @@ class RenderWorker : public QObject { Q_OBJECT public: - RenderWorker(DecoderCache* decoder_cache, QObject* parent = nullptr); + RenderWorker(QObject* parent = nullptr); DISABLE_COPY_MOVE(RenderWorker) @@ -56,14 +56,12 @@ protected: virtual NodeValueTable RenderBlock(TrackOutput *track, const TimeRange& range) = 0; - DecoderCache* decoder_cache(); - QAtomicInt working_; private: bool started_; - DecoderCache* decoder_cache_; + DecoderCache decoder_cache_; }; diff --git a/app/render/backend/videorenderbackend.cpp b/app/render/backend/videorenderbackend.cpp index 5379140b5..3e54f4752 100644 --- a/app/render/backend/videorenderbackend.cpp +++ b/app/render/backend/videorenderbackend.cpp @@ -43,6 +43,8 @@ void VideoRenderBackend::InvalidateCache(const rational &start_range, const rati return; } + RenderBackend::InvalidateCache(start_range, end_range); + // Adjust range to min/max values rational start_range_adj = qMax(rational(0), start_range); rational end_range_adj = qMin(SequenceLength(), end_range); @@ -185,11 +187,6 @@ VideoRenderFrameCache *VideoRenderBackend::frame_cache() return &frame_cache_; } -ColorProcessorCache *VideoRenderBackend::color_cache() -{ - return &color_cache_; -} - const char *VideoRenderBackend::GetCachedFrame(const rational &time) { last_time_requested_ = time; @@ -237,9 +234,3 @@ NodeInput *VideoRenderBackend::GetDependentInput() { return viewer_node()->texture_input(); } - -void VideoRenderBackend::CompletedFrame() -{ - caching_ = false; - CacheNext(); -} diff --git a/app/render/backend/videorenderbackend.h b/app/render/backend/videorenderbackend.h index 261f736e7..975ab856c 100644 --- a/app/render/backend/videorenderbackend.h +++ b/app/render/backend/videorenderbackend.h @@ -82,8 +82,6 @@ protected: VideoRenderFrameCache* frame_cache(); - ColorProcessorCache* color_cache(); - const VideoRenderingParams& params() const; /** @@ -95,8 +93,6 @@ protected: virtual void ConnectWorkerToThis(RenderWorker* processor) override; - void CompletedFrame(); - signals: void CachedFrameReady(const rational& time, QVariant value); void CachedTimeReady(const rational& time); @@ -108,8 +104,6 @@ private: VideoRenderFrameCache frame_cache_; - ColorProcessorCache color_cache_; - rational last_time_requested_; private slots: diff --git a/app/render/backend/videorenderframecache.cpp b/app/render/backend/videorenderframecache.cpp index a6dc985e8..9de93623b 100644 --- a/app/render/backend/videorenderframecache.cpp +++ b/app/render/backend/videorenderframecache.cpp @@ -46,7 +46,7 @@ void VideoRenderFrameCache::SetCacheID(const QString &id) cache_id_ = id; } -QByteArray VideoRenderFrameCache::TimeToHash(const rational &time) +QByteArray VideoRenderFrameCache::TimeToHash(const rational &time) const { return time_hash_map_.value(time); } @@ -80,6 +80,21 @@ void VideoRenderFrameCache::Truncate(const rational &time) } } +QList VideoRenderFrameCache::TimesWithHash(const QByteArray &hash) +{ + QList list; + + QMap::const_iterator iterator; + + for (iterator=time_hash_map_.begin();iterator!=time_hash_map_.end();iterator++) { + if (iterator.value() == hash) { + list.append(iterator.key()); + } + } + + return list; +} + void VideoRenderFrameCache::RemoveHashFromCurrentlyCaching(const QByteArray &hash) { currently_caching_lock_.lock(); @@ -87,7 +102,7 @@ void VideoRenderFrameCache::RemoveHashFromCurrentlyCaching(const QByteArray &has currently_caching_lock_.unlock(); } -QString VideoRenderFrameCache::CachePathName(const QByteArray &hash) +QString VideoRenderFrameCache::CachePathName(const QByteArray &hash) const { QDir this_cache_dir = QDir(GetMediaCacheLocation()).filePath(cache_id_); this_cache_dir.mkpath("."); diff --git a/app/render/backend/videorenderframecache.h b/app/render/backend/videorenderframecache.h index de89ec123..74a40f286 100644 --- a/app/render/backend/videorenderframecache.h +++ b/app/render/backend/videorenderframecache.h @@ -28,17 +28,19 @@ public: /** * @brief Return the path of the cached image at this time */ - QString CachePathName(const QByteArray &hash); + QString CachePathName(const QByteArray &hash) const; void SetCacheID(const QString& id); - QByteArray TimeToHash(const rational& time); + QByteArray TimeToHash(const rational& time) const; void SetHash(const rational& time, const QByteArray& hash); void RemoveHash(const rational& time, const QByteArray &hash); void Truncate(const rational& time); + QList TimesWithHash(const QByteArray& hash); + private: void RemoveHashFromCurrentlyCaching(const QByteArray& hash); diff --git a/app/render/backend/videorenderworker.cpp b/app/render/backend/videorenderworker.cpp index b6de16da0..acfd9035c 100644 --- a/app/render/backend/videorenderworker.cpp +++ b/app/render/backend/videorenderworker.cpp @@ -4,10 +4,9 @@ #include "node/node.h" #include "render/pixelservice.h" -VideoRenderWorker::VideoRenderWorker(DecoderCache *decoder_cache, ColorProcessorCache *color_cache, VideoRenderFrameCache *frame_cache, QObject *parent) : - RenderWorker(decoder_cache, parent), - frame_cache_(frame_cache), - color_cache_(color_cache) +VideoRenderWorker::VideoRenderWorker(VideoRenderFrameCache *frame_cache, QObject *parent) : + RenderWorker(parent), + frame_cache_(frame_cache) { } @@ -19,6 +18,8 @@ const VideoRenderingParams &VideoRenderWorker::video_params() NodeValueTable VideoRenderWorker::RenderInternal(const NodeDependency& path) { + qDebug() << "Rendering" << path.in().toDouble() << "on" << this; + // Get hash of node graph // We use SHA-1 for speed (benchmarks show it's the fastest hash available to us) QCryptographicHash hasher(QCryptographicHash::Sha1); @@ -182,7 +183,7 @@ NodeValueTable VideoRenderWorker::RenderBlock(TrackOutput *track, const TimeRang return table; } -ColorProcessorCache *VideoRenderWorker::color_cache() const +ColorProcessorCache *VideoRenderWorker::color_cache() { - return color_cache_; + return &color_cache_; } diff --git a/app/render/backend/videorenderworker.h b/app/render/backend/videorenderworker.h index 320abee66..20f5d9b0f 100644 --- a/app/render/backend/videorenderworker.h +++ b/app/render/backend/videorenderworker.h @@ -12,7 +12,7 @@ class VideoRenderWorker : public RenderWorker { Q_OBJECT public: - VideoRenderWorker(DecoderCache* decoder_cache, ColorProcessorCache* color_cache, VideoRenderFrameCache* frame_cache, QObject* parent = nullptr); + VideoRenderWorker(VideoRenderFrameCache* frame_cache, QObject* parent = nullptr); void SetParameters(const VideoRenderingParams& video_params); @@ -45,7 +45,7 @@ protected: virtual NodeValueTable RenderBlock(TrackOutput *track, const TimeRange& range) override; - ColorProcessorCache* color_cache() const; + ColorProcessorCache* color_cache(); private: void ProcessNode(); @@ -56,7 +56,7 @@ private: VideoRenderFrameCache* frame_cache_; - ColorProcessorCache* color_cache_; + ColorProcessorCache color_cache_; QByteArray download_buffer_;