diff --git a/app/render/previewautocacher.cpp b/app/render/previewautocacher.cpp index 66973aa7c..8e31da39e 100644 --- a/app/render/previewautocacher.cpp +++ b/app/render/previewautocacher.cpp @@ -202,13 +202,13 @@ void PreviewAutoCacher::VideoRendered() const QByteArray& hash = video_tasks_.value(watcher); // Download frame in another thread - QFutureWatcher* w = new QFutureWatcher(); + RenderTicketWatcher* w = new RenderTicketWatcher(); video_download_tasks_.insert(w, hash); - connect(w, &QFutureWatcher::finished, this, &PreviewAutoCacher::VideoDownloaded); - w->setFuture(QtConcurrent::run(viewer_node_->video_frame_cache(), - &FrameHashCache::SaveCacheFrame, - hash, - watcher->Get().value())); + connect(w, &RenderTicketWatcher::Finished, this, &PreviewAutoCacher::VideoDownloaded); + w->SetTicket(RenderManager::instance()->SaveFrameToCache(viewer_node_->video_frame_cache(), + watcher->Get().value(), + hash, + true)); } video_tasks_.remove(watcher); @@ -224,11 +224,11 @@ void PreviewAutoCacher::VideoRendered() void PreviewAutoCacher::VideoDownloaded() { - QFutureWatcher* watcher = static_cast*>(sender()); + RenderTicketWatcher* watcher = static_cast(sender()); if (video_download_tasks_.contains(watcher)) { - if (!watcher->isCanceled()) { - if (watcher->result()) { + if (!watcher->WasCancelled()) { + if (watcher->Get().toBool()) { const QByteArray& hash = video_download_tasks_.value(watcher); currently_caching_hashes_.removeOne(hash); @@ -375,12 +375,12 @@ void PreviewAutoCacher::ClearVideoDownloadQueue(bool wait) auto copy = video_download_tasks_; for (auto it=copy.cbegin(); it!=copy.cend(); it++) { - it.key()->cancel(); + it.key()->Cancel(); } if (wait) { copy = video_download_tasks_; for (auto it=copy.cbegin(); it!=copy.cend(); it++) { - it.key()->waitForFinished(); + it.key()->WaitForFinished(); } } } diff --git a/app/render/previewautocacher.h b/app/render/previewautocacher.h index b2ab2953a..0190a4e00 100644 --- a/app/render/previewautocacher.h +++ b/app/render/previewautocacher.h @@ -136,7 +136,7 @@ private: QList*> hash_tasks_; QMap audio_tasks_; QMap video_tasks_; - QMap*, QByteArray> video_download_tasks_; + QMap video_download_tasks_; QVector currently_caching_hashes_; diff --git a/app/render/rendermanager.cpp b/app/render/rendermanager.cpp index ac8c3881d..3c0ff4e26 100644 --- a/app/render/rendermanager.cpp +++ b/app/render/rendermanager.cpp @@ -98,6 +98,24 @@ RenderTicketPtr RenderManager::RenderAudio(ViewerOutput* viewer, const TimeRange return ticket; } +RenderTicketPtr RenderManager::SaveFrameToCache(FrameHashCache *cache, FramePtr frame, const QByteArray &hash, bool prioritize) +{ + // Create ticket + RenderTicketPtr ticket = std::make_shared(); + + ticket->setProperty("cache", Node::PtrToValue(cache)); + ticket->setProperty("frame", QVariant::fromValue(frame)); + ticket->setProperty("hash", hash); + ticket->setProperty("type", kTypeVideoDownload); + + // Queue appending the ticket and running the next job on our thread to make this function thread-safe + QMetaObject::invokeMethod(this, "AddTicket", Qt::AutoConnection, + OLIVE_NS_ARG(RenderTicketPtr, ticket), + Q_ARG(bool, prioritize)); + + return ticket; +} + void RenderManager::RunTicket(RenderTicketPtr ticket) const { // Depending on the render ticket type, start a job @@ -110,6 +128,9 @@ void RenderManager::RunTicket(RenderTicketPtr ticket) const case kTypeAudio: RenderAudioInternal(ticket); break; + case kTypeVideoDownload: + SaveFrameToCacheInternal(ticket); + break; default: // Fail ticket->Cancel(); @@ -144,6 +165,17 @@ void RenderManager::RenderAudioInternal(RenderTicketPtr ticket) ticket->Finish(QVariant::fromValue(SampleBuffer::CreateAllocated(viewer->audio_params(), time.length())), false); } +void RenderManager::SaveFrameToCacheInternal(RenderTicketPtr ticket) +{ + FrameHashCache* cache = Node::ValueToPtr(ticket->property("cache")); + FramePtr frame = ticket->property("frame").value(); + QByteArray hash = ticket->property("hash").toByteArray(); + + ticket->Start(); + + ticket->Finish(cache->SaveCacheFrame(hash, frame), false); +} + void RenderManager::WorkerGeneratedWaveform(RenderTicketPtr ticket, TrackOutput *track, AudioVisualWaveform samples, TimeRange range) { ViewerOutput* viewer = Node::ValueToPtr(ticket->property("viewer")); diff --git a/app/render/rendermanager.h b/app/render/rendermanager.h index e8948db6a..035bf7938 100644 --- a/app/render/rendermanager.h +++ b/app/render/rendermanager.h @@ -91,11 +91,14 @@ public: */ RenderTicketPtr RenderAudio(ViewerOutput* viewer, const TimeRange& r, bool prioritize = false); + RenderTicketPtr SaveFrameToCache(FrameHashCache* cache, FramePtr frame, const QByteArray& hash, bool prioritize = false); + virtual void RunTicket(RenderTicketPtr ticket) const override; enum TicketType { kTypeVideo, - kTypeAudio + kTypeAudio, + kTypeVideoDownload }; signals: @@ -105,6 +108,8 @@ private: static void RenderAudioInternal(RenderTicketPtr ticket); + static void SaveFrameToCacheInternal(RenderTicketPtr ticket); + RenderManager(QObject* parent = nullptr); virtual ~RenderManager() override;