framehashcache: use timestamp based vector internally

I think this will be significantly faster, but I guess we'll find out!
This commit is contained in:
itsmattkc
2021-07-10 15:37:06 -07:00
parent cae2c360c2
commit 38c38daf8a
2 changed files with 80 additions and 64 deletions
+63 -62
View File
@@ -32,7 +32,6 @@
#include "codec/frame.h"
#include "common/filefunctions.h"
#include "common/timecodefunctions.h"
#include "render/diskmanager.h"
namespace olive {
@@ -52,9 +51,18 @@ FrameHashCache::FrameHashCache(QObject *parent) :
}
}
QByteArray FrameHashCache::GetHash(const int64_t &time)
{
if (time < GetMapSize()) {
return time_hash_map_.at(time);
} else {
return QByteArray();
}
}
QByteArray FrameHashCache::GetHash(const rational &time)
{
return time_hash_map_.value(time);
return GetHash(ToTimestamp(time));
}
void FrameHashCache::SetHash(const rational &time, const QByteArray &hash, const qint64& job_time, bool frame_exists)
@@ -69,7 +77,15 @@ void FrameHashCache::SetHash(const rational &time, const QByteArray &hash, const
}
}
time_hash_map_.insert(time, hash);
int64_t ts = ToTimestamp(time);
if (ts >= GetMapSize()) {
// Reserve an extra minute to cut down on the amount of reallocations to make
time_hash_map_.reserve(ts + timebase_.flipped().toDouble() * 60);
// Add enough entries to insert this hash
time_hash_map_.resize(ts + 1);
}
time_hash_map_[ts] = hash;
TimeRange validated_range;
if (frame_exists) {
@@ -87,9 +103,9 @@ void FrameHashCache::ValidateFramesWithHash(const QByteArray &hash)
{
const TimeRangeList& invalidated_ranges = GetInvalidatedRanges();
for (auto iterator=time_hash_map_.begin();iterator!=time_hash_map_.end();iterator++) {
if (iterator.value() == hash) {
TimeRange frame_range(iterator.key(), iterator.key() + timebase_);
for (int64_t i=0; i<GetMapSize(); i++) {
if (time_hash_map_[i] == hash) {
TimeRange frame_range(ToTime(i), ToTime(i+1));
if (invalidated_ranges.contains(frame_range)) {
Validate(frame_range);
@@ -102,9 +118,9 @@ QList<rational> FrameHashCache::GetFramesWithHash(const QByteArray &hash)
{
QList<rational> times;
for (auto iterator=time_hash_map_.begin();iterator!=time_hash_map_.end();iterator++) {
if (iterator.value() == hash) {
times.append(iterator.key());
for (int64_t i=0; i<GetMapSize(); i++) {
if (time_hash_map_.at(i) == hash) {
times.append(ToTime(i));
}
}
@@ -116,16 +132,13 @@ QList<rational> FrameHashCache::TakeFramesWithHash(const QByteArray &hash)
TimeRangeList range_to_invalidate;
QList<rational> times;
auto iterator = time_hash_map_.begin();
for (int64_t i=0; i<GetMapSize(); i++) {
if (time_hash_map_.at(i) == hash) {
time_hash_map_[i].clear();
while (iterator != time_hash_map_.end()) {
if (iterator.value() == hash) {
times.append(iterator.key());
range_to_invalidate.insert(TimeRange(iterator.key(), iterator.key() + timebase_));
iterator = time_hash_map_.erase(iterator);
} else {
iterator++;
rational time = ToTime(i);
times.append(time);
range_to_invalidate.insert(TimeRange(time, time + timebase_));
}
}
@@ -138,11 +151,6 @@ QList<rational> FrameHashCache::TakeFramesWithHash(const QByteArray &hash)
return times;
}
QMap<rational, QByteArray> FrameHashCache::time_hash_map()
{
return time_hash_map_;
}
QVector<rational> FrameHashCache::GetFrameListFromTimeRange(TimeRangeList range_list, const rational &timebase)
{
// If timebase is null, this will be an infinite loop
@@ -316,15 +324,11 @@ FramePtr FrameHashCache::LoadCacheFrame(const QString &fn)
void FrameHashCache::LengthChangedEvent(const rational &old, const rational &newlen)
{
if (newlen < old) {
auto i = time_hash_map_.begin();
// Determine length in frames by ceil-ing the time
int64_t new_ts_length = ToTimestamp(newlen, Timecode::kCeil);
while (i != time_hash_map_.end()) {
if (i.key() >= newlen) {
i = time_hash_map_.erase(i);
} else {
i++;
}
}
// Resize vector to this length, which will discard all frames after it
time_hash_map_.resize(new_ts_length);
}
}
@@ -335,51 +339,48 @@ struct HashTimePair {
void FrameHashCache::ShiftEvent(const rational &from, const rational &to)
{
auto i = time_hash_map_.begin();
// POSITIVE if moving forward ->
// NEGATIVE if moving backward <-
rational diff = to - from;
bool diff_is_negative = (diff < 0);
QList<HashTimePair> shifted_times;
while (i != time_hash_map_.end()) {
if (diff_is_negative && i.key() >= to && i.key() < from) {
// This time will be removed in the shift so we just discard it
i = time_hash_map_.erase(i);
} else if (i.key() >= from) {
// This time is after the from time and must be shifted
shifted_times.append({i.key() + diff, i.value()});
i = time_hash_map_.erase(i);
} else {
// Do nothing
i++;
int64_t to_ts = ToTimestamp(to);
int64_t from_ts = ToTimestamp(from);
if (diff_is_negative) {
// We're moving the frames starting at `from` backwards to where `to` is
if (to_ts < GetMapSize()) {
time_hash_map_.erase(time_hash_map_.begin() + to_ts, time_hash_map_.begin() + from_ts);
}
} else {
// We're moving the frames starting at `from` forwards to where `to` is
if (from_ts < GetMapSize()) {
time_hash_map_.insert(time_hash_map_.begin() + from_ts, to_ts - from_ts, QByteArray());
}
}
foreach (const HashTimePair& p, shifted_times) {
time_hash_map_.insert(p.time, p.hash);
}
}
void FrameHashCache::InvalidateEvent(const TimeRange &range)
{
if (!timebase_.isNull()) {
QVector<rational> invalid_frames = GetFrameListFromTimeRange({range});
foreach (const rational& r, invalid_frames) {
time_hash_map_.remove(r);
int64_t start = ToTimestamp(range.in(), Timecode::kCeil);
int64_t end = ToTimestamp(range.out(), Timecode::kCeil);
for (int64_t i=start; i<GetMapSize() && i<end; i++) {
time_hash_map_[i].clear();
}
}
}
rational FrameHashCache::ToTime(const int64_t &ts) const
{
return Timecode::timestamp_to_time(ts, timebase_);
}
int64_t FrameHashCache::ToTimestamp(const rational &ts, Timecode::Rounding rounding) const
{
return Timecode::time_to_timestamp(ts, timebase_, rounding);
}
void FrameHashCache::HashDeleted(const QString& s, const QByteArray &hash)
{
QString cache_dir = GetCacheDirectory();
@@ -388,9 +389,9 @@ void FrameHashCache::HashDeleted(const QString& s, const QByteArray &hash)
}
TimeRangeList ranges_to_invalidate;
for (auto i=time_hash_map_.constBegin(); i!=time_hash_map_.constEnd(); i++) {
if (i.value() == hash) {
ranges_to_invalidate.insert(TimeRange(i.key(), i.key() + timebase_));
for (int64_t i=0; i<GetMapSize(); i++) {
if (time_hash_map_.at(i) == hash) {
ranges_to_invalidate.insert(TimeRange(ToTime(i), ToTime(i+1)));
}
}