Squashed commit of the following:
commit dec7ca6b96c58decf2c5e5194b665fa2342951b2
Author: itsmattkc <34096995+itsmattkc@users.noreply.github.com>
Date: Wed Feb 8 12:32:12 2023 -0800
moved previewautocacher to rendermanager
commit d289d74d82c3911f3fdaa707abe9994c7363594d
Merge: a8a049a28 70d34c674
Author: itsmattkc <34096995+itsmattkc@users.noreply.github.com>
Date: Wed Feb 8 12:15:31 2023 -0800
Merge branch 'master' into move-cacher-to-renderman
commit a8a049a2857c438cbab0f1ab21e3299fdfbf1fa1
Author: itsmattkc <34096995+itsmattkc@users.noreply.github.com>
Date: Wed Feb 8 11:18:25 2023 -0800
initial work
This commit is contained in:
@@ -480,6 +480,7 @@ void Core::AddOpenProject(Project* p, bool add_to_recents)
|
||||
|
||||
connect(p, &Project::ModifiedChanged, this, &Core::ProjectWasModified);
|
||||
open_project_ = p;
|
||||
RenderManager::instance()->SetProject(p);
|
||||
|
||||
if (!p->filename().isEmpty() && add_to_recents) {
|
||||
PushRecentlyOpenedProject(p->filename());
|
||||
@@ -1476,6 +1477,7 @@ bool Core::CloseProject(bool auto_open_new, bool ignore_modified)
|
||||
undo_stack_.clear();
|
||||
|
||||
disconnect(open_project_, &Project::ModifiedChanged, this, &Core::ProjectWasModified);
|
||||
RenderManager::instance()->SetProject(nullptr);
|
||||
emit ProjectClosed(open_project_);
|
||||
delete open_project_;
|
||||
open_project_ = nullptr;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "config/config.h"
|
||||
#include "node/block/transition/transition.h"
|
||||
#include "node/project/sequence/sequence.h"
|
||||
#include "node/output/track/track.h"
|
||||
#include "node/output/viewer/viewer.h"
|
||||
#include "widget/slider/floatslider.h"
|
||||
@@ -233,7 +234,7 @@ void ClipBlock::RequestRangeFromConnected(const TimeRange &range)
|
||||
{
|
||||
TimeRange thumb_range = range.Intersected(max_range);
|
||||
if (GetAdjustedThumbnailRange(&thumb_range)) {
|
||||
connected->thumbnail_cache()->Request(thumb_range);
|
||||
connected->thumbnail_cache()->Request(this->track()->sequence(), thumb_range);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,7 +298,7 @@ void ClipBlock::RequestRangeForCache(PlaybackCache *cache, const TimeRange &max_
|
||||
}
|
||||
|
||||
if (request) {
|
||||
cache->Request(r);
|
||||
cache->Request(this->track()->sequence(), r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -230,15 +230,15 @@ void ViewerOutput::InvalidateCache(const TimeRange& range, const QString& from,
|
||||
//connected->thumbnail_cache()->Request(range.Intersected(max_range), PlaybackCache::kPreviewsOnly);
|
||||
if (autocache_input_video_) {
|
||||
TimeRange max_range = InputTimeAdjustment(from, element, TimeRange(0, GetVideoLength()), false);
|
||||
connected->video_frame_cache()->Request(range.Intersected(max_range));
|
||||
connected->video_frame_cache()->Request(this, range.Intersected(max_range));
|
||||
}
|
||||
} else if (from == kSamplesInput) {
|
||||
TimeRange max_range = InputTimeAdjustment(from, element, TimeRange(0, GetAudioLength()), false);
|
||||
if (waveform_requests_enabled_) {
|
||||
connected->waveform_cache()->Request(range.Intersected(max_range));
|
||||
connected->waveform_cache()->Request(this, range.Intersected(max_range));
|
||||
}
|
||||
if (autocache_input_audio_) {
|
||||
connected->audio_playback_cache()->Request(range.Intersected(max_range));
|
||||
connected->audio_playback_cache()->Request(this, range.Intersected(max_range));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -405,7 +405,7 @@ void ViewerOutput::SetWaveformEnabled(bool e)
|
||||
TimeRange max_range = InputTimeAdjustment(kSamplesInput, -1, TimeRange(0, GetAudioLength()), false);
|
||||
TimeRangeList invalid = connected->waveform_cache()->GetInvalidatedRanges(max_range);
|
||||
for (const TimeRange &r : invalid) {
|
||||
connected->waveform_cache()->Request(r);
|
||||
connected->waveform_cache()->Request(this, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,11 +225,12 @@ void PlaybackCache::InvalidateAll()
|
||||
Invalidate(TimeRange(0, RATIONAL_MAX));
|
||||
}
|
||||
|
||||
void PlaybackCache::Request(const TimeRange &r)
|
||||
void PlaybackCache::Request(ViewerOutput *context, const TimeRange &r)
|
||||
{
|
||||
request_context_ = context;
|
||||
requested_.insert(r);
|
||||
|
||||
emit Requested(r);
|
||||
emit Requested(request_context_, r);
|
||||
}
|
||||
|
||||
void PlaybackCache::Validate(const TimeRange &r, bool signal)
|
||||
|
||||
@@ -108,21 +108,21 @@ public:
|
||||
void ResignalRequests()
|
||||
{
|
||||
for (const TimeRange &r : requested_) {
|
||||
emit Requested(r);
|
||||
emit Requested(request_context_, r);
|
||||
}
|
||||
}
|
||||
|
||||
public slots:
|
||||
void InvalidateAll();
|
||||
|
||||
void Request(const TimeRange &r);
|
||||
void Request(ViewerOutput *context, const TimeRange &r);
|
||||
|
||||
signals:
|
||||
void Invalidated(const TimeRange& r);
|
||||
|
||||
void Validated(const TimeRange& r);
|
||||
|
||||
void Requested(const TimeRange& r);
|
||||
void Requested(ViewerOutput *context, const TimeRange& r);
|
||||
|
||||
void CancelAll();
|
||||
|
||||
@@ -141,6 +141,7 @@ private:
|
||||
TimeRangeList validated_;
|
||||
|
||||
TimeRangeList requested_;
|
||||
ViewerOutput *request_context_;
|
||||
|
||||
QUuid uuid_;
|
||||
|
||||
|
||||
@@ -28,12 +28,13 @@
|
||||
#include "node/inputdragger.h"
|
||||
#include "node/project/project.h"
|
||||
#include "render/diskmanager.h"
|
||||
#include "render/rendermanager.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
PreviewAutoCacher::PreviewAutoCacher(QObject *parent) :
|
||||
QObject(parent),
|
||||
viewer_node_(nullptr),
|
||||
project_(nullptr),
|
||||
use_custom_range_(false),
|
||||
pause_renders_(false),
|
||||
pause_thumbnails_(false),
|
||||
@@ -61,15 +62,15 @@ PreviewAutoCacher::PreviewAutoCacher(QObject *parent) :
|
||||
PreviewAutoCacher::~PreviewAutoCacher()
|
||||
{
|
||||
// Ensure everything is cleaned up appropriately
|
||||
SetViewerNode(nullptr);
|
||||
SetProject(nullptr);
|
||||
}
|
||||
|
||||
RenderTicketPtr PreviewAutoCacher::GetSingleFrame(const rational &t, bool dry)
|
||||
RenderTicketPtr PreviewAutoCacher::GetSingleFrame(ViewerOutput *viewer, const rational &t, bool dry)
|
||||
{
|
||||
return GetSingleFrame(viewer_node_->GetConnectedTextureOutput(), t, dry);
|
||||
return GetSingleFrame(viewer->GetConnectedTextureOutput(), viewer, t, dry);
|
||||
}
|
||||
|
||||
RenderTicketPtr PreviewAutoCacher::GetSingleFrame(Node *n, const rational &t, bool dry)
|
||||
RenderTicketPtr PreviewAutoCacher::GetSingleFrame(Node *n, ViewerOutput *viewer, const rational &t, bool dry)
|
||||
{
|
||||
// If we have a single frame render queued (but not yet sent to the RenderManager), cancel it now
|
||||
CancelQueuedSingleFrameRender();
|
||||
@@ -80,6 +81,7 @@ RenderTicketPtr PreviewAutoCacher::GetSingleFrame(Node *n, const rational &t, bo
|
||||
sfr->setProperty("time", QVariant::fromValue(t));
|
||||
sfr->setProperty("dry", dry);
|
||||
sfr->setProperty("node", Node::PtrToValue(n));
|
||||
sfr->setProperty("viewer", Node::PtrToValue(viewer));
|
||||
|
||||
// Queue it and try to render
|
||||
single_frame_render_ = sfr;
|
||||
@@ -88,9 +90,10 @@ RenderTicketPtr PreviewAutoCacher::GetSingleFrame(Node *n, const rational &t, bo
|
||||
return sfr;
|
||||
}
|
||||
|
||||
RenderTicketPtr PreviewAutoCacher::GetRangeOfAudio(TimeRange range)
|
||||
RenderTicketPtr PreviewAutoCacher::GetRangeOfAudio(ViewerOutput *viewer, TimeRange range)
|
||||
{
|
||||
return RenderAudio(copied_viewer_node_->GetConnectedSampleOutput(), range, nullptr);
|
||||
Node *copy = copier_->GetCopy(viewer->GetConnectedSampleOutput());
|
||||
return RenderAudio(copy, viewer, range, nullptr);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::ClearSingleFrameRenders()
|
||||
@@ -105,22 +108,22 @@ void PreviewAutoCacher::ClearSingleFrameRenders()
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::VideoInvalidatedFromCache(const TimeRange &range)
|
||||
void PreviewAutoCacher::VideoInvalidatedFromCache(ViewerOutput *context, const TimeRange &range)
|
||||
{
|
||||
PlaybackCache *cache = static_cast<PlaybackCache*>(sender());
|
||||
|
||||
cache->ClearRequestRange(range);
|
||||
|
||||
VideoInvalidatedFromNode(cache, range);
|
||||
VideoInvalidatedFromNode(context, cache, range);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::AudioInvalidatedFromCache(const TimeRange &range)
|
||||
void PreviewAutoCacher::AudioInvalidatedFromCache(ViewerOutput *context, const TimeRange &range)
|
||||
{
|
||||
PlaybackCache *cache = static_cast<PlaybackCache*>(sender());
|
||||
|
||||
cache->ClearRequestRange(range);
|
||||
|
||||
AudioInvalidatedFromNode(cache, range);
|
||||
AudioInvalidatedFromNode(context, cache, range);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::CancelForCache()
|
||||
@@ -341,39 +344,39 @@ void PreviewAutoCacher::StartCachingRange(const TimeRange &range, TimeRangeList
|
||||
tracker->insert(range, copier_->GetGraphChangeTime());
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::StartCachingVideoRange(PlaybackCache *cache, const TimeRange &range)
|
||||
void PreviewAutoCacher::StartCachingVideoRange(ViewerOutput *context, PlaybackCache *cache, const TimeRange &range)
|
||||
{
|
||||
Node *node = cache->parent();
|
||||
rational using_tb;
|
||||
if (ThumbnailCache *thumbs = dynamic_cast<ThumbnailCache*>(cache)) {
|
||||
using_tb = thumbs->GetTimebase();
|
||||
} else {
|
||||
using_tb = viewer_node_->GetVideoParams().frame_rate_as_time_base();
|
||||
using_tb = context->GetVideoParams().frame_rate_as_time_base();
|
||||
}
|
||||
|
||||
cache->ClearRequestRange(range);
|
||||
|
||||
TimeRangeListFrameIterator iterator({range}, using_tb);
|
||||
pending_video_jobs_.push_back({node, cache, range, iterator});
|
||||
pending_video_jobs_.push_back({node, context, cache, range, iterator});
|
||||
video_cache_data_[cache].job_tracker.insert(TimeRange(iterator.Snap(range.in()), range.out()), copier_->GetGraphChangeTime());
|
||||
TryRender();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::StartCachingAudioRange(PlaybackCache *cache, const TimeRange &range)
|
||||
void PreviewAutoCacher::StartCachingAudioRange(ViewerOutput *context, PlaybackCache *cache, const TimeRange &range)
|
||||
{
|
||||
Node *node = cache->parent();
|
||||
|
||||
cache->ClearRequestRange(range);
|
||||
|
||||
pending_audio_jobs_.push_back({node, cache, range});
|
||||
pending_audio_jobs_.push_back({node, context, cache, range});
|
||||
audio_cache_data_[cache].job_tracker.insert(range, copier_->GetGraphChangeTime());
|
||||
TryRender();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::VideoInvalidatedFromNode(PlaybackCache *cache, const TimeRange &range)
|
||||
void PreviewAutoCacher::VideoInvalidatedFromNode(ViewerOutput *context, PlaybackCache *cache, const TimeRange &range)
|
||||
{
|
||||
// Ignore render requests if no video is present
|
||||
if (!viewer_node_ || !viewer_node_->GetVideoParams().is_valid()) {
|
||||
if (!context || !context->GetVideoParams().is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -385,14 +388,14 @@ void PreviewAutoCacher::VideoInvalidatedFromNode(PlaybackCache *cache, const Tim
|
||||
|
||||
// If auto-cache is enabled and a slider is not being dragged, queue up to hash these frames
|
||||
if (!NodeInputDragger::IsInputBeingDragged()) {
|
||||
StartCachingVideoRange(cache, range);
|
||||
StartCachingVideoRange(context, cache, range);
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::AudioInvalidatedFromNode(PlaybackCache *cache, const TimeRange &range)
|
||||
void PreviewAutoCacher::AudioInvalidatedFromNode(ViewerOutput *context, PlaybackCache *cache, const TimeRange &range)
|
||||
{
|
||||
// Ignore render requests if no video is present
|
||||
if (!viewer_node_ || !viewer_node_->GetAudioParams().is_valid()) {
|
||||
if (!context || !context->GetAudioParams().is_valid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -403,7 +406,7 @@ void PreviewAutoCacher::AudioInvalidatedFromNode(PlaybackCache *cache, const Tim
|
||||
cache->ClearRequestRange(range);
|
||||
|
||||
// If we're auto-caching audio or require realtime waveforms, we'll have to render this
|
||||
StartCachingAudioRange(cache, range);
|
||||
StartCachingAudioRange(context, cache, range);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::SetPlayhead(const rational &playhead)
|
||||
@@ -492,6 +495,7 @@ void PreviewAutoCacher::TryRender()
|
||||
|
||||
if (copy) {
|
||||
RenderTicketWatcher *watcher = RenderFrame(copy,
|
||||
Node::ValueToPtr<ViewerOutput>(t->property("viewer")),
|
||||
t->property("time").value<rational>(),
|
||||
nullptr,
|
||||
t->property("dry").toBool());
|
||||
@@ -515,7 +519,7 @@ void PreviewAutoCacher::TryRender()
|
||||
// Queue next frames
|
||||
rational t;
|
||||
while (running_video_tasks_.size() < max_tasks && d.iterator.GetNext(&t)) {
|
||||
RenderFrame(copy, t, d.cache, false);
|
||||
RenderFrame(copy, d.context, t, d.cache, false);
|
||||
|
||||
emit SignalCacheProxyTaskProgress(double(d.iterator.frame_index()) / double(d.iterator.size()));
|
||||
|
||||
@@ -556,7 +560,7 @@ void PreviewAutoCacher::TryRender()
|
||||
}
|
||||
}
|
||||
|
||||
RenderAudio(copy, use_range, d.cache);
|
||||
RenderAudio(copy, d.context, use_range, d.cache);
|
||||
} else {
|
||||
qCritical() << "Failed to find node copy for audio job";
|
||||
}
|
||||
@@ -568,7 +572,7 @@ void PreviewAutoCacher::TryRender()
|
||||
}
|
||||
}
|
||||
|
||||
RenderTicketWatcher* PreviewAutoCacher::RenderFrame(Node *node, const rational& time, PlaybackCache *cache, bool dry)
|
||||
RenderTicketWatcher* PreviewAutoCacher::RenderFrame(Node *node, ViewerOutput *context, const rational& time, PlaybackCache *cache, bool dry)
|
||||
{
|
||||
RenderTicketWatcher* watcher = new RenderTicketWatcher();
|
||||
watcher->setProperty("job", QVariant::fromValue(copier_->GetLastUpdateTime()));
|
||||
@@ -579,8 +583,8 @@ RenderTicketWatcher* PreviewAutoCacher::RenderFrame(Node *node, const rational&
|
||||
running_video_tasks_.append(watcher);
|
||||
|
||||
RenderManager::RenderVideoParams rvp(node,
|
||||
copied_viewer_node_->GetVideoParams(),
|
||||
copied_viewer_node_->GetAudioParams(),
|
||||
context->GetVideoParams(),
|
||||
context->GetAudioParams(),
|
||||
time,
|
||||
copied_color_manager_,
|
||||
RenderMode::kOffline);
|
||||
@@ -591,7 +595,7 @@ RenderTicketWatcher* PreviewAutoCacher::RenderFrame(Node *node, const rational&
|
||||
rvp.force_color_output = display_color_processor_;
|
||||
rvp.force_format = PixelFormat::U8;
|
||||
} else {
|
||||
frame_cache->SetTimebase(viewer_node_->GetVideoParams().frame_rate_as_time_base());
|
||||
frame_cache->SetTimebase(context->GetVideoParams().frame_rate_as_time_base());
|
||||
}
|
||||
|
||||
rvp.AddCache(frame_cache);
|
||||
@@ -610,7 +614,7 @@ RenderTicketWatcher* PreviewAutoCacher::RenderFrame(Node *node, const rational&
|
||||
return watcher;
|
||||
}
|
||||
|
||||
RenderTicketPtr PreviewAutoCacher::RenderAudio(Node *node, const TimeRange &r, PlaybackCache *cache)
|
||||
RenderTicketPtr PreviewAutoCacher::RenderAudio(Node *node, ViewerOutput *context, const TimeRange &r, PlaybackCache *cache)
|
||||
{
|
||||
RenderTicketWatcher* watcher = new RenderTicketWatcher();
|
||||
watcher->setProperty("job", QVariant::fromValue(copier_->GetLastUpdateTime()));
|
||||
@@ -622,7 +626,7 @@ RenderTicketPtr PreviewAutoCacher::RenderAudio(Node *node, const TimeRange &r, P
|
||||
|
||||
RenderManager::RenderAudioParams rap(node,
|
||||
r,
|
||||
copied_viewer_node_->GetAudioParams(),
|
||||
context->GetAudioParams(),
|
||||
RenderMode::kOffline);
|
||||
|
||||
rap.generate_waveforms = dynamic_cast<AudioWaveformCache*>(cache);
|
||||
@@ -638,12 +642,13 @@ void PreviewAutoCacher::ConformFinished()
|
||||
// Got an audio conform, requeue all the audio currently needing a conform
|
||||
last_conform_task_.Acquire();
|
||||
|
||||
for (auto it=audio_cache_data_.begin(); it!=audio_cache_data_.end(); it++) {
|
||||
qDebug() << "CONFORM RESPONSE TEMPORARILY DISABLED";
|
||||
/*for (auto it=audio_cache_data_.begin(); it!=audio_cache_data_.end(); it++) {
|
||||
foreach (const TimeRange &range, it.value().needs_conform) {
|
||||
it.key()->Request(range);
|
||||
}
|
||||
it.value().needs_conform.clear();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::CacheProxyTaskCancelled()
|
||||
@@ -653,22 +658,22 @@ void PreviewAutoCacher::CacheProxyTaskCancelled()
|
||||
TryRender();
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::ForceCacheRange(const TimeRange &range)
|
||||
void PreviewAutoCacher::ForceCacheRange(ViewerOutput *context, const TimeRange &range)
|
||||
{
|
||||
use_custom_range_ = true;
|
||||
custom_autocache_range_ = range;
|
||||
|
||||
// Re-hash these frames and start rendering
|
||||
StartCachingVideoRange(viewer_node_->video_frame_cache(), range);
|
||||
StartCachingVideoRange(context, context->video_frame_cache(), range);
|
||||
}
|
||||
|
||||
void PreviewAutoCacher::SetViewerNode(ViewerOutput *viewer_node)
|
||||
void PreviewAutoCacher::SetProject(Project *project)
|
||||
{
|
||||
if (viewer_node_ == viewer_node) {
|
||||
if (project_ == project) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewer_node_) {
|
||||
if (project_) {
|
||||
// We must wait for any jobs to finish because they'll be using our copied graph and we're
|
||||
// about to destroy it
|
||||
|
||||
@@ -702,7 +707,6 @@ void PreviewAutoCacher::SetViewerNode(ViewerOutput *viewer_node)
|
||||
|
||||
// Delete all of our copied nodes
|
||||
copier_->SetProject(nullptr);
|
||||
copied_viewer_node_ = nullptr;
|
||||
|
||||
// Ensure all cache data is cleared
|
||||
video_cache_data_.clear();
|
||||
@@ -712,23 +716,20 @@ void PreviewAutoCacher::SetViewerNode(ViewerOutput *viewer_node)
|
||||
multicam_ = nullptr;
|
||||
}
|
||||
|
||||
viewer_node_ = viewer_node;
|
||||
project_ = project;
|
||||
|
||||
if (viewer_node_) {
|
||||
if (project_) {
|
||||
// Copy graph (this should always be a Project)
|
||||
Project* graph = static_cast<Project*>(viewer_node_->parent());
|
||||
|
||||
SetRendersPaused(true);
|
||||
|
||||
copier_->SetProject(graph);
|
||||
copier_->SetProject(project_);
|
||||
|
||||
for (int i=0; i<graph->nodes().size(); i++) {
|
||||
graph->nodes().at(i)->ConnectedToPreviewEvent();
|
||||
for (int i=0; i<project_->nodes().size(); i++) {
|
||||
project_->nodes().at(i)->ConnectedToPreviewEvent();
|
||||
}
|
||||
|
||||
// Find copied viewer node
|
||||
copied_viewer_node_ = copier_->GetCopy(viewer_node_);
|
||||
copied_color_manager_ = copier_->GetCopy(graph->color_manager());
|
||||
copied_color_manager_ = copier_->GetCopy(project_->color_manager());
|
||||
|
||||
SetRendersPaused(false);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "node/project/project.h"
|
||||
#include "render/projectcopier.h"
|
||||
#include "render/renderjobtracker.h"
|
||||
#include "render/rendermanager.h"
|
||||
#include "render/renderticket.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
@@ -49,17 +49,17 @@ public:
|
||||
|
||||
virtual ~PreviewAutoCacher() override;
|
||||
|
||||
RenderTicketPtr GetSingleFrame(const rational& t, bool dry = false);
|
||||
RenderTicketPtr GetSingleFrame(Node *n, const rational& t, bool dry = false);
|
||||
RenderTicketPtr GetSingleFrame(ViewerOutput *viewer, const rational& t, bool dry = false);
|
||||
RenderTicketPtr GetSingleFrame(Node *n, ViewerOutput *viewer, const rational& t, bool dry = false);
|
||||
|
||||
RenderTicketPtr GetRangeOfAudio(TimeRange range);
|
||||
RenderTicketPtr GetRangeOfAudio(ViewerOutput *viewer, TimeRange range);
|
||||
|
||||
void ClearSingleFrameRenders();
|
||||
|
||||
/**
|
||||
* @brief Set the viewer node to auto-cache
|
||||
*/
|
||||
void SetViewerNode(ViewerOutput *viewer_node);
|
||||
void SetProject(Project *project);
|
||||
|
||||
/**
|
||||
* @brief Force a certain range to be cached
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
* times they may want certain non-playhead-related time ranges to be cached (i.e. entire sequence
|
||||
* or in/out range), so that can be set here.
|
||||
*/
|
||||
void ForceCacheRange(const TimeRange& range);
|
||||
void ForceCacheRange(ViewerOutput *context, const TimeRange& range);
|
||||
|
||||
/**
|
||||
* @brief Updates the range of frames to auto-cache
|
||||
@@ -109,9 +109,9 @@ signals:
|
||||
private:
|
||||
void TryRender();
|
||||
|
||||
RenderTicketWatcher *RenderFrame(Node *node, const rational &time, PlaybackCache *cache, bool dry);
|
||||
RenderTicketWatcher *RenderFrame(Node *node, ViewerOutput *context, const rational &time, PlaybackCache *cache, bool dry);
|
||||
|
||||
RenderTicketPtr RenderAudio(Node *node, const TimeRange &range, PlaybackCache *cache);
|
||||
RenderTicketPtr RenderAudio(Node *node, ViewerOutput *context, const TimeRange &range, PlaybackCache *cache);
|
||||
|
||||
void ConnectToNodeCache(Node *node);
|
||||
void DisconnectFromNodeCache(Node *node);
|
||||
@@ -119,13 +119,13 @@ private:
|
||||
void CancelQueuedSingleFrameRender();
|
||||
|
||||
void StartCachingRange(const TimeRange &range, TimeRangeList *range_list, RenderJobTracker *tracker);
|
||||
void StartCachingVideoRange(PlaybackCache *cache, const TimeRange &range);
|
||||
void StartCachingAudioRange(PlaybackCache *cache, const TimeRange &range);
|
||||
void StartCachingVideoRange(ViewerOutput *context, PlaybackCache *cache, const TimeRange &range);
|
||||
void StartCachingAudioRange(ViewerOutput *context, PlaybackCache *cache, const TimeRange &range);
|
||||
|
||||
void VideoInvalidatedFromNode(PlaybackCache *cache, const olive::TimeRange &range);
|
||||
void AudioInvalidatedFromNode(PlaybackCache *cache, const olive::TimeRange &range);
|
||||
void VideoInvalidatedFromNode(ViewerOutput *context, PlaybackCache *cache, const olive::TimeRange &range);
|
||||
void AudioInvalidatedFromNode(ViewerOutput *context, PlaybackCache *cache, const olive::TimeRange &range);
|
||||
|
||||
ViewerOutput* viewer_node_;
|
||||
Project* project_;
|
||||
|
||||
ProjectCopier *copier_;
|
||||
|
||||
@@ -147,11 +147,11 @@ private:
|
||||
QVector<RenderTicketWatcher*> running_video_tasks_;
|
||||
QVector<RenderTicketWatcher*> running_audio_tasks_;
|
||||
|
||||
ViewerOutput* copied_viewer_node_;
|
||||
ColorManager* copied_color_manager_;
|
||||
|
||||
struct VideoJob {
|
||||
Node *node;
|
||||
ViewerOutput *context;
|
||||
PlaybackCache *cache;
|
||||
TimeRange range;
|
||||
TimeRangeListFrameIterator iterator;
|
||||
@@ -163,6 +163,7 @@ private:
|
||||
|
||||
struct AudioJob {
|
||||
Node *node;
|
||||
ViewerOutput *context;
|
||||
PlaybackCache *cache;
|
||||
TimeRange range;
|
||||
};
|
||||
@@ -188,12 +189,12 @@ private slots:
|
||||
/**
|
||||
* @brief Handler for when the NodeGraph reports a video change over a certain time range
|
||||
*/
|
||||
void VideoInvalidatedFromCache(const olive::TimeRange &range);
|
||||
void VideoInvalidatedFromCache(ViewerOutput *context, const olive::TimeRange &range);
|
||||
|
||||
/**
|
||||
* @brief Handler for when the NodeGraph reports a audio change over a certain time range
|
||||
*/
|
||||
void AudioInvalidatedFromCache(const olive::TimeRange &range);
|
||||
void AudioInvalidatedFromCache(ViewerOutput *context, const olive::TimeRange &range);
|
||||
|
||||
void CancelForCache();
|
||||
|
||||
|
||||
@@ -60,6 +60,8 @@ RenderManager::RenderManager(QObject *parent) :
|
||||
for (size_t i=0; i<waveform_threads_.size(); i++) {
|
||||
waveform_threads_[i] = CreateThread();
|
||||
}
|
||||
|
||||
auto_cacher_ = new PreviewAutoCacher(this);
|
||||
}
|
||||
|
||||
decoder_clear_timer_ = new QTimer(this);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "node/graph.h"
|
||||
#include "node/output/viewer/viewer.h"
|
||||
#include "node/traverser.h"
|
||||
#include "render/previewautocacher.h"
|
||||
#include "render/renderer.h"
|
||||
#include "render/renderticket.h"
|
||||
#include "rendercache.h"
|
||||
@@ -200,6 +201,16 @@ public:
|
||||
return backend_;
|
||||
}
|
||||
|
||||
PreviewAutoCacher *GetCacher() const
|
||||
{
|
||||
return auto_cacher_;
|
||||
}
|
||||
|
||||
void SetProject(Project *p)
|
||||
{
|
||||
auto_cacher_->SetProject(p);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetAggressiveGarbageCollection(bool enabled);
|
||||
|
||||
@@ -238,6 +249,8 @@ private:
|
||||
|
||||
std::list<RenderThread *> render_threads_;
|
||||
|
||||
PreviewAutoCacher *auto_cacher_;
|
||||
|
||||
private slots:
|
||||
void ClearOldDecoders();
|
||||
|
||||
|
||||
@@ -144,8 +144,8 @@ ViewerWidget::ViewerWidget(ViewerDisplayWidget *display, QWidget *parent) :
|
||||
|
||||
instances_.append(this);
|
||||
|
||||
auto_cacher_ = new PreviewAutoCacher(this);
|
||||
connect(display_widget_, &ViewerDisplayWidget::ColorProcessorChanged, auto_cacher_, &PreviewAutoCacher::SetDisplayColorProcessor);
|
||||
qDebug() << "FIXME: No signal connected between VDW and Cacher";
|
||||
//connect(display_widget_, &ViewerDisplayWidget::ColorProcessorChanged, RenderManager::instance()->GetCacher(), &PreviewAutoCacher::SetDisplayColorProcessor);
|
||||
|
||||
UpdateWaveformViewFromMode();
|
||||
|
||||
@@ -195,7 +195,7 @@ void ViewerWidget::TimeChangedEvent(const rational &time)
|
||||
}
|
||||
|
||||
// Send time to auto-cacher
|
||||
auto_cacher_->SetPlayhead(time);
|
||||
RenderManager::instance()->GetCacher()->SetPlayhead(time);
|
||||
|
||||
last_time_ = time;
|
||||
}
|
||||
@@ -290,7 +290,6 @@ void ViewerWidget::DisconnectNodeEvent(ViewerOutput *n)
|
||||
|
||||
void ViewerWidget::ConnectedNodeChangeEvent(ViewerOutput *n)
|
||||
{
|
||||
auto_cacher_->SetViewerNode(n);
|
||||
display_widget_->SetSubtitleTracks(dynamic_cast<Sequence*>(n));
|
||||
}
|
||||
|
||||
@@ -318,6 +317,11 @@ void ViewerWidget::resizeEvent(QResizeEvent *event)
|
||||
UpdateMinimumScale();
|
||||
}
|
||||
|
||||
RenderTicketPtr ViewerWidget::GetSingleFrame(const rational &t, bool dry)
|
||||
{
|
||||
return RenderManager::instance()->GetCacher()->GetSingleFrame(this->GetConnectedNode(), t, dry);
|
||||
}
|
||||
|
||||
void ViewerWidget::TogglePlayPause()
|
||||
{
|
||||
if (IsPlaying()) {
|
||||
@@ -394,13 +398,13 @@ void ViewerWidget::SetFullScreen(QScreen *screen)
|
||||
|
||||
void ViewerWidget::CacheEntireSequence()
|
||||
{
|
||||
auto_cacher_->ForceCacheRange(TimeRange(0, GetConnectedNode()->GetVideoLength()));
|
||||
RenderManager::instance()->GetCacher()->ForceCacheRange(GetConnectedNode(), TimeRange(0, GetConnectedNode()->GetVideoLength()));
|
||||
}
|
||||
|
||||
void ViewerWidget::CacheSequenceInOut()
|
||||
{
|
||||
if (GetConnectedNode() && GetConnectedNode()->GetWorkArea()->enabled()) {
|
||||
auto_cacher_->ForceCacheRange(GetConnectedNode()->GetWorkArea()->range());
|
||||
RenderManager::instance()->GetCacher()->ForceCacheRange(GetConnectedNode(), GetConnectedNode()->GetWorkArea()->range());
|
||||
} else {
|
||||
QMessageBox::warning(this,
|
||||
tr("Error"),
|
||||
@@ -480,7 +484,7 @@ void ViewerWidget::SetEmptyImage()
|
||||
|
||||
void ViewerWidget::UpdateAutoCacher()
|
||||
{
|
||||
auto_cacher_->SetPlayhead(GetConnectedNode()->GetPlayhead());
|
||||
RenderManager::instance()->GetCacher()->SetPlayhead(GetConnectedNode()->GetPlayhead());
|
||||
}
|
||||
|
||||
void ViewerWidget::DecrementPrequeuedAudio()
|
||||
@@ -693,9 +697,10 @@ void ViewerWidget::DetectMulticamNode(const rational &time)
|
||||
if (multicam_panel_) {
|
||||
multicam_panel_->SetMulticamNode(GetConnectedNode(), multicam, clip, time);
|
||||
}
|
||||
auto_cacher()->SetMulticamNode(multicam);
|
||||
// FIXME: Really dirty
|
||||
RenderManager::instance()->GetCacher()->SetMulticamNode(multicam);
|
||||
} else {
|
||||
auto_cacher()->SetMulticamNode(nullptr);
|
||||
RenderManager::instance()->GetCacher()->SetMulticamNode(nullptr);
|
||||
if (multicam_panel_) {
|
||||
multicam_panel_->SetMulticamNode(nullptr, nullptr, nullptr, time);
|
||||
}
|
||||
@@ -740,7 +745,7 @@ void ViewerWidget::QueueNextAudioBuffer()
|
||||
RenderTicketWatcher *watcher = new RenderTicketWatcher(this);
|
||||
connect(watcher, &RenderTicketWatcher::Finished, this, &ViewerWidget::ReceivedAudioBufferForPlayback);
|
||||
audio_playback_queue_.push_back(watcher);
|
||||
watcher->SetTicket(auto_cacher_->GetRangeOfAudio(TimeRange(audio_playback_queue_time_, queue_end)));
|
||||
watcher->SetTicket(RenderManager::instance()->GetCacher()->GetRangeOfAudio(GetConnectedNode(), TimeRange(audio_playback_queue_time_, queue_end)));
|
||||
|
||||
audio_playback_queue_time_ = queue_end;
|
||||
}
|
||||
@@ -857,7 +862,7 @@ void ViewerWidget::ForceRequeueFromCurrentTime()
|
||||
// Allow half a second for requeue to complete
|
||||
static const rational kRequeueWaitTime(1);
|
||||
|
||||
auto_cacher_->ClearSingleFrameRenders();
|
||||
RenderManager::instance()->GetCacher()->ClearSingleFrameRenders();
|
||||
queue_watchers_.clear();
|
||||
int queue = DeterminePlaybackQueueSize();
|
||||
playback_queue_next_frame_ = GetTimestamp() + playback_speed_ * Timecode::time_to_timestamp(kRequeueWaitTime, timebase(), Timecode::kFloor);;
|
||||
@@ -896,7 +901,7 @@ void ViewerWidget::UpdateTextureFromNode()
|
||||
nonqueue_watchers_.append(watcher);
|
||||
|
||||
// Clear queue because we want this frame more than any others
|
||||
auto_cacher_->ClearSingleFrameRenders();
|
||||
RenderManager::instance()->GetCacher()->ClearSingleFrameRenders();
|
||||
|
||||
DetectMulticamNode(time);
|
||||
|
||||
@@ -928,8 +933,8 @@ void ViewerWidget::PlayInternal(int speed, bool in_to_out_only)
|
||||
if (viewer != this) {
|
||||
viewer->PauseInternal();
|
||||
}
|
||||
viewer->auto_cacher_->SetThumbnailsPaused(true);
|
||||
}
|
||||
RenderManager::instance()->GetCacher()->SetThumbnailsPaused(true);
|
||||
|
||||
RenderManager::instance()->SetAggressiveGarbageCollection(true);
|
||||
|
||||
@@ -1016,7 +1021,7 @@ void ViewerWidget::PauseInternal()
|
||||
|
||||
qDeleteAll(queue_watchers_);
|
||||
queue_watchers_.clear();
|
||||
auto_cacher_->ClearSingleFrameRenders();
|
||||
RenderManager::instance()->GetCacher()->ClearSingleFrameRenders();
|
||||
|
||||
playback_backup_timer_.stop();
|
||||
|
||||
@@ -1029,9 +1034,7 @@ void ViewerWidget::PauseInternal()
|
||||
audio_playback_queue_.clear();
|
||||
UpdateAudioProcessor();
|
||||
|
||||
foreach (ViewerWidget* viewer, instances_) {
|
||||
viewer->auto_cacher_->SetThumbnailsPaused(false);
|
||||
}
|
||||
RenderManager::instance()->GetCacher()->SetThumbnailsPaused(false);
|
||||
|
||||
UpdateTextureFromNode();
|
||||
|
||||
@@ -1064,7 +1067,7 @@ void ViewerWidget::PushScrubbedAudio()
|
||||
RenderTicketWatcher *watcher = new RenderTicketWatcher();
|
||||
connect(watcher, &RenderTicketWatcher::Finished, this, &ViewerWidget::ReceivedAudioBufferForScrubbing);
|
||||
audio_scrub_watchers_.push_back(watcher);
|
||||
watcher->SetTicket(auto_cacher_->GetRangeOfAudio(TimeRange(GetConnectedNode()->GetPlayhead(), GetConnectedNode()->GetPlayhead() + interval)));
|
||||
watcher->SetTicket(RenderManager::instance()->GetCacher()->GetRangeOfAudio(GetConnectedNode(), TimeRange(GetConnectedNode()->GetPlayhead(), GetConnectedNode()->GetPlayhead() + interval)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,8 +103,6 @@ public:
|
||||
enable_audio_scrubbing_ = e;
|
||||
}
|
||||
|
||||
PreviewAutoCacher *GetCacher() const { return auto_cacher_; }
|
||||
|
||||
void AddPlaybackDevice(ViewerDisplayWidget *vw)
|
||||
{
|
||||
playback_devices_.push_back(vw);
|
||||
@@ -218,12 +216,7 @@ protected:
|
||||
ignore_scrub_++;
|
||||
}
|
||||
|
||||
virtual RenderTicketPtr GetSingleFrame(const rational &t, bool dry = false)
|
||||
{
|
||||
return auto_cacher_->GetSingleFrame(t, dry);
|
||||
}
|
||||
|
||||
PreviewAutoCacher *auto_cacher() const { return auto_cacher_; }
|
||||
RenderTicketPtr GetSingleFrame(const rational &t, bool dry = false);
|
||||
|
||||
private:
|
||||
int64_t GetTimestamp() const
|
||||
@@ -319,8 +312,6 @@ private:
|
||||
int prequeue_length_;
|
||||
int prequeue_count_;
|
||||
|
||||
PreviewAutoCacher *auto_cacher_;
|
||||
|
||||
QVector<RenderTicketWatcher*> queue_watchers_;
|
||||
|
||||
std::list<RenderTicketWatcher*> audio_playback_queue_;
|
||||
|
||||
Reference in New Issue
Block a user