began exporter classes for handling render backends in an exporting context

This commit is contained in:
itsmattkc
2019-12-20 04:34:32 +11:00
parent 7844a2ed72
commit 757aaa21c4
8 changed files with 303 additions and 34 deletions
+131
View File
@@ -0,0 +1,131 @@
#include "exporter.h"
#include "render/colormanager.h"
#include "render/pixelservice.h"
Exporter::Exporter(ViewerOutput* viewer, const VideoRenderingParams& params, const QMatrix4x4 &transform, ColorProcessorPtr color_processor, QObject* parent) :
QObject(parent),
video_backend_(nullptr),
audio_backend_(nullptr),
viewer_node_(viewer),
params_(params),
color_processor_(color_processor),
export_status_(false),
export_msg_(tr("Export hasn't started yet"))
{
}
bool Exporter::GetExportStatus() const
{
return export_status_;
}
const QString &Exporter::GetExportError() const
{
return export_msg_;
}
void Exporter::StartExporting()
{
// Default to error state until ExportEnd is called
export_status_ = false;
// Create renderers
if (!Initialize()) {
ExportFailed();
return;
}
video_backend_->SetViewerNode(viewer_node_);
video_backend_->SetParameters(VideoRenderingParams(viewer_node_->video_params(), olive::PIX_FMT_RGBA32F, olive::kOnline));
video_backend_->SetExportMode(true);
video_backend_->Compile();
//audio_backend_->SetViewerNode(viewer_node_);
//audio_renderer_->SetParameters(AudioRenderingParams(viewer_node_->audio_params(), SAMPLE_FMT_FLT));
// Connect to renderers
connect(video_backend_, SIGNAL(CachedFrameReady(const rational&, QVariant)), this, SLOT(FrameRendered(const rational&, QVariant)));
connect(video_backend_, SIGNAL(CachedTimeReady(const rational&)), this, SLOT(TimeRendered(const rational&)));
// Create renderers
waiting_for_frame_ = 0;
// Invalidate caches
video_backend_->InvalidateCache(0, viewer_node_->Length());
//viewer_node_->InvalidateCache(0, viewer_node_->Length(), viewer_node_->samples_input());
}
void Exporter::SetExportMessage(const QString &s)
{
export_msg_ = s;
}
void Exporter::ExportSucceeded()
{
Cleanup();
delete video_backend_;
delete audio_backend_;
export_status_ = true;
export_msg_ = tr("Export succeeded");
emit ExportEnded();
}
void Exporter::ExportFailed()
{
emit ExportEnded();
}
void Exporter::FrameRendered(const rational &time, QVariant value)
{
qDebug() << "Retrieved frame" << time.toDouble() << "- waiting for frame" << waiting_for_frame_.toDouble();
if (time == waiting_for_frame_) {
bool get_cached = false;
do {
if (get_cached) {
value = cached_frames_.take(waiting_for_frame_);
} else {
get_cached = true;
}
// Convert texture to frame
FramePtr frame = TextureToFrame(value);
// OCIO conversion requires a frame in 32F format
if (frame->format() != olive::PIX_FMT_RGBA32F) {
frame = PixelService::ConvertPixelFormat(frame, olive::PIX_FMT_RGBA32F);
}
// Color conversion must be done with unassociated alpha, and the pipeline is always associated
ColorManager::DisassociateAlpha(frame);
// Convert color space
color_processor_->ConvertFrame(frame);
// Encode (may require re-associating alpha?)
waiting_for_frame_ += viewer_node_->video_params().time_base();
// Calculate progress
int progress = qRound(100.0 * (waiting_for_frame_.toDouble() / viewer_node_->Length().toDouble()));
qDebug() << "Hello progress" << progress;
emit ProgressChanged(progress);
} while (cached_frames_.contains(waiting_for_frame_));
} else {
cached_frames_.insert(time, value);
}
/*if (time == viewer_node_->Length()) {
ExportSucceeded();
}*/
}
void Exporter::TimeRendered(const rational &time)
{
qDebug() << "Retrieved time rendered!" << time.toDouble();
}
+75
View File
@@ -0,0 +1,75 @@
#ifndef EXPORTER_H
#define EXPORTER_H
#include <QMatrix4x4>
#include <QString>
#include <QObject>
#include "node/output/viewer/viewer.h"
#include "render/backend/audiorenderbackend.h"
#include "render/backend/videorenderbackend.h"
#include "render/colorprocessor.h"
class Exporter : public QObject
{
Q_OBJECT
public:
Exporter(ViewerOutput* viewer, const VideoRenderingParams& params, const QMatrix4x4& transform, ColorProcessorPtr color_processor, QObject* parent = nullptr);
bool GetExportStatus() const;
const QString& GetExportError() const;
public slots:
void StartExporting();
signals:
void ProgressChanged(int);
void ExportEnded();
protected:
virtual bool Initialize() = 0;
virtual void Cleanup() = 0;
virtual FramePtr TextureToFrame(const QVariant &texture) = 0;
void SetExportMessage(const QString& s);
// Renderers
VideoRenderBackend* video_backend_;
AudioRenderBackend* audio_backend_;
// Viewer node
ViewerOutput* viewer_node_;
// Export parameters
VideoRenderingParams params_;
// Export transform
QMatrix4x4 transform_;
// Copied graph
NodeGraph copied_graph_;
private:
void ExportSucceeded();
void ExportFailed();
ColorProcessorPtr color_processor_;
bool export_status_;
QString export_msg_;
rational waiting_for_frame_;
QHash<rational, QVariant> cached_frames_;
private slots:
void FrameRendered(const rational& time, QVariant value);
void TimeRendered(const rational& time);
};
#endif // EXPORTER_H
@@ -0,0 +1,64 @@
#include "openglexporter.h"
#include "render/backend/opengl/functions.h"
OpenGLExporter::OpenGLExporter(ViewerOutput* viewer, const VideoRenderingParams& params, const QMatrix4x4& transform, ColorProcessorPtr color_processor, QObject* parent) :
Exporter(viewer, params, transform, color_processor, parent)
{
}
OpenGLExporter::~OpenGLExporter()
{
}
bool OpenGLExporter::Initialize()
{
QOpenGLContext* ctx = QOpenGLContext::currentContext();
// Create rendering backends
video_backend_ = new OpenGLBackend();
audio_backend_ = new AudioBackend();
// Create blitting framebuffer and texture
buffer_.Create(ctx);
texture_ = std::make_shared<OpenGLTexture>();
texture_->Create(ctx, params_.effective_width(), params_.effective_height(), params_.format());
pipeline_ = OpenGLShader::CreateDefault();
return true;
}
void OpenGLExporter::Cleanup()
{
texture_->Destroy();
buffer_.Destroy();
}
FramePtr OpenGLExporter::TextureToFrame(const QVariant& texture)
{
FramePtr frame = Frame::Create();
frame->set_width(params_.width());
frame->set_height(params_.height());
frame->set_format(params_.format());
frame->allocate();
// Blit for transform if the width/height are different
OpenGLTexturePtr input_tex = texture.value<OpenGLTexturePtr>();
if (input_tex) {
buffer_.Attach(texture_);
buffer_.Bind();
input_tex->Bind();
olive::gl::Blit(pipeline_, false, transform_);
input_tex->Release();
buffer_.Release();
buffer_.Detach();
}
// Perform OpenGL read
return frame;
}
@@ -0,0 +1,33 @@
#ifndef OPENGLEXPORTER_H
#define OPENGLEXPORTER_H
#include "render/backend/exporter.h"
#include "render/backend/opengl/openglbackend.h"
#include "render/backend/audio/audiobackend.h"
#include "render/backend/opengl/openglframebuffer.h"
#include "render/backend/opengl/opengltexture.h"
class OpenGLExporter : public Exporter
{
public:
OpenGLExporter(ViewerOutput *viewer, const VideoRenderingParams &params, const QMatrix4x4 &transform, ColorProcessorPtr color_processor, QObject* parent = nullptr);
virtual ~OpenGLExporter() override;
protected:
virtual bool Initialize() override;
virtual void Cleanup() override;
virtual FramePtr TextureToFrame(const QVariant &texture) override;
private:
OpenGLFramebuffer buffer_;
OpenGLTexturePtr texture_;
OpenGLShaderPtr pipeline_;
};
#endif // OPENGLEXPORTER_H
-6
View File
@@ -1,6 +0,0 @@
#include "exporter.h"
Exporter::Exporter()
{
}
-11
View File
@@ -1,11 +0,0 @@
#ifndef EXPORTER_H
#define EXPORTER_H
class Exporter
{
public:
Exporter();
};
#endif // EXPORTER_H
-6
View File
@@ -1,6 +0,0 @@
#include "openglexporter.h"
OpenGLExporter::OpenGLExporter()
{
}
-11
View File
@@ -1,11 +0,0 @@
#ifndef OPENGLEXPORTER_H
#define OPENGLEXPORTER_H
class OpenGLExporter
{
public:
OpenGLExporter();
};
#endif // OPENGLEXPORTER_H