timeline: implement nest function

Also includes some improved cache/request code
This commit is contained in:
itsmattkc
2022-10-01 13:04:51 -07:00
parent 087325e4b2
commit df97df635d
16 changed files with 230 additions and 45 deletions
+7
View File
@@ -223,6 +223,13 @@ void PlaybackCache::InvalidateAll()
Invalidate(TimeRange(0, RATIONAL_MAX));
}
void PlaybackCache::Request(const TimeRange &r)
{
requested_.insert(r);
emit Requested(r);
}
void PlaybackCache::Validate(const TimeRange &r, bool signal)
{
validated_.insert(r);
+17 -1
View File
@@ -98,15 +98,29 @@ public:
const QVector<Passthrough> &GetPassthroughs() const { return passthroughs_; }
void ClearRequestRange(const olive::TimeRange &r)
{
requested_.remove(r);
}
void ResignalRequests()
{
for (const TimeRange &r : requested_) {
emit Requested(r);
}
}
public slots:
void InvalidateAll();
void Request(const olive::TimeRange &r);
signals:
void Invalidated(const olive::TimeRange& r);
void Validated(const olive::TimeRange& r);
void Request(const olive::TimeRange& r);
void Requested(const olive::TimeRange& r);
void CancelAll();
@@ -124,6 +138,8 @@ protected:
private:
TimeRangeList validated_;
TimeRangeList requested_;
QUuid uuid_;
bool saving_enabled_;
+37 -17
View File
@@ -100,6 +100,8 @@ void PreviewAutoCacher::VideoInvalidatedFromCache(const TimeRange &range)
{
PlaybackCache *cache = static_cast<PlaybackCache*>(sender());
cache->ClearRequestRange(range);
VideoInvalidatedFromNode(cache, range);
}
@@ -107,6 +109,8 @@ void PreviewAutoCacher::AudioInvalidatedFromCache(const TimeRange &range)
{
PlaybackCache *cache = static_cast<PlaybackCache*>(sender());
cache->ClearRequestRange(range);
AudioInvalidatedFromNode(cache, range);
}
@@ -240,7 +244,10 @@ void PreviewAutoCacher::VideoRendered()
void PreviewAutoCacher::ProcessUpdateQueue()
{
// Iterate everything that happened to the graph and do the same thing on our end
foreach (const QueuedJob& job, graph_update_queue_) {
while (!graph_update_queue_.empty()) {
QueuedJob job = graph_update_queue_.front();
graph_update_queue_.pop_front();
switch (job.type) {
case QueuedJob::kNodeAdded:
AddNode(job.node);
@@ -262,7 +269,6 @@ void PreviewAutoCacher::ProcessUpdateQueue()
break;
}
}
graph_update_queue_.clear();
// Indicate that we have synchronized to this point, which is compared with the graph change
// time to see if our copied graph is up to date
@@ -368,22 +374,22 @@ void PreviewAutoCacher::InsertIntoCopyMap(Node *node, Node *copy)
void PreviewAutoCacher::ConnectToNodeCache(Node *node)
{
connect(node->video_frame_cache(),
&PlaybackCache::Request,
&PlaybackCache::Requested,
this,
&PreviewAutoCacher::VideoInvalidatedFromCache);
connect(node->thumbnail_cache(),
&PlaybackCache::Request,
&PlaybackCache::Requested,
this,
&PreviewAutoCacher::VideoInvalidatedFromCache);
connect(node->audio_playback_cache(),
&PlaybackCache::Request,
&PlaybackCache::Requested,
this,
&PreviewAutoCacher::AudioInvalidatedFromCache);
connect(node->waveform_cache(),
&PlaybackCache::Request,
&PlaybackCache::Requested,
this,
&PreviewAutoCacher::AudioInvalidatedFromCache);
@@ -396,27 +402,32 @@ void PreviewAutoCacher::ConnectToNodeCache(Node *node)
&PlaybackCache::CancelAll,
this,
&PreviewAutoCacher::CancelForCache);
node->video_frame_cache()->ResignalRequests();
node->thumbnail_cache()->ResignalRequests();
node->audio_playback_cache()->ResignalRequests();
node->waveform_cache()->ResignalRequests();
}
void PreviewAutoCacher::DisconnectFromNodeCache(Node *node)
{
disconnect(node->video_frame_cache(),
&PlaybackCache::Request,
&PlaybackCache::Requested,
this,
&PreviewAutoCacher::VideoInvalidatedFromCache);
disconnect(node->thumbnail_cache(),
&PlaybackCache::Request,
&PlaybackCache::Requested,
this,
&PreviewAutoCacher::VideoInvalidatedFromCache);
disconnect(node->audio_playback_cache(),
&PlaybackCache::Request,
&PlaybackCache::Requested,
this,
&PreviewAutoCacher::AudioInvalidatedFromCache);
disconnect(node->waveform_cache(),
&PlaybackCache::Request,
&PlaybackCache::Requested,
this,
&PreviewAutoCacher::AudioInvalidatedFromCache);
@@ -466,6 +477,8 @@ void PreviewAutoCacher::StartCachingVideoRange(PlaybackCache *cache, const TimeR
using_tb = viewer_node_->GetVideoParams().frame_rate_as_time_base();
}
cache->ClearRequestRange(range);
TimeRangeListFrameIterator iterator({range}, using_tb);
pending_video_jobs_.push_back({node, cache, range, iterator});
video_cache_data_[cache].job_tracker.insert(TimeRange(iterator.Snap(range.in()), range.out()), graph_changed_time_);
@@ -475,6 +488,9 @@ void PreviewAutoCacher::StartCachingVideoRange(PlaybackCache *cache, const TimeR
void PreviewAutoCacher::StartCachingAudioRange(PlaybackCache *cache, const TimeRange &range)
{
Node *node = cache->parent();
cache->ClearRequestRange(range);
pending_audio_jobs_.push_back({node, cache, range});
audio_cache_data_[cache].job_tracker.insert(range, graph_changed_time_);
TryRender();
@@ -486,6 +502,8 @@ void PreviewAutoCacher::VideoInvalidatedFromNode(PlaybackCache *cache, const Tim
// want to dedicate all our rendering power to realtime feedback for the user
//CancelVideoTasks(node);
cache->ClearRequestRange(range);
// If auto-cache is enabled and a slider is not being dragged, queue up to hash these frames
if (!NodeInputDragger::IsInputBeingDragged()) {
StartCachingVideoRange(cache, range);
@@ -498,6 +516,8 @@ void PreviewAutoCacher::AudioInvalidatedFromNode(PlaybackCache *cache, const Tim
// cancelled, so some areas may end up unrendered forever
// ClearAudioQueue();
cache->ClearRequestRange(range);
// If we're auto-caching audio or require realtime waveforms, we'll have to render this
StartCachingAudioRange(cache, range);
}
@@ -553,37 +573,37 @@ void PreviewAutoCacher::SetRendersPaused(bool e)
void PreviewAutoCacher::NodeAdded(Node *node)
{
graph_update_queue_.append({QueuedJob::kNodeAdded, node, NodeInput(), nullptr});
graph_update_queue_.push_back({QueuedJob::kNodeAdded, node, NodeInput(), nullptr});
UpdateGraphChangeValue();
}
void PreviewAutoCacher::NodeRemoved(Node *node)
{
graph_update_queue_.append({QueuedJob::kNodeRemoved, node, NodeInput(), nullptr});
graph_update_queue_.push_back({QueuedJob::kNodeRemoved, node, NodeInput(), nullptr});
UpdateGraphChangeValue();
}
void PreviewAutoCacher::EdgeAdded(Node *output, const NodeInput &input)
{
graph_update_queue_.append({QueuedJob::kEdgeAdded, nullptr, input, output});
graph_update_queue_.push_back({QueuedJob::kEdgeAdded, nullptr, input, output});
UpdateGraphChangeValue();
}
void PreviewAutoCacher::EdgeRemoved(Node *output, const NodeInput &input)
{
graph_update_queue_.append({QueuedJob::kEdgeRemoved, nullptr, input, output});
graph_update_queue_.push_back({QueuedJob::kEdgeRemoved, nullptr, input, output});
UpdateGraphChangeValue();
}
void PreviewAutoCacher::ValueChanged(const NodeInput &input)
{
graph_update_queue_.append({QueuedJob::kValueChanged, nullptr, input, nullptr});
graph_update_queue_.push_back({QueuedJob::kValueChanged, nullptr, input, nullptr});
UpdateGraphChangeValue();
}
void PreviewAutoCacher::ValueHintChanged(const NodeInput &input)
{
graph_update_queue_.append({QueuedJob::kValueHintChanged, nullptr, input, nullptr});
graph_update_queue_.push_back({QueuedJob::kValueHintChanged, nullptr, input, nullptr});
UpdateGraphChangeValue();
}
@@ -591,7 +611,7 @@ void PreviewAutoCacher::TryRender()
{
delayed_requeue_timer_.stop();
if (!graph_update_queue_.isEmpty()) {
if (!graph_update_queue_.empty()) {
// Check if we have jobs running in other threads that shouldn't be interrupted right now
// NOTE: We don't check for downloads because, while they run in another thread, they don't
// require any access to the graph and therefore don't risk race conditions.
+1 -1
View File
@@ -160,7 +160,7 @@ private:
Project copied_project_;
QVector<QueuedJob> graph_update_queue_;
std::list<QueuedJob> graph_update_queue_;
QHash<Node*, Node*> copy_map_;
QHash<NodeGraph*, NodeGraph*> graph_map_;
ViewerOutput* copied_viewer_node_;