From 13299d0a3be6f254cf0daa2c6809cc4d7c8d6376 Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Sat, 4 Jun 2022 17:29:09 -0700 Subject: [PATCH] cache: implemented base functionality for clip cache --- app/node/node.cpp | 9 ++++++ app/node/node.h | 2 ++ app/node/traverser.cpp | 43 ++++++++++++++++++------- app/node/traverser.h | 10 +++--- app/node/value.h | 2 ++ app/render/job/cachejob.h | 55 ++++++++++++++++++++++++++++++++ app/render/previewautocacher.cpp | 3 ++ app/render/renderprocessor.cpp | 19 +++++++++-- app/render/renderprocessor.h | 2 ++ 9 files changed, 127 insertions(+), 18 deletions(-) create mode 100644 app/render/job/cachejob.h diff --git a/app/node/node.cpp b/app/node/node.cpp index 2b5220195..84f46ef96 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -234,6 +234,14 @@ void Node::DisconnectEdge(Node *output, const NodeInput &input) } } +void Node::CopyCacheUuidsFrom(Node *n) +{ + video_cache_->SetUuid(n->video_cache_->GetUuid()); + audio_cache_->SetUuid(n->audio_cache_->GetUuid()); + thumbnail_cache_->SetUuid(n->thumbnail_cache_->GetUuid()); + waveform_cache_->SetUuid(n->waveform_cache_->GetUuid()); +} + QString Node::GetInputName(const QString &id) const { const Input* i = GetInternalInputData(id); @@ -943,6 +951,7 @@ void Node::InvalidateCache(const TimeRange &range, const QString &from, int elem TimeRange ar = range.Intersected(GetAudioCacheRange()); if (ar.length() != 0) { audio_playback_cache()->Invalidate(ar); + waveform_cache()->Invalidate(ar); } } diff --git a/app/node/node.h b/app/node/node.h index c331d9b6d..d7a3292f9 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -353,6 +353,8 @@ public: static void DisconnectEdge(Node *output, const NodeInput& input); + void CopyCacheUuidsFrom(Node *n); + virtual QString GetInputName(const QString& id) const; void SetInputName(const QString& id, const QString& name); diff --git a/app/node/traverser.cpp b/app/node/traverser.cpp index ca4267d52..c043d0636 100644 --- a/app/node/traverser.cpp +++ b/app/node/traverser.cpp @@ -48,7 +48,7 @@ NodeValueRow NodeTraverser::GenerateRow(NodeValueDatabase *database, const Node NodeValueRow row; for (auto it=database->begin(); it!=database->end(); it++) { // Get hint for which value should be pulled - NodeValue value = GenerateRowValue(node, it.key(), &it.value()); + NodeValue value = GenerateRowValue(node, it.key(), &it.value(), range); row.insert(it.key(), value); } @@ -65,9 +65,9 @@ NodeValueRow NodeTraverser::GenerateRow(const Node *node, const TimeRange &range return GenerateRow(&database, node, range); } -NodeValue NodeTraverser::GenerateRowValue(const Node *node, const QString &input, NodeValueTable *table) +NodeValue NodeTraverser::GenerateRowValue(const Node *node, const QString &input, NodeValueTable *table, const TimeRange &time) { - NodeValue value = GenerateRowValueElement(node, input, -1, table); + NodeValue value = GenerateRowValueElement(node, input, -1, table, time); if (value.array()) { // Resolve each element of array @@ -75,7 +75,7 @@ NodeValue NodeTraverser::GenerateRowValue(const Node *node, const QString &input QVector output(tables.size()); for (int i=0; iGetValueHintForInput(input, element), node->GetInputDataType(input), table); -} - -NodeValue NodeTraverser::GenerateRowValueElement(const Node::ValueHint &hint, NodeValue::Type preferred_type, NodeValueTable *table) -{ - int value_index = GenerateRowValueElementIndex(hint, preferred_type, table); + int value_index = GenerateRowValueElementIndex(node->GetValueHintForInput(input, element), node->GetInputDataType(input), table); if (value_index == -1) { // If value was -1, try getting the last value @@ -103,7 +98,17 @@ NodeValue NodeTraverser::GenerateRowValueElement(const Node::ValueHint &hint, No return NodeValue(); } - return table->TakeAt(value_index); + NodeValue value = table->TakeAt(value_index); + + if (value.type() == NodeValue::kTexture) { + QString cache = node->video_frame_cache()->GetValidCacheFilename(time.in()); + if (!cache.isEmpty()) { + qDebug() << "pushing cache job"; + value.set_value(CacheJob(cache, value.data())); + } + } + + return value; } int NodeTraverser::GenerateRowValueElementIndex(const Node::ValueHint &hint, NodeValue::Type preferred_type, const NodeValueTable *table) @@ -358,6 +363,10 @@ NodeValueTable NodeTraverser::GenerateBlockTable(const Track *track, const TimeR return table; } +TexturePtr NodeTraverser::ProcessVideoCacheJob(const CacheJob &val) +{ + return nullptr; +} QVector2D NodeTraverser::GenerateResolution() const { @@ -367,6 +376,16 @@ QVector2D NodeTraverser::GenerateResolution() const void NodeTraverser::ResolveJobs(NodeValue &val, const TimeRange &range) { if (val.type() == NodeValue::kTexture || val.type() == NodeValue::kSamples) { + if (val.canConvert()) { + CacheJob job = val.value(); + TexturePtr tex = ProcessVideoCacheJob(job); + if (tex) { + val.set_value(tex); + } else { + val.set_value(job.GetFallback()); + } + } + if (val.canConvert()) { ShaderJob job = val.value(); diff --git a/app/node/traverser.h b/app/node/traverser.h index 105955450..e5b736389 100644 --- a/app/node/traverser.h +++ b/app/node/traverser.h @@ -26,8 +26,9 @@ #include "codec/decoder.h" #include "common/cancelableobject.h" #include "node/output/track/track.h" -#include "render/job/footagejob.h" +#include "render/job/cachejob.h" #include "render/job/colortransformjob.h" +#include "render/job/footagejob.h" #include "value.h" namespace olive { @@ -44,9 +45,8 @@ public: NodeValueRow GenerateRow(NodeValueDatabase *database, const Node *node, const TimeRange &range); NodeValueRow GenerateRow(const Node *node, const TimeRange &range); - NodeValue GenerateRowValue(const Node *node, const QString &input, NodeValueTable *table); - NodeValue GenerateRowValueElement(const Node *node, const QString &input, int element, NodeValueTable *table); - NodeValue GenerateRowValueElement(const Node::ValueHint &hint, NodeValue::Type preferred_type, NodeValueTable *table); + NodeValue GenerateRowValue(const Node *node, const QString &input, NodeValueTable *table, const TimeRange &time); + NodeValue GenerateRowValueElement(const Node *node, const QString &input, int element, NodeValueTable *table, const TimeRange &time); int GenerateRowValueElementIndex(const Node::ValueHint &hint, NodeValue::Type preferred_type, const NodeValueTable *table); int GenerateRowValueElementIndex(const Node *node, const QString &input, int element, const NodeValueTable *table); @@ -101,6 +101,8 @@ protected: virtual void ConvertToReferenceSpace(TexturePtr destination, TexturePtr source, const QString &input_cs){} + virtual TexturePtr ProcessVideoCacheJob(const CacheJob &val); + virtual TexturePtr CreateTexture(const VideoParams &p) { return CreateDummyTexture(p); diff --git a/app/node/value.h b/app/node/value.h index 6cf1e537d..9fbd4600e 100644 --- a/app/node/value.h +++ b/app/node/value.h @@ -225,6 +225,8 @@ public: data_ = QVariant::fromValue(v); } + const QVariant &data() const { return data_; } + template bool canConvert() const { diff --git a/app/render/job/cachejob.h b/app/render/job/cachejob.h new file mode 100644 index 000000000..67c6c36b9 --- /dev/null +++ b/app/render/job/cachejob.h @@ -0,0 +1,55 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2022 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#ifndef CACHEJOB_H +#define CACHEJOB_H + +#include +#include + +namespace olive { + +class CacheJob +{ +public: + CacheJob() = default; + CacheJob(const QString &filename, const QVariant &fallback = QVariant()) + { + filename_ = filename; + } + + const QString &GetFilename() const { return filename_; } + void SetFilename(const QString &s) { filename_ = s; } + + const QVariant &GetFallback() const { return fallback_; } + void SetFallback(const QVariant &val) { fallback_ = val; } + +private: + QString filename_; + + QVariant fallback_; + +}; + +} + +Q_DECLARE_METATYPE(olive::CacheJob) + +#endif // CACHEJOB_H diff --git a/app/render/previewautocacher.cpp b/app/render/previewautocacher.cpp index caa604ef1..f3b4c23f9 100644 --- a/app/render/previewautocacher.cpp +++ b/app/render/previewautocacher.cpp @@ -269,6 +269,9 @@ void PreviewAutoCacher::AddNode(Node *node) // Add to project copy->setParent(&copied_project_); + // Copy cache UUIDs + copy->CopyCacheUuidsFrom(node); + // Insert into map InsertIntoCopyMap(node, copy); diff --git a/app/render/renderprocessor.cpp b/app/render/renderprocessor.cpp index e89f3bbc6..4402042d3 100644 --- a/app/render/renderprocessor.cpp +++ b/app/render/renderprocessor.cpp @@ -530,9 +530,10 @@ void RenderProcessor::ProcessSamples(SampleBuffer &destination, const Node *node // Update all non-sample and non-footage inputs for (auto j=job.GetValues().constBegin(); j!=job.GetValues().constEnd(); j++) { - NodeValueTable value = ProcessInput(node, j.key(), TimeRange(this_sample_time, this_sample_time)); + TimeRange r = TimeRange(this_sample_time, this_sample_time); + NodeValueTable value = ProcessInput(node, j.key(), r); - value_db.insert(j.key(), GenerateRowValue(node, j.key(), &value)); + value_db.insert(j.key(), GenerateRowValue(node, j.key(), &value, r)); } node->ProcessSamples(value_db, @@ -559,6 +560,20 @@ void RenderProcessor::ProcessFrameGeneration(TexturePtr destination, const Node destination->Upload(frame->data(), frame->linesize_pixels()); } +TexturePtr RenderProcessor::ProcessVideoCacheJob(const CacheJob &val) +{ + FramePtr frame = FrameHashCache::LoadCacheFrame(val.GetFilename()); + if (frame) { + TexturePtr tex = CreateTexture(frame->video_params()); + if (tex) { + tex->Upload(frame->data(), frame->linesize_pixels()); + return tex; + } + } + + return nullptr; +} + void RenderProcessor::ConvertToReferenceSpace(TexturePtr destination, TexturePtr source, const QString &input_cs) { ColorManager* color_manager = Node::ValueToPtr(ticket_->property("colormanager")); diff --git a/app/render/renderprocessor.h b/app/render/renderprocessor.h index db147bd3e..c2fc5d6c7 100644 --- a/app/render/renderprocessor.h +++ b/app/render/renderprocessor.h @@ -56,6 +56,8 @@ protected: virtual void ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob& job) override; + virtual TexturePtr ProcessVideoCacheJob(const CacheJob &val) override; + virtual TexturePtr CreateTexture(const VideoParams &p) override { return render_ctx_->CreateTexture(p);