began exporter classes for handling render backends in an exporting context
This commit is contained in:
@@ -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();
|
||||
}
|
||||
@@ -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 ¶ms, 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
|
||||
@@ -1,6 +0,0 @@
|
||||
#include "exporter.h"
|
||||
|
||||
Exporter::Exporter()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#ifndef EXPORTER_H
|
||||
#define EXPORTER_H
|
||||
|
||||
|
||||
class Exporter
|
||||
{
|
||||
public:
|
||||
Exporter();
|
||||
};
|
||||
|
||||
#endif // EXPORTER_H
|
||||
@@ -1,6 +0,0 @@
|
||||
#include "openglexporter.h"
|
||||
|
||||
OpenGLExporter::OpenGLExporter()
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#ifndef OPENGLEXPORTER_H
|
||||
#define OPENGLEXPORTER_H
|
||||
|
||||
|
||||
class OpenGLExporter
|
||||
{
|
||||
public:
|
||||
OpenGLExporter();
|
||||
};
|
||||
|
||||
#endif // OPENGLEXPORTER_H
|
||||
Reference in New Issue
Block a user