moved ColorManager to a node

Reduces code by reusing the existing node infrastructure. Also
helps prevent race conditions since the node/render system is
designed for multithreading.
This commit is contained in:
itsmattkc
2021-02-18 14:33:08 +11:00
parent e0e4e42096
commit cc9747ede4
11 changed files with 183 additions and 151 deletions
@@ -195,8 +195,10 @@ void ProjectPropertiesDialog::accept()
}
// This should ripple changes throughout the program that the color config has changed, therefore must be done last
working_project_->color_manager()->SetConfigAndDefaultInput(ocio_filename_->text(),
default_input_colorspace_->currentText());
ColorManager* color_manager = working_project_->color_manager();
color_manager->SetConfigFilename(ocio_filename_->text());
color_manager->SetDefaultInputColorSpace(default_input_colorspace_->currentText());
QDialog::accept();
}
+12 -4
View File
@@ -156,6 +156,15 @@ void Footage::InputValueChangedEvent(const QString &input, int element)
}
}
QString Footage::GetColorspaceToUse(const VideoParams &params) const
{
if (params.colorspace().isEmpty()) {
return project()->color_manager()->GetDefaultInputColorSpace();
} else {
return params.colorspace();
}
}
Footage::StreamReference Footage::GetReferenceFromOutput(const QString &s) const
{
Stream::Type type;
@@ -525,7 +534,7 @@ void Footage::Hash(const QString& output, QCryptographicHash &hash, const ration
if (ref.type() == Stream::kVideo) {
// Current color config and space
hash.addData(project()->color_manager()->GetConfigFilename().toUtf8());
hash.addData(params.colorspace().toUtf8());
hash.addData(GetColorspaceToUse(params).toUtf8());
// Alpha associated setting
hash.addData(QString::number(params.premultiplied_alpha()).toUtf8());
@@ -565,9 +574,8 @@ NodeValueTable Footage::Value(const QString &output, NodeValueDatabase &value) c
if (ref.type() == Stream::kVideo) {
VideoParams vp = GetVideoParams(ref.index());
if (vp.colorspace().isEmpty()) {
vp.set_colorspace(project()->color_manager()->GetDefaultInputColorSpace());
}
// Ensure the colorspace is valid and not empty
vp.set_colorspace(GetColorspaceToUse(vp));
job.set_video_params(vp);
} else {
+2
View File
@@ -299,6 +299,8 @@ protected:
virtual void InputValueChangedEvent(const QString &input, int element) override;
private:
QString GetColorspaceToUse(const VideoParams& params) const;
/**
* @brief Update the icon based on the Footage status
*
+30 -39
View File
@@ -36,12 +36,17 @@ Project::Project() :
is_modified_(false),
autorecovery_saved_(true)
{
root_.setParent(this);
// Adds a color manager "node" to this project so that it synchronizes
color_manager_ = new ColorManager();
color_manager_->setParent(this);
connect(&color_manager_, &ColorManager::ConfigChanged,
this, &Project::ColorConfigChanged);
connect(&color_manager_, &ColorManager::DefaultInputColorSpaceChanged,
this, &Project::DefaultColorSpaceChanged);
// Folder root for project
root_ = new Folder();
root_->setParent(this);
root_->SetLabel(tr("Root"));
connect(color_manager(), &ColorManager::ValueChanged,
this, &Project::ColorManagerValueChanged);
}
void Project::Load(QXmlStreamReader *reader, MainWindowLayoutInfo* layout, uint version, const QAtomicInt* cancelled)
@@ -51,20 +56,7 @@ void Project::Load(QXmlStreamReader *reader, MainWindowLayoutInfo* layout, uint
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("root")) {
root_.Load(reader, xml_node_data, version, cancelled);
} else if (reader->name() == QStringLiteral("colormanagement")) {
// Read color management info
while (XMLReadNextStartElement(reader)) {
if (reader->name() == QStringLiteral("config")) {
color_manager_.SetConfig(reader->readElementText());
} else if (reader->name() == QStringLiteral("default")) {
color_manager_.SetDefaultInputColorSpace(reader->readElementText());
} else {
reader->skipCurrentElement();
}
}
root_->Load(reader, xml_node_data, version, cancelled);
} else if (reader->name() == QStringLiteral("cachepath")) {
@@ -102,7 +94,7 @@ void Project::Load(QXmlStreamReader *reader, MainWindowLayoutInfo* layout, uint
Node* node;
if (is_root) {
node = &root_;
node = root_;
} else {
node = NodeFactory::CreateFromID(id);
}
@@ -138,17 +130,23 @@ void Project::Save(QXmlStreamWriter *writer) const
{
writer->writeTextElement(QStringLiteral("cachepath"), cache_path(false));
writer->writeStartElement(QStringLiteral("root"));
root_.Save(writer);
writer->writeEndElement();
writer->writeStartElement(QStringLiteral("nodes"));
writer->writeStartElement(QStringLiteral("colormanagement"));
foreach (Node* node, nodes()) {
writer->writeStartElement(QStringLiteral("node"));
writer->writeTextElement(QStringLiteral("config"), color_manager_.GetConfigFilename());
if (node == root_) {
writer->writeAttribute(QStringLiteral("root"), QStringLiteral("1"));
}
writer->writeTextElement(QStringLiteral("default"), color_manager_.GetDefaultInputColorSpace());
writer->writeAttribute(QStringLiteral("id"), node->id());
writer->writeEndElement(); // colormanagement
node->Save(writer);
writer->writeEndElement(); // node
}
writer->writeEndElement(); // nodes
// Save main window project layout
MainWindowLayoutInfo main_window_info = Core::instance()->main_window()->SaveLayout();
@@ -157,7 +155,7 @@ void Project::Save(QXmlStreamWriter *writer) const
Folder *Project::root()
{
return &root_;
return root_;
}
QString Project::name() const
@@ -199,7 +197,7 @@ void Project::set_filename(const QString &s)
ColorManager *Project::color_manager()
{
return &color_manager_;
return color_manager_;
}
bool Project::is_modified() const
@@ -238,22 +236,15 @@ const QString &Project::cache_path(bool default_if_empty) const
return cache_path_;
}
void Project::ColorConfigChanged()
void Project::ColorManagerValueChanged(const NodeInput &input, const TimeRange &range)
{
Q_UNUSED(range)
QVector<Footage*> footage = root()->ListOutputsOfType<Footage>();
foreach (Footage* item, footage) {
item->InvalidateAll(QString());
//static_cast<VideoStream*>(s)->ColorConfigChanged();
}
}
void Project::DefaultColorSpaceChanged()
{
QVector<Footage*> footage = root_.ListOutputsOfType<Footage>();
foreach (Footage* item, footage) {
item->InvalidateAll(QString());
//static_cast<VideoStream*>(s)->DefaultColorSpaceChanged();
}
}
+7 -5
View File
@@ -74,6 +74,8 @@ public:
void set_cache_path(const QString& cache_path)
{
cache_path_ = cache_path;
emit CachePathChanged(cache_path_);
}
signals:
@@ -81,12 +83,14 @@ signals:
void ModifiedChanged(bool e);
void CachePathChanged(const QString& s);
private:
Folder root_;
Folder* root_;
QString filename_;
ColorManager color_manager_;
ColorManager* color_manager_;
bool is_modified_;
@@ -95,9 +99,7 @@ private:
QString cache_path_;
private slots:
void ColorConfigChanged();
void DefaultColorSpaceChanged();
void ColorManagerValueChanged(const NodeInput& input, const TimeRange& range);
};
+53 -71
View File
@@ -31,18 +31,27 @@
namespace olive {
const QString ColorManager::kConfigFilenameIn = QStringLiteral("config");
const QString ColorManager::kDefaultColorspaceIn = QStringLiteral("default_input");
const QString ColorManager::kReferenceSpaceIn = QStringLiteral("reference_space");
OCIO::ConstConfigRcPtr ColorManager::default_config_;
ColorManager::ColorManager()
ColorManager::ColorManager() :
config_(nullptr)
{
// Set config to our built-in default
config_ = GetDefaultConfig();
// Filename input
AddInput(kConfigFilenameIn, NodeValue::kFile, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
// Default input space
default_input_color_space_ = QStringLiteral("sRGB OETF");
// Colorspace input
AddInput(kDefaultColorspaceIn, NodeValue::kCombo, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
// Default reference space is scene linear
reference_space_ = OCIO::ROLE_SCENE_LINEAR;
AddInput(kReferenceSpaceIn, NodeValue::kText, OCIO::ROLE_SCENE_LINEAR, InputFlags(kInputFlagNotConnectable | kInputFlagNotKeyframable));
// Set config to our built-in default
SetConfig(GetDefaultConfig());
SetDefaultInputColorSpace(QStringLiteral("sRGB OETF"));
}
OCIO::ConstConfigRcPtr ColorManager::GetConfig() const
@@ -57,9 +66,9 @@ OCIO::ConstConfigRcPtr ColorManager::CreateConfigFromFile(const QString &filenam
return OCIO::Config::CreateFromFile(filename.toUtf8());
}
const QString &ColorManager::GetConfigFilename() const
QString ColorManager::GetConfigFilename() const
{
return config_filename_;
return GetStandardValue(kConfigFilenameIn).toString();
}
OCIO::ConstConfigRcPtr ColorManager::GetDefaultConfig()
@@ -96,57 +105,9 @@ void ColorManager::SetUpDefaultConfig()
}
}
void ColorManager::SetConfig(const QString &filename)
void ColorManager::SetConfigFilename(const QString &filename)
{
if (filename != config_filename_) {
SetConfigInternal(filename);
emit ConfigChanged();
}
}
void ColorManager::SetConfigInternal(const QString &filename)
{
config_filename_ = filename;
OCIO::ConstConfigRcPtr cfg;
if (config_filename_.isEmpty()) {
cfg = OCIO::GetCurrentConfig();
} else {
cfg = OCIO::Config::CreateFromFile(filename.toUtf8());
}
config_ = cfg;
}
void ColorManager::SetDefaultInputColorSpaceInternal(const QString &s)
{
default_input_color_space_ = s;
}
void ColorManager::SetConfigAndDefaultInput(const QString &filename, const QString &s)
{
bool config_changed = false;
bool default_input_changed = false;
if (filename != config_filename_) {
SetConfigInternal(filename);
config_changed = true;
}
if (default_input_color_space_ != s) {
SetDefaultInputColorSpaceInternal(s);
default_input_changed = true;
}
if (config_changed) {
emit ConfigChanged();
}
if (default_input_changed) {
emit DefaultInputColorSpaceChanged();
}
SetStandardValue(kConfigFilenameIn, filename);
}
QStringList ColorManager::ListAvailableDisplays()
@@ -198,35 +159,29 @@ QStringList ColorManager::ListAvailableLooks()
return looks;
}
QStringList ColorManager::ListAvailableColorspaces()
QStringList ColorManager::ListAvailableColorspaces() const
{
return ListAvailableColorspaces(config_);
}
const QString &ColorManager::GetDefaultInputColorSpace() const
QString ColorManager::GetDefaultInputColorSpace() const
{
return default_input_color_space_;
return ListAvailableColorspaces().at(GetStandardValue(kDefaultColorspaceIn).toInt());
}
void ColorManager::SetDefaultInputColorSpace(const QString &s)
{
if (default_input_color_space_ != s) {
SetDefaultInputColorSpaceInternal(s);
emit DefaultInputColorSpaceChanged();
}
SetStandardValue(kDefaultColorspaceIn, ListAvailableColorspaces().indexOf(s));
}
const QString &ColorManager::GetReferenceColorSpace() const
QString ColorManager::GetReferenceColorSpace() const
{
return reference_space_;
return GetStandardValue(kReferenceSpaceIn).toString();
}
void ColorManager::SetReferenceColorSpace(const QString &s)
{
reference_space_ = s;
emit ConfigChanged();
SetStandardValue(kReferenceSpaceIn, s);
}
QString ColorManager::GetCompliantColorSpace(const QString &s)
@@ -307,6 +262,26 @@ Color ColorManager::GetDefaultLumaCoefs() const
return c;
}
void ColorManager::Retranslate()
{
SetInputName(kConfigFilenameIn, tr("Configuration"));
SetInputName(kDefaultColorspaceIn, tr("Default Input"));
SetInputName(kReferenceSpaceIn, tr("Reference Space"));
}
void ColorManager::InputValueChangedEvent(const QString &input, int element)
{
Q_UNUSED(element)
if (input == kConfigFilenameIn) {
try {
SetConfig(OCIO::Config::CreateFromFile(GetConfigFilename().toUtf8()));
} catch (OCIO::Exception& e) {}
}
}
ColorManager::SetLocale::SetLocale(const char* new_locale)
{
old_locale_ = setlocale(LC_NUMERIC, nullptr);
@@ -318,4 +293,11 @@ ColorManager::SetLocale::~SetLocale()
setlocale(LC_NUMERIC, old_locale_.toUtf8());
}
void ColorManager::SetConfig(OCIO::ConstConfigRcPtr config)
{
config_ = config;
SetComboBoxStrings(kDefaultColorspaceIn, ListAvailableColorspaces());
}
}
+40 -20
View File
@@ -26,30 +26,54 @@
#include "codec/frame.h"
#include "colorprocessor.h"
#include "node/node.h"
#define OCIO_SET_C_LOCALE_FOR_SCOPE ColorManager::SetLocale d("C")
namespace olive {
class ColorManager : public QObject
class ColorManager : public Node
{
Q_OBJECT
public:
ColorManager();
virtual QString Name() const override
{
return tr("Color Manager");
}
virtual QString id() const override
{
return QStringLiteral("org.olivevideoeditor.Olive.colormanager");
}
virtual QVector<CategoryID> Category() const override
{
return {kCategoryColor};
}
virtual QString Description() const override
{
return tr("Color management configuration for project.");
}
virtual Node* copy() const override
{
return new ColorManager();
}
OCIO::ConstConfigRcPtr GetConfig() const;
static OCIO::ConstConfigRcPtr CreateConfigFromFile(const QString& filename);
const QString& GetConfigFilename() const;
QString GetConfigFilename() const;
static OCIO::ConstConfigRcPtr GetDefaultConfig();
static void SetUpDefaultConfig();
void SetConfig(const QString& filename);
void SetConfigAndDefaultInput(const QString& filename, const QString& s);
void SetConfigFilename(const QString& filename);
QStringList ListAvailableDisplays();
@@ -61,13 +85,13 @@ public:
QStringList ListAvailableLooks();
QStringList ListAvailableColorspaces();
QStringList ListAvailableColorspaces() const;
const QString& GetDefaultInputColorSpace() const;
QString GetDefaultInputColorSpace() const;
void SetDefaultInputColorSpace(const QString& s);
const QString& GetReferenceColorSpace() const;
QString GetReferenceColorSpace() const;
void SetReferenceColorSpace(const QString& s);
@@ -97,24 +121,20 @@ public:
return &mutex_;
}
signals:
void ConfigChanged();
static const QString kConfigFilenameIn;
static const QString kDefaultColorspaceIn;
static const QString kReferenceSpaceIn;
void DefaultInputColorSpaceChanged();
virtual void Retranslate() override;
protected:
virtual void InputValueChangedEvent(const QString &input, int element) override;
private:
void SetConfigInternal(const QString& filename);
void SetDefaultInputColorSpaceInternal(const QString& s);
void SetConfig(OCIO::ConstConfigRcPtr config);
OCIO::ConstConfigRcPtr config_;
QString config_filename_;
QString default_input_color_space_;
QString reference_space_;
QMutex mutex_;
static OCIO::ConstConfigRcPtr default_config_;
+19 -8
View File
@@ -287,10 +287,10 @@ void PreviewAutoCacher::AddNode(Node *node)
copy->setParent(&copied_project_);
// Insert into map
copy_map_.insert(node, copy);
InsertIntoCopyMap(node, copy);
// Copy parameters
Node::CopyInputs(node, copy, false);
// Keep track of our nodes
created_nodes_.append(copy);
}
void PreviewAutoCacher::RemoveNode(Node *node)
@@ -324,6 +324,15 @@ void PreviewAutoCacher::CopyValue(const NodeInput &input)
Node::CopyValuesOfElement(input.node(), our_input, input.input(), input.element());
}
void PreviewAutoCacher::InsertIntoCopyMap(Node *node, Node *copy)
{
// Insert into map
copy_map_.insert(node, copy);
// Copy parameters
Node::CopyInputs(node, copy, false);
}
void PreviewAutoCacher::SetPlayhead(const rational &playhead)
{
cache_range_ = TimeRange(playhead - Config::Current()[QStringLiteral("DiskCacheBehind")].value<rational>(),
@@ -589,9 +598,8 @@ void PreviewAutoCacher::SetViewerNode(Sequence *viewer_node)
}
// Delete all of our copied nodes
foreach (Node* c, copy_map_) {
delete c;
}
qDeleteAll(created_nodes_);
created_nodes_.clear();
copy_map_.clear();
copied_viewer_node_ = nullptr;
graph_update_queue_.clear();
@@ -624,8 +632,11 @@ void PreviewAutoCacher::SetViewerNode(Sequence *viewer_node)
NodeGraph* graph = viewer_node_->parent();
// Add all nodes
foreach (Node* node, graph->nodes()) {
AddNode(node);
for (int i=0; i<copied_project_.nodes().size(); i++) {
InsertIntoCopyMap(graph->nodes().at(i), copied_project_.nodes().at(i));
}
for (int i=copied_project_.nodes().size(); i<graph->nodes().size(); i++) {
AddNode(graph->nodes().at(i));
}
// Find copied viewer node
+3
View File
@@ -112,6 +112,8 @@ private:
void RemoveEdge(const NodeOutput& output, const NodeInput& input);
void CopyValue(const NodeInput& input);
void InsertIntoCopyMap(Node* node, Node* copy);
class QueuedJob {
public:
enum Type {
@@ -135,6 +137,7 @@ private:
QVector<QueuedJob> graph_update_queue_;
QHash<Node*, Node*> copy_map_;
Sequence* copied_viewer_node_;
QVector<Node*> created_nodes_;
bool paused_;
+11 -2
View File
@@ -86,13 +86,13 @@ void ManagedDisplayWidget::ConnectColorManager(ColorManager *color_manager)
}
if (color_manager_ != nullptr) {
disconnect(color_manager_, &ColorManager::ConfigChanged, this, &ManagedDisplayWidget::ColorConfigChanged);
disconnect(color_manager_, &ColorManager::ValueChanged, this, &ManagedDisplayWidget::ColorManagerValueChanged);
}
color_manager_ = color_manager;
if (color_manager_ != nullptr) {
connect(color_manager_, &ColorManager::ConfigChanged, this, &ManagedDisplayWidget::ColorConfigChanged);
connect(color_manager_, &ColorManager::ValueChanged, this, &ManagedDisplayWidget::ColorManagerValueChanged);
}
ColorConfigChanged();
@@ -350,4 +350,13 @@ void ManagedDisplayWidget::SetupColorProcessor()
emit ColorProcessorChanged(color_service_);
}
void ManagedDisplayWidget::ColorManagerValueChanged(const NodeInput &input, const TimeRange &range)
{
Q_UNUSED(range)
if (input.input() == ColorManager::kConfigFilenameIn || input.input() == ColorManager::kReferenceSpaceIn) {
ColorConfigChanged();
}
}
}
@@ -246,6 +246,8 @@ private slots:
*/
void ColorConfigChanged();
void ColorManagerValueChanged(const NodeInput &input, const TimeRange &range);
/**
* @brief The default context menu shown
*/