From d6483916acd3f3e2a6f47384b97b28007a6fcdef Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Wed, 16 Oct 2019 13:51:56 +1100 Subject: [PATCH] base audio renderer classes created --- app/audio/CMakeLists.txt | 3 +- app/audio/audiomanager.cpp | 12 +- app/audio/audiomanager.h | 2 +- app/{render => audio}/sampleformat.h | 0 app/dialog/sequence/sequence.cpp | 2 +- app/node/blend/alphaover/alphaover.cpp | 4 +- app/node/block/clip/clip.cpp | 2 +- app/node/color/opacity/opacity.cpp | 4 +- app/node/input/media/media.cpp | 4 +- app/node/processor/CMakeLists.txt | 3 +- .../CMakeLists.txt | 16 +- .../processor/audiorenderer/audiorenderer.cpp | 342 ++++++++++++++++++ .../processor/audiorenderer/audiorenderer.h | 177 +++++++++ .../audiorenderer/audiorendererparams.cpp | 23 ++ .../audiorenderer/audiorendererparams.h | 28 ++ .../audiorenderer/audiorendererthread.cpp | 23 ++ .../audiorenderer/audiorendererthread.h | 26 ++ .../audiorenderer/audiorendererthreadbase.cpp | 69 ++++ .../audiorenderer/audiorendererthreadbase.h | 65 ++++ .../processor/videorenderer/CMakeLists.txt | 28 ++ .../videorenderer.cpp} | 72 ++-- .../videorenderer.h} | 10 +- .../videorendererdownloadthread.cpp} | 22 +- .../videorendererdownloadthread.h} | 8 +- .../videorendererprocessthread.cpp} | 8 +- .../videorendererprocessthread.h} | 10 +- .../videorendererthreadbase.cpp} | 12 +- .../videorendererthreadbase.h} | 6 +- .../videorendermanager.cpp} | 0 .../videorendermanager.h} | 0 app/project/item/sequence/sequence.cpp | 26 +- app/project/item/sequence/sequence.h | 4 +- app/render/CMakeLists.txt | 1 - 33 files changed, 896 insertions(+), 116 deletions(-) rename app/{render => audio}/sampleformat.h (100%) rename app/node/processor/{renderer => audiorenderer}/CMakeLists.txt (63%) create mode 100644 app/node/processor/audiorenderer/audiorenderer.cpp create mode 100644 app/node/processor/audiorenderer/audiorenderer.h create mode 100644 app/node/processor/audiorenderer/audiorendererparams.cpp create mode 100644 app/node/processor/audiorenderer/audiorendererparams.h create mode 100644 app/node/processor/audiorenderer/audiorendererthread.cpp create mode 100644 app/node/processor/audiorenderer/audiorendererthread.h create mode 100644 app/node/processor/audiorenderer/audiorendererthreadbase.cpp create mode 100644 app/node/processor/audiorenderer/audiorendererthreadbase.h create mode 100644 app/node/processor/videorenderer/CMakeLists.txt rename app/node/processor/{renderer/renderer.cpp => videorenderer/videorenderer.cpp} (84%) rename app/node/processor/{renderer/renderer.h => videorenderer/videorenderer.h} (96%) rename app/node/processor/{renderer/rendererdownloadthread.cpp => videorenderer/videorendererdownloadthread.cpp} (79%) rename app/node/processor/{renderer/rendererdownloadthread.h => videorenderer/videorendererdownloadthread.h} (78%) rename app/node/processor/{renderer/rendererprocessthread.cpp => videorenderer/videorendererprocessthread.cpp} (94%) rename app/node/processor/{renderer/rendererprocessthread.h => videorenderer/videorendererprocessthread.h} (88%) rename app/node/processor/{renderer/rendererthreadbase.cpp => videorenderer/videorendererthreadbase.cpp} (78%) rename app/node/processor/{renderer/rendererthreadbase.h => videorenderer/videorendererthreadbase.h} (90%) rename app/node/processor/{renderer/rendermanager.cpp => videorenderer/videorendermanager.cpp} (100%) rename app/node/processor/{renderer/rendermanager.h => videorenderer/videorendermanager.h} (100%) diff --git a/app/audio/CMakeLists.txt b/app/audio/CMakeLists.txt index 247a727fe..4feb7d947 100644 --- a/app/audio/CMakeLists.txt +++ b/app/audio/CMakeLists.txt @@ -18,9 +18,8 @@ set(OLIVE_SOURCES ${OLIVE_SOURCES} audio/audiohybriddevice.h audio/audiohybriddevice.cpp - audio/audiolayouts.h - audio/audiolayouts.cpp audio/audiomanager.h audio/audiomanager.cpp + audio/sampleformat.h PARENT_SCOPE ) diff --git a/app/audio/audiomanager.cpp b/app/audio/audiomanager.cpp index c3755c6d9..10f7cf542 100644 --- a/app/audio/audiomanager.cpp +++ b/app/audio/audiomanager.cpp @@ -22,24 +22,24 @@ #include "config/config.h" -AudioManager* AudioManager::audio_ = nullptr; +AudioManager* AudioManager::instance_ = nullptr; void AudioManager::CreateInstance() { - if (audio_ == nullptr) { - audio_ = new AudioManager(); + if (instance_ == nullptr) { + instance_ = new AudioManager(); } } void AudioManager::DestroyInstance() { - delete audio_; - audio_ = nullptr; + delete instance_; + instance_ = nullptr; } AudioManager *AudioManager::instance() { - return audio_; + return instance_; } void AudioManager::RefreshDevices() diff --git a/app/audio/audiomanager.h b/app/audio/audiomanager.h index 60f3b1cae..9d16ca6d0 100644 --- a/app/audio/audiomanager.h +++ b/app/audio/audiomanager.h @@ -95,7 +95,7 @@ private: QList output_devices_; - static AudioManager* audio_; + static AudioManager* instance_; AudioHybridDevice output_manager_; diff --git a/app/render/sampleformat.h b/app/audio/sampleformat.h similarity index 100% rename from app/render/sampleformat.h rename to app/audio/sampleformat.h diff --git a/app/dialog/sequence/sequence.cpp b/app/dialog/sequence/sequence.cpp index 7ab988796..da1f9c13d 100644 --- a/app/dialog/sequence/sequence.cpp +++ b/app/dialog/sequence/sequence.cpp @@ -233,7 +233,7 @@ void SequenceDialog::AddChannelLayout(int layout) layout_name = tr("7.1"); break; default: - layout_name = tr("Unknown (%1)").arg(layout); + layout_name = tr("Unknown (0x%1)").arg(layout, 1, 16); } audio_channels_field_->addItem(layout_name, layout); diff --git a/app/node/blend/alphaover/alphaover.cpp b/app/node/blend/alphaover/alphaover.cpp index d8654f591..d29d1e717 100644 --- a/app/node/blend/alphaover/alphaover.cpp +++ b/app/node/blend/alphaover/alphaover.cpp @@ -20,7 +20,7 @@ #include "alphaover.h" -#include "node/processor/renderer/renderer.h" +#include "node/processor/videorenderer/videorenderer.h" #include "render/gl/functions.h" #include "render/rendertexture.h" #include "render/gl/shadergenerators.h" @@ -52,7 +52,7 @@ void AlphaOverBlend::Release() QVariant AlphaOverBlend::Value(NodeOutput *param, const rational &time) { // Find the current Renderer instance - RenderInstance* renderer = RendererProcessor::CurrentInstance(); + RenderInstance* renderer = VideoRendererProcessor::CurrentInstance(); // If nothing is available, don't return a texture if (renderer == nullptr) { diff --git a/app/node/block/clip/clip.cpp b/app/node/block/clip/clip.cpp index 37b802c6f..112d1faad 100644 --- a/app/node/block/clip/clip.cpp +++ b/app/node/block/clip/clip.cpp @@ -20,7 +20,7 @@ #include "clip.h" -#include "node/processor/renderer/renderer.h" +#include "node/processor/videorenderer/videorenderer.h" ClipBlock::ClipBlock() { diff --git a/app/node/color/opacity/opacity.cpp b/app/node/color/opacity/opacity.cpp index 7573d9d93..568259aaf 100644 --- a/app/node/color/opacity/opacity.cpp +++ b/app/node/color/opacity/opacity.cpp @@ -20,7 +20,7 @@ #include "opacity.h" -#include "node/processor/renderer/renderer.h" +#include "node/processor/videorenderer/videorenderer.h" #include "render/gl/functions.h" #include "render/rendertexture.h" @@ -65,7 +65,7 @@ QString OpacityNode::id() QVariant OpacityNode::Value(NodeOutput *output, const rational &time) { // Find the current Renderer instance - RenderInstance* renderer = RendererProcessor::CurrentInstance(); + RenderInstance* renderer = VideoRendererProcessor::CurrentInstance(); // If nothing is available, don't return a texture if (renderer == nullptr) { diff --git a/app/node/input/media/media.cpp b/app/node/input/media/media.cpp index c5d62d207..c408f169c 100644 --- a/app/node/input/media/media.cpp +++ b/app/node/input/media/media.cpp @@ -25,7 +25,7 @@ #include "core.h" #include "decoder/ffmpeg/ffmpegdecoder.h" -#include "node/processor/renderer/renderer.h" +#include "node/processor/videorenderer/videorenderer.h" #include "project/item/footage/footage.h" #include "render/gl/shadergenerators.h" #include "render/gl/functions.h" @@ -136,7 +136,7 @@ QVariant MediaInput::Value(NodeOutput *output, const rational &time) if (output == texture_output_) { // Find the current Renderer instance - RenderInstance* renderer = RendererProcessor::CurrentInstance(); + RenderInstance* renderer = VideoRendererProcessor::CurrentInstance(); // If nothing is available, don't return a texture if (renderer == nullptr) { diff --git a/app/node/processor/CMakeLists.txt b/app/node/processor/CMakeLists.txt index 090aa2040..285103c0e 100644 --- a/app/node/processor/CMakeLists.txt +++ b/app/node/processor/CMakeLists.txt @@ -14,7 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -add_subdirectory(renderer) +add_subdirectory(audiorenderer) +add_subdirectory(videorenderer) set(OLIVE_SOURCES ${OLIVE_SOURCES} diff --git a/app/node/processor/renderer/CMakeLists.txt b/app/node/processor/audiorenderer/CMakeLists.txt similarity index 63% rename from app/node/processor/renderer/CMakeLists.txt rename to app/node/processor/audiorenderer/CMakeLists.txt index fd148df72..60057f8d2 100644 --- a/app/node/processor/renderer/CMakeLists.txt +++ b/app/node/processor/audiorenderer/CMakeLists.txt @@ -16,13 +16,13 @@ set(OLIVE_SOURCES ${OLIVE_SOURCES} - node/processor/renderer/renderer.h - node/processor/renderer/renderer.cpp - node/processor/renderer/rendererthreadbase.h - node/processor/renderer/rendererthreadbase.cpp - node/processor/renderer/rendererdownloadthread.h - node/processor/renderer/rendererdownloadthread.cpp - node/processor/renderer/rendererprocessthread.h - node/processor/renderer/rendererprocessthread.cpp + node/processor/audiorenderer/audiorenderer.h + node/processor/audiorenderer/audiorenderer.cpp + node/processor/audiorenderer/audiorendererparams.h + node/processor/audiorenderer/audiorendererparams.cpp + node/processor/audiorenderer/audiorendererthread.h + node/processor/audiorenderer/audiorendererthread.cpp + node/processor/audiorenderer/audiorendererthreadbase.h + node/processor/audiorenderer/audiorendererthreadbase.cpp PARENT_SCOPE ) diff --git a/app/node/processor/audiorenderer/audiorenderer.cpp b/app/node/processor/audiorenderer/audiorenderer.cpp new file mode 100644 index 000000000..d30138840 --- /dev/null +++ b/app/node/processor/audiorenderer/audiorenderer.cpp @@ -0,0 +1,342 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#include "audiorenderer.h" + +#include +#include +#include +#include +#include +#include + +#include "common/filefunctions.h" +#include "render/pixelservice.h" + +AudioRendererProcessor::AudioRendererProcessor() : + started_(false), + caching_(false), + starting_(false) +{ + texture_input_ = new NodeInput("tex_in"); + texture_input_->add_data_input(NodeInput::kTexture); + AddParameter(texture_input_); + + length_input_ = new NodeInput("length_in"); + length_input_->add_data_input(NodeInput::kRational); + AddParameter(length_input_); + + texture_output_ = new NodeOutput("tex_out"); + texture_output_->set_data_type(NodeInput::kTexture); + AddParameter(texture_output_); +} + +QString AudioRendererProcessor::Name() +{ + return tr("Audio Renderer"); +} + +QString AudioRendererProcessor::Category() +{ + return tr("Processor"); +} + +QString AudioRendererProcessor::Description() +{ + return tr("A multi-threaded PCM audio renderer."); +} + +QString AudioRendererProcessor::id() +{ + return "org.olivevideoeditor.Olive.rendererneptune"; +} + +void AudioRendererProcessor::SetCacheName(const QString &s) +{ + cache_name_ = s; + cache_time_ = QDateTime::currentMSecsSinceEpoch(); + + GenerateCacheIDInternal(); +} + +QVariant AudioRendererProcessor::Value(NodeOutput* output, const rational& time) +{ + Q_UNUSED(output) + Q_UNUSED(time) + + /*if (output == texture_output_) { + if (!texture_input_->IsConnected()) { + // Nothing is connected - nothing to show or render + return 0; + } + + if (cache_id_.isEmpty()) { + qWarning() << "RendererProcessor has no cache ID"; + return 0; + } + + if (timebase_.isNull()) { + qWarning() << "RendererProcessor has no timebase"; + return 0; + } + + // Find frame in map + if (time_hash_map_.contains(time)) { + QString fn = CachePathName(time_hash_map_[time]); + + if (QFileInfo::exists(fn)) { + auto in = OIIO::ImageInput::open(fn.toStdString()); + + if (in) { + in->read_image(PixelService::GetPixelFormatInfo(format_).oiio_desc, cache_frame_load_buffer_.data()); + + in->close(); + + master_texture_->Upload(cache_frame_load_buffer_.data()); + + return QVariant::fromValue(master_texture_); + } else { + qWarning() << "OIIO Error:" << OIIO::geterror().c_str(); + } + } + } + }*/ + + return 0; +} + +void AudioRendererProcessor::Release() +{ + Stop(); +} + +void AudioRendererProcessor::InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from) +{ + Q_UNUSED(from) + + if (timebase_.isNull()) { + return; + } + + //ClearCachedValuesInParameters(start_range, end_range); + texture_input_->ClearCachedValue(); + length_input_->ClearCachedValue(); + + // Adjust range to min/max values + rational start_range_adj = qMax(rational(0), start_range); + rational end_range_adj = qMin(length_input()->get_value(0).value(), end_range); + + qDebug() << "Cache invalidated between" + << start_range_adj.toDouble() + << "and" + << end_range_adj.toDouble(); + + // Snap start_range to timebase + double start_range_dbl = start_range_adj.toDouble(); + double start_range_numf = start_range_dbl * static_cast(timebase_.denominator()); + int64_t start_range_numround = qFloor(start_range_numf/static_cast(timebase_.numerator())) * timebase_.numerator(); + rational true_start_range(start_range_numround, timebase_.denominator()); + + for (rational r=true_start_range;r<=end_range_adj;r+=timebase_) { + // Try to order the queue from closest to the playhead to furthest + rational last_time = texture_output()->LastRequestedTime(); + + rational diff = r - last_time; + + if (diff < 0) { + // FIXME: Hardcoded number + // If the number is before the playhead, we still prioritize its closeness but not nearly as much (5:1 in this + // example) + diff = qAbs(diff) * 5; + } + + bool contains = false; + bool added = false; + QLinkedList::iterator insert_iterator; + + for (QLinkedList::iterator i = cache_queue_.begin();i != cache_queue_.end();i++) { + rational compare = *i; + + if (!added) { + rational compare_diff = compare - last_time; + + if (compare_diff > diff) { + insert_iterator = i; + added = true; + } + } + + if (compare == r) { + contains = true; + break; + } + } + + if (!contains) { + if (added) { + cache_queue_.insert(insert_iterator, r); + } else { + cache_queue_.append(r); + } + } + } + + CacheNext(); +} + +void AudioRendererProcessor::SetTimebase(const rational &timebase) +{ + timebase_ = timebase; + timebase_dbl_ = timebase_.toDouble(); +} + +void AudioRendererProcessor::SetParameters(const int &sample_rate, + const uint64_t &channel_layout, + const olive::SampleFormat &format) +{ + // Since we're changing parameters, all the existing threads are invalid and must be removed. They will start again + // next time this Node has to process anything. + Stop(); + + // Set new parameters + sample_rate_ = sample_rate; + channel_layout_ = channel_layout; + format_ = format; + + // Regenerate the cache ID + GenerateCacheIDInternal(); +} + +void AudioRendererProcessor::Start() +{ + if (started_) { + return; + } + + int background_thread_count = QThread::idealThreadCount(); + + threads_.resize(background_thread_count); + + for (int i=0;i(sample_rate_, channel_layout_, format_); + threads_[i]->StartThread(QThread::LowPriority); + + // Ensure this connection is "Queued" so that it always runs in this object's threaded rather than any of the + // other threads + connect(threads_.at(i).get(), + SIGNAL(RequestSibling(NodeDependency)), + this, + SLOT(ThreadRequestSibling(NodeDependency)), + Qt::QueuedConnection); + } + + // Connect first thread (master thread) to the callback + connect(threads_.first().get(), + SIGNAL(CachedFrame(RenderTexturePtr, const rational&, const QByteArray&)), + this, + SLOT(ThreadCallback(RenderTexturePtr, const rational&, const QByteArray&)), + Qt::QueuedConnection); + connect(threads_.first().get(), + SIGNAL(FrameSkipped(const rational&, const QByteArray&)), + this, + SLOT(ThreadSkippedFrame(const rational&, const QByteArray&)), + Qt::QueuedConnection); + + started_ = true; +} + +void AudioRendererProcessor::Stop() +{ + if (!started_) { + return; + } + + started_ = false; + + foreach (AudioRendererThreadPtr process_thread, threads_) { + process_thread->Cancel(); + } + threads_.clear(); +} + +void AudioRendererProcessor::GenerateCacheIDInternal() +{ + if (cache_name_.isEmpty() || sample_rate_ == 0 || channel_layout_ == 0) { + return; + } + + // Generate an ID that is more or less guaranteed to be unique to this Sequence + QCryptographicHash hash(QCryptographicHash::Sha1); + hash.addData(cache_name_.toUtf8()); + hash.addData(QString::number(cache_time_).toUtf8()); + hash.addData(QString::number(sample_rate_).toUtf8()); + hash.addData(QString::number(channel_layout_).toUtf8()); + hash.addData(QString::number(format_).toUtf8()); + + QByteArray bytes = hash.result(); + cache_id_ = bytes.toHex(); +} + +void AudioRendererProcessor::CacheNext() +{ + if (cache_queue_.isEmpty() || !texture_input_->IsConnected() || caching_) { + return; + } + + // Make sure cache has started + Start(); + + rational cache_frame = cache_queue_.takeFirst(); + + qDebug() << "Caching" << cache_frame.toDouble(); + + caching_ = true; +} + +AudioRendererThreadBase *AudioRendererProcessor::CurrentThread() +{ + return dynamic_cast(QThread::currentThread()); +} + +AudioRendererParams *AudioRendererProcessor::CurrentInstance() +{ + AudioRendererThreadBase* thread = CurrentThread(); + + if (thread != nullptr) { + return thread->params(); + } + + return nullptr; +} + +NodeInput *AudioRendererProcessor::texture_input() +{ + return texture_input_; +} + +NodeInput *AudioRendererProcessor::length_input() +{ + return length_input_; +} + +NodeOutput *AudioRendererProcessor::texture_output() +{ + return texture_output_; +} diff --git a/app/node/processor/audiorenderer/audiorenderer.h b/app/node/processor/audiorenderer/audiorenderer.h new file mode 100644 index 000000000..8882ccf5a --- /dev/null +++ b/app/node/processor/audiorenderer/audiorenderer.h @@ -0,0 +1,177 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#ifndef AUDIORENDERER_H +#define AUDIORENDERER_H + +#include +#include + +#include "node/node.h" +#include "render/pixelformat.h" +#include "render/rendermodes.h" +#include "audiorendererthread.h" + +/** + * @brief A multithreaded PCM audio renderer + */ +class AudioRendererProcessor : public Node +{ + Q_OBJECT +public: + /** + * @brief Renderer Constructor + * + * Constructing a Renderer object will not start any threads/backend on its own. Use Start() to do this and Stop() + * when the Renderer is about to be destroyed. + */ + AudioRendererProcessor(); + + virtual QString Name() override; + virtual QString Category() override; + virtual QString Description() override; + virtual QString id() override; + + void SetCacheName(const QString& s); + + virtual void Release() override; + + virtual void InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from = nullptr) override; + + void SetTimebase(const rational& timebase); + + /** + * @brief Set parameters of the Renderer + * + * The Renderer owns the buffers that are used in the rendering process and this function sets the kind of buffers + * to use. The Renderer must be stopped when calling this function. + * + * @param width + * + * Buffer width + * + * @param height + * + * Buffer height + * + * @param format + * + * Buffer pixel format + */ + void SetParameters(const int& sample_rate, + const uint64_t& channel_layout, + const olive::SampleFormat& format); + + /** + * @brief Return whether a frame is currently being cached + */ + bool IsCaching(const QByteArray& hash); + + /** + * @brief Check if a frame is currently being cached, and if not reserve it + */ + bool TryCache(const QByteArray& hash); + + /** + * @brief Return current instance of a RenderThread (or nullptr if there is none) + * + * This function attempts a dynamic_cast on QThread::currentThread() to RendererThread, which will return nullptr if + * the cast fails (e.g. if this function is called from the main thread rather than a RendererThread). + */ + static AudioRendererThreadBase* CurrentThread(); + + static AudioRendererParams* CurrentInstance(); + + NodeInput* texture_input(); + + NodeInput* length_input(); + + NodeOutput* texture_output(); + +protected: + virtual QVariant Value(NodeOutput* output, const rational& time) override; + +private: + struct HashTimeMapping { + rational time; + QByteArray hash; + }; + + /** + * @brief Allocate and start the multithreaded backend + */ + void Start(); + + /** + * @brief Terminate and deallocate the multithreaded backend + */ + void Stop(); + + /** + * @brief Internal function for generating the cache ID + */ + void GenerateCacheIDInternal(); + + /** + * @brief Function called when there are frames in the queue to cache + * + * This function is NOT thread-safe and should only be called in the main thread. + */ + void CacheNext(); + + bool ShouldPushTexture(const rational &time); + + /** + * @brief Internal list of RenderProcessThreads + */ + QVector threads_; + + /** + * @brief Internal variable that contains whether the Renderer has started or not + */ + bool started_; + + NodeInput* texture_input_; + + NodeInput* length_input_; + + NodeOutput* texture_output_; + + rational timebase_; + double timebase_dbl_; + + int sample_rate_; + uint64_t channel_layout_; + olive::SampleFormat format_; + + QLinkedList cache_queue_; + QString cache_name_; + qint64 cache_time_; + QString cache_id_; + + bool caching_; + + bool starting_; + +private slots: + +}; + +#endif // AUDIORENDERER_H diff --git a/app/node/processor/audiorenderer/audiorendererparams.cpp b/app/node/processor/audiorenderer/audiorendererparams.cpp new file mode 100644 index 000000000..612cba7be --- /dev/null +++ b/app/node/processor/audiorenderer/audiorendererparams.cpp @@ -0,0 +1,23 @@ +#include "audiorendererparams.h" + +AudioRendererParams::AudioRendererParams(const int &sample_rate, const uint64_t &channel_layout, const olive::SampleFormat &format) : + sample_rate_(sample_rate), + channel_layout_(channel_layout), + format_(format) +{ +} + +const int &AudioRendererParams::sample_rate() +{ + return sample_rate_; +} + +const uint64_t &AudioRendererParams::channel_layout() +{ + return channel_layout_; +} + +const olive::SampleFormat &AudioRendererParams::format() +{ + return format_; +} diff --git a/app/node/processor/audiorenderer/audiorendererparams.h b/app/node/processor/audiorenderer/audiorendererparams.h new file mode 100644 index 000000000..7a3f7ac67 --- /dev/null +++ b/app/node/processor/audiorenderer/audiorendererparams.h @@ -0,0 +1,28 @@ +#ifndef AUDIORENDERERPARAMS_H +#define AUDIORENDERERPARAMS_H + +#include + +#include "audio/sampleformat.h" + +class AudioRendererParams +{ +public: + AudioRendererParams(const int& sample_rate, const uint64_t& channel_layout, const olive::SampleFormat& format); + + const int& sample_rate(); + + const uint64_t& channel_layout(); + + const olive::SampleFormat& format(); + +private: + int sample_rate_; + + uint64_t channel_layout_; + + olive::SampleFormat format_; + +}; + +#endif // AUDIORENDERERPARAMS_H diff --git a/app/node/processor/audiorenderer/audiorendererthread.cpp b/app/node/processor/audiorenderer/audiorendererthread.cpp new file mode 100644 index 000000000..04a63c167 --- /dev/null +++ b/app/node/processor/audiorenderer/audiorendererthread.cpp @@ -0,0 +1,23 @@ +#include "audiorendererthread.h" + +AudioRendererThread::AudioRendererThread(const int &sample_rate, const uint64_t &channel_layout, const olive::SampleFormat &format) : + AudioRendererThreadBase(sample_rate, channel_layout, format), + cancelled_(false) +{ +} + +void AudioRendererThread::Cancel() +{ + cancelled_ = true; + + mutex_.lock(); + wait_cond_.wakeAll(); + mutex_.unlock(); + + wait(); +} + +void AudioRendererThread::ProcessLoop() +{ + +} diff --git a/app/node/processor/audiorenderer/audiorendererthread.h b/app/node/processor/audiorenderer/audiorendererthread.h new file mode 100644 index 000000000..269fdc32c --- /dev/null +++ b/app/node/processor/audiorenderer/audiorendererthread.h @@ -0,0 +1,26 @@ +#ifndef AUDIORENDERERTHREAD_H +#define AUDIORENDERERTHREAD_H + +#include "audiorendererthreadbase.h" + +class AudioRendererThread : public AudioRendererThreadBase +{ + Q_OBJECT +public: + AudioRendererThread(const int& sample_rate, + const uint64_t& channel_layout, + const olive::SampleFormat& format); + +public slots: + virtual void Cancel() override; + +protected: + virtual void ProcessLoop() override; + +private: + bool cancelled_; +}; + +using AudioRendererThreadPtr = std::shared_ptr; + +#endif // AUDIORENDERERTHREAD_H diff --git a/app/node/processor/audiorenderer/audiorendererthreadbase.cpp b/app/node/processor/audiorenderer/audiorendererthreadbase.cpp new file mode 100644 index 000000000..0dd565449 --- /dev/null +++ b/app/node/processor/audiorenderer/audiorendererthreadbase.cpp @@ -0,0 +1,69 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#include "audiorendererthreadbase.h" + +#include + +AudioRendererThreadBase::AudioRendererThreadBase(const int &sample_rate, const uint64_t &channel_layout, const olive::SampleFormat &format) : + audio_params_(sample_rate, channel_layout, format) +{ +} + +AudioRendererParams *AudioRendererThreadBase::params() +{ + return &audio_params_; +} + +void AudioRendererThreadBase::run() +{ + // Lock mutex for main loop + mutex_.lock(); + + // Signal that main thread can continue now + WakeCaller(); + + // Main loop (use Cancel() to exit it) + ProcessLoop(); + + // Unlock mutex before exiting + mutex_.unlock(); +} + +void AudioRendererThreadBase::WakeCaller() +{ + // Signal that main thread can continue now + caller_mutex_.lock(); + wait_cond_.wakeAll(); + caller_mutex_.unlock(); +} + +void AudioRendererThreadBase::StartThread(QThread::Priority priority) +{ + caller_mutex_.lock(); + + // Start the thread + QThread::start(priority); + + // Wait for thread to finish completion + wait_cond_.wait(&caller_mutex_); + + caller_mutex_.unlock(); +} diff --git a/app/node/processor/audiorenderer/audiorendererthreadbase.h b/app/node/processor/audiorenderer/audiorendererthreadbase.h new file mode 100644 index 000000000..fd242a2ca --- /dev/null +++ b/app/node/processor/audiorenderer/audiorendererthreadbase.h @@ -0,0 +1,65 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2019 Olive Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +***/ + +#ifndef AUDIORENDERTHREADBASE_H +#define AUDIORENDERTHREADBASE_H + +#include +#include +#include +#include + +#include "audiorendererparams.h" +#include "node/node.h" + +class AudioRendererThreadBase : public QThread +{ + Q_OBJECT +public: + AudioRendererThreadBase(const int& sample_rate, + const uint64_t& channel_layout, + const olive::SampleFormat& format); + + AudioRendererParams* params(); + + void StartThread(Priority priority = InheritPriority); + + virtual void run() override; + +public slots: + virtual void Cancel() = 0; + +protected: + virtual void ProcessLoop() = 0; + + QWaitCondition wait_cond_; + + QMutex mutex_; + + QMutex caller_mutex_; + +private: + void WakeCaller(); + + AudioRendererParams audio_params_; + +}; + +#endif // RENDERTHREAD_H diff --git a/app/node/processor/videorenderer/CMakeLists.txt b/app/node/processor/videorenderer/CMakeLists.txt new file mode 100644 index 000000000..297c91f9c --- /dev/null +++ b/app/node/processor/videorenderer/CMakeLists.txt @@ -0,0 +1,28 @@ +# Olive - Non-Linear Video Editor +# Copyright (C) 2019 Olive Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set(OLIVE_SOURCES + ${OLIVE_SOURCES} + node/processor/videorenderer/videorenderer.h + node/processor/videorenderer/videorenderer.cpp + node/processor/videorenderer/videorendererthreadbase.h + node/processor/videorenderer/videorendererthreadbase.cpp + node/processor/videorenderer/videorendererdownloadthread.h + node/processor/videorenderer/videorendererdownloadthread.cpp + node/processor/videorenderer/videorendererprocessthread.h + node/processor/videorenderer/videorendererprocessthread.cpp + PARENT_SCOPE +) diff --git a/app/node/processor/renderer/renderer.cpp b/app/node/processor/videorenderer/videorenderer.cpp similarity index 84% rename from app/node/processor/renderer/renderer.cpp rename to app/node/processor/videorenderer/videorenderer.cpp index 38788fa9d..7015f163c 100644 --- a/app/node/processor/renderer/renderer.cpp +++ b/app/node/processor/videorenderer/videorenderer.cpp @@ -18,7 +18,7 @@ ***/ -#include "renderer.h" +#include "videorenderer.h" #include #include @@ -31,7 +31,7 @@ #include "common/filefunctions.h" #include "render/pixelservice.h" -RendererProcessor::RendererProcessor() : +VideoRendererProcessor::VideoRendererProcessor() : started_(false), width_(0), height_(0), @@ -52,27 +52,27 @@ RendererProcessor::RendererProcessor() : AddParameter(texture_output_); } -QString RendererProcessor::Name() +QString VideoRendererProcessor::Name() { - return tr("Renderer"); + return tr("Video Renderer"); } -QString RendererProcessor::Category() +QString VideoRendererProcessor::Category() { return tr("Processor"); } -QString RendererProcessor::Description() +QString VideoRendererProcessor::Description() { return tr("A multi-threaded OpenGL hardware-accelerated node compositor."); } -QString RendererProcessor::id() +QString VideoRendererProcessor::id() { return "org.olivevideoeditor.Olive.renderervenus"; } -void RendererProcessor::SetCacheName(const QString &s) +void VideoRendererProcessor::SetCacheName(const QString &s) { cache_name_ = s; cache_time_ = QDateTime::currentMSecsSinceEpoch(); @@ -80,7 +80,7 @@ void RendererProcessor::SetCacheName(const QString &s) GenerateCacheIDInternal(); } -QVariant RendererProcessor::Value(NodeOutput* output, const rational& time) +QVariant VideoRendererProcessor::Value(NodeOutput* output, const rational& time) { if (output == texture_output_) { if (!texture_input_->IsConnected()) { @@ -123,12 +123,12 @@ QVariant RendererProcessor::Value(NodeOutput* output, const rational& time) return 0; } -void RendererProcessor::Release() +void VideoRendererProcessor::Release() { Stop(); } -void RendererProcessor::InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from) +void VideoRendererProcessor::InvalidateCache(const rational &start_range, const rational &end_range, NodeInput *from) { Q_UNUSED(from) @@ -202,13 +202,13 @@ void RendererProcessor::InvalidateCache(const rational &start_range, const ratio CacheNext(); } -void RendererProcessor::SetTimebase(const rational &timebase) +void VideoRendererProcessor::SetTimebase(const rational &timebase) { timebase_ = timebase; timebase_dbl_ = timebase_.toDouble(); } -void RendererProcessor::SetParameters(const int &width, +void VideoRendererProcessor::SetParameters(const int &width, const int &height, const olive::PixelFormat &format, const olive::RenderMode &mode, @@ -235,7 +235,7 @@ void RendererProcessor::SetParameters(const int &width, GenerateCacheIDInternal(); } -void RendererProcessor::SetDivider(const int ÷r) +void VideoRendererProcessor::SetDivider(const int ÷r) { Q_ASSERT(divider_ > 0); @@ -249,7 +249,7 @@ void RendererProcessor::SetDivider(const int ÷r) GenerateCacheIDInternal(); } -void RendererProcessor::Start() +void VideoRendererProcessor::Start() { if (started_) { return; @@ -294,7 +294,7 @@ void RendererProcessor::Start() for (int i=0;i(ctx, effective_width_, effective_height_, divider_, format_, mode_); + download_threads_[i] = std::make_shared(ctx, effective_width_, effective_height_, divider_, format_, mode_); download_threads_[i]->StartThread(QThread::LowPriority); connect(download_threads_[i].get(), @@ -318,7 +318,7 @@ void RendererProcessor::Start() started_ = true; } -void RendererProcessor::Stop() +void VideoRendererProcessor::Stop() { if (!started_) { return; @@ -341,7 +341,7 @@ void RendererProcessor::Stop() cache_frame_load_buffer_.clear(); } -void RendererProcessor::GenerateCacheIDInternal() +void VideoRendererProcessor::GenerateCacheIDInternal() { if (cache_name_.isEmpty() || effective_width_ == 0 || effective_height_ == 0) { return; @@ -360,7 +360,7 @@ void RendererProcessor::GenerateCacheIDInternal() cache_id_ = bytes.toHex(); } -void RendererProcessor::CacheNext() +void VideoRendererProcessor::CacheNext() { if (cache_queue_.isEmpty() || !texture_input_->IsConnected() || caching_) { return; @@ -378,7 +378,7 @@ void RendererProcessor::CacheNext() caching_ = true; } -QString RendererProcessor::CachePathName(const QByteArray &hash) +QString VideoRendererProcessor::CachePathName(const QByteArray &hash) { QDir this_cache_dir = QDir(GetMediaCacheLocation()).filePath(cache_id_); this_cache_dir.mkpath("."); @@ -388,17 +388,17 @@ QString RendererProcessor::CachePathName(const QByteArray &hash) return this_cache_dir.filePath(filename); } -void RendererProcessor::DeferMap(const rational &time, const QByteArray &hash) +void VideoRendererProcessor::DeferMap(const rational &time, const QByteArray &hash) { deferred_maps_.append({time, hash}); } -bool RendererProcessor::HasHash(const QByteArray &hash) +bool VideoRendererProcessor::HasHash(const QByteArray &hash) { return QFileInfo::exists(CachePathName(hash)); } -bool RendererProcessor::IsCaching(const QByteArray &hash) +bool VideoRendererProcessor::IsCaching(const QByteArray &hash) { cache_hash_list_mutex_.lock(); @@ -409,7 +409,7 @@ bool RendererProcessor::IsCaching(const QByteArray &hash) return is_caching; } -bool RendererProcessor::TryCache(const QByteArray &hash) +bool VideoRendererProcessor::TryCache(const QByteArray &hash) { cache_hash_list_mutex_.lock(); @@ -424,13 +424,13 @@ bool RendererProcessor::TryCache(const QByteArray &hash) return !is_caching; } -void RendererProcessor::CalculateEffectiveDimensions() +void VideoRendererProcessor::CalculateEffectiveDimensions() { effective_width_ = width_ / divider_; effective_height_ = height_ / divider_; } -void RendererProcessor::ThreadCallback(RenderTexturePtr texture, const rational& time, const QByteArray& hash) +void VideoRendererProcessor::ThreadCallback(RenderTexturePtr texture, const rational& time, const QByteArray& hash) { // Threads are all done now, time to proceed caching_ = false; @@ -461,7 +461,7 @@ void RendererProcessor::ThreadCallback(RenderTexturePtr texture, const rational& CacheNext(); } -void RendererProcessor::ThreadRequestSibling(NodeDependency dep) +void VideoRendererProcessor::ThreadRequestSibling(NodeDependency dep) { // Try to queue another thread to run this dep in advance for (int i=1;i(QThread::currentThread()); + return dynamic_cast(QThread::currentThread()); } -RenderInstance *RendererProcessor::CurrentInstance() +RenderInstance *VideoRendererProcessor::CurrentInstance() { - RendererThreadBase* thread = CurrentThread(); + VideoRendererThreadBase* thread = CurrentThread(); if (thread != nullptr) { return thread->render_instance(); @@ -526,17 +526,17 @@ RenderInstance *RendererProcessor::CurrentInstance() return nullptr; } -NodeInput *RendererProcessor::texture_input() +NodeInput *VideoRendererProcessor::texture_input() { return texture_input_; } -NodeInput *RendererProcessor::length_input() +NodeInput *VideoRendererProcessor::length_input() { return length_input_; } -NodeOutput *RendererProcessor::texture_output() +NodeOutput *VideoRendererProcessor::texture_output() { return texture_output_; } diff --git a/app/node/processor/renderer/renderer.h b/app/node/processor/videorenderer/videorenderer.h similarity index 96% rename from app/node/processor/renderer/renderer.h rename to app/node/processor/videorenderer/videorenderer.h index 521e0e82a..e7eab905a 100644 --- a/app/node/processor/renderer/renderer.h +++ b/app/node/processor/videorenderer/videorenderer.h @@ -27,13 +27,13 @@ #include "node/node.h" #include "render/pixelformat.h" #include "render/rendermodes.h" -#include "rendererdownloadthread.h" -#include "rendererprocessthread.h" +#include "videorendererdownloadthread.h" +#include "videorendererprocessthread.h" /** * @brief A multithreaded OpenGL based renderer for node systems */ -class RendererProcessor : public Node +class VideoRendererProcessor : public Node { Q_OBJECT public: @@ -43,7 +43,7 @@ public: * Constructing a Renderer object will not start any threads/backend on its own. Use Start() to do this and Stop() * when the Renderer is about to be destroyed. */ - RendererProcessor(); + VideoRendererProcessor(); virtual QString Name() override; virtual QString Category() override; @@ -105,7 +105,7 @@ public: * This function attempts a dynamic_cast on QThread::currentThread() to RendererThread, which will return nullptr if * the cast fails (e.g. if this function is called from the main thread rather than a RendererThread). */ - static RendererThreadBase* CurrentThread(); + static VideoRendererThreadBase* CurrentThread(); static RenderInstance* CurrentInstance(); diff --git a/app/node/processor/renderer/rendererdownloadthread.cpp b/app/node/processor/videorenderer/videorendererdownloadthread.cpp similarity index 79% rename from app/node/processor/renderer/rendererdownloadthread.cpp rename to app/node/processor/videorenderer/videorendererdownloadthread.cpp index 91f030d94..0d9966cdb 100644 --- a/app/node/processor/renderer/rendererdownloadthread.cpp +++ b/app/node/processor/videorenderer/videorendererdownloadthread.cpp @@ -1,4 +1,4 @@ -#include "rendererdownloadthread.h" +#include "videorendererdownloadthread.h" #include #include @@ -7,18 +7,18 @@ #include "common/define.h" #include "render/pixelservice.h" -RendererDownloadThread::RendererDownloadThread(QOpenGLContext *share_ctx, - const int &width, - const int &height, - const int ÷r, - const olive::PixelFormat &format, - const olive::RenderMode &mode) : - RendererThreadBase(share_ctx, width, height, divider, format, mode), +VideoRendererDownloadThread::VideoRendererDownloadThread(QOpenGLContext *share_ctx, + const int &width, + const int &height, + const int ÷r, + const olive::PixelFormat &format, + const olive::RenderMode &mode) : + VideoRendererThreadBase(share_ctx, width, height, divider, format, mode), cancelled_(false) { } -void RendererDownloadThread::Queue(RenderTexturePtr texture, const QString& fn, const QByteArray &hash) +void VideoRendererDownloadThread::Queue(RenderTexturePtr texture, const QString& fn, const QByteArray &hash) { texture_queue_lock_.lock(); @@ -29,7 +29,7 @@ void RendererDownloadThread::Queue(RenderTexturePtr texture, const QString& fn, texture_queue_lock_.unlock(); } -void RendererDownloadThread::Cancel() +void VideoRendererDownloadThread::Cancel() { cancelled_ = true; @@ -40,7 +40,7 @@ void RendererDownloadThread::Cancel() wait(); } -void RendererDownloadThread::ProcessLoop() +void VideoRendererDownloadThread::ProcessLoop() { QOpenGLFunctions* f = render_instance()->context()->functions(); QOpenGLExtraFunctions* xf = render_instance()->context()->extraFunctions(); diff --git a/app/node/processor/renderer/rendererdownloadthread.h b/app/node/processor/videorenderer/videorendererdownloadthread.h similarity index 78% rename from app/node/processor/renderer/rendererdownloadthread.h rename to app/node/processor/videorenderer/videorendererdownloadthread.h index 9c7b6bc45..bc6f291c2 100644 --- a/app/node/processor/renderer/rendererdownloadthread.h +++ b/app/node/processor/videorenderer/videorendererdownloadthread.h @@ -1,13 +1,13 @@ #ifndef RENDERERDOWNLOADTHREAD_H #define RENDERERDOWNLOADTHREAD_H -#include "rendererthreadbase.h" +#include "videorendererthreadbase.h" -class RendererDownloadThread : public RendererThreadBase +class VideoRendererDownloadThread : public VideoRendererThreadBase { Q_OBJECT public: - RendererDownloadThread(QOpenGLContext* share_ctx, + VideoRendererDownloadThread(QOpenGLContext* share_ctx, const int& width, const int& height, const int ÷r, @@ -44,6 +44,6 @@ private: }; -using RendererDownloadThreadPtr = std::shared_ptr; +using RendererDownloadThreadPtr = std::shared_ptr; #endif // RENDERERDOWNLOADTHREAD_H diff --git a/app/node/processor/renderer/rendererprocessthread.cpp b/app/node/processor/videorenderer/videorendererprocessthread.cpp similarity index 94% rename from app/node/processor/renderer/rendererprocessthread.cpp rename to app/node/processor/videorenderer/videorendererprocessthread.cpp index 0292fce83..9a0d98182 100644 --- a/app/node/processor/renderer/rendererprocessthread.cpp +++ b/app/node/processor/videorenderer/videorendererprocessthread.cpp @@ -18,18 +18,18 @@ ***/ -#include "rendererprocessthread.h" +#include "videorendererprocessthread.h" -#include "renderer.h" +#include "videorenderer.h" -RendererProcessThread::RendererProcessThread(RendererProcessor* parent, +RendererProcessThread::RendererProcessThread(VideoRendererProcessor* parent, QOpenGLContext *share_ctx, const int &width, const int &height, const int ÷r, const olive::PixelFormat &format, const olive::RenderMode &mode) : - RendererThreadBase(share_ctx, width, height, divider, format, mode), + VideoRendererThreadBase(share_ctx, width, height, divider, format, mode), parent_(parent), cancelled_(false) { diff --git a/app/node/processor/renderer/rendererprocessthread.h b/app/node/processor/videorenderer/videorendererprocessthread.h similarity index 88% rename from app/node/processor/renderer/rendererprocessthread.h rename to app/node/processor/videorenderer/videorendererprocessthread.h index 906db85ce..ef1ed9fc8 100644 --- a/app/node/processor/renderer/rendererprocessthread.h +++ b/app/node/processor/videorenderer/videorendererprocessthread.h @@ -21,15 +21,15 @@ #ifndef RENDERERPROCESSTHREAD_H #define RENDERERPROCESSTHREAD_H -#include "rendererthreadbase.h" +#include "videorendererthreadbase.h" -class RendererProcessor; +class VideoRendererProcessor; -class RendererProcessThread : public RendererThreadBase +class RendererProcessThread : public VideoRendererThreadBase { Q_OBJECT public: - RendererProcessThread(RendererProcessor* parent, + RendererProcessThread(VideoRendererProcessor* parent, QOpenGLContext* share_ctx, const int& width, const int& height, const int ÷r, @@ -52,7 +52,7 @@ signals: void FrameSkipped(const rational& time, const QByteArray& hash); private: - RendererProcessor* parent_; + VideoRendererProcessor* parent_; NodeDependency path_; diff --git a/app/node/processor/renderer/rendererthreadbase.cpp b/app/node/processor/videorenderer/videorendererthreadbase.cpp similarity index 78% rename from app/node/processor/renderer/rendererthreadbase.cpp rename to app/node/processor/videorenderer/videorendererthreadbase.cpp index fbd3965a8..6c53c11c7 100644 --- a/app/node/processor/renderer/rendererthreadbase.cpp +++ b/app/node/processor/videorenderer/videorendererthreadbase.cpp @@ -18,23 +18,23 @@ ***/ -#include "rendererthreadbase.h" +#include "videorendererthreadbase.h" #include -RendererThreadBase::RendererThreadBase(QOpenGLContext *share_ctx, const int &width, const int &height, const int ÷r, const olive::PixelFormat &format, const olive::RenderMode &mode) : +VideoRendererThreadBase::VideoRendererThreadBase(QOpenGLContext *share_ctx, const int &width, const int &height, const int ÷r, const olive::PixelFormat &format, const olive::RenderMode &mode) : share_ctx_(share_ctx), render_instance_(width, height, divider, format, mode) { connect(share_ctx_, SIGNAL(aboutToBeDestroyed()), this, SLOT(Cancel())); } -RenderInstance *RendererThreadBase::render_instance() +RenderInstance *VideoRendererThreadBase::render_instance() { return &render_instance_; } -void RendererThreadBase::run() +void VideoRendererThreadBase::run() { // Lock mutex for main loop mutex_.lock(); @@ -61,7 +61,7 @@ void RendererThreadBase::run() mutex_.unlock(); } -void RendererThreadBase::WakeCaller() +void VideoRendererThreadBase::WakeCaller() { // Signal that main thread can continue now caller_mutex_.lock(); @@ -69,7 +69,7 @@ void RendererThreadBase::WakeCaller() caller_mutex_.unlock(); } -void RendererThreadBase::StartThread(QThread::Priority priority) +void VideoRendererThreadBase::StartThread(QThread::Priority priority) { caller_mutex_.lock(); diff --git a/app/node/processor/renderer/rendererthreadbase.h b/app/node/processor/videorenderer/videorendererthreadbase.h similarity index 90% rename from app/node/processor/renderer/rendererthreadbase.h rename to app/node/processor/videorenderer/videorendererthreadbase.h index 88c1fe68d..879db21ce 100644 --- a/app/node/processor/renderer/rendererthreadbase.h +++ b/app/node/processor/videorenderer/videorendererthreadbase.h @@ -29,11 +29,11 @@ #include "node/node.h" #include "render/renderinstance.h" -class RendererThreadBase : public QThread +class VideoRendererThreadBase : public QThread { Q_OBJECT public: - RendererThreadBase(QOpenGLContext* share_ctx, + VideoRendererThreadBase(QOpenGLContext* share_ctx, const int& width, const int& height, const int& divider, @@ -67,6 +67,6 @@ private: }; -using RendererThreadPtr = std::shared_ptr; +using RendererThreadPtr = std::shared_ptr; #endif // RENDERTHREAD_H diff --git a/app/node/processor/renderer/rendermanager.cpp b/app/node/processor/videorenderer/videorendermanager.cpp similarity index 100% rename from app/node/processor/renderer/rendermanager.cpp rename to app/node/processor/videorenderer/videorendermanager.cpp diff --git a/app/node/processor/renderer/rendermanager.h b/app/node/processor/videorenderer/videorendermanager.h similarity index 100% rename from app/node/processor/renderer/rendermanager.h rename to app/node/processor/videorenderer/videorendermanager.h diff --git a/app/project/item/sequence/sequence.cpp b/app/project/item/sequence/sequence.cpp index 3dd0c77c3..7ce6200b7 100644 --- a/app/project/item/sequence/sequence.cpp +++ b/app/project/item/sequence/sequence.cpp @@ -32,7 +32,7 @@ Sequence::Sequence() : timeline_output_(nullptr), - renderer_processor_(nullptr), + video_renderer_processor_(nullptr), viewer_output_(nullptr), video_track_output_(nullptr), audio_track_output_(nullptr) @@ -61,9 +61,9 @@ void Sequence::AddDefaultNodes() timeline_output_->SetCanBeDeleted(false); AddNode(timeline_output_); - renderer_processor_ = new RendererProcessor(); - renderer_processor_->SetCanBeDeleted(false); - AddNode(renderer_processor_); + video_renderer_processor_ = new VideoRendererProcessor(); + video_renderer_processor_->SetCanBeDeleted(false); + AddNode(video_renderer_processor_); viewer_output_ = new ViewerOutput(); viewer_output_->SetCanBeDeleted(false); @@ -78,20 +78,20 @@ void Sequence::AddDefaultNodes() AddNode(audio_track_output_); // Connect track to renderer - NodeParam::ConnectEdge(video_track_output_->texture_output(), renderer_processor_->texture_input()); + NodeParam::ConnectEdge(video_track_output_->texture_output(), video_renderer_processor_->texture_input()); // Connect renderer to viewer - NodeParam::ConnectEdge(renderer_processor_->texture_output(), viewer_output_->texture_input()); + NodeParam::ConnectEdge(video_renderer_processor_->texture_output(), viewer_output_->texture_input()); // Connect track to timeline NodeParam::ConnectEdge(video_track_output_->track_output(), timeline_output_->track_input(kTrackTypeVideo)); NodeParam::ConnectEdge(audio_track_output_->track_output(), timeline_output_->track_input(kTrackTypeAudio)); // Connect timeline end point to renderer - NodeParam::ConnectEdge(timeline_output_->length_output(), renderer_processor_->length_input()); + NodeParam::ConnectEdge(timeline_output_->length_output(), video_renderer_processor_->length_input()); // Update the timebase on these nodes - renderer_processor_->SetCacheName(name()); + video_renderer_processor_->SetCacheName(name()); set_video_time_base(video_time_base_); update_video_parameters(); } @@ -163,8 +163,8 @@ void Sequence::set_video_time_base(const rational &time_base) if (viewer_output_ != nullptr) viewer_output_->SetTimebase(video_time_base_); - if (renderer_processor_ != nullptr) - renderer_processor_->SetTimebase(video_time_base_); + if (video_renderer_processor_ != nullptr) + video_renderer_processor_->SetTimebase(video_time_base_); } const rational &Sequence::audio_time_base() @@ -200,16 +200,16 @@ void Sequence::SetDefaultParameters() void Sequence::update_video_parameters() { - if (renderer_processor_ != nullptr) { + if (video_renderer_processor_ != nullptr) { // Set renderer's parameters based on sequence's parameters - renderer_processor_->SetParameters(video_width_, + video_renderer_processor_->SetParameters(video_width_, video_height_, olive::PIX_FMT_RGBA16F, // FIXME: Make this configurable olive::RenderMode::kOffline, 2); // Set the "cache name" only here to aid the cache ID's uniqueness - renderer_processor_->SetCacheName(name()); + video_renderer_processor_->SetCacheName(name()); } if (viewer_output_ != nullptr) { diff --git a/app/project/item/sequence/sequence.h b/app/project/item/sequence/sequence.h index 47e5d0962..21cfea61b 100644 --- a/app/project/item/sequence/sequence.h +++ b/app/project/item/sequence/sequence.h @@ -25,7 +25,7 @@ #include "node/graph.h" #include "node/output/timeline/timeline.h" #include "node/output/viewer/viewer.h" -#include "node/processor/renderer/renderer.h" +#include "node/processor/videorenderer/videorenderer.h" #include "project/item/item.h" class Sequence; @@ -78,7 +78,7 @@ private: void update_video_parameters(); TimelineOutput* timeline_output_; - RendererProcessor* renderer_processor_; + VideoRendererProcessor* video_renderer_processor_; ViewerOutput* viewer_output_; TrackOutput* video_track_output_; TrackOutput* audio_track_output_; diff --git a/app/render/CMakeLists.txt b/app/render/CMakeLists.txt index 5a26e69d0..05f649d8e 100644 --- a/app/render/CMakeLists.txt +++ b/app/render/CMakeLists.txt @@ -33,6 +33,5 @@ set(OLIVE_SOURCES render/renderframebuffer.cpp render/rendertexture.h render/rendertexture.cpp - render/sampleformat.h PARENT_SCOPE )