cache: began base implementation of "shifting" the cache

Should be a fairly important optimization to make.
This commit is contained in:
itsmattkc
2020-06-02 01:38:12 +10:00
parent 6acfe995fa
commit 11bfe61208
8 changed files with 154 additions and 0 deletions
+6
View File
@@ -87,6 +87,12 @@ QString ViewerOutput::Description() const
return tr("Interface between a Viewer panel and the node system.");
}
void ViewerOutput::ShiftCache(const rational &from, const rational &to)
{
video_frame_cache_.Shift(from, to);
audio_playback_cache_.Shift(from, to);
}
void ViewerOutput::InvalidateCache(const TimeRange &range, NodeInput *from, NodeInput *source)
{
emit GraphChangedFrom(source);
+2
View File
@@ -54,6 +54,8 @@ public:
virtual QList<CategoryID> Category() const override;
virtual QString Description() const override;
void ShiftCache(const rational& from, const rational& to);
NodeInput* texture_input() const {
return texture_input_;
}
+68
View File
@@ -111,6 +111,74 @@ void AudioPlaybackCache::WriteSilence(const TimeRange &range)
}
}
void AudioPlaybackCache::ShiftEvent(const rational &from, const rational &to)
{
QFile f(filename_);
if (f.open(QFile::ReadWrite)) {
qint64 from_offset = params_.time_to_bytes(from);
qint64 to_offset = params_.time_to_bytes(to);
qint64 chunk = qAbs(to_offset - from_offset);
QByteArray buf(chunk, Qt::Uninitialized);
if (to > from) {
// Shifting forwards, we must insert a new region and shift all the bytes there
// For shifting forwards, we copy bytes starting at the back so that bytes we need don't
// get overwritten.
qint64 read_offset = f.size();
f.resize(f.size() + chunk);
qint64 write_offset = f.size();
do {
// Calculate how much will be read this time
qint64 chunk_sz = qMin(chunk, read_offset - from_offset);
read_offset -= chunk_sz;
// Read that chunk
f.seek(read_offset);
f.read(buf.data(), chunk_sz);
// Write it at the destination
write_offset -= chunk_sz;
f.seek(write_offset);
f.write(buf.data(), chunk_sz);
} while (read_offset != from_offset);
// Replace remainder with silence
f.seek(from_offset);
buf.fill(0);
f.write(buf);
} else {
// Shifting backwards, we will shift bytes and truncate
do {
// Read region to be shifted
f.seek(from_offset);
qint64 read_sz = f.read(buf.data(), buf.size());
from_offset += read_sz;
// Write it at the destination
f.seek(to_offset);
to_offset += f.write(buf, read_sz);
} while (from_offset != f.size());
// Truncate
f.resize(f.size() - chunk);
}
f.close();
} else {
qWarning() << "Failed to write PCM data to" << filename_;
}
}
const QString &AudioPlaybackCache::GetCacheFilename() const
{
return filename_;
+3
View File
@@ -48,6 +48,9 @@ public:
signals:
void ParametersChanged();
protected:
virtual void ShiftEvent(const rational& from, const rational& to) override;
private:
QString filename_;
+41
View File
@@ -185,6 +185,47 @@ void FrameHashCache::InvalidateEvent(const TimeRange &r)
}
}
struct HashTimePair {
rational time;
QByteArray hash;
};
void FrameHashCache::ShiftEvent(const rational &from, const rational &to)
{
QMap<rational, QByteArray>::iterator i = time_hash_map_.begin();
// POSITIVE if moving forward ->
// NEGATIVE if moving backward <-
rational diff = to - from;
bool diff_is_negative = (diff < rational());
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++;
}
}
foreach (const HashTimePair& p, shifted_times) {
time_hash_map_.insert(p.time, p.hash);
}
}
QString FrameHashCache::CachePathName(const QByteArray& hash, const PixelFormat::Format& pix_fmt)
{
QString ext = GetFormatExtension(pix_fmt);
+2
View File
@@ -75,6 +75,8 @@ protected:
virtual void InvalidateEvent(const TimeRange& range) override;
virtual void ShiftEvent(const rational& from, const rational& to) override;
private:
QMap<rational, QByteArray> time_hash_map_;
+28
View File
@@ -61,6 +61,30 @@ bool PlaybackCache::IsFullyValidated() const
return invalidated_.isEmpty();
}
void PlaybackCache::Shift(const rational &from, const rational &to)
{
// An region between `from` and `to` will be inserted or spliced out
TimeRangeList ranges_to_shift = invalidated_.Intersects(TimeRange(from, RATIONAL_MAX));
// Remove everything from the minimum point
invalidated_.RemoveTimeRange(TimeRange(qMin(from, to), RATIONAL_MAX));
// Shift everything in our ranges to shift list
//
// `diff` is POSITIVE when moving forward -> and NEGATIVE when moving backward <-
rational diff = to - from;
foreach (const TimeRange& r, ranges_to_shift) {
invalidated_.InsertTimeRange(r + diff);
}
ShiftEvent(from, to);
if (diff > rational()) {
// If shifting forward, add this section to the invalidated region
Invalidate(TimeRange(from, to));
}
}
void PlaybackCache::Validate(const TimeRange &r)
{
invalidated_.RemoveTimeRange(r);
@@ -81,4 +105,8 @@ void PlaybackCache::InvalidateEvent(const TimeRange &)
{
}
void PlaybackCache::ShiftEvent(const rational &, const rational &)
{
}
OLIVE_NAMESPACE_EXIT
+4
View File
@@ -46,6 +46,8 @@ public:
bool IsFullyValidated() const;
void Shift(const rational& from, const rational& to);
const TimeRangeList& GetInvalidatedRanges() const
{
return invalidated_;
@@ -70,6 +72,8 @@ protected:
virtual void InvalidateEvent(const TimeRange& range);
virtual void ShiftEvent(const rational& from, const rational& to);
private:
TimeRangeList invalidated_;