|
|
|
@@ -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.
|
|
|
|
|