From 7ff419b0a31c9ed4063aaad20ffa4d9e75473c91 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 12 Jul 2021 00:48:26 -0700 Subject: [PATCH] render: use events to iterate gradually through frame queue Fixes #1665 --- app/common/timerange.h | 6 ++++ app/render/previewautocacher.cpp | 47 ++++++++++++++++---------------- app/render/previewautocacher.h | 3 ++ app/render/rendermanager.h | 5 ++++ 4 files changed, 37 insertions(+), 24 deletions(-) diff --git a/app/common/timerange.h b/app/common/timerange.h index 78c95d8db..3a7be3054 100644 --- a/app/common/timerange.h +++ b/app/common/timerange.h @@ -151,6 +151,7 @@ private: class TimeRangeListFrameIterator { public: + TimeRangeListFrameIterator() = default; TimeRangeListFrameIterator(const TimeRangeList &list, const rational &timebase); bool GetNext(rational *out); @@ -168,6 +169,11 @@ public: int size(); + void reset() + { + *this = TimeRangeListFrameIterator(); + } + private: void UpdateIndexIfNecessary(); diff --git a/app/render/previewautocacher.cpp b/app/render/previewautocacher.cpp index a27313cfa..567e5ed19 100644 --- a/app/render/previewautocacher.cpp +++ b/app/render/previewautocacher.cpp @@ -274,6 +274,8 @@ void PreviewAutoCacher::VideoRendered() TryRender(); } + QueueNextFrameInRange(1); + delete watcher; } @@ -442,6 +444,7 @@ void PreviewAutoCacher::ClearVideoQueue(bool hard) has_changed_ = true; use_custom_range_ = false; + queued_frame_iterator_.reset(); } void PreviewAutoCacher::ClearAudioQueue(bool hard) @@ -579,31 +582,9 @@ void PreviewAutoCacher::RequeueFrames() } TimeRangeList invalidated = viewer_node_->video_frame_cache()->GetInvalidatedRanges().Intersects(using_range); - TimeRangeListFrameIterator invalidated_ranges(invalidated, viewer_node_->video_frame_cache()->GetTimebase()); + queued_frame_iterator_ = TimeRangeListFrameIterator(invalidated, viewer_node_->video_frame_cache()->GetTimebase()); - rational t; - while (invalidated_ranges.GetNext(&t)) { - const QByteArray& hash = viewer_node_->video_frame_cache()->GetHash(t); - - RenderTicketWatcher* render_task = video_tasks_.key(hash); - - if (t >= using_range.in() - && t < using_range.out()) { - // We want this hash, if we're not already rendering, start render now - if (!render_task && !video_download_tasks_.key(hash)) { - // Don't render any hash more than once - RenderFrame(hash, t, false, false); - } - } else if (render_task) { - // Cancel this frame unless it's already started - QMutexLocker locker(render_task->GetTicket()->lock()); - - if (!render_task->GetTicket()->IsRunning(false)) { - video_tasks_.remove(render_task); - delete render_task; - } - } - } + QueueNextFrameInRange(RenderManager::GetNumberOfIdealConcurrentJobs()); has_changed_ = false; } @@ -777,6 +758,24 @@ void PreviewAutoCacher::ClearQueueRemoveEventInternal(QVectorvideo_frame_cache()->GetHash(t); + + RenderTicketWatcher* render_task = video_tasks_.key(hash); + + // We want this hash, if we're not already rendering, start render now + if (!render_task && !video_download_tasks_.key(hash)) { + // Don't render any hash more than once + RenderFrame(hash, t, false, false); + + max--; + } + } +} + template void PreviewAutoCacher::ClearQueueInternal(T& list, bool hard, Func member) { diff --git a/app/render/previewautocacher.h b/app/render/previewautocacher.h index 7869249ef..e60ca6c2a 100644 --- a/app/render/previewautocacher.h +++ b/app/render/previewautocacher.h @@ -115,6 +115,9 @@ private: void ClearQueueRemoveEventInternal(QMap::iterator it); void ClearQueueRemoveEventInternal(QVector::iterator it); + void QueueNextFrameInRange(int max); + TimeRangeListFrameIterator queued_frame_iterator_; + class QueuedJob { public: enum Type { diff --git a/app/render/rendermanager.h b/app/render/rendermanager.h index 34f8532d9..816394dac 100644 --- a/app/render/rendermanager.h +++ b/app/render/rendermanager.h @@ -123,6 +123,11 @@ public: return backend_; } + static int GetNumberOfIdealConcurrentJobs() + { + return QThread::idealThreadCount(); + } + signals: private: