From 7385e3dc569c42eec6b72f09d54f49e2b783f633 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 18 Nov 2019 02:14:54 +0900 Subject: [PATCH] fixes jitters by using signals/slots to pass image buffers around Updating values rapidly would cause strange jitters as a byproduct of the viewer trying to update from the renderer while it was still working. Rather than the viewer trying to access the the renderer, we now send textures in the initial update signal to keep everything synchronized. --- app/render/backend/audiorenderworker.cpp | 4 ++- app/render/backend/audiorenderworker.h | 2 +- app/render/backend/opengl/openglbackend.cpp | 31 ++++++++------------- app/render/backend/opengl/openglbackend.h | 6 ++-- app/render/backend/renderworker.h | 2 +- app/render/backend/videorenderbackend.cpp | 2 +- app/render/backend/videorenderbackend.h | 3 +- app/render/backend/videorenderworker.cpp | 8 ++++-- app/render/backend/videorenderworker.h | 4 +-- app/widget/viewer/viewer.cpp | 12 ++++++-- app/widget/viewer/viewer.h | 3 +- app/window/mainwindow/mainwindow.cpp | 2 +- 12 files changed, 43 insertions(+), 36 deletions(-) diff --git a/app/render/backend/audiorenderworker.cpp b/app/render/backend/audiorenderworker.cpp index 403ecf73c..11e8c848e 100644 --- a/app/render/backend/audiorenderworker.cpp +++ b/app/render/backend/audiorenderworker.cpp @@ -12,7 +12,7 @@ void AudioRenderWorker::SetParameters(const AudioRenderingParams &audio_params) audio_params_ = audio_params; } -void AudioRenderWorker::RenderAsSibling(NodeDependency dep) +QVariant AudioRenderWorker::RenderAsSibling(NodeDependency dep) { NodeOutput* output = dep.node(); Node* node = output->parent(); @@ -49,6 +49,8 @@ void AudioRenderWorker::RenderAsSibling(NodeDependency dep) // End this working state working_--; + + return value; } bool AudioRenderWorker::InitInternal() diff --git a/app/render/backend/audiorenderworker.h b/app/render/backend/audiorenderworker.h index 46bb351d6..3166018fa 100644 --- a/app/render/backend/audiorenderworker.h +++ b/app/render/backend/audiorenderworker.h @@ -12,7 +12,7 @@ public: void SetParameters(const AudioRenderingParams& audio_params); public slots: - virtual void RenderAsSibling(NodeDependency dep) override; + virtual QVariant RenderAsSibling(NodeDependency dep) override; protected: virtual bool InitInternal() override; diff --git a/app/render/backend/opengl/openglbackend.cpp b/app/render/backend/opengl/openglbackend.cpp index 6f1b24055..54ddbc503 100644 --- a/app/render/backend/opengl/openglbackend.cpp +++ b/app/render/backend/opengl/openglbackend.cpp @@ -6,9 +6,7 @@ #include "functions.h" OpenGLBackend::OpenGLBackend(QObject *parent) : - VideoRenderBackend(parent), - push_texture_(nullptr), - push_time_(-1) + VideoRenderBackend(parent) { } @@ -58,21 +56,11 @@ void OpenGLBackend::CloseInternal() //copy_buffer_.Destroy(); master_texture_ = nullptr; - push_texture_ = nullptr; //copy_pipeline_ = nullptr; } OpenGLTexturePtr OpenGLBackend::GetCachedFrameAsTexture(const rational &time) { - if (push_time_ >= 0) { - rational temp_push_time = push_time_; - push_time_ = -1; - - if (time == temp_push_time) { - return push_texture_; - } - } - const char* cached_frame = GetCachedFrame(time); if (cached_frame != nullptr) { @@ -167,11 +155,16 @@ bool OpenGLBackend::TraverseCompiling(Node *n) return true; } -void OpenGLBackend::ThreadCompletedFrame(NodeDependency path, QByteArray hash) +bool OpenGLBackend::TimeIsCached(const TimeRange &time) +{ + return cache_queue_.contains(time); +} + +void OpenGLBackend::ThreadCompletedFrame(NodeDependency path, QByteArray hash, QVariant value) { caching_ = false; - OpenGLTexturePtr texture = path.node()->get_cached_value(path.range()).value(); + OpenGLTexturePtr texture = value.value(); if (texture == nullptr) { // No frame received, we set hash to an empty @@ -197,9 +190,9 @@ void OpenGLBackend::ThreadCompletedFrame(NodeDependency path, QByteArray hash) } // Set as push texture - push_time_ = path.in(); - push_texture_ = texture; - emit CachedFrameReady(push_time_); + if (!TimeIsCached(TimeRange(path.in(), path.in()))) { + emit CachedFrameReady(path.in(), value); + } CacheNext(); } @@ -208,7 +201,7 @@ void OpenGLBackend::ThreadCompletedDownload(NodeDependency dep, QByteArray hash) { frame_cache()->SetHash(dep.in(), hash); - emit CachedFrameReady(dep.in()); + emit CachedTimeReady(dep.in()); } void OpenGLBackend::ThreadSkippedFrame() diff --git a/app/render/backend/opengl/openglbackend.h b/app/render/backend/opengl/openglbackend.h index 36e50408a..45b39842e 100644 --- a/app/render/backend/opengl/openglbackend.h +++ b/app/render/backend/opengl/openglbackend.h @@ -30,9 +30,9 @@ protected: private: bool TraverseCompiling(Node* n); + bool TimeIsCached(const TimeRange &time); + OpenGLTexturePtr master_texture_; - OpenGLTexturePtr push_texture_; - rational push_time_; /*OpenGLFramebuffer copy_buffer_; OpenGLShaderPtr copy_pipeline_;*/ @@ -40,7 +40,7 @@ private: OpenGLShaderCache shader_cache_; private slots: - void ThreadCompletedFrame(NodeDependency path, QByteArray hash); + void ThreadCompletedFrame(NodeDependency path, QByteArray hash, QVariant value); void ThreadCompletedDownload(NodeDependency dep, QByteArray hash); void ThreadSkippedFrame(); void ThreadHashAlreadyExists(NodeDependency dep, QByteArray hash); diff --git a/app/render/backend/renderworker.h b/app/render/backend/renderworker.h index 134012363..9128143bf 100644 --- a/app/render/backend/renderworker.h +++ b/app/render/backend/renderworker.h @@ -26,7 +26,7 @@ public slots: void Render(NodeDependency path); - virtual void RenderAsSibling(NodeDependency dep) = 0; + virtual QVariant RenderAsSibling(NodeDependency dep) = 0; signals: void RequestSibling(NodeDependency path); diff --git a/app/render/backend/videorenderbackend.cpp b/app/render/backend/videorenderbackend.cpp index 9849055d0..db2c1a9f7 100644 --- a/app/render/backend/videorenderbackend.cpp +++ b/app/render/backend/videorenderbackend.cpp @@ -165,7 +165,7 @@ void VideoRenderBackend::CacheIDChangedEvent(const QString &id) void VideoRenderBackend::ConnectWorkerToThis(RenderWorker *processor) { - connect(processor, SIGNAL(CompletedFrame(NodeDependency, QByteArray)), this, SLOT(ThreadCompletedFrame(NodeDependency, QByteArray))); + connect(processor, SIGNAL(CompletedFrame(NodeDependency, QByteArray, QVariant)), this, SLOT(ThreadCompletedFrame(NodeDependency, QByteArray, QVariant))); connect(processor, SIGNAL(HashAlreadyBeingCached()), this, SLOT(ThreadSkippedFrame())); connect(processor, SIGNAL(CompletedDownload(NodeDependency, QByteArray)), this, SLOT(ThreadCompletedDownload(NodeDependency, QByteArray))); connect(processor, SIGNAL(HashAlreadyExists(NodeDependency, QByteArray)), this, SLOT(ThreadHashAlreadyExists(NodeDependency, QByteArray))); diff --git a/app/render/backend/videorenderbackend.h b/app/render/backend/videorenderbackend.h index 6a642c785..c6875e1a9 100644 --- a/app/render/backend/videorenderbackend.h +++ b/app/render/backend/videorenderbackend.h @@ -93,7 +93,8 @@ protected: virtual void ConnectWorkerToThis(RenderWorker* processor) override; signals: - void CachedFrameReady(const rational& time); + void CachedFrameReady(const rational& time, QVariant value); + void CachedTimeReady(const rational& time); private: VideoRenderingParams params_; diff --git a/app/render/backend/videorenderworker.cpp b/app/render/backend/videorenderworker.cpp index f9c578852..499dea727 100644 --- a/app/render/backend/videorenderworker.cpp +++ b/app/render/backend/videorenderworker.cpp @@ -29,9 +29,9 @@ void VideoRenderWorker::RenderInternal(const NodeDependency& path) emit HashAlreadyExists(path, hash); } else if (frame_cache_->TryCache(hash)) { // This hash is available for us to cache, start traversing graph - RenderAsSibling(path); + QVariant value = RenderAsSibling(path); - emit CompletedFrame(path, hash); + emit CompletedFrame(path, hash, value); } else { // Another thread must be caching this already, nothing to be done emit HashAlreadyBeingCached(); @@ -115,7 +115,7 @@ void VideoRenderWorker::CloseInternal() download_buffer_.clear(); } -void VideoRenderWorker::RenderAsSibling(NodeDependency dep) +QVariant VideoRenderWorker::RenderAsSibling(NodeDependency dep) { NodeOutput* output = dep.node(); Node* original_node = output->parent(); @@ -158,6 +158,8 @@ void VideoRenderWorker::RenderAsSibling(NodeDependency dep) // End this working state working_--; + + return value; } void VideoRenderWorker::Download(NodeDependency dep, QByteArray hash, QVariant texture, QString filename) diff --git a/app/render/backend/videorenderworker.h b/app/render/backend/videorenderworker.h index 9f370ba52..59093368e 100644 --- a/app/render/backend/videorenderworker.h +++ b/app/render/backend/videorenderworker.h @@ -16,12 +16,12 @@ public: void SetParameters(const VideoRenderingParams& video_params); public slots: - virtual void RenderAsSibling(NodeDependency dep) override; + virtual QVariant RenderAsSibling(NodeDependency dep) override; void Download(NodeDependency dep, QByteArray hash, QVariant texture, QString filename); signals: - void CompletedFrame(NodeDependency path, QByteArray hash); + void CompletedFrame(NodeDependency path, QByteArray hash, QVariant value); void CompletedDownload(NodeDependency path, QByteArray hash); diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index a618b0a5c..58c58f1cd 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -77,7 +77,8 @@ ViewerWidget::ViewerWidget(QWidget *parent) : // Start background renderers video_renderer_ = new OpenGLBackend(this); - connect(video_renderer_, SIGNAL(CachedFrameReady(const rational&)), this, SLOT(RendererCachedFrame(const rational&))); + connect(video_renderer_, SIGNAL(CachedFrameReady(const rational&, QVariant)), this, SLOT(RendererCachedFrame(const rational&, QVariant))); + connect(video_renderer_, SIGNAL(CachedTimeReady(const rational&)), this, SLOT(RendererCachedTime(const rational&))); audio_renderer_ = new AudioBackend(this); } @@ -347,7 +348,14 @@ void ViewerWidget::PlaybackTimerUpdate() SetTime(current_time); } -void ViewerWidget::RendererCachedFrame(const rational &time) +void ViewerWidget::RendererCachedFrame(const rational &time, QVariant value) +{ + if (GetTime() == time) { + SetTexture(value.value()); + } +} + +void ViewerWidget::RendererCachedTime(const rational &time) { if (GetTime() == time) { UpdateTextureFromNode(GetTime()); diff --git a/app/widget/viewer/viewer.h b/app/widget/viewer/viewer.h index f8aec5760..178085f29 100644 --- a/app/widget/viewer/viewer.h +++ b/app/widget/viewer/viewer.h @@ -143,7 +143,8 @@ private slots: void PlaybackTimerUpdate(); - void RendererCachedFrame(const rational& time); + void RendererCachedFrame(const rational& time, QVariant value); + void RendererCachedTime(const rational& time); void SizeChangedSlot(int width, int height); diff --git a/app/window/mainwindow/mainwindow.cpp b/app/window/mainwindow/mainwindow.cpp index 42eadc73a..46e9ed80b 100644 --- a/app/window/mainwindow/mainwindow.cpp +++ b/app/window/mainwindow/mainwindow.cpp @@ -152,7 +152,7 @@ void olive::MainWindow::closeEvent(QCloseEvent *e) // FIXME: Test code - We have no cache management and the cache is very much testing only, so we delete it on close // as to not clog up HDD space QDir(GetMediaCacheLocation()).removeRecursively(); - QDir(GetMediaIndexLocation()).removeRecursively(); + //QDir(GetMediaIndexLocation()).removeRecursively(); // End test code QMainWindow::closeEvent(e);