diff --git a/app/node/output/track/track.h b/app/node/output/track/track.h index 85c995870..87c2c75a3 100644 --- a/app/node/output/track/track.h +++ b/app/node/output/track/track.h @@ -199,6 +199,11 @@ public: return waveform_; } + QMutex* waveform_lock() + { + return &waveform_lock_; + } + public slots: void SetTrackName(const QString& name); @@ -276,6 +281,7 @@ private: rational queued_length_; AudioVisualWaveform waveform_; + QMutex waveform_lock_; private slots: void BlockConnected(NodeEdgePtr edge); diff --git a/app/render/backend/renderbackend.cpp b/app/render/backend/renderbackend.cpp index 3cd726bf9..69a0feead 100644 --- a/app/render/backend/renderbackend.cpp +++ b/app/render/backend/renderbackend.cpp @@ -34,7 +34,8 @@ OLIVE_NAMESPACE_ENTER RenderBackend::RenderBackend(QObject *parent) : QObject(parent), viewer_node_(nullptr), - update_with_graph_(false) + update_with_graph_(false), + preview_job_time_(0) { } @@ -270,7 +271,6 @@ void RenderBackend::RunNextJob() RenderWorker* worker = CreateNewWorker(); connect(worker, &RenderWorker::FinishedJob, this, &RenderBackend::WorkerFinished); - connect(worker, &RenderWorker::WaveformGenerated, this, &RenderBackend::WorkerGeneratedWaveform); workers_.replace(i, {worker, false}); } @@ -288,7 +288,9 @@ void RenderBackend::RunNextJob() worker->SetVideoParams(video_params_); worker->SetAudioParams(audio_params_); worker->SetVideoDownloadMatrix(video_download_matrix_); - worker->SetGeneratePreviews(generate_previews_); + if (preview_job_time_) { + worker->EnablePreviewGeneration(viewer_node_->audio_playback_cache(), preview_job_time_); + } worker->SetCopyMap(©_map_); RenderTicketPtr ticket = render_queue_.front(); @@ -351,37 +353,6 @@ void RenderBackend::WorkerFinished() } } -void RenderBackend::WorkerGeneratedWaveform(const TrackOutput *copied_track, const AudioVisualWaveform& samples, const rational &r) -{ - if (!viewer_node_) { - return; - } - - TrackOutput* track = nullptr; - - /* - if (!viewer_node_->audio_playback_cache()->JobIsCurrent(r)) { - return; - } - */ - - QHash::const_iterator i; - for (i=copy_map_.constBegin(); i!=copy_map_.constEnd(); i++) { - if (i.value() == copied_track) { - track = static_cast(i.key()); - break; - } - } - - if (track) { - track->waveform().set_channel_count(audio_params_.channel_count()); - track->waveform().OverwriteSums(samples, r); - emit track->PreviewChanged(); - } else { - qDebug() << "Failed to find track"; - } -} - void RenderBackend::CopyNodeInputValue(NodeInput *input) { // Find our copy of this parameter diff --git a/app/render/backend/renderbackend.h b/app/render/backend/renderbackend.h index 6812b6db2..b80105661 100644 --- a/app/render/backend/renderbackend.h +++ b/app/render/backend/renderbackend.h @@ -50,9 +50,9 @@ public: update_with_graph_ = e; } - void SetGeneratePreviews(bool e) + void EnablePreviewGeneration(qint64 job_time) { - generate_previews_ = e; + preview_job_time_ = job_time; } void ClearVideoQueue(); @@ -121,13 +121,11 @@ private: bool update_with_graph_; - bool generate_previews_; + qint64 preview_job_time_; private slots: void WorkerFinished(); - void WorkerGeneratedWaveform(const OLIVE_NAMESPACE::TrackOutput* copied_track, const OLIVE_NAMESPACE::AudioVisualWaveform& samples, const OLIVE_NAMESPACE::rational& start); - }; OLIVE_NAMESPACE_EXIT diff --git a/app/render/backend/renderworker.cpp b/app/render/backend/renderworker.cpp index a0c3aa762..472929dc5 100644 --- a/app/render/backend/renderworker.cpp +++ b/app/render/backend/renderworker.cpp @@ -35,7 +35,7 @@ RenderWorker::RenderWorker(RenderBackend* parent) : parent_(parent), available_(true), audio_mode_is_preview_(false), - generate_previews_(false) + preview_cache_(nullptr) { } @@ -127,12 +127,41 @@ NodeValueTable RenderWorker::GenerateBlockTable(const TrackOutput *track, const NodeValueTable::Merge({merged_table, table}); } - if (generate_previews_) { - // Generate visual waveform in this background thread - AudioVisualWaveform visual_waveform; - visual_waveform.set_channel_count(audio_params_.channel_count()); - visual_waveform.AddSamples(block_range_buffer, audio_params_.sample_rate()); - emit WaveformGenerated(track, visual_waveform, range.in()); + if (preview_cache_) { + // Find original track object + TrackOutput* original_track = nullptr; + + QList valid_ranges = preview_cache_->GetValidRanges(range, preview_job_time_); + if (!valid_ranges.isEmpty()) { + qDebug() << "Worker generated valid waveform for" << range << preview_cache_; + + QHash::const_iterator i; + for (i=copy_map_->constBegin(); i!=copy_map_->constEnd(); i++) { + if (i.value() == track) { + original_track = static_cast(i.key()); + break; + } + } + + // Generate visual waveform in this background thread + if (original_track) { + AudioVisualWaveform visual_waveform; + visual_waveform.set_channel_count(audio_params_.channel_count()); + visual_waveform.AddSamples(block_range_buffer, audio_params_.sample_rate()); + + original_track->waveform_lock()->lock(); + + original_track->waveform().set_channel_count(audio_params_.channel_count()); + + foreach (const TimeRange& r, valid_ranges) { + original_track->waveform().OverwriteSums(visual_waveform, r.in(), r.in() - range.in(), r.length()); + } + + original_track->waveform_lock()->unlock(); + + emit original_track->PreviewChanged(); + } + } } merged_table.Push(NodeParam::kSamples, QVariant::fromValue(block_range_buffer)); diff --git a/app/render/backend/renderworker.h b/app/render/backend/renderworker.h index 8ebc3d8f3..1b96d2d90 100644 --- a/app/render/backend/renderworker.h +++ b/app/render/backend/renderworker.h @@ -73,9 +73,10 @@ public: copy_map_ = copy_map; } - void SetGeneratePreviews(bool e) + void EnablePreviewGeneration(AudioPlaybackCache* cache, qint64 job_time) { - generate_previews_ = e; + preview_cache_ = cache; + preview_job_time_ = job_time; } /** @@ -132,7 +133,7 @@ signals: void FinishedJob(); - void WaveformGenerated(const OLIVE_NAMESPACE::TrackOutput* track, const OLIVE_NAMESPACE::AudioVisualWaveform& samples, const OLIVE_NAMESPACE::rational& start); + void WaveformGenerated(OLIVE_NAMESPACE::TrackOutput* track, OLIVE_NAMESPACE::AudioVisualWaveform samples, OLIVE_NAMESPACE::TimeRange start); private: NodeValue GetDataFromStream(StreamPtr stream, const TimeRange& input_time); @@ -164,7 +165,8 @@ private: bool audio_mode_is_preview_; - bool generate_previews_; + AudioPlaybackCache* preview_cache_; + qint64 preview_job_time_; QHash* copy_map_; diff --git a/app/task/cache/cache.cpp b/app/task/cache/cache.cpp index ed9df21c6..ab2b0415d 100644 --- a/app/task/cache/cache.cpp +++ b/app/task/cache/cache.cpp @@ -33,7 +33,7 @@ CacheTask::CacheTask(ViewerOutput* viewer, const VideoRenderingParams& vparams, { SetTitle(tr("Caching \"%1\"").arg(viewer->media_name())); - backend()->SetGeneratePreviews(true); + backend()->EnablePreviewGeneration(job_time()); } bool CacheTask::Run() diff --git a/app/widget/timelinewidget/view/timelineviewblockitem.cpp b/app/widget/timelinewidget/view/timelineviewblockitem.cpp index 8195fa4b7..74bbc66bf 100644 --- a/app/widget/timelinewidget/view/timelineviewblockitem.cpp +++ b/app/widget/timelinewidget/view/timelineviewblockitem.cpp @@ -99,6 +99,8 @@ void TimelineViewBlockItem::paint(QPainter *painter, const QStyleOptionGraphicsI painter->setPen(QColor(64, 64, 64)); TrackOutput* track = TrackOutput::TrackFromBlock(block_); if (track) { + QMutexLocker locker(track->waveform_lock()); + AudioVisualWaveform::DrawWaveform(painter, rect().toRect(), this->GetScale(),