playbackcache: more intelligent job matching

Ensures audio ranges can be anticipated and accurately ignored if they're
old or acknowledged if they're current.
This commit is contained in:
itsmattkc
2020-06-05 15:23:16 +10:00
parent b143b39869
commit 7609754103
5 changed files with 141 additions and 103 deletions
+37 -14
View File
@@ -67,29 +67,37 @@ void AudioPlaybackCache::WritePCM(const TimeRange &range, SampleBufferPtr sample
{
QMutexLocker locker(lock());
if (!JobIsCurrent(range, job_time)) {
QList<TimeRange> valid_ranges = NoLockGetValidRanges(range, job_time);
if (valid_ranges.isEmpty()) {
return;
}
QFile f(filename_);
if (f.open(QFile::ReadWrite)) {
qint64 start_offset = params_.time_to_bytes(range.in());
qint64 max_len = params_.time_to_bytes(range.out());
qint64 write_len = max_len - start_offset;
QByteArray a = samples->toPackedData();
if (f.size() < max_len) {
f.resize(max_len);
}
foreach (const TimeRange& r, valid_ranges) {
// Calculate destination offsets
qint64 start_offset = params_.time_to_bytes(r.in());
qint64 max_len = params_.time_to_bytes(r.out());
f.seek(start_offset);
f.write(a);
if (f.size() < max_len) {
f.resize(max_len);
}
if (write_len > a.size()) {
// Fill remaining space with silence
QByteArray s(write_len - a.size(), 0x00);
f.write(s);
// Calculate source offsets
qint64 sample_start = params_.time_to_bytes(r.in() - range.in());
qint64 sample_len = params_.time_to_bytes(r.length());
qint64 actual_write = qMin(sample_len, a.size() - sample_start);
f.seek(start_offset);
f.write(a.data() + sample_start, actual_write);
if (actual_write < sample_len) {
// Fill remaining space with silence
QByteArray s(sample_len - actual_write, 0x00);
f.write(s);
}
}
f.close();
@@ -213,6 +221,21 @@ void AudioPlaybackCache::LengthChangedEvent(const rational& old, const rational&
}
}
QList<TimeRange> AudioPlaybackCache::NoLockGetValidRanges(const TimeRange& range, const qint64& job_time)
{
QList<TimeRange> valid_ranges;
for (int i=jobs_.size()-1;i>=0;i--) {
const JobIdentifier& job = jobs_.at(i);
if (job_time >= job.job_time && job.range.OverlapsWith(range)) {
valid_ranges.append(job.range.Intersected(range));
}
}
return valid_ranges;
}
const QString &AudioPlaybackCache::GetCacheFilename() const
{
return filename_;