base audio renderer classes created
This commit is contained in:
@@ -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
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -95,7 +95,7 @@ private:
|
||||
|
||||
QList<QAudioDeviceInfo> output_devices_;
|
||||
|
||||
static AudioManager* audio_;
|
||||
static AudioManager* instance_;
|
||||
|
||||
AudioHybridDevice output_manager_;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#include "clip.h"
|
||||
|
||||
#include "node/processor/renderer/renderer.h"
|
||||
#include "node/processor/videorenderer/videorenderer.h"
|
||||
|
||||
ClipBlock::ClipBlock()
|
||||
{
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
add_subdirectory(renderer)
|
||||
add_subdirectory(audiorenderer)
|
||||
add_subdirectory(videorenderer)
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
|
||||
+8
-8
@@ -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
|
||||
)
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "audiorenderer.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QtMath>
|
||||
|
||||
#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<rational>(), 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<double>(timebase_.denominator());
|
||||
int64_t start_range_numround = qFloor(start_range_numf/static_cast<double>(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<rational>::iterator insert_iterator;
|
||||
|
||||
for (QLinkedList<rational>::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<threads_.size();i++) {
|
||||
threads_[i] = std::make_shared<AudioRendererThread>(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<AudioRendererThreadBase*>(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_;
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef AUDIORENDERER_H
|
||||
#define AUDIORENDERER_H
|
||||
|
||||
#include <QLinkedList>
|
||||
#include <QOpenGLTexture>
|
||||
|
||||
#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<AudioRendererThreadPtr> 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<rational> cache_queue_;
|
||||
QString cache_name_;
|
||||
qint64 cache_time_;
|
||||
QString cache_id_;
|
||||
|
||||
bool caching_;
|
||||
|
||||
bool starting_;
|
||||
|
||||
private slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // AUDIORENDERER_H
|
||||
@@ -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_;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef AUDIORENDERERPARAMS_H
|
||||
#define AUDIORENDERERPARAMS_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#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
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -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<AudioRendererThread>;
|
||||
|
||||
#endif // AUDIORENDERERTHREAD_H
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "audiorendererthreadbase.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef AUDIORENDERTHREADBASE_H
|
||||
#define AUDIORENDERTHREADBASE_H
|
||||
|
||||
#include <memory>
|
||||
#include <QMutex>
|
||||
#include <QThread>
|
||||
#include <QWaitCondition>
|
||||
|
||||
#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
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
)
|
||||
+36
-36
@@ -18,7 +18,7 @@
|
||||
|
||||
***/
|
||||
|
||||
#include "renderer.h"
|
||||
#include "videorenderer.h"
|
||||
|
||||
#include <OpenImageIO/imageio.h>
|
||||
#include <QApplication>
|
||||
@@ -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<download_threads_.size();i++) {
|
||||
// Create download thread
|
||||
download_threads_[i] = std::make_shared<RendererDownloadThread>(ctx, effective_width_, effective_height_, divider_, format_, mode_);
|
||||
download_threads_[i] = std::make_shared<VideoRendererDownloadThread>(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<threads_.size();i++) {
|
||||
@@ -471,7 +471,7 @@ void RendererProcessor::ThreadRequestSibling(NodeDependency dep)
|
||||
}
|
||||
}
|
||||
|
||||
void RendererProcessor::ThreadSkippedFrame(const rational& time, const QByteArray& hash)
|
||||
void VideoRendererProcessor::ThreadSkippedFrame(const rational& time, const QByteArray& hash)
|
||||
{
|
||||
caching_ = false;
|
||||
|
||||
@@ -491,7 +491,7 @@ void RendererProcessor::ThreadSkippedFrame(const rational& time, const QByteArra
|
||||
CacheNext();
|
||||
}
|
||||
|
||||
void RendererProcessor::DownloadThreadComplete(const QByteArray &hash)
|
||||
void VideoRendererProcessor::DownloadThreadComplete(const QByteArray &hash)
|
||||
{
|
||||
cache_hash_list_mutex_.lock();
|
||||
cache_hash_list_.removeAll(hash);
|
||||
@@ -510,14 +510,14 @@ void RendererProcessor::DownloadThreadComplete(const QByteArray &hash)
|
||||
}
|
||||
}
|
||||
|
||||
RendererThreadBase* RendererProcessor::CurrentThread()
|
||||
VideoRendererThreadBase* VideoRendererProcessor::CurrentThread()
|
||||
{
|
||||
return dynamic_cast<RendererThreadBase*>(QThread::currentThread());
|
||||
return dynamic_cast<VideoRendererThreadBase*>(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_;
|
||||
}
|
||||
+5
-5
@@ -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();
|
||||
|
||||
+11
-11
@@ -1,4 +1,4 @@
|
||||
#include "rendererdownloadthread.h"
|
||||
#include "videorendererdownloadthread.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QFloat16>
|
||||
@@ -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();
|
||||
+4
-4
@@ -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<RendererDownloadThread>;
|
||||
using RendererDownloadThreadPtr = std::shared_ptr<VideoRendererDownloadThread>;
|
||||
|
||||
#endif // RENDERERDOWNLOADTHREAD_H
|
||||
+4
-4
@@ -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)
|
||||
{
|
||||
+5
-5
@@ -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_;
|
||||
|
||||
+6
-6
@@ -18,23 +18,23 @@
|
||||
|
||||
***/
|
||||
|
||||
#include "rendererthreadbase.h"
|
||||
#include "videorendererthreadbase.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
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();
|
||||
|
||||
+3
-3
@@ -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<RendererThreadBase>;
|
||||
using RendererThreadPtr = std::shared_ptr<VideoRendererThreadBase>;
|
||||
|
||||
#endif // RENDERTHREAD_H
|
||||
@@ -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) {
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -33,6 +33,5 @@ set(OLIVE_SOURCES
|
||||
render/renderframebuffer.cpp
|
||||
render/rendertexture.h
|
||||
render/rendertexture.cpp
|
||||
render/sampleformat.h
|
||||
PARENT_SCOPE
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user