cache: use disk states to share caches

This commit is contained in:
itsmattkc
2022-06-05 19:47:33 -07:00
parent 13299d0a3b
commit 25699ef05b
14 changed files with 109 additions and 50 deletions
+6 -2
View File
@@ -215,7 +215,9 @@ void ClipBlock::RequestInvalidatedForCache(PlaybackCache *cache, const TimeRange
{
if ((range.in() == RATIONAL_MIN && range.out() == RATIONAL_MAX) || !range.length().isNull()) {
// Request only this range
emit cache->Request(range.Intersected(max_range));
TimeRange r = range.Intersected(max_range);
cache->Invalidate(r);
emit cache->Request(r);
} else {
// Request all ranges currently marked as invalid
TimeRangeList invalid = cache->GetInvalidatedRanges(max_range);
@@ -232,7 +234,9 @@ void ClipBlock::InvalidateCache(const TimeRange& range, const QString& from, int
// If signal is from texture input, transform all times from media time to sequence time
if (from == kBufferIn) {
// Render caches where necessary
RequestInvalidatedFromConnected(range);
if (AreCachesEnabled()) {
RequestInvalidatedFromConnected(range);
}
// Adjust range from media time to sequence time
TimeRange adj;
+4
View File
@@ -39,6 +39,10 @@ void NodeGraph::Clear()
{
// By deleting the last nodes first, we assume that nodes that are most important are deleted last
// (e.g. Project's ColorManager or ProjectSettingsNode.
for (auto it=node_children_.cbegin(); it!=node_children_.cend(); it++) {
(*it)->SetCachesEnabled(false);
}
while (!node_children_.isEmpty()) {
delete node_children_.last();
}
+14 -12
View File
@@ -48,8 +48,8 @@ Node::Node() :
can_be_deleted_(true),
override_color_(-1),
folder_(nullptr),
cache_result_(false),
flags_(kNone)
flags_(kNone),
caches_enabled_(true)
{
AddInput(kEnabledInput, NodeValue::kBoolean, true);
@@ -942,16 +942,18 @@ void Node::InvalidateCache(const TimeRange &range, const QString &from, int elem
Q_UNUSED(from)
Q_UNUSED(element)
if (range.in() != range.out()) {
TimeRange vr = range.Intersected(GetVideoCacheRange());
if (vr.length() != 0) {
video_frame_cache()->Invalidate(vr);
thumbnail_cache()->Invalidate(vr);
}
TimeRange ar = range.Intersected(GetAudioCacheRange());
if (ar.length() != 0) {
audio_playback_cache()->Invalidate(ar);
waveform_cache()->Invalidate(ar);
if (AreCachesEnabled()) {
if (range.in() != range.out()) {
TimeRange vr = range.Intersected(GetVideoCacheRange());
if (vr.length() != 0) {
video_frame_cache()->Invalidate(vr);
thumbnail_cache()->Invalidate(vr);
}
TimeRange ar = range.Intersected(GetAudioCacheRange());
if (ar.length() != 0) {
audio_playback_cache()->Invalidate(ar);
waveform_cache()->Invalidate(ar);
}
}
}
+5 -12
View File
@@ -355,6 +355,9 @@ public:
void CopyCacheUuidsFrom(Node *n);
bool AreCachesEnabled() const { return caches_enabled_; }
void SetCachesEnabled(bool e) { caches_enabled_ = e; }
virtual QString GetInputName(const QString& id) const;
void SetInputName(const QString& id, const QString& name);
@@ -930,16 +933,6 @@ public:
folder_ = folder;
}
bool GetCacheTextures() const
{
return cache_result_;
}
void SetCacheTextures(bool e)
{
cache_result_ = e;
}
class ArrayRemoveCommand : public UndoCommand
{
public:
@@ -1405,8 +1398,6 @@ private:
Folder* folder_;
bool cache_result_;
QMap<InputElementPair, ValueHint> value_hints_;
PositionMap context_positions_;
@@ -1423,6 +1414,8 @@ private:
AudioPlaybackCache *audio_cache_;
AudioWaveformCache *waveform_cache_;
bool caches_enabled_;
private slots:
/**
* @brief Slot when a keyframe's time changes to keep the keyframes correctly sorted by time
-2
View File
@@ -47,8 +47,6 @@ Footage::Footage(const QString &filename) :
valid_(false),
cancelled_(nullptr)
{
SetCacheTextures(true);
PrependInput(kLoopModeInput, NodeValue::kCombo, 0, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
PrependInput(kFilenameInput, NodeValue::kFile, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
@@ -90,7 +90,11 @@ ProjectSerializer220403::LoadData ProjectSerializer220403::Load(Project *project
qWarning() << "Failed to find node with ID" << id;
reader->skipCurrentElement();
} else {
// Disable cache while node is being loaded (we'll re-enable it later)
node->SetCachesEnabled(false);
LoadNode(node, xml_node_data, reader);
node->setParent(project);
}
}
@@ -312,6 +316,11 @@ ProjectSerializer220403::LoadData ProjectSerializer220403::Load(Project *project
}
}
// Re-enable caches
for (Node *n : project->nodes()) {
n->SetCachesEnabled(true);
}
return load_data;
}
+4 -1
View File
@@ -101,9 +101,12 @@ NodeValue NodeTraverser::GenerateRowValueElement(const Node *node, const QString
NodeValue value = table->TakeAt(value_index);
if (value.type() == NodeValue::kTexture) {
QMutexLocker locker(node->video_frame_cache()->mutex());
node->video_frame_cache()->LoadState();
QString cache = node->video_frame_cache()->GetValidCacheFilename(time.in());
if (!cache.isEmpty()) {
qDebug() << "pushing cache job";
value.set_value(CacheJob(cache, value.data()));
}
}
+36 -5
View File
@@ -177,15 +177,46 @@ FramePtr FrameHashCache::LoadCacheFrame(const QString &fn)
}
file.setFrameBuffer(framebuffer);
file.readPixels(dw.min.y, dw.max.y);
} catch (const std::exception &e) {
qCritical() << "Failed to read cache frame:" << e.what();
// Not an EXR, maybe it's a JPEG?
QImage img;
// Clear frame to signal that nothing was loaded
frame = nullptr;
if (img.load(fn, "jpg")) {
// Assume this frame is corrupt in some way and delete it
QMetaObject::invokeMethod(DiskManager::instance(), "DeleteSpecificFile", Q_ARG(QString, fn));
// FIXME: Hardcoded
const int div = 1;
const VideoParams::Format image_format = VideoParams::kFormatUnsigned8;
const int channel_count = 4;
const rational par(1, 1);
frame = Frame::Create();
frame->set_video_params(VideoParams(img.width() * div,
img.height() * div,
image_format,
channel_count,
par,
VideoParams::kInterlaceNone,
div));
frame->allocate();
for (int i=0; i<img.height(); i++) {
memcpy(frame->data() + frame->linesize_bytes() * i,
img.bits() + img.bytesPerLine() * i,
frame->width() * frame->video_params().GetBytesPerPixel());
}
} else {
qCritical() << "Failed to read cache frame:" << e.what();
// Clear frame to signal that nothing was loaded
frame = nullptr;
// Assume this frame is corrupt in some way and delete it
QMetaObject::invokeMethod(DiskManager::instance(), "DeleteSpecificFile", Q_ARG(QString, fn));
}
}
}
+11 -2
View File
@@ -39,6 +39,8 @@ void PlaybackCache::Invalidate(const TimeRange &r)
InvalidateEvent(r);
emit Invalidated(r);
SaveState();
}
Node *PlaybackCache::parent() const
@@ -89,8 +91,6 @@ void PlaybackCache::LoadState()
}
f.close();
f.close();
}
}
@@ -165,6 +165,8 @@ void PlaybackCache::Validate(const TimeRange &r, bool signal)
if (signal) {
emit Validated(r);
}
SaveState();
}
void PlaybackCache::InvalidateEvent(const TimeRange &)
@@ -182,6 +184,13 @@ PlaybackCache::PlaybackCache(QObject *parent) :
uuid_ = QUuid::createUuid();
}
void PlaybackCache::SetUuid(const QUuid &u)
{
uuid_ = u;
LoadState();
}
TimeRangeList PlaybackCache::GetInvalidatedRanges(TimeRange intersecting) const
{
TimeRangeList invalidated;
+6 -1
View File
@@ -22,6 +22,7 @@
#define PLAYBACKCACHE_H
#include <QDir>
#include <QMutex>
#include <QObject>
#include <QPainter>
#include <QUuid>
@@ -42,7 +43,7 @@ public:
PlaybackCache(QObject* parent = nullptr);
const QUuid &GetUuid() const { return uuid_; }
void SetUuid(const QUuid &u) { uuid_ = u; }
void SetUuid(const QUuid &u);
TimeRangeList GetInvalidatedRanges(TimeRange intersecting) const;
TimeRangeList GetInvalidatedRanges(const rational &length) const
@@ -78,6 +79,8 @@ public:
return QFontMetrics(QFont()).height()/4;
}
QMutex *mutex() { return &mutex_; }
public slots:
void InvalidateAll();
@@ -106,6 +109,8 @@ private:
QUuid uuid_;
QMutex mutex_;
};
}
+3 -8
View File
@@ -269,6 +269,9 @@ void PreviewAutoCacher::AddNode(Node *node)
// Add to project
copy->setParent(&copied_project_);
// Disable caches for copy
copy->SetCachesEnabled(false);
// Copy cache UUIDs
copy->CopyCacheUuidsFrom(node);
@@ -380,10 +383,6 @@ void PreviewAutoCacher::ConnectToNodeCache(Node *node)
&PlaybackCache::CancelAll,
this,
&PreviewAutoCacher::CancelForCache);
node->video_frame_cache()->LoadState();
node->audio_playback_cache()->LoadState();
node->thumbnail_cache()->LoadState();
}
void PreviewAutoCacher::DisconnectFromNodeCache(Node *node)
@@ -417,10 +416,6 @@ void PreviewAutoCacher::DisconnectFromNodeCache(Node *node)
&PlaybackCache::CancelAll,
this,
&PreviewAutoCacher::CancelForCache);
node->video_frame_cache()->SaveState();
node->audio_playback_cache()->SaveState();
node->thumbnail_cache()->SaveState();
}
void PreviewAutoCacher::UpdateGraphChangeValue()
+2
View File
@@ -74,6 +74,8 @@ TexturePtr Renderer::InterlaceTexture(TexturePtr top, TexturePtr bottom, const V
QVariant Renderer::GetDefaultShader()
{
QMutexLocker locker(&color_cache_mutex_);
if (default_shader_.isNull()) {
default_shader_ = CreateNativeShader(ShaderCode(QString(), QString()));
}
+8 -4
View File
@@ -253,21 +253,25 @@ DecoderPtr RenderProcessor::ResolveDecoderFromInput(const QString& decoder_id, c
qint64 file_last_modified = QFileInfo(stream.filename()).lastModified().toMSecsSinceEpoch();
if (!decoder.decoder || decoder.last_modified != file_last_modified) {
DecoderPtr dec = nullptr;
if (decoder.decoder && decoder.last_modified == file_last_modified) {
dec = decoder.decoder;
} else {
// No decoder
decoder.decoder = Decoder::CreateFromID(decoder_id);
decoder.decoder = dec = Decoder::CreateFromID(decoder_id);
decoder.last_modified = file_last_modified;
decoder_cache_->insert(stream, decoder);
locker.unlock();
if (!decoder.decoder->Open(stream)) {
if (!dec->Open(stream)) {
qWarning() << "Failed to open decoder for" << stream.filename()
<< "::" << stream.stream();
return nullptr;
}
}
return decoder.decoder;
return dec;
}
void RenderProcessor::Process(RenderTicketPtr ticket, Renderer *render_ctx, DecoderCache *decoder_cache, ShaderCache *shader_cache)
+1 -1
View File
@@ -252,7 +252,7 @@ void TimeRuler::drawForeground(QPainter *p, const QRectF &rect)
}
// If cache status is enabled
if (show_cache_status_ && playback_cache_) {
if (show_cache_status_ && playback_cache_ && playback_cache_->HasValidatedRanges()) {
// FIXME: Hardcoded to get video length, if we ever need audio length, this will have to change
int h = PlaybackCache::GetCacheIndicatorHeight();
QRect cache_rect(0, height() - h, width(), h);