diff --git a/app/render/backend/audiorenderbackend.cpp b/app/render/backend/audiorenderbackend.cpp index 368d70195..9e819c0c8 100644 --- a/app/render/backend/audiorenderbackend.cpp +++ b/app/render/backend/audiorenderbackend.cpp @@ -124,7 +124,7 @@ TimeRange AudioRenderBackend::PopNextFrameFromQueue() return range; } -void AudioRenderBackend::InvalidateCacheInternal(const rational &start_range, const rational &end_range, bool only_visible) +void AudioRenderBackend::InvalidateCacheInternal(const rational &start_range, const rational &end_range) { if (!ic_from_conform_) { // Cancel any ranges waiting on a conform here since obviously the contents have changed @@ -153,7 +153,7 @@ void AudioRenderBackend::InvalidateCacheInternal(const rational &start_range, co } } - RenderBackend::InvalidateCacheInternal(start_range, end_range, only_visible); + RenderBackend::InvalidateCacheInternal(start_range, end_range); } void AudioRenderBackend::ListenForConformSignal(AudioStreamPtr s) diff --git a/app/render/backend/audiorenderbackend.h b/app/render/backend/audiorenderbackend.h index 6c6dd04f2..ef6e6a090 100644 --- a/app/render/backend/audiorenderbackend.h +++ b/app/render/backend/audiorenderbackend.h @@ -67,7 +67,7 @@ protected: virtual TimeRange PopNextFrameFromQueue() override; - virtual void InvalidateCacheInternal(const rational &start_range, const rational &end_range, bool only_visible) override; + virtual void InvalidateCacheInternal(const rational &start_range, const rational &end_range) override; private: struct ConformWaitInfo { diff --git a/app/render/backend/renderbackend.cpp b/app/render/backend/renderbackend.cpp index 96f14883f..1c1dec7da 100644 --- a/app/render/backend/renderbackend.cpp +++ b/app/render/backend/renderbackend.cpp @@ -292,14 +292,24 @@ void RenderBackend::CancelQueue() cancel_dialog_->RunIfWorkersAreBusy(); } -void RenderBackend::InvalidateVisible(const TimeRange &range, NodeInput *from) -{ - InvalidateCacheVeryInternal(range, from, true); -} - void RenderBackend::InvalidateCache(const TimeRange &range, NodeInput *from) { - InvalidateCacheVeryInternal(range, from, false); + // Adjust range to min/max values + rational start_range_adj = qMax(rational(0), range.in()); + rational end_range_adj = qMin(GetSequenceLength(), range.out()); + + qDebug() << "Cache invalidated between" + << start_range_adj.toDouble() + << "and" + << end_range_adj.toDouble(); + + if (from) { + // Queue value update + qDebug() << " from" << from->parentNode()->id() << "::" << from->id(); + QueueValueUpdate(from); + } + + InvalidateCacheInternal(start_range_adj, end_range_adj); } bool RenderBackend::ViewerIsConnected() const @@ -341,26 +351,6 @@ void RenderBackend::SetWorkerBusyState(RenderWorker *worker, bool busy) processor_busy_state_.replace(processors_.indexOf(worker), busy); } -void RenderBackend::InvalidateCacheVeryInternal(const TimeRange &range, NodeInput *from, bool only_visible) -{ - // Adjust range to min/max values - rational start_range_adj = qMax(rational(0), range.in()); - rational end_range_adj = qMin(GetSequenceLength(), range.out()); - - qDebug() << "Cache invalidated between" - << start_range_adj.toDouble() - << "and" - << end_range_adj.toDouble(); - - if (from) { - // Queue value update - qDebug() << " from" << from->parentNode()->id() << "::" << from->id(); - QueueValueUpdate(from); - } - - InvalidateCacheInternal(start_range_adj, end_range_adj, only_visible); -} - void RenderBackend::CopyNodeInputValue(NodeInput *input) { // Find our copy of this parameter @@ -463,10 +453,8 @@ const QVector &RenderBackend::threads() return threads_; } -void RenderBackend::InvalidateCacheInternal(const rational &start_range, const rational &end_range, bool only_visible) +void RenderBackend::InvalidateCacheInternal(const rational &start_range, const rational &end_range) { - Q_UNUSED(only_visible) - // Add the range to the list cache_queue_.InsertTimeRange(TimeRange(start_range, end_range)); diff --git a/app/render/backend/renderbackend.h b/app/render/backend/renderbackend.h index 86659b750..4e53f7758 100644 --- a/app/render/backend/renderbackend.h +++ b/app/render/backend/renderbackend.h @@ -51,8 +51,6 @@ public: void CancelQueue(); - void InvalidateVisible(const TimeRange &range, NodeInput *from); - public slots: void InvalidateCache(const TimeRange &range, NodeInput *from); @@ -79,7 +77,7 @@ protected: */ virtual bool GenerateCacheIDInternal(QCryptographicHash& hash) = 0; - virtual void InvalidateCacheInternal(const rational &start_range, const rational &end_range, bool only_visible); + virtual void InvalidateCacheInternal(const rational &start_range, const rational &end_range); virtual void CacheIDChangedEvent(const QString& id); @@ -124,8 +122,6 @@ protected: NodeGraph copied_graph_; private: - void InvalidateCacheVeryInternal(const TimeRange &range, NodeInput *from, bool only_visible); - void CopyNodeInputValue(NodeInput* input); Node *CopyNodeConnections(Node *src_node); void CopyNodeMakeConnection(NodeInput *src_input, NodeInput *dst_input); diff --git a/app/render/backend/videorenderbackend.cpp b/app/render/backend/videorenderbackend.cpp index 9147980a3..492652e5d 100644 --- a/app/render/backend/videorenderbackend.cpp +++ b/app/render/backend/videorenderbackend.cpp @@ -40,9 +40,7 @@ VideoRenderBackend::VideoRenderBackend(QObject *parent) : RenderBackend(parent), operating_mode_(VideoRenderWorker::kRenderOnly), only_signal_last_frame_requested_(true), - limit_caching_(true), - pop_toggle_(false), - queue_is_visible_only_(false) + limit_caching_(true) { connect(DiskManager::instance(), &DiskManager::DeletedFrame, this, &VideoRenderBackend::FrameRemovedFromDiskCache); } @@ -153,47 +151,22 @@ void VideoRenderBackend::ConnectWorkerToThis(RenderWorker *processor) connect(video_processor, &VideoRenderWorker::GeneratedFrame, this, &VideoRenderBackend::ThreadGeneratedFrame, Qt::QueuedConnection); } -void VideoRenderBackend::InvalidateCacheInternal(const rational &start_range, const rational &end_range, bool only_visible) +void VideoRenderBackend::InvalidateCacheInternal(const rational &start_range, const rational &end_range) { TimeRange invalidated(start_range, end_range); - invalidated_.InsertTimeRange(invalidated); + if (limit_caching_) { + invalidated_.InsertTimeRange(invalidated); + } else { + RenderBackend::InvalidateCacheInternal(start_range, end_range); + } emit RangeInvalidated(invalidated); - - queue_is_visible_only_ = only_visible; - - if (only_visible) { - - // We're only caching this frame, and for maximum responsiveness, should cancel the rest of the - // queue - cache_queue_.clear(); - cache_queue_.InsertTimeRange(TimeRange(start_range, end_range)); - - CacheNext(); - - } else { - - // Rework the queue - Requeue(); - - } } -void VideoRenderBackend::WorkerAboutToStartEvent(RenderWorker *worker) +void VideoRenderBackend::RenderFrame(const rational &time) { - if (operating_mode_ & VideoRenderWorker::kDownloadOnly) { - int mode = operating_mode_; - - if (queue_is_visible_only_) { - mode &= ~VideoRenderWorker::kDownloadOnly; - } else { - mode |= VideoRenderWorker::kDownloadOnly; - } - - static_cast(worker)-> - SetOperatingMode(static_cast(mode)); - } + RenderBackend::InvalidateCacheInternal(time, time); } VideoRenderFrameCache *VideoRenderBackend::frame_cache() @@ -234,11 +207,7 @@ QString VideoRenderBackend::GetCachedFrame(const rational &time) void VideoRenderBackend::UpdateLastRequestedTime(const rational &time) { - if (last_time_requested_ != time) { - last_time_requested_ = time; - - Requeue(); - } + last_time_requested_ = time; } NodeInput *VideoRenderBackend::GetDependentInput() @@ -253,41 +222,28 @@ bool VideoRenderBackend::CanRender() TimeRange VideoRenderBackend::PopNextFrameFromQueue() { - // Try to find the frame that's closest to the last time requested (the playhead) - rational earliest_allowed_time = (pop_toggle_) ? 0 : last_time_requested_; - pop_toggle_ = !pop_toggle_; + rational earliest_frame = RATIONAL_MAX; - // Set up playhead frame range to see if the queue contains this frame precisely - TimeRange test_range(earliest_allowed_time, earliest_allowed_time + params_.time_base()); - - // Use this variable to find the closest frame in the range - rational closest_time = RATIONAL_MAX; - - foreach (const TimeRange& range_here, cache_queue_) { - if (range_here.OverlapsWith(test_range, false, false)) { - closest_time = RATIONAL_MAX; - break; - } - - if (range_here.in() >= earliest_allowed_time) { - rational frame_here = Timecode::snap_time_to_timebase(range_here.in(), params_.time_base()); - - if (frame_here > range_here.in()) { - frame_here = qMax(rational(), frame_here - params_.time_base()); - } - - closest_time = qMin(closest_time, frame_here); + // Find earliest frame in the cache queue + foreach (const TimeRange& range, cache_queue_) { + if (range.in() < earliest_frame) { + earliest_frame = range.in(); } } - TimeRange frame_range; + // Snap this frame to the timebase + rational snapped_frame = Timecode::snap_time_to_timebase(earliest_frame, params_.time_base()); + rational next_frame; - if (closest_time == RATIONAL_MAX) { - frame_range = test_range; + if (snapped_frame > earliest_frame) { + next_frame = snapped_frame; + snapped_frame -= params_.time_base(); } else { - frame_range = TimeRange(closest_time, closest_time + params_.time_base()); + next_frame = snapped_frame + params_.time_base(); } + TimeRange frame_range(snapped_frame, next_frame); + // Remove this particular frame from the queue cache_queue_.RemoveTimeRange(frame_range); @@ -358,9 +314,6 @@ void VideoRenderBackend::TruncateFrameCacheLength(const rational &length) if (last_time_requested_ >= length) { emit CachedTimeReady(last_time_requested_, QDateTime::currentMSecsSinceEpoch()); } - - // Adjust queue for new invalidated range - Requeue(); } void VideoRenderBackend::FrameRemovedFromDiskCache(const QByteArray &hash) @@ -398,23 +351,4 @@ bool VideoRenderBackend::SetFrameHash(const NodeDependency &dep, const QByteArra return false; } -void VideoRenderBackend::Requeue() -{ - if (limit_caching_) { - - // Reset queue around the last time requested - TimeRange queueable_range(last_time_requested_ - Config::Current()["DiskCacheBehind"].value(), - last_time_requested_ + Config::Current()["DiskCacheAhead"].value()); - - cache_queue_ = invalidated_.Intersects(queueable_range); - - } else { - - cache_queue_ = invalidated_; - - } - - CacheNext(); -} - OLIVE_NAMESPACE_EXIT diff --git a/app/render/backend/videorenderbackend.h b/app/render/backend/videorenderbackend.h index 97b1f09f9..486cfebdb 100644 --- a/app/render/backend/videorenderbackend.h +++ b/app/render/backend/videorenderbackend.h @@ -74,6 +74,8 @@ public: const VideoRenderingParams& params() const; + void RenderFrame(const rational& time); + protected: struct HashTimeMapping { rational time; @@ -99,12 +101,10 @@ protected: virtual void ConnectWorkerToThis(RenderWorker* processor) override; - virtual void InvalidateCacheInternal(const rational &start_range, const rational &end_range, bool only_visible) override; + virtual void InvalidateCacheInternal(const rational &start_range, const rational &end_range) override; virtual void ParamsChangedEvent(){} - virtual void WorkerAboutToStartEvent(RenderWorker* worker) override; - VideoRenderWorker::OperatingMode operating_mode_; signals: @@ -121,8 +121,6 @@ private: bool SetFrameHash(const NodeDependency& dep, const QByteArray& hash, const qint64& job_time); - void Requeue(); - VideoRenderingParams params_; VideoRenderFrameCache frame_cache_; @@ -135,10 +133,6 @@ private: bool limit_caching_; - bool pop_toggle_; - - bool queue_is_visible_only_; - private slots: void ThreadCompletedDownload(NodeDependency dep, qint64 job_time, QByteArray hash); void ThreadSkippedFrame(NodeDependency dep, qint64 job_time, QByteArray hash); diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index 88f32232b..097cca3aa 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -375,7 +375,9 @@ void ViewerWidget::UpdateTextureFromNode(const rational& time) if (FrameExistsAtTime(time)) { QString frame_fn = GetCachedFilenameFromTime(time); - if (!frame_fn.isEmpty()) { + if (frame_fn.isEmpty()) { + video_renderer_->RenderFrame(time); + } else { FramePtr f = DecodeCachedImage(frame_fn); SetDisplayImage(f, false); } @@ -1037,7 +1039,8 @@ void ViewerWidget::SetZoomFromMenu(QAction *action) void ViewerWidget::InvalidateVisible(NodeInput* source) { - video_renderer_->InvalidateVisible(TimeRange(GetTime(), GetTime()), source); + video_renderer_->InvalidateCache(TimeRange(GetTime(), GetTime()), source); + video_renderer_->RenderFrame(GetTime()); } OLIVE_NAMESPACE_EXIT