render: use single base thread for rendering
This commit is contained in:
@@ -838,7 +838,7 @@ AVFramePtr FFmpegDecoder::RetrieveFrame(const rational& time, const QAtomicInt *
|
||||
} else {
|
||||
|
||||
// Cut down to thread count - 1 before we acquire a new frame
|
||||
if (cached_frames_.size() == size_t(MaximumQueueSize())) {
|
||||
if (cached_frames_.size() > size_t(MaximumQueueSize())) {
|
||||
RemoveFirstFrame();
|
||||
}
|
||||
|
||||
@@ -1041,7 +1041,11 @@ void FFmpegDecoder::RemoveFirstFrame()
|
||||
|
||||
int FFmpegDecoder::MaximumQueueSize()
|
||||
{
|
||||
return QThread::idealThreadCount();
|
||||
// Fairly arbitrary size. This used to need to be the number of current threads to ensure any
|
||||
// thread that arrived would have its frame available, but if we only have one render thread,
|
||||
// that's no longer a concern. Now, this value could technically be 1, but some memory cache
|
||||
// may be useful for reversing. This value may be tweaked over time.
|
||||
return 2;
|
||||
}
|
||||
|
||||
FFmpegDecoder::Instance::Instance() :
|
||||
|
||||
@@ -38,8 +38,9 @@ namespace olive {
|
||||
RenderManager* RenderManager::instance_ = nullptr;
|
||||
|
||||
RenderManager::RenderManager(QObject *parent) :
|
||||
ThreadPool(0, parent),
|
||||
backend_(kOpenGL)
|
||||
ThreadPool(1, parent),
|
||||
backend_(kOpenGL),
|
||||
aggressive_gc_(0)
|
||||
{
|
||||
Renderer* graphics_renderer = nullptr;
|
||||
|
||||
@@ -60,10 +61,10 @@ RenderManager::RenderManager(QObject *parent) :
|
||||
decoder_cache_ = nullptr;
|
||||
}
|
||||
|
||||
QTimer *decoder_clear_timer = new QTimer(this);
|
||||
decoder_clear_timer->setInterval(kDecoderMaximumInactivity);
|
||||
connect(decoder_clear_timer, &QTimer::timeout, this, &RenderManager::ClearOldDecoders);
|
||||
decoder_clear_timer->start();
|
||||
decoder_clear_timer_ = new QTimer(this);
|
||||
decoder_clear_timer_->setInterval(kDecoderMaximumInactivity);
|
||||
connect(decoder_clear_timer_, &QTimer::timeout, this, &RenderManager::ClearOldDecoders);
|
||||
decoder_clear_timer_->start();
|
||||
}
|
||||
|
||||
RenderManager::~RenderManager()
|
||||
@@ -162,6 +163,17 @@ void RenderManager::RunTicket(RenderTicketPtr ticket) const
|
||||
RenderProcessor::Process(ticket, context_, decoder_cache_, shader_cache_);
|
||||
}
|
||||
|
||||
void RenderManager::SetAggressiveGarbageCollection(bool enabled)
|
||||
{
|
||||
aggressive_gc_ += enabled ? 1 : -1;
|
||||
|
||||
if (aggressive_gc_ > 0) {
|
||||
decoder_clear_timer_->setInterval(kDecoderMaximumInactivityAggressive);
|
||||
} else {
|
||||
decoder_clear_timer_->setInterval(kDecoderMaximumInactivity);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderManager::ClearOldDecoders()
|
||||
{
|
||||
QMutexLocker locker(decoder_cache_->mutex());
|
||||
|
||||
@@ -113,6 +113,9 @@ public:
|
||||
return QThread::idealThreadCount();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetAggressiveGarbageCollection(bool enabled);
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
@@ -130,7 +133,12 @@ private:
|
||||
|
||||
ShaderCache* shader_cache_;
|
||||
|
||||
static constexpr auto kDecoderMaximumInactivity = 10000;
|
||||
static constexpr auto kDecoderMaximumInactivityAggressive = 1000;
|
||||
static constexpr auto kDecoderMaximumInactivity = 5000;
|
||||
|
||||
int aggressive_gc_;
|
||||
|
||||
QTimer *decoder_clear_timer_;
|
||||
|
||||
private slots:
|
||||
void ClearOldDecoders();
|
||||
|
||||
@@ -44,6 +44,8 @@ bool RenderTask::Render(ColorManager* manager,
|
||||
const QMatrix4x4 &force_matrix, VideoParams::Format force_format,
|
||||
ColorProcessorPtr force_color_output)
|
||||
{
|
||||
QMetaObject::invokeMethod(RenderManager::instance(), "SetAggressiveGarbageCollection", Q_ARG(bool, true));
|
||||
|
||||
// Run watchers in another thread so they can accept signals even while this thread is blocked
|
||||
QThread watcher_thread;
|
||||
watcher_thread.start();
|
||||
@@ -236,6 +238,8 @@ bool RenderTask::Render(ColorManager* manager,
|
||||
watcher_thread.quit();
|
||||
watcher_thread.wait();
|
||||
|
||||
QMetaObject::invokeMethod(RenderManager::instance(), "SetAggressiveGarbageCollection", Q_ARG(bool, false));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -765,6 +765,8 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only)
|
||||
viewer->auto_cacher_.SetAudioPaused(true);
|
||||
}
|
||||
|
||||
RenderManager::instance()->SetAggressiveGarbageCollection(true);
|
||||
|
||||
// Disarm recording if armed
|
||||
if (record_armed_) {
|
||||
DisarmRecording();
|
||||
@@ -861,6 +863,8 @@ void ViewerWidget::PauseInternal()
|
||||
}
|
||||
|
||||
UpdateTextureFromNode();
|
||||
|
||||
RenderManager::instance()->SetAggressiveGarbageCollection(false);
|
||||
}
|
||||
|
||||
prequeuing_video_ = false;
|
||||
@@ -1108,7 +1112,9 @@ void ViewerWidget::RendererGeneratedFrameForQueue()
|
||||
prequeuing_video_ = false;
|
||||
FinishPlayPreprocess();
|
||||
} else {
|
||||
RequestNextFrameForQueue();
|
||||
// This call was mostly necessary to keep the threads busy between prequeue and playback.
|
||||
// If we only have a single render thread, it's no longer necessary.
|
||||
//RequestNextFrameForQueue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user