diff --git a/app/render/backend/opengl/openglworker.cpp b/app/render/backend/opengl/openglworker.cpp index b3e3c5fc1..eaed586f4 100644 --- a/app/render/backend/opengl/openglworker.cpp +++ b/app/render/backend/opengl/openglworker.cpp @@ -45,8 +45,6 @@ bool OpenGLWorker::InitInternal() ctx_->moveToThread(this->thread()); - //qDebug() << "Processor initialized in thread" << thread() << "- context is in" << ctx_->thread(); - // The rest of the initialization needs to occur in the other thread, so we signal for it to start QMetaObject::invokeMethod(this, "FinishInit", Qt::QueuedConnection); diff --git a/app/render/backend/videorenderbackend.cpp b/app/render/backend/videorenderbackend.cpp index 1299f1f78..dcc911955 100644 --- a/app/render/backend/videorenderbackend.cpp +++ b/app/render/backend/videorenderbackend.cpp @@ -27,6 +27,7 @@ #include #include +#include "common/timecodefunctions.h" #include "render/pixelservice.h" #include "videorenderworker.h" @@ -55,12 +56,10 @@ void VideoRenderBackend::InvalidateCache(const rational &start_range, const rati << end_range_adj.toDouble(); // Snap start_range to timebase - double start_range_dbl = start_range_adj.toDouble(); - double start_range_numf = start_range_dbl * static_cast(params_.time_base().denominator()); - int64_t start_range_numround = qFloor(start_range_numf/static_cast(params_.time_base().numerator())) * params_.time_base().numerator(); - rational true_start_range(start_range_numround, params_.time_base().denominator()); + int64_t timestamp = olive::time_to_timestamp(start_range_adj, params_.time_base()); + rational true_start = olive::timestamp_to_time(timestamp, params_.time_base()); - for (rational r=true_start_range;r<=end_range_adj;r+=params_.time_base()) { + for (rational r=true_start;r times_with_this_hash = frame_cache()->DeferredMapsWithHash(hash); + foreach (const rational& t, times_with_this_hash) { + EmitCachedFrameReady(t, texture); + } + } + } + if (!export_mode_) { if (texture.isNull()) { // No frame received, we set hash to an empty @@ -268,18 +279,6 @@ void VideoRenderBackend::ThreadCompletedFrame(NodeDependency path, QByteArray ha } } - // Check if this frame has changed once again, in which case we may not want to draw it (it'll look jittery to the user) - if (!TimeIsQueued(TimeRange(path.in(), path.in()))) { - EmitCachedFrameReady(path.in(), texture); - - if (export_mode_) { - QList times_with_this_hash = frame_cache()->TimesWithHash(hash); - foreach (const rational& t, times_with_this_hash) { - EmitCachedFrameReady(t, texture); - } - } - } - // Queue up a new frame for this worker CacheNext(); } @@ -287,17 +286,18 @@ void VideoRenderBackend::ThreadCompletedFrame(NodeDependency path, QByteArray ha void VideoRenderBackend::ThreadCompletedDownload(NodeDependency dep, QByteArray hash) { frame_cache()->SetHash(dep.in(), hash); + emit CachedTimeReady(dep.in()); // Emit for each frame that has this hash (some may have been added in ThreadSkippedFrame) - QList times_with_this_hash = frame_cache()->TimesWithHash(hash); + QList times_with_this_hash = frame_cache()->DeferredMapsWithHash(hash); foreach (const rational& t, times_with_this_hash) { + frame_cache()->SetHash(t, hash); emit CachedTimeReady(t); } } void VideoRenderBackend::ThreadSkippedFrame(NodeDependency dep, QByteArray hash) { - frame_cache()->SetHash(dep.in(), hash); SetWorkerBusyState(static_cast(sender()), false); // Queue up a new frame for this worker diff --git a/app/render/backend/videorenderframecache.cpp b/app/render/backend/videorenderframecache.cpp index 9de93623b..0056224e1 100644 --- a/app/render/backend/videorenderframecache.cpp +++ b/app/render/backend/videorenderframecache.cpp @@ -26,13 +26,15 @@ bool VideoRenderFrameCache::IsCaching(const QByteArray &hash) return is_caching; } -bool VideoRenderFrameCache::TryCache(const QByteArray &hash) +bool VideoRenderFrameCache::TryCache(const rational& time, const QByteArray &hash) { currently_caching_lock_.lock(); bool is_caching = currently_caching_list_.contains(hash); - if (!is_caching) { + if (is_caching) { + deferred_maps_.insert(time, hash); + } else { currently_caching_list_.append(hash); } @@ -80,18 +82,27 @@ void VideoRenderFrameCache::Truncate(const rational &time) } } -QList VideoRenderFrameCache::TimesWithHash(const QByteArray &hash) +QList VideoRenderFrameCache::DeferredMapsWithHash(const QByteArray &hash) { QList list; - QMap::const_iterator iterator; + currently_caching_lock_.lock(); - for (iterator=time_hash_map_.begin();iterator!=time_hash_map_.end();iterator++) { + QMap::iterator iterator = deferred_maps_.begin(); + + while (iterator != deferred_maps_.end()) { if (iterator.value() == hash) { list.append(iterator.key()); + iterator = deferred_maps_.erase(iterator); + } else { + iterator++; } } + currently_caching_list_.removeOne(hash); + + currently_caching_lock_.unlock(); + return list; } diff --git a/app/render/backend/videorenderframecache.h b/app/render/backend/videorenderframecache.h index 74a40f286..c8d4cb382 100644 --- a/app/render/backend/videorenderframecache.h +++ b/app/render/backend/videorenderframecache.h @@ -23,7 +23,7 @@ public: /** * @brief Check if a frame is currently being cached, and if not reserve it */ - bool TryCache(const QByteArray& hash); + bool TryCache(const rational &time, const QByteArray& hash); /** * @brief Return the path of the cached image at this time @@ -39,12 +39,13 @@ public: void Truncate(const rational& time); - QList TimesWithHash(const QByteArray& hash); + QList DeferredMapsWithHash(const QByteArray& hash); private: void RemoveHashFromCurrentlyCaching(const QByteArray& hash); QMap time_hash_map_; + QMap deferred_maps_; QMutex currently_caching_lock_; QVector currently_caching_list_; diff --git a/app/render/backend/videorenderworker.cpp b/app/render/backend/videorenderworker.cpp index ee00ff8d9..3c670baef 100644 --- a/app/render/backend/videorenderworker.cpp +++ b/app/render/backend/videorenderworker.cpp @@ -30,7 +30,7 @@ NodeValueTable VideoRenderWorker::RenderInternal(const NodeDependency& path) if (frame_cache_->HasHash(hash)) { // We've already cached this hash, no need to continue emit HashAlreadyExists(path, hash); - } else if (frame_cache_->TryCache(hash)) { + } else if (frame_cache_->TryCache(path.in(), hash)) { // This hash is available for us to cache, start traversing graph value = ProcessNode(path);