only disk cache around the playhead

This commit is contained in:
itsmattkc
2020-01-10 20:35:48 +11:00
parent ea42ca36f5
commit d32306f88b
16 changed files with 222 additions and 136 deletions
+43 -100
View File
@@ -33,6 +33,7 @@ extern "C" {
#include <QtMath>
#include "codec/waveinput.h"
#include "common/define.h"
#include "common/filefunctions.h"
#include "common/timecodefunctions.h"
#include "ffmpegcommon.h"
@@ -41,8 +42,7 @@ extern "C" {
FFmpegDecoder::FFmpegDecoder() :
fmt_ctx_(nullptr),
codec_ctx_(nullptr),
opts_(nullptr),
scale_ctx_(nullptr)
opts_(nullptr)
{
}
@@ -129,41 +129,20 @@ bool FFmpegDecoder::Open()
return false;
}
// Set up
if (codec_ctx_->codec_type == AVMEDIA_TYPE_VIDEO) {
// Set up pixel format conversion for video
AVPixelFormat pix_fmt = static_cast<AVPixelFormat>(avstream_->codecpar->format);
if (avstream_->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
// Get an Olive compatible AVPixelFormat
AVPixelFormat ideal_pix_fmt = FFmpegCommon::GetCompatiblePixelFormat(pix_fmt);
ideal_pix_fmt_ = FFmpegCommon::GetCompatiblePixelFormat(static_cast<AVPixelFormat>(avstream_->codecpar->format));
// Determine which Olive native pixel format we retrieved
// Note that FFmpeg doesn't support float formats
switch (ideal_pix_fmt) {
case AV_PIX_FMT_RGBA:
output_fmt_ = PixelFormat::PIX_FMT_RGBA8;
break;
case AV_PIX_FMT_RGBA64:
output_fmt_ = PixelFormat::PIX_FMT_RGBA16U;
break;
default:
// We should never get here, but if we do there's nothing we can do with this format
return false;
if (ideal_pix_fmt_ == AV_PIX_FMT_RGBA) {
native_pix_fmt_ = PixelFormat::PIX_FMT_RGBA8;
} else if (ideal_pix_fmt_ == AV_PIX_FMT_RGBA64) {
native_pix_fmt_ = PixelFormat::PIX_FMT_RGBA16U;
} else {
// We should never get here, but just in case...
qFatal("Invalid output format");
}
scale_ctx_ = sws_getContext(avstream_->codecpar->width,
avstream_->codecpar->height,
pix_fmt,
avstream_->codecpar->width,
avstream_->codecpar->height,
ideal_pix_fmt,
0,
nullptr,
nullptr,
nullptr);
} else if (codec_ctx_->codec_type == AVMEDIA_TYPE_AUDIO) {
// FIXME: Fill this in
}
// All allocation succeeded so we set the state to open
@@ -192,56 +171,18 @@ FramePtr FFmpegDecoder::RetrieveVideo(const rational &timecode)
QFile compressed_frame(GetIndexFilename().append(QString::number(target_ts)));
if (compressed_frame.open(QFile::ReadOnly)) {
QByteArray frame_loader = qUncompress(compressed_frame.readAll());
AVFrame* frame = av_frame_alloc();
if (frame == nullptr) {
qWarning() << "Failed to create AVFrame for swscale";
return nullptr;
}
frame->width = avstream_->codecpar->width;
frame->height = avstream_->codecpar->height;
QDataStream ds(&frame_loader, QIODevice::ReadOnly);
ds >> frame->format;
if (av_frame_get_buffer(frame, 0) != 0) {
qWarning() << "Failed to get AVFrame buffer";
av_frame_free(&frame);
return nullptr;
}
// Read data
size_t pos = sizeof(int);
for (int i=0;i<AV_NUM_DATA_POINTERS;i++) {
size_t plane_size = static_cast<size_t>(frame->linesize[i] * CalculatePlaneHeight(frame->height, static_cast<AVPixelFormat>(frame->format), i));
memcpy(frame->data[i], frame_loader.data() + pos, plane_size);
pos += plane_size;
}
QByteArray frame_loader = qUncompress(compressed_frame.readAll());
// Frame was valid, now we convert it to a native Olive frame
FramePtr frame_container = Frame::Create();
frame_container->set_width(frame->width);
frame_container->set_height(frame->height);
frame_container->set_format(static_cast<PixelFormat::Format>(output_fmt_));
frame_container->set_width(avstream_->codecpar->width);
frame_container->set_height(avstream_->codecpar->height);
frame_container->set_format(native_pix_fmt_);
frame_container->set_timestamp(Timecode::timestamp_to_time(target_ts, avstream_->time_base));
frame_container->allocate();
// Convert pixel format/linesize if necessary
uint8_t* dst_data = reinterpret_cast<uint8_t*>(frame_container->data());
int dst_linesize = frame_container->width() * PixelService::BytesPerPixel(static_cast<PixelFormat::Format>(output_fmt_));
// Perform pixel conversion
sws_scale(scale_ctx_,
frame->data,
frame->linesize,
0,
frame->height,
&dst_data,
&dst_linesize);
av_frame_free(&frame);
memcpy(frame_container->data(), frame_loader.constData(), frame_loader.size());
return frame_container;
}
@@ -291,11 +232,6 @@ void FFmpegDecoder::Close()
{
frame_index_.clear();
if (scale_ctx_ != nullptr) {
sws_freeContext(scale_ctx_);
scale_ctx_ = nullptr;
}
if (opts_ != nullptr) {
av_dict_free(&opts_);
opts_ = nullptr;
@@ -839,6 +775,17 @@ void FFmpegDecoder::IndexVideo(AVPacket* pkt, AVFrame* frame)
// Iterate through every single frame and get each timestamp
// NOTE: Expects no frames to have been read so far
SwsContext* scale_ctx = sws_getContext(avstream_->codecpar->width,
avstream_->codecpar->height,
static_cast<AVPixelFormat>(avstream_->codecpar->format),
avstream_->codecpar->width,
avstream_->codecpar->height,
ideal_pix_fmt_,
0,
nullptr,
nullptr,
nullptr);
int ret;
while (true) {
@@ -846,20 +793,25 @@ void FFmpegDecoder::IndexVideo(AVPacket* pkt, AVFrame* frame)
if (ret >= 0) {
// Save frame
QByteArray frame_save;
QDataStream ds(&frame_save, QIODevice::WriteOnly);
int buffer_size = PixelService::GetBufferSize(native_pix_fmt_, avstream_->codecpar->width, avstream_->codecpar->height);
ds << frame->format;
QByteArray frame_save(buffer_size, Qt::Uninitialized);
// Save data
for (int i=0;i<AV_NUM_DATA_POINTERS;i++) {
frame_save.append(reinterpret_cast<const char*>(frame->data[i]),
frame->linesize[i] * CalculatePlaneHeight(frame->height, static_cast<AVPixelFormat>(frame->format), i));
}
char* data = frame_save.data();
int line_size = avstream_->codecpar->width * kRGBAChannels;
// Perform pixel conversion
sws_scale(scale_ctx,
frame->data,
frame->linesize,
0,
avstream_->codecpar->height,
reinterpret_cast<uint8_t**>(&data),
&line_size);
QFile compressed_frame(GetIndexFilename().append(QString::number(frame->pts)));
if (compressed_frame.open(QFile::WriteOnly)) {
compressed_frame.write(qCompress(frame_save));
compressed_frame.write(qCompress(frame_save, 9));
compressed_frame.close();
}
@@ -870,6 +822,8 @@ void FFmpegDecoder::IndexVideo(AVPacket* pkt, AVFrame* frame)
}
}
sws_freeContext(scale_ctx);
// Save index to file
SaveIndex();
}
@@ -919,17 +873,6 @@ int FFmpegDecoder::GetFrame(AVPacket *pkt, AVFrame *frame)
return ret;
}
int FFmpegDecoder::CalculatePlaneHeight(int frame_height, const AVPixelFormat &format, int plane)
{
// FIXME: This seems dumb, but I can't find any FFmpeg function that returns this information
if ((plane == 1 || plane == 2)
&& format == AV_PIX_FMT_YUV420P) {
return frame_height/2;
}
return frame_height;
}
int64_t FFmpegDecoder::GetClosestTimestampInIndex(const int64_t &ts)
{
// Index now if we haven't already
+2 -4
View File
@@ -139,15 +139,13 @@ private:
void Seek(int64_t timestamp);
int CalculatePlaneHeight(int frame_height, const AVPixelFormat& format, int plane);
AVFormatContext* fmt_ctx_;
AVCodecContext* codec_ctx_;
AVStream* avstream_;
AVDictionary* opts_;
SwsContext* scale_ctx_;
int output_fmt_;
AVPixelFormat ideal_pix_fmt_;
PixelFormat::Format native_pix_fmt_;
QVector<int64_t> frame_index_;
+22
View File
@@ -149,3 +149,25 @@ bool TimeRangeList::ContainsTimeRange(const TimeRange &range) const
return false;
}
TimeRangeList TimeRangeList::Intersects(const TimeRange &range)
{
TimeRangeList intersect_list;
for (int i=0;i<size();i++) {
const TimeRange& compare = at(i);
if (compare.out() <= range.in() || compare.in() >= range.out()) {
// No intersect
continue;
} else {
// Crop the time range to the range and add it to the list
TimeRange cropped(qMax(range.in(), compare.in()),
qMin(range.out(), compare.out()));
intersect_list.append(cropped);
}
}
return intersect_list;
}
+2
View File
@@ -45,6 +45,8 @@ public:
bool ContainsTimeRange(const TimeRange& range) const;
TimeRangeList Intersects(const TimeRange& range);
};
#endif // TIMERANGE_H
+3 -1
View File
@@ -75,7 +75,9 @@ void Config::SetDefaults()
config_map_["Autoscroll"] = AutoScroll::kPage;
config_map_["DiskCachePath"] = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
config_map_["DiskCacheSize"] = 20.0;
config_map_["DiskCacheSize"] = 0.025;
config_map_["DiskCacheBehind"] = QVariant::fromValue(rational(5));
config_map_["DiskCacheAhead"] = QVariant::fromValue(rational(30));
config_map_["ClearDiskCacheOnClose"] = false;
config_map_["DefaultSequenceWidth"] = 1920;
@@ -3,50 +3,76 @@
#include <QDir>
#include <QFileDialog>
#include <QGridLayout>
#include <QGroupBox>
#include <QLabel>
#include <QMessageBox>
#include <QPushButton>
#include "render/diskmanager.h"
PreferencesDiskTab::PreferencesDiskTab()
{
QVBoxLayout* outer_layout = new QVBoxLayout(this);
QGridLayout* layout = new QGridLayout();
outer_layout->addLayout(layout);
QGroupBox* disk_management_group = new QGroupBox(tr("Disk Management"));
outer_layout->addWidget(disk_management_group);
QGridLayout* disk_management_layout = new QGridLayout(disk_management_group);
int row = 0;
layout->addWidget(new QLabel(tr("Disk Cache Location:")), row, 0);
disk_management_layout->addWidget(new QLabel(tr("Disk Cache Location:")), row, 0);
disk_cache_location_ = new QLineEdit();
disk_cache_location_->setText(Config::Current()["DiskCachePath"].toString());
connect(disk_cache_location_, &QLineEdit::textChanged, this, &PreferencesDiskTab::DiskCacheLineEditChanged);
layout->addWidget(disk_cache_location_, row, 1);
disk_management_layout->addWidget(disk_cache_location_, row, 1);
QPushButton* browse_btn = new QPushButton(tr("Browse"));
connect(browse_btn, &QPushButton::clicked, this, &PreferencesDiskTab::BrowseDiskCachePath);
layout->addWidget(browse_btn, row, 2);
disk_management_layout->addWidget(browse_btn, row, 2);
row++;
layout->addWidget(new QLabel(tr("Maximum Disk Cache:")), row, 0);
disk_management_layout->addWidget(new QLabel(tr("Maximum Disk Cache:")), row, 0);
maximum_cache_slider_ = new FloatSlider();
maximum_cache_slider_->SetSuffix(QStringLiteral(" GB"));
maximum_cache_slider_->SetMinimum(1.0);
maximum_cache_slider_->SetValue(Config::Current()["DiskCacheSize"].toDouble());
layout->addWidget(maximum_cache_slider_, row, 1, 1, 2);
disk_management_layout->addWidget(maximum_cache_slider_, row, 1, 1, 2);
row++;
QPushButton* clear_cache_btn = new QPushButton(tr("Clear Disk Cache"));
connect(clear_cache_btn, &QPushButton::clicked, this, &PreferencesDiskTab::ClearDiskCache);
layout->addWidget(clear_cache_btn, row, 1, 1, 2);
disk_management_layout->addWidget(clear_cache_btn, row, 1, 1, 2);
row++;
clear_disk_cache_ = new QCheckBox(tr("Automatically clear disk cache on close"));
clear_disk_cache_->setChecked(Config::Current()["ClearDiskCacheOnClose"].toBool());
layout->addWidget(clear_disk_cache_, row, 1, 1, 2);
disk_management_layout->addWidget(clear_disk_cache_, row, 1, 1, 2);
QGroupBox* cache_behavior = new QGroupBox(tr("Cache Behavior"));
outer_layout->addWidget(cache_behavior);
QGridLayout* cache_behavior_layout = new QGridLayout(cache_behavior);
row = 0;
cache_behavior_layout->addWidget(new QLabel(tr("Cache Ahead:")), row, 0);
cache_ahead_slider_ = new FloatSlider();
cache_ahead_slider_->SetSuffix(QStringLiteral(" seconds"));
cache_ahead_slider_->SetValue(Config::Current()["DiskCacheAhead"].value<rational>().toDouble());
cache_behavior_layout->addWidget(cache_ahead_slider_, row, 1);
cache_behavior_layout->addWidget(new QLabel(tr("Cache Behind:")), row, 2);
cache_behind_slider_ = new FloatSlider();
cache_behind_slider_->SetSuffix(QStringLiteral(" seconds"));
cache_behind_slider_->SetValue(Config::Current()["DiskCacheBehind"].value<rational>().toDouble());
cache_behavior_layout->addWidget(cache_behind_slider_, row, 3);
outer_layout->addStretch();
}
@@ -56,6 +82,8 @@ void PreferencesDiskTab::Accept()
Config::Current()["DiskCachePath"] = disk_cache_location_->text();
Config::Current()["DiskCacheSize"] = maximum_cache_slider_->GetValue();
Config::Current()["ClearDiskCacheOnClose"] = clear_disk_cache_->isChecked();
Config::Current()["DiskCacheBehind"] = QVariant::fromValue(rational::fromDouble(cache_behind_slider_->GetValue()));
Config::Current()["DiskCacheAhead"] = QVariant::fromValue(rational::fromDouble(cache_ahead_slider_->GetValue()));
}
void PreferencesDiskTab::DiskCacheLineEditChanged()
@@ -80,5 +108,20 @@ void PreferencesDiskTab::BrowseDiskCachePath()
void PreferencesDiskTab::ClearDiskCache()
{
qDebug() << "Clear" << Config::Current()["DiskCachePath"];
if (QMessageBox::question(this,
tr("Clear Disk Cache"),
tr("Are you sure you want to clear the disk cache in '%1'?").arg(Config::Current()["DiskCachePath"].toString()),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
if (DiskManager::instance()->ClearDiskCache()) {
QMessageBox::information(this,
tr("Clear Disk Cache"),
tr("Disk cache cleared successfully"),
QMessageBox::Ok);
} else {
QMessageBox::information(this,
tr("Clear Disk Cache"),
tr("Disk cache failed to fully clear. You may have to delete the cache files manually."),
QMessageBox::Ok);
}
}
}
@@ -20,6 +20,10 @@ private:
FloatSlider* maximum_cache_slider_;
FloatSlider* cache_ahead_slider_;
FloatSlider* cache_behind_slider_;
QCheckBox* clear_disk_cache_;
private slots:
+9 -4
View File
@@ -115,13 +115,10 @@ void RenderBackend::InvalidateCache(const rational &start_range, const rational
<< "and"
<< end_range_adj.toDouble();
// Add the range to the list
cache_queue_.InsertTimeRange(TimeRange(start_range_adj, end_range_adj));
// Queue value update
QueueValueUpdate();
CacheNext();
InvalidateCacheInternal(start_range_adj, end_range_adj);
}
bool RenderBackend::Compile()
@@ -356,6 +353,14 @@ const QVector<QThread *> &RenderBackend::threads()
return threads_;
}
void RenderBackend::InvalidateCacheInternal(const rational &start_range, const rational &end_range)
{
// Add the range to the list
cache_queue_.InsertTimeRange(TimeRange(start_range, end_range));
CacheNext();
}
void RenderBackend::CacheIDChangedEvent(const QString &id)
{
Q_UNUSED(id)
+2
View File
@@ -63,6 +63,8 @@ protected:
*/
virtual bool GenerateCacheIDInternal(QCryptographicHash& hash) = 0;
virtual void InvalidateCacheInternal(const rational &start_range, const rational &end_range);
virtual void CacheIDChangedEvent(const QString& id);
void SetError(const QString& error);
+52 -5
View File
@@ -28,6 +28,8 @@
#include <QtMath>
#include "common/timecodefunctions.h"
#include "config/config.h"
#include "render/diskmanager.h"
#include "render/diskmanager.h"
#include "render/pixelservice.h"
#include "videorenderworker.h"
@@ -37,6 +39,7 @@ VideoRenderBackend::VideoRenderBackend(QObject *parent) :
operating_mode_(VideoRenderWorker::kHashRenderCache),
only_signal_last_frame_requested_(true)
{
connect(DiskManager::instance(), &DiskManager::DeletedFrame, this, &VideoRenderBackend::FrameRemovedFromDiskCache);
}
bool VideoRenderBackend::InitInternal()
@@ -142,10 +145,21 @@ void VideoRenderBackend::ConnectWorkerToThis(RenderWorker *processor)
video_processor->SetOperatingMode(operating_mode_);
connect(video_processor, &VideoRenderWorker::CompletedFrame, this, &VideoRenderBackend::ThreadCompletedFrame);
connect(video_processor, &VideoRenderWorker::HashAlreadyBeingCached, this, &VideoRenderBackend::ThreadSkippedFrame);
connect(video_processor, &VideoRenderWorker::CompletedDownload, this, &VideoRenderBackend::ThreadCompletedDownload);
connect(video_processor, &VideoRenderWorker::HashAlreadyExists, this, &VideoRenderBackend::ThreadHashAlreadyExists);
connect(video_processor, &VideoRenderWorker::CompletedFrame, this, &VideoRenderBackend::ThreadCompletedFrame, Qt::QueuedConnection);
connect(video_processor, &VideoRenderWorker::HashAlreadyBeingCached, this, &VideoRenderBackend::ThreadSkippedFrame, Qt::QueuedConnection);
connect(video_processor, &VideoRenderWorker::CompletedDownload, this, &VideoRenderBackend::ThreadCompletedDownload, Qt::QueuedConnection);
connect(video_processor, &VideoRenderWorker::HashAlreadyExists, this, &VideoRenderBackend::ThreadHashAlreadyExists, Qt::QueuedConnection);
}
void VideoRenderBackend::InvalidateCacheInternal(const rational &start_range, const rational &end_range)
{
TimeRange invalidated(start_range, end_range);
missing_cache_.InsertTimeRange(invalidated);
emit RangeInvalidated(invalidated);
Requeue();
}
VideoRenderFrameCache *VideoRenderBackend::frame_cache()
@@ -172,6 +186,8 @@ const char *VideoRenderBackend::GetCachedFrame(const rational &time)
return nullptr;
}
Requeue();
// Find frame in map
QByteArray frame_hash = frame_cache_.TimeToHash(time);
@@ -220,8 +236,13 @@ TimeRange VideoRenderBackend::PopNextFrameFromQueue()
snapped_in -= params_.time_base();
}
TimeRange frame_range(snapped_in, snapped_in + params_.time_base());
// Remove this particular frame from the queue
cache_queue_.RemoveTimeRange(TimeRange(snapped_in, snapped_in + params_.time_base()));
cache_queue_.RemoveTimeRange(frame_range);
// Remove this particular frame from missing frames
missing_cache_.RemoveTimeRange(frame_range);
// Return the snapped frame
return TimeRange(snapped_in, snapped_in);
@@ -293,6 +314,19 @@ void VideoRenderBackend::TruncateFrameCacheLength(const rational &length)
frame_cache_.Truncate(length);
}
void VideoRenderBackend::FrameRemovedFromDiskCache(const QByteArray &hash)
{
QList<rational> deleted_frames = frame_cache()->FramesWithHash(hash);
foreach (const rational& frame, deleted_frames) {
TimeRange invalidated(frame, frame+params_.time_base());
missing_cache_.InsertTimeRange(invalidated);
emit RangeInvalidated(invalidated);
}
}
bool VideoRenderBackend::TimeIsQueued(const TimeRange &time) const
{
return cache_queue_.ContainsTimeRange(time);
@@ -314,3 +348,16 @@ bool VideoRenderBackend::SetFrameHash(const NodeDependency &dep, const QByteArra
return false;
}
void VideoRenderBackend::Requeue()
{
cache_queue_.clear();
// Reset queue around the last time requested
TimeRange queueable_range(last_time_requested_ - Config::Current()["DiskCacheBehind"].value<rational>(),
last_time_requested_ + Config::Current()["DiskCacheAhead"].value<rational>());
cache_queue_ = missing_cache_.Intersects(queueable_range);
CacheNext();
}
+10
View File
@@ -103,12 +103,16 @@ protected:
virtual void EmitCachedFrameReady(const rational &time, const QVariant& value, qint64 job_time) = 0;
virtual void InvalidateCacheInternal(const rational &start_range, const rational &end_range) override;
VideoRenderWorker::OperatingMode operating_mode_;
signals:
void CachedFrameReady(const rational& time, QVariant value, qint64 job_time);
void CachedTimeReady(const rational& time, qint64 job_time);
void RangeInvalidated(const TimeRange& range);
private:
bool TimeIsQueued(const TimeRange &time) const;
@@ -116,12 +120,16 @@ private:
bool SetFrameHash(const NodeDependency& dep, const QByteArray& hash, const qint64& job_time);
void Requeue();
VideoRenderingParams params_;
QByteArray cache_frame_load_buffer_;
VideoRenderFrameCache frame_cache_;
TimeRangeList missing_cache_;
rational last_time_requested_;
bool only_signal_last_frame_requested_;
@@ -134,6 +142,8 @@ private slots:
void TruncateFrameCacheLength(const rational& length);
void FrameRemovedFromDiskCache(const QByteArray& hash);
};
#endif // VIDEORENDERERBACKEND_H
+14 -7
View File
@@ -4,6 +4,7 @@
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include "common/filefunctions.h"
#include "config/config.h"
@@ -19,8 +20,6 @@ DiskManager::DiskManager() :
if (cache_index_file.open(QFile::ReadOnly)) {
QDataStream ds(&cache_index_file);
ds >> consumption_;
while (!cache_index_file.atEnd()) {
HashTime h;
@@ -29,7 +28,10 @@ DiskManager::DiskManager() :
ds >> h.access_time;
ds >> h.file_size;
disk_data_.append(h);
if (QFileInfo::exists(h.file_name)) {
consumption_ += h.file_size;
disk_data_.append(h);
}
}
}
}
@@ -38,7 +40,7 @@ DiskManager::~DiskManager()
{
if (Config::Current()["ClearDiskCacheOnClose"].toBool()) {
// Clear all cache data
QDir(GetMediaCacheLocation()).removeRecursively();
ClearDiskCache();
} else {
// Save current cache index
QFile cache_index_file(QDir(GetMediaCacheLocation()).filePath("index"));
@@ -46,8 +48,6 @@ DiskManager::~DiskManager()
if (cache_index_file.open(QFile::WriteOnly)) {
QDataStream ds(&cache_index_file);
ds << consumption_;
foreach (const HashTime& h, disk_data_) {
ds << h.file_name;
ds << h.hash;
@@ -97,7 +97,7 @@ void DiskManager::CreatedFile(const QString &file_name, const QByteArray &hash)
{
qint64 file_size = QFile(file_name).size();
disk_data_.append({file_name, hash, QDateTime::currentMSecsSinceEpoch(), });
disk_data_.append({file_name, hash, QDateTime::currentMSecsSinceEpoch(), file_size});
consumption_ += file_size;
@@ -106,6 +106,13 @@ void DiskManager::CreatedFile(const QString &file_name, const QByteArray &hash)
}
}
bool DiskManager::ClearDiskCache()
{
disk_data_.clear();
return QDir(GetMediaCacheLocation()).removeRecursively();
}
void DiskManager::DeleteLeastRecent()
{
HashTime h = disk_data_.takeFirst();
+2
View File
@@ -17,6 +17,8 @@ public:
void CreatedFile(const QString& file_name, const QByteArray& hash);
bool ClearDiskCache();
signals:
void DeletedFrame(const QByteArray& hash);
+2 -2
View File
@@ -109,9 +109,9 @@ void TimeRuler::SetScroll(int s)
update();
}
void TimeRuler::CacheInvalidatedRange(const rational& in, const rational& out)
void TimeRuler::CacheInvalidatedRange(const TimeRange& range)
{
dirty_cache_ranges_.InsertTimeRange(TimeRange(in, out));
dirty_cache_ranges_.InsertTimeRange(range);
update();
}
+1 -1
View File
@@ -48,7 +48,7 @@ public slots:
void SetScroll(int s);
void CacheInvalidatedRange(const rational& in, const rational& out);
void CacheInvalidatedRange(const TimeRange &range);
void CacheTimeReady(const rational& time);
+1 -2
View File
@@ -82,6 +82,7 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
connect(video_renderer_, &VideoRenderBackend::CachedFrameReady, this, &ViewerWidget::RendererCachedFrame);
connect(video_renderer_, &VideoRenderBackend::CachedTimeReady, this, &ViewerWidget::RendererCachedTime);
connect(video_renderer_, &VideoRenderBackend::CachedTimeReady, ruler_, &TimeRuler::CacheTimeReady);
connect(video_renderer_, &VideoRenderBackend::RangeInvalidated, ruler_, &TimeRuler::CacheInvalidatedRange);
audio_renderer_ = new AudioBackend(this);
}
@@ -142,7 +143,6 @@ void ViewerWidget::ConnectViewerNode(ViewerOutput *node, ColorManager* color_man
disconnect(viewer_node_, &ViewerOutput::TimebaseChanged, this, &ViewerWidget::SetTimebase);
disconnect(viewer_node_, &ViewerOutput::SizeChanged, this, &ViewerWidget::SizeChangedSlot);
disconnect(viewer_node_, &ViewerOutput::LengthChanged, this, &ViewerWidget::LengthChangedSlot);
disconnect(viewer_node_, &ViewerOutput::VideoChangedBetween, ruler_, &TimeRuler::CacheInvalidatedRange);
// Effectively disables the viewer and clears the state
SizeChangedSlot(0, 0);
@@ -164,7 +164,6 @@ void ViewerWidget::ConnectViewerNode(ViewerOutput *node, ColorManager* color_man
connect(viewer_node_, &ViewerOutput::TimebaseChanged, this, &ViewerWidget::SetTimebase);
connect(viewer_node_, &ViewerOutput::SizeChanged, this, &ViewerWidget::SizeChangedSlot);
connect(viewer_node_, &ViewerOutput::LengthChanged, this, &ViewerWidget::LengthChangedSlot);
connect(viewer_node_, &ViewerOutput::VideoChangedBetween, ruler_, &TimeRuler::CacheInvalidatedRange);
SizeChangedSlot(viewer_node_->video_params().width(), viewer_node_->video_params().height());
LengthChangedSlot(viewer_node_->Length());