exporter: updated exporter to function with new render system
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
#include "export.h"
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QFileDialog>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
@@ -12,7 +11,7 @@
|
||||
|
||||
#include "project/item/sequence/sequence.h"
|
||||
#include "project/project.h"
|
||||
#include "render/backend/opengl/openglexporter.h"
|
||||
#include "render/backend/exporter.h"
|
||||
#include "render/pixelservice.h"
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
@@ -27,8 +26,8 @@ ExportDialog::ExportDialog(ViewerOutput *viewer_node, QWidget *parent) :
|
||||
splitter->setChildrenCollapsible(false);
|
||||
layout->addWidget(splitter);
|
||||
|
||||
QWidget* preferences_area = new QWidget();
|
||||
QGridLayout* preferences_layout = new QGridLayout(preferences_area);
|
||||
preferences_area_ = new QWidget();
|
||||
QGridLayout* preferences_layout = new QGridLayout(preferences_area_);
|
||||
|
||||
int row = 0;
|
||||
|
||||
@@ -120,15 +119,15 @@ ExportDialog::ExportDialog(ViewerOutput *viewer_node, QWidget *parent) :
|
||||
|
||||
row++;
|
||||
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox();
|
||||
buttons->setCenterButtons(true);
|
||||
buttons->addButton(tr("Export"), QDialogButtonBox::AcceptRole);
|
||||
buttons->addButton(QDialogButtonBox::Cancel);
|
||||
connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttons, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
preferences_layout->addWidget(buttons, row, 0, 1, 4);
|
||||
buttons_ = new QDialogButtonBox();
|
||||
buttons_->setCenterButtons(true);
|
||||
buttons_->addButton(tr("Export"), QDialogButtonBox::AcceptRole);
|
||||
buttons_->addButton(QDialogButtonBox::Cancel);
|
||||
connect(buttons_, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
connect(buttons_, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
preferences_layout->addWidget(buttons_, row, 0, 1, 4);
|
||||
|
||||
splitter->addWidget(preferences_area);
|
||||
splitter->addWidget(preferences_area_);
|
||||
|
||||
QWidget* preview_area = new QWidget();
|
||||
QVBoxLayout* preview_layout = new QVBoxLayout(preview_area);
|
||||
@@ -242,7 +241,7 @@ void ExportDialog::accept()
|
||||
|
||||
Encoder* encoder = Encoder::CreateFromID("ffmpeg", encoding_params);
|
||||
|
||||
OpenGLExporter* exporter = new OpenGLExporter(viewer_node_, encoder);
|
||||
Exporter* exporter = new Exporter(viewer_node_, encoder);
|
||||
|
||||
if (video_enabled_->isChecked()) {
|
||||
exporter->EnableVideo(video_render_params, transform, color_processor);
|
||||
@@ -256,6 +255,8 @@ void ExportDialog::accept()
|
||||
connect(exporter, &Exporter::ProgressChanged, progress_bar_, &QProgressBar::setValue);
|
||||
|
||||
QMetaObject::invokeMethod(exporter, "StartExporting", Qt::QueuedConnection);
|
||||
|
||||
SetUIElementsEnabled(false);
|
||||
}
|
||||
|
||||
void ExportDialog::closeEvent(QCloseEvent *e)
|
||||
@@ -442,6 +443,12 @@ QMatrix4x4 ExportDialog::GenerateMatrix(ExportVideoTab::ScalingMethod method, in
|
||||
return preview_matrix;
|
||||
}
|
||||
|
||||
void ExportDialog::SetUIElementsEnabled(bool enabled)
|
||||
{
|
||||
preferences_area_->setEnabled(enabled);
|
||||
//buttons_->setEnabled(false);
|
||||
}
|
||||
|
||||
void ExportDialog::UpdateViewerDimensions()
|
||||
{
|
||||
preview_viewer_->SetOverrideSize(static_cast<int>(video_tab_->width_slider()->GetValue()),
|
||||
@@ -461,12 +468,16 @@ void ExportDialog::ExporterIsDone()
|
||||
if (exporter->GetExportStatus()) {
|
||||
QMessageBox::information(this,
|
||||
tr("Export Status"),
|
||||
tr("Export completed successfully!"),
|
||||
tr("Export completed successfully."),
|
||||
QMessageBox::Ok);
|
||||
|
||||
QDialog::accept();
|
||||
} else {
|
||||
QMessageBox::critical(this,
|
||||
tr("Export Status"),
|
||||
tr("Export failed: %1").arg(exporter->GetExportError()),
|
||||
QMessageBox::Ok);
|
||||
|
||||
SetUIElementsEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLineEdit>
|
||||
#include <QProgressBar>
|
||||
|
||||
@@ -31,6 +32,8 @@ private:
|
||||
|
||||
QMatrix4x4 GenerateMatrix(ExportVideoTab::ScalingMethod method, int source_width, int source_height, int dest_width, int height);
|
||||
|
||||
void SetUIElementsEnabled(bool enabled);
|
||||
|
||||
ViewerOutput* viewer_node_;
|
||||
|
||||
QList<ExportFormat> formats_;
|
||||
@@ -54,6 +57,9 @@ private:
|
||||
|
||||
QProgressBar* progress_bar_;
|
||||
|
||||
QWidget* preferences_area_;
|
||||
QDialogButtonBox* buttons_;
|
||||
|
||||
enum Format {
|
||||
kFormatDNxHD,
|
||||
kFormatMatroska,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "exporter.h"
|
||||
|
||||
#include "render/backend/audio/audiobackend.h"
|
||||
#include "render/backend/opengl/openglbackend.h"
|
||||
#include "render/colormanager.h"
|
||||
#include "render/pixelservice.h"
|
||||
|
||||
@@ -50,15 +52,11 @@ void Exporter::StartExporting()
|
||||
// Default to error state until ExportEnd is called
|
||||
export_status_ = false;
|
||||
|
||||
// Create renderers
|
||||
if (!Initialize()) {
|
||||
SetExportMessage("Failed to initialize exporter");
|
||||
ExportFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create renderers
|
||||
if (!video_done_) {
|
||||
video_backend_ = new OpenGLBackend();
|
||||
|
||||
video_backend_->SetLimitCaching(false);
|
||||
video_backend_->SetViewerNode(viewer_node_);
|
||||
video_backend_->SetParameters(VideoRenderingParams(viewer_node_->video_params().width(),
|
||||
viewer_node_->video_params().height(),
|
||||
@@ -70,6 +68,8 @@ void Exporter::StartExporting()
|
||||
}
|
||||
|
||||
if (!audio_done_) {
|
||||
audio_backend_ = new AudioBackend();
|
||||
|
||||
audio_backend_->SetViewerNode(viewer_node_);
|
||||
audio_backend_->SetParameters(audio_params_);
|
||||
}
|
||||
@@ -96,8 +96,6 @@ void Exporter::ExportSucceeded()
|
||||
return;
|
||||
}
|
||||
|
||||
Cleanup();
|
||||
|
||||
if (video_backend_) {
|
||||
video_backend_->deleteLater();
|
||||
}
|
||||
@@ -116,74 +114,64 @@ void Exporter::ExportFailed()
|
||||
emit ExportEnded();
|
||||
}
|
||||
|
||||
void Exporter::EncodeFrame(const rational &time, QVariant value)
|
||||
void Exporter::EncodeFrame()
|
||||
{
|
||||
if (time == waiting_for_frame_) {
|
||||
bool get_cached = false;
|
||||
while (cached_frames_.contains(waiting_for_frame_)) {
|
||||
FramePtr frame = cached_frames_.take(waiting_for_frame_);
|
||||
|
||||
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() != PixelFormat::PIX_FMT_RGBA32F) {
|
||||
frame = PixelService::ConvertPixelFormat(frame, PixelFormat::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);
|
||||
|
||||
// Set frame timestamp
|
||||
frame->set_timestamp(waiting_for_frame_);
|
||||
|
||||
// Encode (may require re-associating alpha?)
|
||||
QMetaObject::invokeMethod(encoder_,
|
||||
"WriteFrame",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(FramePtr, frame));
|
||||
|
||||
waiting_for_frame_ += video_params_.time_base();
|
||||
|
||||
// Calculate progress
|
||||
int progress = qRound(100.0 * (waiting_for_frame_.toDouble() / viewer_node_->Length().toDouble()));
|
||||
emit ProgressChanged(progress);
|
||||
|
||||
} while (cached_frames_.contains(waiting_for_frame_));
|
||||
|
||||
if (waiting_for_frame_ >= viewer_node_->Length()) {
|
||||
video_done_ = true;
|
||||
|
||||
ExportSucceeded();
|
||||
// OCIO conversion requires a frame in 32F format
|
||||
if (frame->format() != PixelFormat::PIX_FMT_RGBA32F) {
|
||||
frame = PixelService::ConvertPixelFormat(frame, PixelFormat::PIX_FMT_RGBA32F);
|
||||
}
|
||||
} else {
|
||||
cached_frames_.insert(time, value);
|
||||
|
||||
// Color conversion must be done with unassociated alpha, and the pipeline is always associated
|
||||
ColorManager::DisassociateAlpha(frame);
|
||||
|
||||
// Convert color space
|
||||
color_processor_->ConvertFrame(frame);
|
||||
|
||||
// Set frame timestamp
|
||||
frame->set_timestamp(waiting_for_frame_);
|
||||
|
||||
// Encode (may require re-associating alpha?)
|
||||
QMetaObject::invokeMethod(encoder_,
|
||||
"WriteFrame",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(FramePtr, frame));
|
||||
|
||||
waiting_for_frame_ += video_params_.time_base();
|
||||
|
||||
// Calculate progress
|
||||
int progress = qRound(100.0 * (waiting_for_frame_.toDouble() / viewer_node_->Length().toDouble()));
|
||||
emit ProgressChanged(progress);
|
||||
}
|
||||
|
||||
if (waiting_for_frame_ >= viewer_node_->Length()) {
|
||||
video_done_ = true;
|
||||
|
||||
ExportSucceeded();
|
||||
}
|
||||
}
|
||||
|
||||
void Exporter::FrameRendered(const rational &time, QVariant value)
|
||||
void Exporter::FrameRendered(const rational &time, FramePtr value)
|
||||
{
|
||||
qDebug() << "Received" << time.toDouble() << "- waiting for" << waiting_for_frame_.toDouble();
|
||||
|
||||
const QMap<rational, QByteArray>& time_hash_map = video_backend_->frame_cache()->time_hash_map();
|
||||
|
||||
QByteArray map_hash = time_hash_map.value(time);
|
||||
QByteArray this_hash = time_hash_map.value(time);
|
||||
|
||||
EncodeFrame(time, value);
|
||||
qDebug() << "Received" << this_hash.toHex();
|
||||
|
||||
QList<rational> matching_times = time_hash_map.keys(this_hash);
|
||||
|
||||
QList<rational> matching_times = matched_frames_.value(map_hash);
|
||||
foreach (const rational& t, matching_times) {
|
||||
qDebug() << " Also matches" << t;
|
||||
EncodeFrame(t, value);
|
||||
qDebug() << " Matches" << t.toDouble();
|
||||
|
||||
cached_frames_.insert(t, value);
|
||||
}
|
||||
|
||||
qDebug() << " Waiting for" << waiting_for_frame_.toDouble();
|
||||
|
||||
EncodeFrame();
|
||||
}
|
||||
|
||||
void Exporter::AudioRendered()
|
||||
@@ -279,7 +267,7 @@ void Exporter::VideoHashesComplete()
|
||||
video_backend_->SetOnlySignalLastFrameRequested(false);
|
||||
|
||||
// FIXME: Exporting is now broken because of this
|
||||
//connect(video_backend_, &VideoRenderBackend::CachedFrameReady, this, &Exporter::FrameRendered);
|
||||
connect(video_backend_, &VideoRenderBackend::GeneratedFrame, this, &Exporter::FrameRendered);
|
||||
|
||||
foreach (const TimeRange& range, ranges) {
|
||||
video_backend_->InvalidateCache(range);
|
||||
|
||||
@@ -34,11 +34,6 @@ signals:
|
||||
void ExportEnded();
|
||||
|
||||
protected:
|
||||
virtual bool Initialize() = 0;
|
||||
virtual void Cleanup() = 0;
|
||||
|
||||
virtual FramePtr TextureToFrame(const QVariant &texture) = 0;
|
||||
|
||||
void SetExportMessage(const QString& s);
|
||||
|
||||
// Renderers
|
||||
@@ -64,7 +59,7 @@ private:
|
||||
|
||||
void ExportFailed();
|
||||
|
||||
void EncodeFrame(const rational &time, QVariant value);
|
||||
void EncodeFrame();
|
||||
|
||||
ColorProcessorPtr color_processor_;
|
||||
|
||||
@@ -76,12 +71,12 @@ private:
|
||||
|
||||
rational waiting_for_frame_;
|
||||
|
||||
QHash<rational, QVariant> cached_frames_;
|
||||
QHash<rational, FramePtr> cached_frames_;
|
||||
|
||||
QHash< QByteArray, QList<rational> > matched_frames_;
|
||||
|
||||
private slots:
|
||||
void FrameRendered(const rational& time, QVariant value);
|
||||
void FrameRendered(const rational &time, FramePtr value);
|
||||
|
||||
void AudioRendered();
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ set(OLIVE_SOURCES
|
||||
render/backend/opengl/openglbackend.cpp
|
||||
render/backend/opengl/openglcolorprocessor.h
|
||||
render/backend/opengl/openglcolorprocessor.cpp
|
||||
render/backend/opengl/openglexporter.h
|
||||
render/backend/opengl/openglexporter.cpp
|
||||
render/backend/opengl/openglframebuffer.h
|
||||
render/backend/opengl/openglframebuffer.cpp
|
||||
render/backend/opengl/openglproxy.h
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
#include "openglexporter.h"
|
||||
|
||||
#include "render/backend/opengl/openglrenderfunctions.h"
|
||||
#include "render/pixelservice.h"
|
||||
|
||||
OpenGLExporter::OpenGLExporter(ViewerOutput* viewer, Encoder *encoder, QObject* parent) :
|
||||
Exporter(viewer, encoder, parent),
|
||||
texture_(nullptr),
|
||||
pipeline_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
OpenGLExporter::~OpenGLExporter()
|
||||
{
|
||||
}
|
||||
|
||||
bool OpenGLExporter::Initialize()
|
||||
{
|
||||
QOpenGLContext* ctx = QOpenGLContext::currentContext();
|
||||
|
||||
// Create rendering backends
|
||||
if (!video_done_) {
|
||||
video_backend_ = new OpenGLBackend();
|
||||
|
||||
// Create blitting framebuffer and texture
|
||||
buffer_.Create(ctx);
|
||||
|
||||
texture_ = std::make_shared<OpenGLTexture>();
|
||||
texture_->Create(ctx, video_params_.effective_width(), video_params_.effective_height(), video_params_.format());
|
||||
|
||||
pipeline_ = OpenGLShader::CreateDefault();
|
||||
}
|
||||
|
||||
if (!audio_done_) {
|
||||
audio_backend_ = new AudioBackend();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpenGLExporter::Cleanup()
|
||||
{
|
||||
if (texture_) {
|
||||
texture_->Destroy();
|
||||
texture_ = nullptr;
|
||||
}
|
||||
|
||||
pipeline_ = nullptr;
|
||||
|
||||
buffer_.Destroy();
|
||||
}
|
||||
|
||||
FramePtr OpenGLExporter::TextureToFrame(const QVariant& texture)
|
||||
{
|
||||
FramePtr frame = Frame::Create();
|
||||
frame->set_width(video_params_.width());
|
||||
frame->set_height(video_params_.height());
|
||||
frame->set_format(video_params_.format());
|
||||
frame->allocate();
|
||||
|
||||
// Blit for transform if the width/height are different
|
||||
OpenGLTexturePtr input_tex = texture.value<OpenGLTexturePtr>();
|
||||
if (input_tex) {
|
||||
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
|
||||
f->glViewport(0, 0, texture_->width(), texture_->height());
|
||||
|
||||
buffer_.Attach(texture_);
|
||||
buffer_.Bind();
|
||||
input_tex->Bind();
|
||||
|
||||
OpenGLRenderFunctions::Blit(pipeline_, false, transform_);
|
||||
|
||||
input_tex->Release();
|
||||
buffer_.Release();
|
||||
buffer_.Detach();
|
||||
|
||||
// Perform OpenGL read
|
||||
buffer_.Attach(texture_);
|
||||
buffer_.Bind();
|
||||
|
||||
PixelFormat::Info format_info = PixelService::GetPixelFormatInfo(video_params_.format());
|
||||
|
||||
f->glReadPixels(0,
|
||||
0,
|
||||
texture_->width(),
|
||||
texture_->height(),
|
||||
format_info.pixel_format,
|
||||
format_info.gl_pixel_type,
|
||||
frame->data());
|
||||
|
||||
buffer_.Release();
|
||||
buffer_.Detach();
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
#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,
|
||||
Encoder* encoder,
|
||||
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
|
||||
@@ -380,7 +380,7 @@ void OpenGLProxy::RunNodeAccelerated(const Node *node, const TimeRange &range, c
|
||||
output_params->Push(NodeParam::kTexture, QVariant::fromValue(output_tex));
|
||||
}
|
||||
|
||||
void OpenGLProxy::TextureToBuffer(const QVariant &tex_in, QByteArray &buffer)
|
||||
void OpenGLProxy::TextureToBuffer(const QVariant &tex_in, void *buffer)
|
||||
{
|
||||
OpenGLTextureCache::ReferencePtr texture = tex_in.value<OpenGLTextureCache::ReferencePtr>();
|
||||
|
||||
@@ -396,7 +396,7 @@ void OpenGLProxy::TextureToBuffer(const QVariant &tex_in, QByteArray &buffer)
|
||||
video_params_.effective_height(),
|
||||
format_info.pixel_format,
|
||||
format_info.gl_pixel_type,
|
||||
buffer.data());
|
||||
buffer);
|
||||
|
||||
buffer_.Release();
|
||||
buffer_.Detach();
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
|
||||
void RunNodeAccelerated(const Node *node, const TimeRange &range, const NodeValueDatabase &input_params, NodeValueTable* output_params);
|
||||
|
||||
void TextureToBuffer(const QVariant& texture, QByteArray& buffer);
|
||||
void TextureToBuffer(const QVariant& texture, void *buffer);
|
||||
|
||||
void SetParameters(const VideoRenderingParams& params);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ void OpenGLWorker::RunNodeAccelerated(const Node *node, const TimeRange &range,
|
||||
emit RequestRunNodeAccelerated(node, range, input_params, output_params);
|
||||
}
|
||||
|
||||
void OpenGLWorker::TextureToBuffer(const QVariant &tex_in, QByteArray &buffer)
|
||||
void OpenGLWorker::TextureToBuffer(const QVariant &tex_in, void *buffer)
|
||||
{
|
||||
emit RequestTextureToBuffer(tex_in, buffer);
|
||||
}
|
||||
|
||||
@@ -20,14 +20,14 @@ signals:
|
||||
|
||||
void RequestRunNodeAccelerated(const Node *node, const TimeRange &range, const NodeValueDatabase &input_params, NodeValueTable* output_params);
|
||||
|
||||
void RequestTextureToBuffer(const QVariant& texture, QByteArray& buffer);
|
||||
void RequestTextureToBuffer(const QVariant& texture, void *buffer);
|
||||
|
||||
protected:
|
||||
virtual void FrameToValue(DecoderPtr decoder, StreamPtr stream, const TimeRange &range, NodeValueTable* table) override;
|
||||
|
||||
virtual void RunNodeAccelerated(const Node *node, const TimeRange &range, const NodeValueDatabase &input_params, NodeValueTable* output_params) override;
|
||||
|
||||
virtual void TextureToBuffer(const QVariant& texture, QByteArray& buffer) override;
|
||||
virtual void TextureToBuffer(const QVariant& texture, void *buffer) override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
VideoRenderBackend::VideoRenderBackend(QObject *parent) :
|
||||
RenderBackend(parent),
|
||||
operating_mode_(VideoRenderWorker::kHashRenderCache),
|
||||
only_signal_last_frame_requested_(true)
|
||||
only_signal_last_frame_requested_(true),
|
||||
limit_caching_(true)
|
||||
{
|
||||
connect(DiskManager::instance(), &DiskManager::DeletedFrame, this, &VideoRenderBackend::FrameRemovedFromDiskCache);
|
||||
}
|
||||
@@ -108,6 +109,11 @@ bool VideoRenderBackend::IsRendered(const rational &time) const
|
||||
return !TimeIsQueued(range) && !render_job_info_.contains(range);
|
||||
}
|
||||
|
||||
void VideoRenderBackend::SetLimitCaching(bool limit)
|
||||
{
|
||||
limit_caching_ = limit;
|
||||
}
|
||||
|
||||
bool VideoRenderBackend::GenerateCacheIDInternal(QCryptographicHash& hash)
|
||||
{
|
||||
if (!params_.is_valid()) {
|
||||
@@ -138,6 +144,7 @@ void VideoRenderBackend::ConnectWorkerToThis(RenderWorker *processor)
|
||||
connect(video_processor, &VideoRenderWorker::HashAlreadyBeingCached, this, &VideoRenderBackend::ThreadSkippedFrame, Qt::QueuedConnection);
|
||||
connect(video_processor, &VideoRenderWorker::CompletedDownload, this, &VideoRenderBackend::ThreadCompletedDownload, Qt::QueuedConnection);
|
||||
connect(video_processor, &VideoRenderWorker::HashAlreadyExists, this, &VideoRenderBackend::ThreadHashAlreadyExists, Qt::QueuedConnection);
|
||||
connect(video_processor, &VideoRenderWorker::GeneratedFrame, this, &VideoRenderBackend::GeneratedFrame, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void VideoRenderBackend::InvalidateCacheInternal(const rational &start_range, const rational &end_range)
|
||||
@@ -371,13 +378,19 @@ bool VideoRenderBackend::SetFrameHash(const NodeDependency &dep, const QByteArra
|
||||
|
||||
void VideoRenderBackend::Requeue()
|
||||
{
|
||||
cache_queue_.clear();
|
||||
if (limit_caching_) {
|
||||
|
||||
// Reset queue around the last time requested
|
||||
TimeRange queueable_range(last_time_requested_ - Config::Current()["DiskCacheBehind"].value<rational>(),
|
||||
last_time_requested_ + Config::Current()["DiskCacheAhead"].value<rational>());
|
||||
// Reset queue around the last time requested
|
||||
TimeRange queueable_range(last_time_requested_ - Config::Current()["DiskCacheBehind"].value<rational>(),
|
||||
last_time_requested_ + Config::Current()["DiskCacheAhead"].value<rational>());
|
||||
|
||||
cache_queue_ = invalidated_.Intersects(queueable_range);
|
||||
cache_queue_ = invalidated_.Intersects(queueable_range);
|
||||
|
||||
} else {
|
||||
|
||||
cache_queue_ = invalidated_;
|
||||
|
||||
}
|
||||
|
||||
CacheNext();
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ public:
|
||||
|
||||
bool IsRendered(const rational& time) const;
|
||||
|
||||
void SetLimitCaching(bool limit);
|
||||
|
||||
QString GetCachedFrame(const rational& time);
|
||||
|
||||
VideoRenderFrameCache* frame_cache();
|
||||
@@ -102,6 +104,8 @@ signals:
|
||||
|
||||
void RangeInvalidated(const TimeRange& range);
|
||||
|
||||
void GeneratedFrame(const rational &time, FramePtr frame);
|
||||
|
||||
private:
|
||||
bool TimeIsQueued(const TimeRange &time) const;
|
||||
|
||||
@@ -121,6 +125,8 @@ private:
|
||||
|
||||
bool only_signal_last_frame_requested_;
|
||||
|
||||
bool limit_caching_;
|
||||
|
||||
private slots:
|
||||
void ThreadCompletedFrame(NodeDependency path, qint64 job_time, QByteArray hash, QVariant value);
|
||||
void ThreadCompletedDownload(NodeDependency dep, qint64 job_time, QByteArray hash, bool texture_existed);
|
||||
|
||||
@@ -66,14 +66,14 @@ NodeValueTable VideoRenderWorker::RenderInternal(const NodeDependency& path, con
|
||||
emit CompletedFrame(path, job_time, hash, texture);
|
||||
|
||||
// If we actually have a texture, download it into the disk cache
|
||||
if ((operating_mode_ & kDownloadOnly) && !texture.isNull()) {
|
||||
Download(texture, frame_cache_->CachePathName(hash, video_params_.format()));
|
||||
if (!texture.isNull()) {
|
||||
Download(path.in(), texture, frame_cache_->CachePathName(hash, video_params_.format()));
|
||||
}
|
||||
|
||||
frame_cache_->RemoveHashFromCurrentlyCaching(hash);
|
||||
|
||||
// Signal that this job is complete
|
||||
if (operating_mode_ & kDownloadOnly) {
|
||||
// Signal that this job is complete
|
||||
emit CompletedDownload(path, job_time, hash, !texture.isNull());
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ void VideoRenderWorker::CloseInternal()
|
||||
download_buffer_.clear();
|
||||
}
|
||||
|
||||
void VideoRenderWorker::Download(QVariant texture, QString filename)
|
||||
void VideoRenderWorker::Download(const rational& time, QVariant texture, QString filename)
|
||||
{
|
||||
PixelFormat::Info format_info = PixelService::GetPixelFormatInfo(video_params().format());
|
||||
|
||||
@@ -236,25 +236,41 @@ void VideoRenderWorker::Download(QVariant texture, QString filename)
|
||||
spec.attribute("compression", "dwaa:200");
|
||||
}
|
||||
|
||||
TextureToBuffer(texture, download_buffer_);
|
||||
if (operating_mode_ & kDownloadOnly) {
|
||||
|
||||
std::string working_fn_std = filename.toStdString();
|
||||
TextureToBuffer(texture, download_buffer_.data());
|
||||
|
||||
auto out = OIIO::ImageOutput::create(working_fn_std);
|
||||
std::string working_fn_std = filename.toStdString();
|
||||
|
||||
// Keep export to this thread only
|
||||
out->threads(1);
|
||||
auto out = OIIO::ImageOutput::create(working_fn_std);
|
||||
|
||||
if (out) {
|
||||
out->open(working_fn_std, spec);
|
||||
out->write_image(format_info.oiio_desc, download_buffer_.data());
|
||||
out->close();
|
||||
// Keep export to this thread only
|
||||
out->threads(1);
|
||||
|
||||
if (out) {
|
||||
out->open(working_fn_std, spec);
|
||||
out->write_image(format_info.oiio_desc, download_buffer_.data());
|
||||
out->close();
|
||||
|
||||
#if OIIO_VERSION < 10903
|
||||
OIIO::ImageOutput::destroy(out);
|
||||
OIIO::ImageOutput::destroy(out);
|
||||
#endif
|
||||
} else {
|
||||
qWarning() << "Failed to open output file:" << filename;
|
||||
}
|
||||
|
||||
} else {
|
||||
qWarning() << "Failed to open output file:" << filename;
|
||||
|
||||
FramePtr frame = Frame::Create();
|
||||
frame->set_width(video_params().width());
|
||||
frame->set_height(video_params().height());
|
||||
frame->set_format(video_params().format());
|
||||
frame->allocate();
|
||||
|
||||
TextureToBuffer(texture, frame->data());
|
||||
|
||||
emit GeneratedFrame(time, frame);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ signals:
|
||||
|
||||
void HashAlreadyExists(NodeDependency CurrentPath, qint64 job_time, QByteArray hash);
|
||||
|
||||
void GeneratedFrame(const rational &time, FramePtr frame);
|
||||
|
||||
void Aborted();
|
||||
|
||||
protected:
|
||||
@@ -67,7 +69,7 @@ protected:
|
||||
|
||||
virtual void ParametersChangedEvent(){}
|
||||
|
||||
virtual void TextureToBuffer(const QVariant& texture, QByteArray& buffer) = 0;
|
||||
virtual void TextureToBuffer(const QVariant& texture, void *buffer) = 0;
|
||||
|
||||
virtual NodeValueTable RenderInternal(const NodeDependency& CurrentPath, const qint64& job_time) override;
|
||||
|
||||
@@ -80,7 +82,7 @@ protected:
|
||||
private:
|
||||
void HashNodeRecursively(QCryptographicHash* hash, const Node *n, const rational &time);
|
||||
|
||||
void Download(QVariant texture, QString filename);
|
||||
void Download(const rational &time, QVariant texture, QString filename);
|
||||
|
||||
void ResizeDownloadBuffer();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user