From 3dae723bbc0776d40588f90f8f418ba51317de68 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 23 Mar 2021 00:56:03 +1100 Subject: [PATCH] rendertask: limit maximum frames that can be rendered concurrently Fixes #1418 --- app/task/render/render.cpp | 56 ++++++++++++++++++++++++++++---------- app/task/render/render.h | 2 ++ 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/app/task/render/render.cpp b/app/task/render/render.cpp index dd6ae327d..d397d9ec3 100644 --- a/app/task/render/render.cpp +++ b/app/task/render/render.cpp @@ -72,6 +72,7 @@ bool RenderTask::Render(ColorManager* manager, // Look up hashes QMap > time_map; + QVector > frame_render_order; if (!video_range.isEmpty()) { // Get list of discrete frames from range @@ -95,21 +96,11 @@ bool RenderTask::Render(ColorManager* manager, const QByteArray& hash = hashes.at(i); - time_map[hash].append(times.at(i)); + QVector& hash_time_list = time_map[hash]; + hash_time_list.append(times.at(i)); - if (time_map[hash].size() == 1) { - // This is the first frame with this hash, so we signal a render - RenderTicketWatcher* watcher = new RenderTicketWatcher(); - watcher->setProperty("hash", hash); - PrepareWatcher(watcher, &watcher_thread); - - IncrementRunningTickets(); - - watcher->SetTicket(RenderManager::instance()->RenderFrame(viewer_, manager, times.at(i), - mode, video_params_, audio_params_, - force_size, force_matrix, - force_format, force_color_output, - cache)); + if (hash_time_list.size() == 1) { + frame_render_order.append({times.at(i), hash}); } } @@ -117,6 +108,18 @@ bool RenderTask::Render(ColorManager* manager, total_length += video_frame_sz * time_map.size(); } + // Start a render of a limited amount, and then render one frame for each frame that gets + // finished. This prevents rendered frames from stacking up in memory indefinitely while the + // encoder is processing them. The amount is kind of arbitrary, but we use the thread count so + // each of the system's threads are utilized as memory allows. + const int maximum_rendered_frames = QThread::idealThreadCount(); + auto frame_iterator = frame_render_order.cbegin(); + + for (int i=0; isecond, &watcher_thread, manager, frame_iterator->first, + mode, cache, force_size, force_matrix, force_format, force_color_output); + } + finished_watcher_mutex_.lock(); while (!IsCancelled()) { @@ -165,6 +168,13 @@ bool RenderTask::Render(ColorManager* manager, emit ProgressChanged(progress_counter / total_length); + if (frame_iterator != frame_render_order.cend()) { + StartTicket(frame_iterator->second, &watcher_thread, manager, frame_iterator->first, + mode, cache, force_size, force_matrix, force_format, force_color_output); + + frame_iterator++; + } + } delete watcher; @@ -229,6 +239,24 @@ void RenderTask::IncrementRunningTickets() finished_watcher_mutex_.unlock(); } +void RenderTask::StartTicket(const QByteArray& hash, QThread* watcher_thread, ColorManager* manager, + const rational& time, RenderMode::Mode mode, FrameHashCache* cache, + const QSize &force_size, const QMatrix4x4 &force_matrix, + VideoParams::Format force_format, ColorProcessorPtr force_color_output) +{ + RenderTicketWatcher* watcher = new RenderTicketWatcher(); + watcher->setProperty("hash", hash); + PrepareWatcher(watcher, watcher_thread); + + IncrementRunningTickets(); + + watcher->SetTicket(RenderManager::instance()->RenderFrame(viewer_, manager, time, + mode, video_params_, audio_params_, + force_size, force_matrix, + force_format, force_color_output, + cache)); +} + void RenderTask::TicketDone(RenderTicketWatcher* watcher) { finished_watcher_mutex_.lock(); diff --git a/app/task/render/render.h b/app/task/render/render.h index 8f111f7ec..b4a2aaeee 100644 --- a/app/task/render/render.h +++ b/app/task/render/render.h @@ -85,6 +85,8 @@ private: void IncrementRunningTickets(); + void StartTicket(const QByteArray &hash, QThread *watcher_thread, ColorManager *manager, const rational &time, RenderMode::Mode mode, FrameHashCache *cache, const QSize &force_size, const QMatrix4x4 &force_matrix, VideoParams::Format force_format, ColorProcessorPtr force_color_output); + Sequence* viewer_; VideoParams video_params_;