diff --git a/app/common/timerange.h b/app/common/timerange.h index 41d7c4026..61e759abf 100644 --- a/app/common/timerange.h +++ b/app/common/timerange.h @@ -66,6 +66,11 @@ class TimeRangeList : public QList { public: TimeRangeList() = default; + TimeRangeList(std::initializer_list r) : + QList(r) + { + } + void InsertTimeRange(const TimeRange& range); void RemoveTimeRange(const TimeRange& range); diff --git a/app/render/framehashcache.cpp b/app/render/framehashcache.cpp index e83dd6169..d0b38f88c 100644 --- a/app/render/framehashcache.cpp +++ b/app/render/framehashcache.cpp @@ -29,6 +29,7 @@ #include "codec/frame.h" #include "common/filefunctions.h" +#include "common/timecodefunctions.h" #include "render/diskmanager.h" OLIVE_NAMESPACE_ENTER @@ -104,6 +105,36 @@ QString FrameHashCache::GetFormatExtension(const PixelFormat::Format &f) } } +QList FrameHashCache::GetFrameListFromTimeRange(TimeRangeList range_list, const rational &timebase) +{ + QList times; + + while (!range_list.isEmpty()) { + const TimeRange& range = range_list.first(); + + rational time = range.in(); + rational snapped = Timecode::snap_time_to_timebase(time, timebase); + rational next; + + if (snapped > time) { + next = snapped; + snapped -= timebase; + } else { + next = snapped + timebase; + } + + times.append(snapped); + range_list.RemoveTimeRange(TimeRange(snapped, next)); + } + + return times; +} + +QList FrameHashCache::GetFrameListFromTimeRange(const TimeRangeList &range) const +{ + return GetFrameListFromTimeRange(range, timebase_); +} + void FrameHashCache::SaveCacheFrame(const QByteArray& hash, char* data, const VideoRenderingParams& vparam) diff --git a/app/render/framehashcache.h b/app/render/framehashcache.h index 3c57310b8..fa5f66410 100644 --- a/app/render/framehashcache.h +++ b/app/render/framehashcache.h @@ -66,6 +66,9 @@ public: static QString GetFormatExtension(const PixelFormat::Format& f); + static QList GetFrameListFromTimeRange(TimeRangeList range_list, const rational& timebase); + QList GetFrameListFromTimeRange(const TimeRangeList &range) const; + protected: virtual void LengthChangedEvent(const rational& old, const rational& newlen) override; diff --git a/app/task/export/export.cpp b/app/task/export/export.cpp index 2db6038e3..232d2baa9 100644 --- a/app/task/export/export.cpp +++ b/app/task/export/export.cpp @@ -85,9 +85,7 @@ bool ExportTask::Run() } // Start render process - TimeRangeList ranges; - ranges.InsertTimeRange(range); - Render(ranges, mat, params_.audio_enabled()); + Render({range}, mat, params_.audio_enabled()); bool success = true; diff --git a/app/task/render/render.cpp b/app/task/render/render.cpp index 16d88c19e..f50d33646 100644 --- a/app/task/render/render.cpp +++ b/app/task/render/render.cpp @@ -73,25 +73,10 @@ void RenderTask::Render(const TimeRangeList& range_to_cache, QLinkedList hash_list; { - TimeRangeList range_list = range_to_cache; - while (!range_list.isEmpty()) { - const TimeRange& range = range_list.first(); + QList times = viewer_->video_frame_cache()->GetFrameListFromTimeRange(range_to_cache); - const rational& timebase = viewer_->video_params().time_base(); - - rational time = range.in(); - rational snapped = Timecode::snap_time_to_timebase(time, timebase); - rational next; - - if (snapped > time) { - next = snapped; - snapped -= timebase; - } else { - next = snapped + timebase; - } - - hash_list.append({snapped, backend.Hash(snapped, false)}); - range_list.RemoveTimeRange(TimeRange(snapped, next)); + foreach (const rational& r, times) { + hash_list.append({r, backend.Hash(r, false)}); } } diff --git a/app/widget/viewer/viewer.cpp b/app/widget/viewer/viewer.cpp index 66ec98831..0741399e5 100644 --- a/app/widget/viewer/viewer.cpp +++ b/app/widget/viewer/viewer.cpp @@ -732,6 +732,24 @@ void ViewerWidget::RendererGeneratedFrameForQueue() } } +void ViewerWidget::HashGenerated() +{ + QFutureWatcher* watcher = static_cast*>(sender()); + + if (hash_watchers_.contains(watcher)) { + QString cache_fn = GetConnectedNode()->video_frame_cache()->CachePathName(watcher->result(), GetCurrentPixelFormat()); + + if (QFileInfo::exists(cache_fn)) { + GetConnectedNode()->video_frame_cache()->SetHash(hash_watchers_.value(watcher), + watcher->result()); + } + + hash_watchers_.remove(watcher); + } + + watcher->deleteLater(); +} + void ViewerWidget::UpdateRendererParameters() { renderer_->SetVideoParams(VideoRenderingParams(GetConnectedNode()->video_params(), @@ -1071,6 +1089,14 @@ void ViewerWidget::ViewerInvalidatedRange(const TimeRange &range) if (GetTime() >= range.in() && (GetTime() < range.out() || range.in() == range.out())) { ForceUpdate(); } + + QList invalidated_frames = GetConnectedNode()->video_frame_cache()->GetFrameListFromTimeRange({range}); + foreach (const rational& r, invalidated_frames) { + QFutureWatcher* watcher = new QFutureWatcher(); + connect(watcher, &QFutureWatcher::finished, this, &ViewerWidget::HashGenerated); + hash_watchers_.insert(watcher, r); + watcher->setFuture(renderer_->Hash(r, true)); + } } OLIVE_NAMESPACE_EXIT diff --git a/app/widget/viewer/viewer.h b/app/widget/viewer/viewer.h index d7b65109d..6d7516cc8 100644 --- a/app/widget/viewer/viewer.h +++ b/app/widget/viewer/viewer.h @@ -233,6 +233,8 @@ private: QList< QFutureWatcher* > nonqueue_watchers_; + QHash*, rational> hash_watchers_; + private slots: void PlaybackTimerUpdate(); @@ -268,6 +270,8 @@ private slots: void RendererGeneratedFrameForQueue(); + void HashGenerated(); + }; OLIVE_NAMESPACE_EXIT