From 78daf9e28ae552b74a1b9e0d9d3e9c32cca8a155 Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Tue, 25 Feb 2020 20:03:15 +1100 Subject: [PATCH] exporter: updated exporter to function with new render system --- app/dialog/export/export.cpp | 39 +++--- app/dialog/export/export.h | 6 + app/render/backend/exporter.cpp | 118 +++++++++---------- app/render/backend/exporter.h | 11 +- app/render/backend/opengl/CMakeLists.txt | 2 - app/render/backend/opengl/openglexporter.cpp | 96 --------------- app/render/backend/opengl/openglexporter.h | 35 ------ app/render/backend/opengl/openglproxy.cpp | 4 +- app/render/backend/opengl/openglproxy.h | 2 +- app/render/backend/opengl/openglworker.cpp | 2 +- app/render/backend/opengl/openglworker.h | 4 +- app/render/backend/videorenderbackend.cpp | 25 +++- app/render/backend/videorenderbackend.h | 6 + app/render/backend/videorenderworker.cpp | 46 +++++--- app/render/backend/videorenderworker.h | 6 +- 15 files changed, 153 insertions(+), 249 deletions(-) delete mode 100644 app/render/backend/opengl/openglexporter.cpp delete mode 100644 app/render/backend/opengl/openglexporter.h diff --git a/app/dialog/export/export.cpp b/app/dialog/export/export.cpp index d45a03ebc..c6b8a4582 100644 --- a/app/dialog/export/export.cpp +++ b/app/dialog/export/export.cpp @@ -1,6 +1,5 @@ #include "export.h" -#include #include #include #include @@ -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(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); } } diff --git a/app/dialog/export/export.h b/app/dialog/export/export.h index dc4af5133..c0ff94903 100644 --- a/app/dialog/export/export.h +++ b/app/dialog/export/export.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -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 formats_; @@ -54,6 +57,9 @@ private: QProgressBar* progress_bar_; + QWidget* preferences_area_; + QDialogButtonBox* buttons_; + enum Format { kFormatDNxHD, kFormatMatroska, diff --git a/app/render/backend/exporter.cpp b/app/render/backend/exporter.cpp index 231bf27a1..cabaca780 100644 --- a/app/render/backend/exporter.cpp +++ b/app/render/backend/exporter.cpp @@ -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& 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 matching_times = time_hash_map.keys(this_hash); - QList 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); diff --git a/app/render/backend/exporter.h b/app/render/backend/exporter.h index eeac9c181..f5b111372 100644 --- a/app/render/backend/exporter.h +++ b/app/render/backend/exporter.h @@ -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 cached_frames_; + QHash cached_frames_; QHash< QByteArray, QList > matched_frames_; private slots: - void FrameRendered(const rational& time, QVariant value); + void FrameRendered(const rational &time, FramePtr value); void AudioRendered(); diff --git a/app/render/backend/opengl/CMakeLists.txt b/app/render/backend/opengl/CMakeLists.txt index e00ae7620..e2972b85f 100644 --- a/app/render/backend/opengl/CMakeLists.txt +++ b/app/render/backend/opengl/CMakeLists.txt @@ -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 diff --git a/app/render/backend/opengl/openglexporter.cpp b/app/render/backend/opengl/openglexporter.cpp deleted file mode 100644 index 6942b5294..000000000 --- a/app/render/backend/opengl/openglexporter.cpp +++ /dev/null @@ -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(); - 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(); - 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; -} diff --git a/app/render/backend/opengl/openglexporter.h b/app/render/backend/opengl/openglexporter.h deleted file mode 100644 index 868e8b15e..000000000 --- a/app/render/backend/opengl/openglexporter.h +++ /dev/null @@ -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 diff --git a/app/render/backend/opengl/openglproxy.cpp b/app/render/backend/opengl/openglproxy.cpp index 262a98ef8..de72d1ee8 100644 --- a/app/render/backend/opengl/openglproxy.cpp +++ b/app/render/backend/opengl/openglproxy.cpp @@ -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(); @@ -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(); diff --git a/app/render/backend/opengl/openglproxy.h b/app/render/backend/opengl/openglproxy.h index 6e77a2a9d..d1b397706 100644 --- a/app/render/backend/opengl/openglproxy.h +++ b/app/render/backend/opengl/openglproxy.h @@ -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); diff --git a/app/render/backend/opengl/openglworker.cpp b/app/render/backend/opengl/openglworker.cpp index 14580fea2..b3d364628 100644 --- a/app/render/backend/opengl/openglworker.cpp +++ b/app/render/backend/opengl/openglworker.cpp @@ -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); } diff --git a/app/render/backend/opengl/openglworker.h b/app/render/backend/opengl/openglworker.h index 914f839a8..fc5bdd0d5 100644 --- a/app/render/backend/opengl/openglworker.h +++ b/app/render/backend/opengl/openglworker.h @@ -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; }; diff --git a/app/render/backend/videorenderbackend.cpp b/app/render/backend/videorenderbackend.cpp index 23331e808..0ebf86f22 100644 --- a/app/render/backend/videorenderbackend.cpp +++ b/app/render/backend/videorenderbackend.cpp @@ -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(), - last_time_requested_ + Config::Current()["DiskCacheAhead"].value()); + // Reset queue around the last time requested + TimeRange queueable_range(last_time_requested_ - Config::Current()["DiskCacheBehind"].value(), + last_time_requested_ + Config::Current()["DiskCacheAhead"].value()); - cache_queue_ = invalidated_.Intersects(queueable_range); + cache_queue_ = invalidated_.Intersects(queueable_range); + + } else { + + cache_queue_ = invalidated_; + + } CacheNext(); } diff --git a/app/render/backend/videorenderbackend.h b/app/render/backend/videorenderbackend.h index ada89920c..517232782 100644 --- a/app/render/backend/videorenderbackend.h +++ b/app/render/backend/videorenderbackend.h @@ -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); diff --git a/app/render/backend/videorenderworker.cpp b/app/render/backend/videorenderworker.cpp index b33b69e39..951f2926f 100644 --- a/app/render/backend/videorenderworker.cpp +++ b/app/render/backend/videorenderworker.cpp @@ -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); + } } diff --git a/app/render/backend/videorenderworker.h b/app/render/backend/videorenderworker.h index 007a5fed2..0520f8412 100644 --- a/app/render/backend/videorenderworker.h +++ b/app/render/backend/videorenderworker.h @@ -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();