From 377e2316be03f41387f995a6d9318b7204be1c0a Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Mon, 16 Dec 2019 16:46:15 +1100 Subject: [PATCH] completed color management implementation This commit adds the background functionality of the render cache invalidating whenever a footage's color space is changed. This includes when the project's configuration is changed as well. --- .../footageproperties/footageproperties.cpp | 1 + app/node/input/media/media.cpp | 29 ++++++++++++++++++- app/node/input/media/media.h | 7 +++++ app/project/item/footage/imagestream.cpp | 21 ++++++++++++-- app/project/item/item.cpp | 15 +++++++++- app/project/item/item.h | 7 +++++ app/project/project.cpp | 1 + app/render/backend/colorprocessorcache.h | 2 +- app/render/backend/opengl/openglworker.cpp | 16 ++++------ app/render/backend/videorenderworker.cpp | 5 ++-- 10 files changed, 85 insertions(+), 19 deletions(-) diff --git a/app/dialog/footageproperties/footageproperties.cpp b/app/dialog/footageproperties/footageproperties.cpp index 94582b53c..c6f40af4d 100644 --- a/app/dialog/footageproperties/footageproperties.cpp +++ b/app/dialog/footageproperties/footageproperties.cpp @@ -31,6 +31,7 @@ #include #include +#include "render/colormanager.h" #include "streamproperties/audiostreamproperties.h" #include "streamproperties/videostreamproperties.h" #include "undo/undostack.h" diff --git a/app/node/input/media/media.cpp b/app/node/input/media/media.cpp index 7bb66f79f..876f32398 100644 --- a/app/node/input/media/media.cpp +++ b/app/node/input/media/media.cpp @@ -20,10 +20,13 @@ #include "media.h" -MediaInput::MediaInput() +MediaInput::MediaInput() : + connected_footage_(nullptr) { footage_input_ = new NodeInput("footage_in"); footage_input_->set_data_type(NodeInput::kFootage); + footage_input_->SetConnectable(false); + connect(footage_input_, SIGNAL(ValueChanged(const rational&, const rational&)), this, SLOT(FootageChanged())); AddInput(footage_input_); } @@ -41,3 +44,27 @@ void MediaInput::Retranslate() { footage_input_->set_name(tr("Footage")); } + +void MediaInput::FootageChanged() +{ + StreamPtr new_footage = footage_input_->get_value_at_time(0).value(); + + if (new_footage == connected_footage_) { + return; + } + + if (connected_footage_ != nullptr) { + disconnect(connected_footage_.get(), SIGNAL(ColorSpaceChanged()), this, SLOT(FootageColorSpaceChanged())); + } + + connected_footage_ = new_footage; + + if (connected_footage_ != nullptr) { + connect(connected_footage_.get(), SIGNAL(ColorSpaceChanged()), this, SLOT(FootageColorSpaceChanged())); + } +} + +void MediaInput::FootageColorSpaceChanged() +{ + InvalidateCache(0, RATIONAL_MAX, footage_input_); +} diff --git a/app/node/input/media/media.h b/app/node/input/media/media.h index be08e14c0..39bdc8dc0 100644 --- a/app/node/input/media/media.h +++ b/app/node/input/media/media.h @@ -41,6 +41,13 @@ public: protected: NodeInput* footage_input_; + StreamPtr connected_footage_; + +private slots: + void FootageChanged(); + + void FootageColorSpaceChanged(); + }; #endif // MEDIAINPUT_H diff --git a/app/project/item/footage/imagestream.cpp b/app/project/item/footage/imagestream.cpp index 48b250299..51a6e72b0 100644 --- a/app/project/item/footage/imagestream.cpp +++ b/app/project/item/footage/imagestream.cpp @@ -20,6 +20,8 @@ #include "imagestream.h" +#include "footage.h" +#include "project/project.h" #include "render/colormanager.h" ImageStream::ImageStream() : @@ -69,7 +71,11 @@ void ImageStream::set_premultiplied_alpha(bool e) const QString &ImageStream::colorspace() { - return colorspace_; + if (colorspace_.isEmpty()) { + return footage()->project()->default_input_colorspace(); + } else { + return colorspace_; + } } void ImageStream::set_colorspace(const QString &color) @@ -81,6 +87,15 @@ void ImageStream::set_colorspace(const QString &color) void ImageStream::ColorConfigChangedSlot() { - // FIXME: Update colorspace correctly - colorspace_.clear(); + // Check if this colorspace is in the new config + if (!colorspace_.isEmpty()) { + QStringList colorspaces = ColorManager::ListAvailableInputColorspaces(OCIO::GetCurrentConfig()); + if (!colorspaces.contains(colorspace_)) { + // Set to empty if not + colorspace_.clear(); + } + } + + // Either way, the color calculation has likely changed so we signal here + emit ColorSpaceChanged(); } diff --git a/app/project/item/item.cpp b/app/project/item/item.cpp index d7ad5b767..c5f3f7b00 100644 --- a/app/project/item/item.cpp +++ b/app/project/item/item.cpp @@ -21,7 +21,8 @@ #include "item.h" Item::Item() : - parent_(nullptr) + parent_(nullptr), + project_(nullptr) { } @@ -127,6 +128,18 @@ const Item *Item::root() const return item; } +Project *Item::project() const +{ + const Item* root_item = root(); + + return root_item->project_; +} + +void Item::set_project(Project *project) +{ + project_ = project; +} + bool Item::CanHaveChildren() const { return false; diff --git a/app/project/item/item.h b/app/project/item/item.h index bb13ef87a..1b1749942 100644 --- a/app/project/item/item.h +++ b/app/project/item/item.h @@ -29,6 +29,8 @@ #include "common/threadedobject.h" +class Project; + class Item; using ItemPtr = std::shared_ptr; @@ -101,6 +103,9 @@ public: Item *parent() const; const Item* root() const; + Project* project() const; + void set_project(Project* project); + virtual bool CanHaveChildren() const; bool ChildExistsWithName(const QString& name); @@ -112,6 +117,8 @@ private: Item* parent_; + Project* project_; + QString name_; QString tooltip_; diff --git a/app/project/project.cpp b/app/project/project.cpp index a811acd2b..f4cda0d84 100644 --- a/app/project/project.cpp +++ b/app/project/project.cpp @@ -23,6 +23,7 @@ Project::Project() { name_ = tr("(untitled)"); + root_.set_project(this); } Folder *Project::root() diff --git a/app/render/backend/colorprocessorcache.h b/app/render/backend/colorprocessorcache.h index 70512d02e..9346b810b 100644 --- a/app/render/backend/colorprocessorcache.h +++ b/app/render/backend/colorprocessorcache.h @@ -5,6 +5,6 @@ #include "render/colorprocessor.h" #include "rendercache.h" -using ColorProcessorCache = RenderCache; +using ColorProcessorCache = RenderCache; #endif // COLORPROCESSORCACHE_H diff --git a/app/render/backend/opengl/openglworker.cpp b/app/render/backend/opengl/openglworker.cpp index 5d74d6c68..4bb7e4c85 100644 --- a/app/render/backend/opengl/openglworker.cpp +++ b/app/render/backend/opengl/openglworker.cpp @@ -55,9 +55,6 @@ bool OpenGLWorker::InitInternal() void OpenGLWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable *table) { - // Set up OCIO context - OpenGLColorProcessorPtr color_processor = std::static_pointer_cast(color_cache()->Get(stream.get())); - // Ensure stream is video or image type if (stream->type() != Stream::kVideo && stream->type() != Stream::kImage) { return; @@ -65,16 +62,13 @@ void OpenGLWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable ImageStreamPtr video_stream = std::static_pointer_cast(stream); - if (!color_processor) { - QString input_colorspace = video_stream->colorspace(); - if (input_colorspace.isEmpty()) { - // FIXME: Should use Stream->Footage to find the Project* since that's a direct chain - input_colorspace = olive::core.GetActiveProject()->default_input_colorspace(); - } + // Set up OCIO context + OpenGLColorProcessorPtr color_processor = std::static_pointer_cast(color_cache()->Get(video_stream->colorspace())); - color_processor = OpenGLColorProcessor::CreateOpenGL(input_colorspace, + if (!color_processor) { + color_processor = OpenGLColorProcessor::CreateOpenGL(video_stream->colorspace(), OCIO::ROLE_SCENE_LINEAR); - color_cache()->Add(stream.get(), color_processor); + color_cache()->Add(video_stream->colorspace(), color_processor); } // OCIO's CPU conversion is more accurate, so for online we render on CPU but offline we render GPU diff --git a/app/render/backend/videorenderworker.cpp b/app/render/backend/videorenderworker.cpp index 806fba049..ee00ff8d9 100644 --- a/app/render/backend/videorenderworker.cpp +++ b/app/render/backend/videorenderworker.cpp @@ -2,6 +2,7 @@ #include "common/define.h" #include "node/node.h" +#include "project/project.h" #include "render/pixelservice.h" VideoRenderWorker::VideoRenderWorker(VideoRenderFrameCache *frame_cache, QObject *parent) : @@ -102,8 +103,8 @@ void VideoRenderWorker::HashNodeRecursively(QCryptographicHash *hash, const Node // Footage timestamp hash->addData(QString::number(decoder->GetTimestampFromTime(input_time)).toUtf8()); - // Current colorspace - // FIXME: Handle empty colorspace... + // Current color config and space + hash->addData(video_stream->footage()->project()->ocio_config().toUtf8()); hash->addData(video_stream->colorspace().toUtf8()); // Alpha associated setting