renderer: use iterator rather than creating vectors

Creating vectors from the FrameHashCache was one of the slowest functions in the program, this should be significantly faster.
This commit is contained in:
itsmattkc
2021-07-11 16:47:12 -07:00
parent 9b0b3962fe
commit 8a58ee2bdb
9 changed files with 126 additions and 95 deletions
-71
View File
@@ -114,77 +114,6 @@ void FrameHashCache::ValidateFramesWithHash(const QByteArray &hash)
}
}
QList<rational> FrameHashCache::GetFramesWithHash(const QByteArray &hash)
{
QList<rational> times;
for (int64_t i=0; i<GetMapSize(); i++) {
if (time_hash_map_.at(i) == hash) {
times.append(ToTime(i));
}
}
return times;
}
QList<rational> FrameHashCache::TakeFramesWithHash(const QByteArray &hash)
{
TimeRangeList range_to_invalidate;
QList<rational> times;
for (int64_t i=0; i<GetMapSize(); i++) {
if (time_hash_map_.at(i) == hash) {
time_hash_map_[i].clear();
rational time = ToTime(i);
times.append(time);
range_to_invalidate.insert(TimeRange(time, time + timebase_));
}
}
foreach (const TimeRange& r, range_to_invalidate) {
// We apply a 0 job time because the graph hasn't changed to get here, so any renderer should
// be up to date already
Invalidate(r, 0);
}
return times;
}
QVector<rational> FrameHashCache::GetFrameListFromTimeRange(TimeRangeList range_list, const rational &timebase)
{
// If timebase is null, this will be an infinite loop
Q_ASSERT(!timebase.isNull());
QVector<rational> times;
foreach (const TimeRange &range, range_list) {
rational frame = Timecode::snap_time_to_timebase(range.in(), timebase, Timecode::kCeil);
while (frame < range.out()) {
times.append(frame);
frame += timebase;
}
}
return times;
}
QVector<rational> FrameHashCache::GetFrameListFromTimeRange(const TimeRangeList &range)
{
return GetFrameListFromTimeRange(range, timebase_);
}
QVector<rational> FrameHashCache::GetInvalidatedFrames()
{
return GetFrameListFromTimeRange(GetInvalidatedRanges());
}
QVector<rational> FrameHashCache::GetInvalidatedFrames(const TimeRange &intersecting)
{
return GetFrameListFromTimeRange(GetInvalidatedRanges().Intersects(intersecting));
}
bool FrameHashCache::SaveCacheFrame(const QByteArray& hash,
char* data,
const VideoParams& vparam,
-15
View File
@@ -50,16 +50,6 @@ public:
void ValidateFramesWithHash(const QByteArray& hash);
/**
* @brief Returns a list of frames that use a particular hash
*/
QList<rational> GetFramesWithHash(const QByteArray& hash);
/**
* @brief Same as FramesWithHash() but also removes these frames from the map
*/
QList<rational> TakeFramesWithHash(const QByteArray& hash);
QMap<rational, QByteArray> time_hash_map();
/**
@@ -77,11 +67,6 @@ public:
FramePtr LoadCacheFrame(const QByteArray& hash) const;
static FramePtr LoadCacheFrame(const QString& fn);
static QVector<rational> GetFrameListFromTimeRange(TimeRangeList range_list, const rational& timebase);
QVector<rational> GetFrameListFromTimeRange(const TimeRangeList &range);
QVector<rational> GetInvalidatedFrames();
QVector<rational> GetInvalidatedFrames(const TimeRange& intersecting);
public slots:
void SetHash(const olive::rational &time, const QByteArray& hash, const qint64 &job_time, bool frame_exists);
+8 -4
View File
@@ -91,8 +91,10 @@ void GenerateHashesInternal(ViewerOutput *viewer, FrameHashCache* cache, const Q
}
}
void PreviewAutoCacher::GenerateHashes(ViewerOutput *viewer, FrameHashCache* cache, const QVector<rational> &times, qint64 job_time)
void PreviewAutoCacher::GenerateHashes(ViewerOutput *viewer, FrameHashCache* cache, TimeRangeListFrameIterator iterator, qint64 job_time)
{
QVector<rational> times = iterator.ToVector();
// Ensure number of threads doesn't exceed idealThreadCount for maximum concurrency
int hashes_per_thread = times.size() / qMax(1, QThread::idealThreadCount()-1);
@@ -493,7 +495,7 @@ void PreviewAutoCacher::TryRender()
// If we're here, we must be able to render
if (!invalidated_video_.isEmpty()) {
QVector<rational> frames = viewer_node_->video_frame_cache()->GetFrameListFromTimeRange(invalidated_video_);
TimeRangeListFrameIterator frames(invalidated_video_, viewer_node_->video_frame_cache()->GetTimebase());
QFutureWatcher<void>* watcher = new QFutureWatcher<void>();
hash_tasks_.append(watcher);
@@ -578,9 +580,11 @@ void PreviewAutoCacher::RequeueFrames()
using_range = cache_range_;
}
QVector<rational> invalidated_ranges = viewer_node_->video_frame_cache()->GetInvalidatedFrames(using_range);
TimeRangeList invalidated = viewer_node_->video_frame_cache()->GetInvalidatedRanges().Intersects(using_range);
TimeRangeListFrameIterator invalidated_ranges(invalidated, viewer_node_->video_frame_cache()->GetTimebase());
foreach (const rational& t, invalidated_ranges) {
rational t;
while (invalidated_ranges.GetNext(&t)) {
const QByteArray& hash = viewer_node_->video_frame_cache()->GetHash(t);
RenderTicketWatcher* render_task = video_tasks_.key(hash);
+1 -1
View File
@@ -80,7 +80,7 @@ public:
void ClearVideoDownloadQueue(bool wait = false);
private:
static void GenerateHashes(ViewerOutput *viewer, FrameHashCache *cache, const QVector<rational>& times, qint64 job_time);
static void GenerateHashes(ViewerOutput *viewer, FrameHashCache *cache, TimeRangeListFrameIterator times, qint64 job_time);
void TryRender();