cache: implemented base functionality for clip cache
This commit is contained in:
@@ -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
|
QString Node::GetInputName(const QString &id) const
|
||||||
{
|
{
|
||||||
const Input* i = GetInternalInputData(id);
|
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());
|
TimeRange ar = range.Intersected(GetAudioCacheRange());
|
||||||
if (ar.length() != 0) {
|
if (ar.length() != 0) {
|
||||||
audio_playback_cache()->Invalidate(ar);
|
audio_playback_cache()->Invalidate(ar);
|
||||||
|
waveform_cache()->Invalidate(ar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -353,6 +353,8 @@ public:
|
|||||||
|
|
||||||
static void DisconnectEdge(Node *output, const NodeInput& input);
|
static void DisconnectEdge(Node *output, const NodeInput& input);
|
||||||
|
|
||||||
|
void CopyCacheUuidsFrom(Node *n);
|
||||||
|
|
||||||
virtual QString GetInputName(const QString& id) const;
|
virtual QString GetInputName(const QString& id) const;
|
||||||
|
|
||||||
void SetInputName(const QString& id, const QString& name);
|
void SetInputName(const QString& id, const QString& name);
|
||||||
|
|||||||
+31
-12
@@ -48,7 +48,7 @@ NodeValueRow NodeTraverser::GenerateRow(NodeValueDatabase *database, const Node
|
|||||||
NodeValueRow row;
|
NodeValueRow row;
|
||||||
for (auto it=database->begin(); it!=database->end(); it++) {
|
for (auto it=database->begin(); it!=database->end(); it++) {
|
||||||
// Get hint for which value should be pulled
|
// 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);
|
row.insert(it.key(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,9 +65,9 @@ NodeValueRow NodeTraverser::GenerateRow(const Node *node, const TimeRange &range
|
|||||||
return GenerateRow(&database, node, 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()) {
|
if (value.array()) {
|
||||||
// Resolve each element of array
|
// Resolve each element of array
|
||||||
@@ -75,7 +75,7 @@ NodeValue NodeTraverser::GenerateRowValue(const Node *node, const QString &input
|
|||||||
QVector<NodeValue> output(tables.size());
|
QVector<NodeValue> output(tables.size());
|
||||||
|
|
||||||
for (int i=0; i<tables.size(); i++) {
|
for (int i=0; i<tables.size(); i++) {
|
||||||
output[i] = GenerateRowValueElement(node, input, i, &tables[i]);
|
output[i] = GenerateRowValueElement(node, input, i, &tables[i], time);
|
||||||
}
|
}
|
||||||
|
|
||||||
value = NodeValue(value.type(), QVariant::fromValue(output), value.source(), value.array(), value.tag());
|
value = NodeValue(value.type(), QVariant::fromValue(output), value.source(), value.array(), value.tag());
|
||||||
@@ -84,14 +84,9 @@ NodeValue NodeTraverser::GenerateRowValue(const Node *node, const QString &input
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeValue NodeTraverser::GenerateRowValueElement(const Node *node, const QString &input, int element, NodeValueTable *table)
|
NodeValue NodeTraverser::GenerateRowValueElement(const Node *node, const QString &input, int element, NodeValueTable *table, const TimeRange &time)
|
||||||
{
|
{
|
||||||
return GenerateRowValueElement(node->GetValueHintForInput(input, element), node->GetInputDataType(input), table);
|
int value_index = GenerateRowValueElementIndex(node->GetValueHintForInput(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);
|
|
||||||
|
|
||||||
if (value_index == -1) {
|
if (value_index == -1) {
|
||||||
// If value was -1, try getting the last value
|
// If value was -1, try getting the last value
|
||||||
@@ -103,7 +98,17 @@ NodeValue NodeTraverser::GenerateRowValueElement(const Node::ValueHint &hint, No
|
|||||||
return NodeValue();
|
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)
|
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;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TexturePtr NodeTraverser::ProcessVideoCacheJob(const CacheJob &val)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
QVector2D NodeTraverser::GenerateResolution() const
|
QVector2D NodeTraverser::GenerateResolution() const
|
||||||
{
|
{
|
||||||
@@ -367,6 +376,16 @@ QVector2D NodeTraverser::GenerateResolution() const
|
|||||||
void NodeTraverser::ResolveJobs(NodeValue &val, const TimeRange &range)
|
void NodeTraverser::ResolveJobs(NodeValue &val, const TimeRange &range)
|
||||||
{
|
{
|
||||||
if (val.type() == NodeValue::kTexture || val.type() == NodeValue::kSamples) {
|
if (val.type() == NodeValue::kTexture || val.type() == NodeValue::kSamples) {
|
||||||
|
if (val.canConvert<CacheJob>()) {
|
||||||
|
CacheJob job = val.value<CacheJob>();
|
||||||
|
TexturePtr tex = ProcessVideoCacheJob(job);
|
||||||
|
if (tex) {
|
||||||
|
val.set_value(tex);
|
||||||
|
} else {
|
||||||
|
val.set_value(job.GetFallback());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (val.canConvert<ShaderJob>()) {
|
if (val.canConvert<ShaderJob>()) {
|
||||||
|
|
||||||
ShaderJob job = val.value<ShaderJob>();
|
ShaderJob job = val.value<ShaderJob>();
|
||||||
|
|||||||
@@ -26,8 +26,9 @@
|
|||||||
#include "codec/decoder.h"
|
#include "codec/decoder.h"
|
||||||
#include "common/cancelableobject.h"
|
#include "common/cancelableobject.h"
|
||||||
#include "node/output/track/track.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/colortransformjob.h"
|
||||||
|
#include "render/job/footagejob.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
|
||||||
namespace olive {
|
namespace olive {
|
||||||
@@ -44,9 +45,8 @@ public:
|
|||||||
NodeValueRow GenerateRow(NodeValueDatabase *database, const Node *node, const TimeRange &range);
|
NodeValueRow GenerateRow(NodeValueDatabase *database, const Node *node, const TimeRange &range);
|
||||||
NodeValueRow GenerateRow(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 GenerateRowValue(const Node *node, const QString &input, NodeValueTable *table, const TimeRange &time);
|
||||||
NodeValue GenerateRowValueElement(const Node *node, const QString &input, int element, NodeValueTable *table);
|
NodeValue GenerateRowValueElement(const Node *node, const QString &input, int element, NodeValueTable *table, const TimeRange &time);
|
||||||
NodeValue GenerateRowValueElement(const Node::ValueHint &hint, NodeValue::Type preferred_type, NodeValueTable *table);
|
|
||||||
int GenerateRowValueElementIndex(const Node::ValueHint &hint, NodeValue::Type preferred_type, const NodeValueTable *table);
|
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);
|
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 void ConvertToReferenceSpace(TexturePtr destination, TexturePtr source, const QString &input_cs){}
|
||||||
|
|
||||||
|
virtual TexturePtr ProcessVideoCacheJob(const CacheJob &val);
|
||||||
|
|
||||||
virtual TexturePtr CreateTexture(const VideoParams &p)
|
virtual TexturePtr CreateTexture(const VideoParams &p)
|
||||||
{
|
{
|
||||||
return CreateDummyTexture(p);
|
return CreateDummyTexture(p);
|
||||||
|
|||||||
@@ -225,6 +225,8 @@ public:
|
|||||||
data_ = QVariant::fromValue(v);
|
data_ = QVariant::fromValue(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QVariant &data() const { return data_; }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool canConvert() const
|
bool canConvert() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***/
|
||||||
|
|
||||||
|
#ifndef CACHEJOB_H
|
||||||
|
#define CACHEJOB_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
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
|
||||||
@@ -269,6 +269,9 @@ void PreviewAutoCacher::AddNode(Node *node)
|
|||||||
// Add to project
|
// Add to project
|
||||||
copy->setParent(&copied_project_);
|
copy->setParent(&copied_project_);
|
||||||
|
|
||||||
|
// Copy cache UUIDs
|
||||||
|
copy->CopyCacheUuidsFrom(node);
|
||||||
|
|
||||||
// Insert into map
|
// Insert into map
|
||||||
InsertIntoCopyMap(node, copy);
|
InsertIntoCopyMap(node, copy);
|
||||||
|
|
||||||
|
|||||||
@@ -530,9 +530,10 @@ void RenderProcessor::ProcessSamples(SampleBuffer &destination, const Node *node
|
|||||||
|
|
||||||
// Update all non-sample and non-footage inputs
|
// Update all non-sample and non-footage inputs
|
||||||
for (auto j=job.GetValues().constBegin(); j!=job.GetValues().constEnd(); j++) {
|
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,
|
node->ProcessSamples(value_db,
|
||||||
@@ -559,6 +560,20 @@ void RenderProcessor::ProcessFrameGeneration(TexturePtr destination, const Node
|
|||||||
destination->Upload(frame->data(), frame->linesize_pixels());
|
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)
|
void RenderProcessor::ConvertToReferenceSpace(TexturePtr destination, TexturePtr source, const QString &input_cs)
|
||||||
{
|
{
|
||||||
ColorManager* color_manager = Node::ValueToPtr<ColorManager>(ticket_->property("colormanager"));
|
ColorManager* color_manager = Node::ValueToPtr<ColorManager>(ticket_->property("colormanager"));
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ protected:
|
|||||||
|
|
||||||
virtual void ProcessFrameGeneration(TexturePtr destination, const Node *node, const GenerateJob& job) override;
|
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
|
virtual TexturePtr CreateTexture(const VideoParams &p) override
|
||||||
{
|
{
|
||||||
return render_ctx_->CreateTexture(p);
|
return render_ctx_->CreateTexture(p);
|
||||||
|
|||||||
Reference in New Issue
Block a user