cache: attempt to automatically re-match hashes on invalidate
This code is slow and unoptimized. Will require some more work.
This commit is contained in:
@@ -66,6 +66,11 @@ class TimeRangeList : public QList<TimeRange> {
|
||||
public:
|
||||
TimeRangeList() = default;
|
||||
|
||||
TimeRangeList(std::initializer_list<TimeRange> r) :
|
||||
QList<TimeRange>(r)
|
||||
{
|
||||
}
|
||||
|
||||
void InsertTimeRange(const TimeRange& range);
|
||||
|
||||
void RemoveTimeRange(const TimeRange& range);
|
||||
|
||||
@@ -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<rational> FrameHashCache::GetFrameListFromTimeRange(TimeRangeList range_list, const rational &timebase)
|
||||
{
|
||||
QList<rational> 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<rational> FrameHashCache::GetFrameListFromTimeRange(const TimeRangeList &range) const
|
||||
{
|
||||
return GetFrameListFromTimeRange(range, timebase_);
|
||||
}
|
||||
|
||||
void FrameHashCache::SaveCacheFrame(const QByteArray& hash,
|
||||
char* data,
|
||||
const VideoRenderingParams& vparam)
|
||||
|
||||
@@ -66,6 +66,9 @@ public:
|
||||
|
||||
static QString GetFormatExtension(const PixelFormat::Format& f);
|
||||
|
||||
static QList<rational> GetFrameListFromTimeRange(TimeRangeList range_list, const rational& timebase);
|
||||
QList<rational> GetFrameListFromTimeRange(const TimeRangeList &range) const;
|
||||
|
||||
protected:
|
||||
virtual void LengthChangedEvent(const rational& old, const rational& newlen) override;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -73,25 +73,10 @@ void RenderTask::Render(const TimeRangeList& range_to_cache,
|
||||
QLinkedList<TimeHashFuturePair> hash_list;
|
||||
|
||||
{
|
||||
TimeRangeList range_list = range_to_cache;
|
||||
while (!range_list.isEmpty()) {
|
||||
const TimeRange& range = range_list.first();
|
||||
QList<rational> 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)});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -732,6 +732,24 @@ void ViewerWidget::RendererGeneratedFrameForQueue()
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWidget::HashGenerated()
|
||||
{
|
||||
QFutureWatcher<QByteArray>* watcher = static_cast<QFutureWatcher<QByteArray>*>(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<rational> invalidated_frames = GetConnectedNode()->video_frame_cache()->GetFrameListFromTimeRange({range});
|
||||
foreach (const rational& r, invalidated_frames) {
|
||||
QFutureWatcher<QByteArray>* watcher = new QFutureWatcher<QByteArray>();
|
||||
connect(watcher, &QFutureWatcher<QByteArray>::finished, this, &ViewerWidget::HashGenerated);
|
||||
hash_watchers_.insert(watcher, r);
|
||||
watcher->setFuture(renderer_->Hash(r, true));
|
||||
}
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -233,6 +233,8 @@ private:
|
||||
|
||||
QList< QFutureWatcher<FramePtr>* > nonqueue_watchers_;
|
||||
|
||||
QHash<QFutureWatcher<QByteArray>*, rational> hash_watchers_;
|
||||
|
||||
private slots:
|
||||
void PlaybackTimerUpdate();
|
||||
|
||||
@@ -268,6 +270,8 @@ private slots:
|
||||
|
||||
void RendererGeneratedFrameForQueue();
|
||||
|
||||
void HashGenerated();
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Reference in New Issue
Block a user