added second frame cache for thumbnails

This commit is contained in:
itsmattkc
2022-05-27 19:16:08 -07:00
parent 3d8c0114fb
commit e9404ba869
10 changed files with 64 additions and 67 deletions
+3 -3
View File
@@ -187,7 +187,7 @@ void ClipBlock::InvalidateCache(const TimeRange& range, const QString& from, int
if (Node *connected = GetConnectedOutput(from, element)) {
TimeRange max_range = InputTimeAdjustment(from, element, TimeRange(0, length()));
if (type == Track::kVideo) {
emit connected->video_frame_cache()->Request(range.Intersected(max_range), PlaybackCache::kPreviewsOnly);
emit connected->thumbnail_cache()->Request(range.Intersected(max_range), PlaybackCache::kPreviewsOnly);
} else if (type == Track::kAudio) {
emit connected->audio_playback_cache()->Request(range.Intersected(max_range), PlaybackCache::kPreviewsOnly);
}
@@ -250,7 +250,7 @@ void ClipBlock::InputConnectedEvent(const QString &input, int element, Node *out
super::InputConnectedEvent(input, element, output);
if (input == kBufferIn) {
connect(output->video_frame_cache(), &FrameHashCache::ThumbnailsUpdated, this, &Block::PreviewChanged);
connect(output->thumbnail_cache(), &FrameHashCache::Validated, this, &Block::PreviewChanged);
connect(output->audio_playback_cache(), &AudioPlaybackCache::WaveformUpdated, this, &Block::PreviewChanged);
}
}
@@ -260,7 +260,7 @@ void ClipBlock::InputDisconnectedEvent(const QString &input, int element, Node *
super::InputDisconnectedEvent(input, element, output);
if (input == kBufferIn) {
disconnect(output->video_frame_cache(), &FrameHashCache::ThumbnailsUpdated, this, &Block::PreviewChanged);
disconnect(output->thumbnail_cache(), &FrameHashCache::Validated, this, &Block::PreviewChanged);
disconnect(output->audio_playback_cache(), &AudioPlaybackCache::WaveformUpdated, this, &Block::PreviewChanged);
}
}
+1 -1
View File
@@ -122,7 +122,7 @@ public:
const FrameHashCache *thumbnails()
{
if (Node *n = GetConnectedOutput(kBufferIn)) {
return n->video_frame_cache();
return n->thumbnail_cache();
} else {
return nullptr;
}
+2
View File
@@ -54,6 +54,7 @@ Node::Node() :
AddInput(kEnabledInput, NodeValue::kBoolean, true);
video_cache_ = new FrameHashCache(this);
thumbnail_cache_ = new FrameHashCache(this);
audio_cache_ = new AudioPlaybackCache(this);
}
@@ -936,6 +937,7 @@ void Node::InvalidateCache(const TimeRange &range, const QString &from, int elem
TimeRange vr = range.Intersected(GetVideoCacheRange());
if (vr.length() != 0) {
video_frame_cache()->Invalidate(vr);
thumbnail_cache()->Invalidate(vr);
}
TimeRange ar = range.Intersected(GetAudioCacheRange());
if (ar.length() != 0) {
+6
View File
@@ -226,6 +226,11 @@ public:
return video_cache_;
}
FrameHashCache* thumbnail_cache() const
{
return thumbnail_cache_;
}
AudioPlaybackCache* audio_playback_cache() const
{
return audio_cache_;
@@ -1402,6 +1407,7 @@ private:
QString effect_input_;
FrameHashCache *video_cache_;
FrameHashCache *thumbnail_cache_;
AudioPlaybackCache *audio_cache_;
-41
View File
@@ -340,47 +340,6 @@ bool FrameHashCache::SaveCacheFrame(const QString &filename, const FramePtr fram
QImage img(reinterpret_cast<const uchar*>(frame->data()), frame->width(), frame->height(), frame->linesize_bytes(), fmt);
return img.save(filename, "jpg");
/*
qDebug() << "hello?" << filename;
// Integer types are stored in JPG
QString tmp = filename;
tmp.append(QStringLiteral(".jpg"));
std::string tmp_std = tmp.toStdString();
auto out = OIIO::ImageOutput::create(tmp_std);
if (!out) {
qDebug() << "fail create";
return false;
}
auto fmt = OIIOUtils::GetOIIOBaseTypeFromFormat(frame->format());
qDebug() << "writing" << fmt;
if (!out->open(tmp_std, OIIO::ImageSpec(frame->width(), frame->height(), frame->channel_count(), fmt))) {
qDebug() << "fail open";
return false;
}
bool ret = out->write_image(fmt, frame->data(), OIIO::AutoStride, frame->linesize_bytes());
out->close();
if (ret) {
QFile f(filename);
if (f.exists()) {
f.remove();
}
ret = QFile::rename(tmp, filename);
if (!ret) {
qDebug() << "fail rename from" << tmp << "to" << filename;
}
} else {
qDebug() << "fail write";
}
return ret;
*/
}
}
-3
View File
@@ -65,9 +65,6 @@ public:
FramePtr LoadCacheFrame(const int64_t &time) const;
static FramePtr LoadCacheFrame(const QString& fn);
signals:
void ThumbnailsUpdated();
private:
rational ToTime(const int64_t &ts) const;
int64_t ToTimestamp(const rational &ts, Timecode::Rounding rounding = Timecode::kRound) const;
+36 -16
View File
@@ -83,11 +83,18 @@ RenderTicketPtr PreviewAutoCacher::GetRangeOfAudio(TimeRange range, RenderTicket
return RenderAudio(copied_viewer_node_->GetConnectedSampleOutput(), range, PlaybackCache::kCacheOnly, priority);
}
void PreviewAutoCacher::VideoInvalidatedFromCache(const TimeRange &range, PlaybackCache::RequestType type)
void PreviewAutoCacher::VideoInvalidatedFromCache(const TimeRange &range)
{
FrameHashCache *cache = static_cast<FrameHashCache*>(sender());
VideoInvalidatedFromNode(cache->parent(), range, type);
VideoInvalidatedFromNode(cache->parent(), range, PlaybackCache::kCacheOnly);
}
void PreviewAutoCacher::ThumbnailsInvalidatedFromCache(const TimeRange &range)
{
FrameHashCache *cache = static_cast<FrameHashCache*>(sender());
VideoInvalidatedFromNode(cache->parent(), range, PlaybackCache::kPreviewsOnly);
}
void PreviewAutoCacher::AudioInvalidatedFromCache(const TimeRange &range, PlaybackCache::RequestType type)
@@ -162,17 +169,9 @@ void PreviewAutoCacher::VideoRendered()
if (it != video_tasks_.end()) {
// Assume that a "result" is a fully completed image and a non-result is a cancelled ticket
if (watcher->HasResult()) {
PlaybackCache::RequestType type = PlaybackCache::RequestType(watcher->property("type").toInt());
if (type == PlaybackCache::kCacheOnly) {
if (watcher->GetTicket()->property("cached").toBool()) {
if (FrameHashCache *cache = Node::ValueToPtr<FrameHashCache>(watcher->property("cache"))) {
cache->ValidateTime(it.value());
}
}
} else {
if (watcher->GetTicket()->property("cached").toBool()) {
if (FrameHashCache *cache = Node::ValueToPtr<FrameHashCache>(watcher->property("cache"))) {
emit cache->ThumbnailsUpdated();
cache->ValidateTime(it.value());
}
}
}
@@ -336,6 +335,11 @@ void PreviewAutoCacher::ConnectToNodeCache(Node *node)
this,
&PreviewAutoCacher::VideoInvalidatedFromCache);
connect(node->thumbnail_cache(),
&PlaybackCache::Request,
this,
&PreviewAutoCacher::ThumbnailsInvalidatedFromCache);
connect(node->audio_playback_cache(),
&PlaybackCache::Request,
this,
@@ -368,6 +372,11 @@ void PreviewAutoCacher::DisconnectFromNodeCache(Node *node)
this,
&PreviewAutoCacher::VideoInvalidatedFromCache);
disconnect(node->thumbnail_cache(),
&PlaybackCache::Request,
this,
&PreviewAutoCacher::ThumbnailsInvalidatedFromCache);
disconnect(node->audio_playback_cache(),
&PlaybackCache::Request,
this,
@@ -606,7 +615,15 @@ void PreviewAutoCacher::TryRender()
// We want this hash, if we're not already rendering, start render now
if (!render_task) {
// Don't render any hash more than once
RenderFrame(copy, t, d.type, RenderTicketPriority::kNormal, d.node->video_frame_cache());
FrameHashCache *using_cache;
if (d.type == PlaybackCache::kCacheOnly) {
using_cache = d.node->video_frame_cache();
} else {
using_cache = d.node->thumbnail_cache();
}
RenderFrame(copy, t, d.type, RenderTicketPriority::kNormal, using_cache);
}
emit SignalCacheProxyTaskProgress(double(d.iterator.frame_index()) / double(d.iterator.size()));
@@ -658,14 +675,17 @@ RenderTicketWatcher* PreviewAutoCacher::RenderFrame(Node *node, const rational&
copied_color_manager_);
if (cache) {
cache->SetTimebase(viewer_node_->GetVideoParams().frame_rate_as_time_base());
rvp.AddCache(cache);
if (type == PlaybackCache::kPreviewsOnly) {
rvp.video_params.set_divider(VideoParams::GetDividerForTargetResolution(rvp.video_params.width(), rvp.video_params.height(), 160, 120));
rvp.force_color_output = display_color_processor_;
rvp.force_format = VideoParams::kFormatUnsigned8;
cache->SetTimebase(rational(1, 10));
} else {
cache->SetTimebase(viewer_node_->GetVideoParams().frame_rate_as_time_base());
}
rvp.AddCache(cache);
}
rvp.priority = priority;
+2 -1
View File
@@ -227,7 +227,8 @@ private slots:
/**
* @brief Handler for when the NodeGraph reports a video change over a certain time range
*/
void VideoInvalidatedFromCache(const olive::TimeRange &range, olive::PlaybackCache::RequestType type);
void VideoInvalidatedFromCache(const olive::TimeRange &range);
void ThumbnailsInvalidatedFromCache(const olive::TimeRange &range);
/**
* @brief Handler for when the NodeGraph reports a audio change over a certain time range
@@ -64,6 +64,9 @@ rational TimeScaledObject::SceneToTime(const double &x, const double &x_scale, c
if (round) {
rounded_x_mvmt = qRound64(unscaled_time);
} else if (unscaled_time < 0) {
// "floor" to zero
rounded_x_mvmt = qCeil(unscaled_time);
} else {
rounded_x_mvmt = qFloor(unscaled_time);
}
@@ -529,11 +529,20 @@ void TimelineView::DrawBlock(QPainter *painter, bool foreground, Block *block, q
painter->setClipRect(preview_rect);
painter->setRenderHint(QPainter::SmoothPixmapTransform);
for (int i=preview_rect.left(); i<preview_rect.right(); i+=thumb_rect.width()+1) {
rational time_here = SceneToTime(i - block_in, GetScale(), connected_track_list_->parent()->GetAudioParams().sample_rate_as_time_base()) + media_in;
rational time_here = SceneToTime(i - block_in, GetScale(), connected_track_list_->parent()->GetVideoParams().frame_rate_as_time_base()) + media_in;
QString thumbnail = thumbs->GetValidCacheFilename(time_here);
if (thumbnail.isEmpty()) {
break;
// Jump ahead to next frame, ensuring that frame width > 0 for optimization
if (thumb_rect.width() == 0 && clip->track() && clip->track()->sequence()) {
Sequence *s = clip->track()->sequence();
int width = s->GetVideoParams().width();
int height = s->GetVideoParams().height();
if (height > 0) { // Prevent divide by zero/invalid params
double scale = double(preview_rect.height())/double(height);
thumb_rect.setWidth(width * scale);
}
}
} else {
QImage img;
if (img.load(thumbnail, "jpg")) {