allow setting of pixel format/ocio method/sample format in preferences

Implementation isn't perfect yet, viewer/renderer doesn't update yet when
the preference is changed so a sequence needs to be re-opened for the change to
take effect.
This commit is contained in:
itsmattkc
2020-01-18 03:37:36 +11:00
parent e6b45c75c3
commit 1101b58ee8
30 changed files with 421 additions and 380 deletions
+8 -8
View File
@@ -106,32 +106,32 @@ void AudioManager::SetOutputDevice(const QAudioDeviceInfo &info)
format.setByteOrder(QAudioFormat::LittleEndian);
switch (output_params_.format()) {
case SAMPLE_FMT_U8:
case SampleFormat::SAMPLE_FMT_U8:
format.setSampleSize(8);
format.setSampleType(QAudioFormat::UnSignedInt);
break;
case SAMPLE_FMT_S16:
case SampleFormat::SAMPLE_FMT_S16:
format.setSampleSize(16);
format.setSampleType(QAudioFormat::SignedInt);
break;
case SAMPLE_FMT_S32:
case SampleFormat::SAMPLE_FMT_S32:
format.setSampleSize(32);
format.setSampleType(QAudioFormat::SignedInt);
break;
case SAMPLE_FMT_S64:
case SampleFormat::SAMPLE_FMT_S64:
format.setSampleSize(64);
format.setSampleType(QAudioFormat::SignedInt);
break;
case SAMPLE_FMT_FLT:
case SampleFormat::SAMPLE_FMT_FLT:
format.setSampleSize(32);
format.setSampleType(QAudioFormat::Float);
break;
case SAMPLE_FMT_DBL:
case SampleFormat::SAMPLE_FMT_DBL:
format.setSampleSize(64);
format.setSampleType(QAudioFormat::Float);
break;
case SAMPLE_FMT_COUNT:
case SAMPLE_FMT_INVALID:
case SampleFormat::SAMPLE_FMT_COUNT:
case SampleFormat::SAMPLE_FMT_INVALID:
abort();
}
+35
View File
@@ -1 +1,36 @@
#include "sampleformat.h"
#include "core.h"
QString SampleFormat::GetSampleFormatName(const SampleFormat::Format &f)
{
switch (f) {
case SAMPLE_FMT_U8:
return tr("Unsigned 8-bit");
case SAMPLE_FMT_S16:
return tr("Signed 16-bit");
case SAMPLE_FMT_S32:
return tr("Signed 32-bit");
case SAMPLE_FMT_S64:
return tr("Signed 64-bit");
case SAMPLE_FMT_FLT:
return tr("32-bit Float");
case SAMPLE_FMT_DBL:
return tr("64-bit Float");
case SAMPLE_FMT_COUNT:
case SAMPLE_FMT_INVALID:
break;
}
return tr("Invalid");
}
SampleFormat::Format SampleFormat::GetConfiguredFormatForMode(RenderMode::Mode mode)
{
return static_cast<SampleFormat::Format>(Core::GetPreferenceForRenderMode(mode, QStringLiteral("SampleFormat")).toInt());
}
void SampleFormat::SetConfiguredFormatForMode(RenderMode::Mode mode, SampleFormat::Format format)
{
Core::SetPreferenceForRenderMode(mode, QStringLiteral("SampleFormat"), format);
}
+26 -9
View File
@@ -21,17 +21,34 @@
#ifndef SAMPLEFORMAT_H
#define SAMPLEFORMAT_H
enum SampleFormat {
SAMPLE_FMT_INVALID = -1,
#include <QObject>
SAMPLE_FMT_U8,
SAMPLE_FMT_S16,
SAMPLE_FMT_S32,
SAMPLE_FMT_S64,
SAMPLE_FMT_FLT,
SAMPLE_FMT_DBL,
#include "render/rendermodes.h"
class SampleFormat : public QObject
{
Q_OBJECT
public:
SampleFormat() = default;
enum Format {
SAMPLE_FMT_INVALID = -1,
SAMPLE_FMT_U8,
SAMPLE_FMT_S16,
SAMPLE_FMT_S32,
SAMPLE_FMT_S64,
SAMPLE_FMT_FLT,
SAMPLE_FMT_DBL,
SAMPLE_FMT_COUNT
};
static QString GetSampleFormatName(const Format& f);
static Format GetConfiguredFormatForMode(RenderMode::Mode mode);
static void SetConfiguredFormatForMode(RenderMode::Mode mode, Format format);
SAMPLE_FMT_COUNT
};
#endif // SAMPLEFORMAT_H
+17 -17
View File
@@ -14,21 +14,21 @@ AVPixelFormat FFmpegCommon::GetCompatiblePixelFormat(const AVPixelFormat &pix_fm
nullptr);
}
SampleFormat FFmpegCommon::GetNativeSampleFormat(const AVSampleFormat &smp_fmt)
SampleFormat::Format FFmpegCommon::GetNativeSampleFormat(const AVSampleFormat &smp_fmt)
{
switch (smp_fmt) {
case AV_SAMPLE_FMT_U8:
return SAMPLE_FMT_U8;
return SampleFormat::SAMPLE_FMT_U8;
case AV_SAMPLE_FMT_S16:
return SAMPLE_FMT_S16;
return SampleFormat::SAMPLE_FMT_S16;
case AV_SAMPLE_FMT_S32:
return SAMPLE_FMT_S32;
return SampleFormat::SAMPLE_FMT_S32;
case AV_SAMPLE_FMT_S64:
return SAMPLE_FMT_S64;
return SampleFormat::SAMPLE_FMT_S64;
case AV_SAMPLE_FMT_FLT:
return SAMPLE_FMT_FLT;
return SampleFormat::SAMPLE_FMT_FLT;
case AV_SAMPLE_FMT_DBL:
return SAMPLE_FMT_DBL;
return SampleFormat::SAMPLE_FMT_DBL;
case AV_SAMPLE_FMT_U8P :
case AV_SAMPLE_FMT_S16P:
case AV_SAMPLE_FMT_S32P:
@@ -40,26 +40,26 @@ SampleFormat FFmpegCommon::GetNativeSampleFormat(const AVSampleFormat &smp_fmt)
break;
}
return SAMPLE_FMT_INVALID;
return SampleFormat::SAMPLE_FMT_INVALID;
}
AVSampleFormat FFmpegCommon::GetFFmpegSampleFormat(const SampleFormat &smp_fmt)
AVSampleFormat FFmpegCommon::GetFFmpegSampleFormat(const SampleFormat::Format &smp_fmt)
{
switch (smp_fmt) {
case SAMPLE_FMT_U8:
case SampleFormat::SAMPLE_FMT_U8:
return AV_SAMPLE_FMT_U8;
case SAMPLE_FMT_S16:
case SampleFormat::SAMPLE_FMT_S16:
return AV_SAMPLE_FMT_S16;
case SAMPLE_FMT_S32:
case SampleFormat::SAMPLE_FMT_S32:
return AV_SAMPLE_FMT_S32;
case SAMPLE_FMT_S64:
case SampleFormat::SAMPLE_FMT_S64:
return AV_SAMPLE_FMT_S64;
case SAMPLE_FMT_FLT:
case SampleFormat::SAMPLE_FMT_FLT:
return AV_SAMPLE_FMT_FLT;
case SAMPLE_FMT_DBL:
case SampleFormat::SAMPLE_FMT_DBL:
return AV_SAMPLE_FMT_DBL;
case SAMPLE_FMT_INVALID:
case SAMPLE_FMT_COUNT:
case SampleFormat::SAMPLE_FMT_INVALID:
case SampleFormat::SAMPLE_FMT_COUNT:
break;
}
+2 -2
View File
@@ -28,12 +28,12 @@ public:
/**
* @brief Returns a native sample format type for a given AVSampleFormat
*/
static SampleFormat GetNativeSampleFormat(const AVSampleFormat& smp_fmt);
static SampleFormat::Format GetNativeSampleFormat(const AVSampleFormat& smp_fmt);
/**
* @brief Returns an FFmpeg sample format type for a given native type
*/
static AVSampleFormat GetFFmpegSampleFormat(const SampleFormat& smp_fmt);
static AVSampleFormat GetFFmpegSampleFormat(const SampleFormat::Format &smp_fmt);
};
#endif // FFMPEGABSTRACTION_H
+7 -7
View File
@@ -85,27 +85,27 @@ bool WaveInput::open()
uint16_t bits_per_sample;
data_stream >> bits_per_sample;
SampleFormat format;
SampleFormat::Format format;
switch (bits_per_sample) {
case 8:
format = SAMPLE_FMT_U8;
format = SampleFormat::SAMPLE_FMT_U8;
break;
case 16:
format = SAMPLE_FMT_S16;
format = SampleFormat::SAMPLE_FMT_S16;
break;
case 32:
if (data_is_float) {
format = SAMPLE_FMT_FLT;
format = SampleFormat::SAMPLE_FMT_FLT;
} else {
format = SAMPLE_FMT_S32;
format = SampleFormat::SAMPLE_FMT_S32;
}
break;
case 64:
if (data_is_float) {
format = SAMPLE_FMT_DBL;
format = SampleFormat::SAMPLE_FMT_DBL;
} else {
format = SAMPLE_FMT_S64;
format = SampleFormat::SAMPLE_FMT_S64;
}
break;
default:
+8 -8
View File
@@ -38,18 +38,18 @@ bool WaveOutput::open()
// Type of format
switch (params_.format()) {
case SAMPLE_FMT_U8:
case SAMPLE_FMT_S16:
case SAMPLE_FMT_S32:
case SAMPLE_FMT_S64:
case SampleFormat::SAMPLE_FMT_U8:
case SampleFormat::SAMPLE_FMT_S16:
case SampleFormat::SAMPLE_FMT_S32:
case SampleFormat::SAMPLE_FMT_S64:
write_int<int16_t>(&file_, kWAVIntegerFormat);
break;
case SAMPLE_FMT_FLT:
case SAMPLE_FMT_DBL:
case SampleFormat::SAMPLE_FMT_FLT:
case SampleFormat::SAMPLE_FMT_DBL:
write_int<int16_t>(&file_, kWAVFloatFormat);
break;
case SAMPLE_FMT_INVALID:
case SAMPLE_FMT_COUNT:
case SampleFormat::SAMPLE_FMT_INVALID:
case SampleFormat::SAMPLE_FMT_COUNT:
qWarning() << "Invalid sample format for WAVE audio";
file_.close();
return false;
+8
View File
@@ -85,6 +85,14 @@ void Config::SetDefaults()
config_map_["DefaultSequenceFrameRate"] = QVariant::fromValue(rational(1001, 30000));
config_map_["DefaultSequenceAudioFrequency"] = 48000;
config_map_["DefaultSequenceAudioLayout"] = AV_CH_LAYOUT_STEREO;
// Online/offline settings
config_map_["OnlinePixelFormat"] = PixelFormat::PIX_FMT_RGBA32F;
config_map_["OfflinePixelFormat"] = PixelFormat::PIX_FMT_RGBA16F;
config_map_["OnlineSampleFormat"] = SampleFormat::SAMPLE_FMT_FLT;
config_map_["OfflineSampleFormat"] = SampleFormat::SAMPLE_FMT_FLT;
config_map_["OnlineOCIOMethod"] = ColorManager::kOCIOAccurate;
config_map_["OfflineOCIOMethod"] = ColorManager::kOCIOFast;
}
void Config::Load()
+19
View File
@@ -600,6 +600,25 @@ int Core::CountFilesInFileList(const QFileInfoList &filenames)
return file_count;
}
QString GetRenderModePreferencePrefix(RenderMode::Mode mode, const QString &preference) {
QString key;
key.append((mode == RenderMode::kOffline) ? QStringLiteral("Offline") : QStringLiteral("Online"));
key.append(preference);
return key;
}
QVariant Core::GetPreferenceForRenderMode(RenderMode::Mode mode, const QString &preference)
{
return Config::Current()[GetRenderModePreferencePrefix(mode, preference)];
}
void Core::SetPreferenceForRenderMode(RenderMode::Mode mode, const QString &preference, const QVariant &value)
{
Config::Current()[GetRenderModePreferencePrefix(mode, preference)] = value;
}
void Core::InitiateOpenSaveProcess(Task *manager, const QString& dialog_text, const QString& dialog_title)
{
// Create save dialog
+3
View File
@@ -171,6 +171,9 @@ public:
*/
static int CountFilesInFileList(const QFileInfoList &filenames);
static QVariant GetPreferenceForRenderMode(RenderMode::Mode mode, const QString& preference);
static void SetPreferenceForRenderMode(RenderMode::Mode mode, const QString& preference, const QVariant& value);
public slots:
/**
* @brief Starts an open file dialog to load a project from file
+9 -4
View File
@@ -13,6 +13,7 @@
#include "project/item/sequence/sequence.h"
#include "project/project.h"
#include "render/backend/opengl/openglexporter.h"
#include "render/pixelservice.h"
#include "ui/icons/icons.h"
ExportDialog::ExportDialog(ViewerOutput *viewer_node, QWidget *parent) :
@@ -205,13 +206,17 @@ void ExportDialog::accept()
dest_height);
}
// FIXME: Hardcoded pixel format
VideoRenderingParams video_render_params(dest_width, dest_height, video_tab_->frame_rate().flipped(), PixelFormat::PIX_FMT_RGBA32F, RenderMode::kOnline);
RenderMode::Mode render_mode = RenderMode::kOnline;
VideoRenderingParams video_render_params(dest_width,
dest_height,
video_tab_->frame_rate().flipped(),
PixelService::GetConfiguredFormatForMode(render_mode),
render_mode);
// FIXME: Hardcoded sample format
AudioRenderingParams audio_render_params(audio_tab_->sample_rate_combobox()->currentData().toInt(),
audio_tab_->channel_layout_combobox()->currentData().toULongLong(),
SAMPLE_FMT_FLT);
SampleFormat::GetConfiguredFormatForMode(render_mode));
ColorProcessorPtr color_processor = ColorProcessor::Create(color_manager_->GetConfig(),
OCIO::ROLE_SCENE_LINEAR,
+2 -244
View File
@@ -29,7 +29,7 @@
#include "tabs/preferencesgeneraltab.h"
#include "tabs/preferencesbehaviortab.h"
#include "tabs/preferencesappearancetab.h"
#include "tabs/preferencesplaybacktab.h"
#include "tabs/preferencesqualitytab.h"
#include "tabs/preferencesdisktab.h"
#include "tabs/preferencesaudiotab.h"
#include "tabs/preferenceskeyboardtab.h"
@@ -52,8 +52,8 @@ PreferencesDialog::PreferencesDialog(QWidget *parent, QMenuBar* main_menu_bar) :
AddTab(new PreferencesGeneralTab(), tr("General"));
AddTab(new PreferencesAppearanceTab(), tr("Appearance"));
AddTab(new PreferencesBehaviorTab(), tr("Behavior"));
AddTab(new PreferencesQualityTab(), tr("Quality"));
AddTab(new PreferencesDiskTab(), tr("Disk"));
AddTab(new PreferencesPlaybackTab(), tr("Playback"));
AddTab(new PreferencesAudioTab(), tr("Audio"));
AddTab(new PreferencesKeyboardTab(main_menu_bar), tr("Keyboard"));
@@ -70,7 +70,6 @@ PreferencesDialog::PreferencesDialog(QWidget *parent, QMenuBar* main_menu_bar) :
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
connect(list_widget_, SIGNAL(currentRowChanged(int)), preference_pane_stack_, SLOT(setCurrentIndex(int)));
}
void PreferencesDialog::accept()
@@ -86,247 +85,6 @@ void PreferencesDialog::accept()
}
QDialog::accept();
/*
bool restart_after_saving = false;
bool reinit_audio = false;
bool reload_language = false;
bool reload_effects = false;
bool reset_ocio_shaders = false;
bool reset_render_threads = false;
// Validate whether the specified CSS file exists
if (!custom_css_fn->text().isEmpty() && !QFileInfo::exists(custom_css_fn->text())) {
QMessageBox::critical(
this,
tr("Invalid CSS File"),
tr("CSS file '%1' does not exist.").arg(custom_css_fn->text())
);
return;
}
// Validate whether the chosen OCIO configuration file
if (enable_color_management->isChecked()) {
// Check whether the file exists
if (!QFileInfo::exists(ocio_config_file->text())) {
QString msg_title = tr("Invalid OpenColorIO Configuration File");
QString msg_body;
if (ocio_config_file->text().isEmpty()) {
msg_body = tr("You must specify an OpenColorIO configuration file if color management is enabled.");
} else {
msg_body = tr("OpenColorIO configuration file '%1' does not exist.").arg(ocio_config_file->text());
}
QMessageBox::critical(
this,
msg_title,
msg_body
);
return;
} else if (olive::config.ocio_config_path != ocio_config_file->text()) {
// Check whether OCIO can load it
OCIO::ConstConfigRcPtr file_config = TestOCIOConfig(ocio_config_file->text().toUtf8());
if (!file_config) {
return;
}
}
}
// Validate whether one of the bool options requires a restart
bool bool_requires_restart = false;
for (int i=0;i<bool_restart_required.size();i++) {
if (bool_restart_required.at(i)
&& bool_ui.at(i)->isChecked() != *bool_value.at(i)) {
bool_requires_restart = true;
break;
}
}
// Check if any settings will require a restart of Olive (including the bool options determined above)
if (bool_requires_restart
|| olive::config.thumbnail_resolution != thumbnail_res_spinbox->value()
|| olive::config.waveform_resolution != waveform_res_spinbox->value()
|| olive::config.css_path != custom_css_fn->text()
|| olive::config.style != static_cast<olive::styling::Style>(ui_style->currentData().toInt())) {
// any changes to these settings will require a restart - ask the user if we should do one now or later
int ret = QMessageBox::question(this,
"Restart Required",
"Some of the changed settings will require a restart of Olive. Would you like "
"to restart now?",
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
if (ret == QMessageBox::Cancel) {
// Return to Preferences dialog without saving any settings
return;
} else if (ret == QMessageBox::Yes) {
// Check if we can close the current project. If not, we'll treat it as if the user clicked "Cancel".
if (olive::Global->can_close_project()) {
restart_after_saving = true;
} else {
return;
}
}
// Selecting "No" will save the settings and not restart. They will become active next time Olive opens.
}
// Everything checks out, start saving settings from the UI to the backend
olive::config.css_path = custom_css_fn->text();
olive::config.recording_mode = recordingComboBox->currentIndex() + 1;
olive::config.img_seq_formats = imgSeqFormatEdit->text();
olive::config.upcoming_queue_size = upcoming_queue_spinbox->value();
olive::config.upcoming_queue_type = upcoming_queue_type->currentIndex();
olive::config.previous_queue_size = previous_queue_spinbox->value();
olive::config.previous_queue_type = previous_queue_type->currentIndex();
// Audio settings may require the audio device to be re-initiated.
if (kUsingAudioOutput != audio_output_devices->currentData().toString()
|| olive::config.preferred_audio_input != audio_input_devices->currentData().toString()
|| olive::config.audio_rate != audio_sample_rate->currentData().toInt()) {
reinit_audio = true;
}
kUsingAudioOutput = audio_output_devices->currentData().toString();
olive::config.preferred_audio_input = audio_input_devices->currentData().toString();
olive::config.audio_rate = audio_sample_rate->currentData().toInt();
olive::config.effect_textbox_lines = effect_textbox_lines_field->value();
// see if the language file should be reloaded (not necessary if the app is restarting anyway)
if (!restart_after_saving
&& olive::config.language_file != language_combobox->currentData().toString()) {
reload_language = true;
}
olive::config.language_file = language_combobox->currentData().toString();
// Check whether OCIO settings will require a reset of the render threads
if (olive::config.playback_bit_depth != playback_bit_depth->currentIndex()
|| olive::config.export_bit_depth != export_bit_depth->currentIndex()) {
reset_render_threads = true;
}
if (olive::config.ocio_config_path != ocio_config_file->text()
|| olive::config.ocio_display != ocio_display->currentText()
|| olive::config.ocio_view != ocio_view->currentText()
|| olive::config.ocio_look != ocio_look->currentData().toString()) {
reset_ocio_shaders = true;
}
if (olive::config.ocio_config_path != ocio_config_file->text()) {
OCIO::SetCurrentConfig(OCIO::Config::CreateFromFile(ocio_config_file->text().toUtf8()));
olive::config.ocio_config_path = ocio_config_file->text();
}
olive::config.enable_color_management = enable_color_management->isChecked();
olive::config.playback_bit_depth = playback_bit_depth->currentIndex();
olive::config.export_bit_depth = export_bit_depth->currentIndex();
olive::config.ocio_display = ocio_display->currentText();
olive::config.ocio_default_input_colorspace = ocio_default_input->currentText();
olive::config.ocio_view = ocio_view->currentText();
// We use data here instead of text because there's a "(None)" option with an empty string
olive::config.ocio_look = ocio_look->currentData().toString();
// Set default sequence options
olive::config.default_sequence_width = default_sequence.width();
olive::config.default_sequence_height = default_sequence.height();
olive::config.default_sequence_framerate = default_sequence.frame_rate();
olive::config.default_sequence_audio_frequency = default_sequence.audio_frequency();
olive::config.default_sequence_audio_channel_layout = default_sequence.audio_layout();
// Set all bool options
for (int i=0;i<bool_ui.size();i++) {
*bool_value[i] = bool_ui.at(i)->isChecked();
}
// Set new style
olive::config.style = static_cast<olive::styling::Style>(ui_style->currentData().toInt());
// Check if the thumbnail or waveform icon fields have changed, we may need to recreate the previews if so
if (olive::config.thumbnail_resolution != thumbnail_res_spinbox->value()
|| olive::config.waveform_resolution != waveform_res_spinbox->value()) {
// we're changing the size of thumbnails and waveforms, so let's delete them and regenerate them next start
// delete nothing
PreviewDeleteTypes delete_type = DELETE_NONE;
if (olive::config.thumbnail_resolution != thumbnail_res_spinbox->value()) {
// delete existing thumbnails
olive::config.thumbnail_resolution = thumbnail_res_spinbox->value();
// delete only thumbnails
delete_type = DELETE_THUMBNAILS;
}
if (olive::config.waveform_resolution != waveform_res_spinbox->value()) {
// delete existing waveforms
olive::config.waveform_resolution = waveform_res_spinbox->value();
// if we're already deleting thumbnails
if (delete_type == DELETE_THUMBNAILS) {
// delete all
delete_type = DELETE_BOTH;
} else {
// just delete waveforms
delete_type = DELETE_WAVEFORMS;
}
}
delete_previews(delete_type);
}
QDialog::accept();
if (restart_after_saving) {
// since we already ran can_close_project(), bypass checking again by running set_modified(false)
olive::Global->set_modified(false);
olive::MainWindow->close();
QProcess::startDetached(QApplication::applicationFilePath(), { olive::ActiveProjectFilename });
} else {
// Audio settings may require the audio device to be re-initiated.
if (reinit_audio) {
init_audio();
}
if (reload_effects) {
panel_effect_controls->Reload();
}
// reload language file if it changed
if (reload_language) {
olive::Global->load_translation_from_config();
}
if (reset_render_threads) {
if (panel_footage_viewer->seq != nullptr) {
panel_footage_viewer->seq->Close();
}
panel_footage_viewer->viewer_widget()->get_renderer()->delete_ctx();
if (panel_sequence_viewer->seq != nullptr) {
panel_sequence_viewer->seq->Close();
}
panel_sequence_viewer->viewer_widget()->get_renderer()->delete_ctx();
} else if (reset_ocio_shaders) {
panel_footage_viewer->viewer_widget()->get_renderer()->destroy_ocio();
panel_sequence_viewer->viewer_widget()->get_renderer()->destroy_ocio();
}
}
*/
}
void PreferencesDialog::AddTab(PreferencesTab *tab, const QString &title)
+2 -2
View File
@@ -24,8 +24,8 @@ set(OLIVE_SOURCES
dialog/preferences/tabs/preferencesdisktab.cpp
dialog/preferences/tabs/preferencesappearancetab.h
dialog/preferences/tabs/preferencesappearancetab.cpp
dialog/preferences/tabs/preferencesplaybacktab.h
dialog/preferences/tabs/preferencesplaybacktab.cpp
dialog/preferences/tabs/preferencesqualitytab.h
dialog/preferences/tabs/preferencesqualitytab.cpp
dialog/preferences/tabs/preferencesaudiotab.h
dialog/preferences/tabs/preferencesaudiotab.cpp
dialog/preferences/tabs/preferenceskeyboardtab.h
@@ -1,14 +0,0 @@
#include "preferencesplaybacktab.h"
#include <QGroupBox>
#include <QLabel>
#include <QVBoxLayout>
PreferencesPlaybackTab::PreferencesPlaybackTab()
{
}
void PreferencesPlaybackTab::Accept()
{
}
@@ -1,20 +0,0 @@
#ifndef PREFERENCESPLAYBACKTAB_H
#define PREFERENCESPLAYBACKTAB_H
#include <QComboBox>
#include <QDoubleSpinBox>
#include "preferencestab.h"
class PreferencesPlaybackTab : public PreferencesTab
{
Q_OBJECT
public:
PreferencesPlaybackTab();
virtual void Accept() override;
private:
};
#endif // PREFERENCESPLAYBACKTAB_H
@@ -0,0 +1,122 @@
#include "preferencesqualitytab.h"
#include <QGroupBox>
#include <QLabel>
#include <QVBoxLayout>
#include "render/colormanager.h"
#include "render/pixelservice.h"
PreferencesQualityTab::PreferencesQualityTab()
{
QVBoxLayout* layout = new QVBoxLayout(this);
QHBoxLayout* profile_layout = new QHBoxLayout();
profile_layout->setMargin(0);
profile_layout->addWidget(new QLabel(tr("Profile:")));
QComboBox* profile_combobox = new QComboBox();
profile_combobox->addItem(tr("Preview (Offline)"));
profile_combobox->addItem(tr("Export (Online)"));
profile_layout->addWidget(profile_combobox);
layout->addLayout(profile_layout);
quality_stack_ = new QStackedWidget();
offline_group_ = new PreferencesQualityGroup(tr("Offline Quality"));
offline_group_->bit_depth_combobox()->setCurrentIndex(PixelService::GetConfiguredFormatForMode(RenderMode::kOffline));
offline_group_->sample_fmt_combobox()->setCurrentIndex(SampleFormat::GetConfiguredFormatForMode(RenderMode::kOffline));
offline_group_->ocio_method()->setCurrentIndex(ColorManager::GetOCIOMethodForMode(RenderMode::kOffline));
quality_stack_->addWidget(offline_group_);
online_group_ = new PreferencesQualityGroup(tr("Online Quality"));
online_group_->bit_depth_combobox()->setCurrentIndex(PixelService::GetConfiguredFormatForMode(RenderMode::kOnline));
online_group_->sample_fmt_combobox()->setCurrentIndex(SampleFormat::GetConfiguredFormatForMode(RenderMode::kOnline));
online_group_->ocio_method()->setCurrentIndex(ColorManager::GetOCIOMethodForMode(RenderMode::kOnline));
quality_stack_->addWidget(online_group_);
layout->addWidget(quality_stack_);
connect(profile_combobox, SIGNAL(currentIndexChanged(int)), quality_stack_, SLOT(setCurrentIndex(int)));
}
void PreferencesQualityTab::Accept()
{
ColorManager::SetOCIOMethodForMode(RenderMode::kOffline, static_cast<ColorManager::OCIOMethod>(offline_group_->ocio_method()->currentIndex()));
ColorManager::SetOCIOMethodForMode(RenderMode::kOnline, static_cast<ColorManager::OCIOMethod>(online_group_->ocio_method()->currentIndex()));
PixelService::SetConfiguredFormatForMode(RenderMode::kOffline, static_cast<PixelFormat::Format>(offline_group_->bit_depth_combobox()->currentData().toInt()));
PixelService::SetConfiguredFormatForMode(RenderMode::kOnline, static_cast<PixelFormat::Format>(online_group_->bit_depth_combobox()->currentData().toInt()));
SampleFormat::SetConfiguredFormatForMode(RenderMode::kOffline, static_cast<SampleFormat::Format>(offline_group_->sample_fmt_combobox()->currentData().toInt()));
SampleFormat::SetConfiguredFormatForMode(RenderMode::kOnline, static_cast<SampleFormat::Format>(online_group_->sample_fmt_combobox()->currentData().toInt()));
}
PreferencesQualityGroup::PreferencesQualityGroup(const QString &title, QWidget *parent) :
QGroupBox(title, parent)
{
QVBoxLayout* quality_outer_layout = new QVBoxLayout(this);
QGroupBox* video_group = new QGroupBox(tr("Video"));
QGridLayout* video_layout = new QGridLayout(video_group);
quality_outer_layout->addWidget(video_group);
int row = 0;
video_layout->addWidget(new QLabel(tr("Pixel Format:")), row, 0);
bit_depth_combobox_ = new QComboBox();
// Populate with bit depths
for (int i=0;i<PixelFormat::PIX_FMT_COUNT;i++) {
bit_depth_combobox_->addItem(PixelService::GetPixelFormatInfo(static_cast<PixelFormat::Format>(i)).name,
i);
}
video_layout->addWidget(bit_depth_combobox_, row, 1);
row++;
video_layout->addWidget(new QLabel(tr("OpenColorIO Method:")), row, 0);
ocio_method_ = new QComboBox();
ocio_method_->addItem(tr("Fast"));
ocio_method_->addItem(tr("Accurate"));
video_layout->addWidget(ocio_method_, row, 1);
row = 0;
QGroupBox* audio_group = new QGroupBox(tr("Audio"));
QGridLayout* audio_layout = new QGridLayout(audio_group);
quality_outer_layout->addWidget(audio_group);
audio_layout->addWidget(new QLabel(tr("Sample Format:")), row, 0);
sample_fmt_combobox_ = new QComboBox();
for (int i=0;i<SampleFormat::SAMPLE_FMT_COUNT;i++) {
sample_fmt_combobox_->addItem(SampleFormat::GetSampleFormatName(static_cast<SampleFormat::Format>(i)),
i);
}
audio_layout->addWidget(sample_fmt_combobox_, row, 1);
quality_outer_layout->addStretch();
}
QComboBox *PreferencesQualityGroup::bit_depth_combobox()
{
return bit_depth_combobox_;
}
QComboBox *PreferencesQualityGroup::ocio_method()
{
return ocio_method_;
}
QComboBox *PreferencesQualityGroup::sample_fmt_combobox()
{
return sample_fmt_combobox_;
}
@@ -0,0 +1,49 @@
#ifndef PREFERENCESQUALITYTAB_H
#define PREFERENCESQUALITYTAB_H
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QGroupBox>
#include <QStackedWidget>
#include "preferencestab.h"
class PreferencesQualityGroup : public QGroupBox
{
Q_OBJECT
public:
PreferencesQualityGroup(const QString& title, QWidget* parent = nullptr);
QComboBox* bit_depth_combobox();
QComboBox* ocio_method();
QComboBox* sample_fmt_combobox();
private:
QComboBox* bit_depth_combobox_;
QComboBox* ocio_method_;
QComboBox* sample_fmt_combobox_;
};
class PreferencesQualityTab : public PreferencesTab
{
Q_OBJECT
public:
PreferencesQualityTab();
virtual void Accept() override;
private:
QStackedWidget* quality_stack_;
PreferencesQualityGroup* offline_group_;
PreferencesQualityGroup* online_group_;
};
#endif // PREFERENCESQUALITYTAB_H
+14 -14
View File
@@ -27,23 +27,23 @@ const uint64_t &AudioParams::channel_layout() const
}
AudioRenderingParams::AudioRenderingParams() :
format_(SAMPLE_FMT_INVALID)
format_(SampleFormat::SAMPLE_FMT_INVALID)
{
}
AudioRenderingParams::AudioRenderingParams(const int &sample_rate, const uint64_t &channel_layout, const SampleFormat &format) :
AudioRenderingParams::AudioRenderingParams(const int &sample_rate, const uint64_t &channel_layout, const SampleFormat::Format &format) :
AudioParams(sample_rate, channel_layout),
format_(format)
{
}
AudioRenderingParams::AudioRenderingParams(const AudioParams &params, const SampleFormat &format) :
AudioRenderingParams::AudioRenderingParams(const AudioParams &params, const SampleFormat::Format &format) :
AudioParams(params),
format_(format)
{
}
const SampleFormat &AudioRenderingParams::format() const
const SampleFormat::Format &AudioRenderingParams::format() const
{
return format_;
}
@@ -98,18 +98,18 @@ int AudioRenderingParams::channel_count() const
int AudioRenderingParams::bytes_per_sample_per_channel() const
{
switch (format_) {
case SAMPLE_FMT_U8:
case SampleFormat::SAMPLE_FMT_U8:
return 1;
case SAMPLE_FMT_S16:
case SampleFormat::SAMPLE_FMT_S16:
return 2;
case SAMPLE_FMT_S32:
case SAMPLE_FMT_FLT:
case SampleFormat::SAMPLE_FMT_S32:
case SampleFormat::SAMPLE_FMT_FLT:
return 4;
case SAMPLE_FMT_DBL:
case SAMPLE_FMT_S64:
case SampleFormat::SAMPLE_FMT_DBL:
case SampleFormat::SAMPLE_FMT_S64:
return 8;
case SAMPLE_FMT_INVALID:
case SAMPLE_FMT_COUNT:
case SampleFormat::SAMPLE_FMT_INVALID:
case SampleFormat::SAMPLE_FMT_COUNT:
break;
}
@@ -125,8 +125,8 @@ bool AudioRenderingParams::is_valid() const
{
bool valid = (sample_rate() > 0
&& channel_layout() > 0
&& format_ != SAMPLE_FMT_INVALID
&& format_ != SAMPLE_FMT_COUNT);
&& format_ != SampleFormat::SAMPLE_FMT_INVALID
&& format_ != SampleFormat::SAMPLE_FMT_COUNT);
if (!valid) {
qWarning() << "Invalid params found:" << sample_rate() << channel_layout() << format();
+4 -4
View File
@@ -25,8 +25,8 @@ private:
class AudioRenderingParams : public AudioParams {
public:
AudioRenderingParams();
AudioRenderingParams(const int& sample_rate, const uint64_t& channel_layout, const SampleFormat& format);
AudioRenderingParams(const AudioParams& params, const SampleFormat& format);
AudioRenderingParams(const int& sample_rate, const uint64_t& channel_layout, const SampleFormat::Format& format);
AudioRenderingParams(const AudioParams& params, const SampleFormat::Format& format);
int time_to_bytes(const rational& time) const;
int time_to_samples(const rational& time) const;
@@ -37,13 +37,13 @@ public:
int bits_per_sample() const;
bool is_valid() const;
const SampleFormat& format() const;
const SampleFormat::Format &format() const;
bool operator==(const AudioRenderingParams& other) const;
bool operator!=(const AudioRenderingParams& other) const;
private:
SampleFormat format_;
SampleFormat::Format format_;
};
Q_DECLARE_METATYPE(AudioRenderingParams)
+9 -11
View File
@@ -185,17 +185,15 @@ void OpenGLTexture::CreateInternal(QOpenGLContext* create_ctx, GLuint* tex, cons
// Allocate storage for texture
const PixelFormat::Info& bit_depth = PixelService::GetPixelFormatInfo(format_);
f->glTexImage2D(
GL_TEXTURE_2D,
0,
bit_depth.internal_format,
width_,
height_,
0,
bit_depth.pixel_format,
bit_depth.gl_pixel_type,
data
);
f->glTexImage2D(GL_TEXTURE_2D,
0,
bit_depth.internal_format,
width_,
height_,
0,
bit_depth.pixel_format,
bit_depth.gl_pixel_type,
data);
// Set texture filtering to bilinear
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+4 -2
View File
@@ -71,8 +71,10 @@ void OpenGLWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable
color_cache()->Add(video_stream->colorspace(), color_processor);
}
ColorManager::OCIOMethod ocio_method = ColorManager::GetOCIOMethodForMode(video_params().mode());
// OCIO's CPU conversion is more accurate, so for online we render on CPU but offline we render GPU
if (video_params().mode() == RenderMode::kOnline) {
if (ocio_method == ColorManager::kOCIOAccurate) {
// If alpha is associated, disassociate for the color transform
if (video_stream->premultiplied_alpha()) {
ColorManager::DisassociateAlpha(frame);
@@ -96,7 +98,7 @@ void OpenGLWorker::FrameToValue(StreamPtr stream, FramePtr frame, NodeValueTable
OpenGLTextureCache::ReferencePtr footage_tex_ref = texture_cache_->Get(ctx_, footage_params, frame->data());
if (video_params().mode() == RenderMode::kOffline) {
if (ocio_method == ColorManager::kOCIOFast) {
if (!color_processor->IsEnabled()) {
color_processor->Enable(ctx_, video_stream->premultiplied_alpha());
}
+3 -3
View File
@@ -192,7 +192,7 @@ const char *VideoRenderBackend::GetCachedFrame(const rational &time)
QByteArray frame_hash = frame_cache_.TimeToHash(time);
if (!frame_hash.isEmpty()) {
QString fn = frame_cache_.CachePathName(frame_hash);
QString fn = frame_cache_.CachePathName(frame_hash, params_.format());
if (QFileInfo::exists(fn)) {
auto in = OIIO::ImageInput::open(fn.toStdString());
@@ -304,7 +304,7 @@ void VideoRenderBackend::ThreadCompletedDownload(NodeDependency dep, qint64 job_
// Register frame with the disk manager
if (operating_mode_ & VideoRenderWorker::kDownloadOnly) {
DiskManager::instance()->CreatedFile(frame_cache()->CachePathName(hash), hash);
DiskManager::instance()->CreatedFile(frame_cache()->CachePathName(hash, params_.format()), hash);
}
QList<rational> hashes_with_time = frame_cache()->FramesWithHash(hash);
@@ -322,7 +322,7 @@ void VideoRenderBackend::ThreadSkippedFrame(NodeDependency dep, qint64 job_time,
SetWorkerBusyState(static_cast<RenderWorker*>(sender()), false);
if (SetFrameHash(dep, hash, job_time)
&& frame_cache_.HasHash(hash)) {
&& frame_cache_.HasHash(hash, params_.format())) {
emit CachedTimeReady(dep.in(), job_time);
}
+13 -4
View File
@@ -21,9 +21,9 @@ void VideoRenderFrameCache::Clear()
cache_id_.clear();
}
bool VideoRenderFrameCache::HasHash(const QByteArray &hash)
bool VideoRenderFrameCache::HasHash(const QByteArray &hash, const PixelFormat::Format& format)
{
return QFileInfo::exists(CachePathName(hash)) && !IsCaching(hash);
return QFileInfo::exists(CachePathName(hash, format)) && !IsCaching(hash);
}
bool VideoRenderFrameCache::IsCaching(const QByteArray &hash)
@@ -114,12 +114,21 @@ const QMap<rational, QByteArray> &VideoRenderFrameCache::time_hash_map() const
return time_hash_map_;
}
QString VideoRenderFrameCache::CachePathName(const QByteArray &hash) const
QString VideoRenderFrameCache::CachePathName(const QByteArray &hash, const PixelFormat::Format& pix_fmt) const
{
QDir this_cache_dir = QDir(GetMediaCacheLocation());
this_cache_dir.mkpath(".");
QString filename = QStringLiteral("%1.exr").arg(QString(hash.toHex()));
QString ext;
if (pix_fmt == PixelFormat::PIX_FMT_RGBA8) {
// For some reason, 8-bit EXRs are extremely slow to load, so we use TIFF instead.
ext = QStringLiteral("tiff");
} else {
ext = QStringLiteral("exr");
}
QString filename = QStringLiteral("%1.%2").arg(QString(hash.toHex()), ext);
return this_cache_dir.filePath(filename);
}
+3 -2
View File
@@ -4,6 +4,7 @@
#include <QMutex>
#include "common/rational.h"
#include "render/pixelformat.h"
class VideoRenderFrameCache
{
@@ -15,7 +16,7 @@ public:
/**
* @brief Return whether a frame with this hash already exists
*/
bool HasHash(const QByteArray& hash);
bool HasHash(const QByteArray& hash, const PixelFormat::Format &format);
/**
* @brief Return whether a frame is currently being cached
@@ -30,7 +31,7 @@ public:
/**
* @brief Return the path of the cached image at this time
*/
QString CachePathName(const QByteArray &hash) const;
QString CachePathName(const QByteArray &hash, const PixelFormat::Format& pix_fmt) const;
void SetCacheID(const QString& id);
+7 -3
View File
@@ -49,7 +49,7 @@ NodeValueTable VideoRenderWorker::RenderInternal(const NodeDependency& path, con
// Emit only the hash
emit CompletedDownload(path, job_time, hash);
} else if ((operating_mode_ & kHashOnly) && frame_cache_->HasHash(hash)) {
} else if ((operating_mode_ & kHashOnly) && frame_cache_->HasHash(hash, video_params_.format())) {
// We've already cached this hash, no need to continue
emit HashAlreadyExists(path, job_time, hash);
@@ -67,7 +67,7 @@ NodeValueTable VideoRenderWorker::RenderInternal(const NodeDependency& path, con
// If we actually have a texture, download it into the disk cache
if ((operating_mode_ & kDownloadOnly) && !texture.isNull()) {
Download(path, hash, texture, frame_cache_->CachePathName(hash));
Download(path, hash, texture, frame_cache_->CachePathName(hash, video_params_.format()));
}
frame_cache_->RemoveHashFromCurrentlyCaching(hash);
@@ -212,7 +212,11 @@ void VideoRenderWorker::Download(NodeDependency dep, QByteArray hash, QVariant t
// Set up OIIO::ImageSpec for compressing cached images on disk
OIIO::ImageSpec spec(video_params().effective_width(), video_params().effective_height(), kRGBAChannels, format_info.oiio_desc);
spec.attribute("compression", "dwaa:200");
if (video_params_.format() != PixelFormat::PIX_FMT_RGBA8) {
// 8-bit doesn't use EXR because EXR loading is really slow on 8-bit
spec.attribute("compression", "dwaa:200");
}
TextureToBuffer(texture, download_buffer_);
+11
View File
@@ -4,6 +4,7 @@
#include "common/define.h"
#include "config/config.h"
#include "core.h"
ColorManager::ColorManager()
{
@@ -110,6 +111,16 @@ QStringList ColorManager::ListAvailableInputColorspaces(OCIO::ConstConfigRcPtr c
return spaces;
}
ColorManager::OCIOMethod ColorManager::GetOCIOMethodForMode(RenderMode::Mode mode)
{
return static_cast<OCIOMethod>(Core::GetPreferenceForRenderMode(mode, QStringLiteral("OCIOMethod")).toInt());
}
void ColorManager::SetOCIOMethodForMode(RenderMode::Mode mode, ColorManager::OCIOMethod method)
{
Core::SetPreferenceForRenderMode(mode, QStringLiteral("OCIOMethod"), method);
}
void ColorManager::AssociateAlphaPixFmtFilter(ColorManager::AlphaAction action, FramePtr f)
{
int pixel_count = f->width() * f->height() * kRGBAChannels;
+9
View File
@@ -38,6 +38,15 @@ public:
static QStringList ListAvailableInputColorspaces(OCIO::ConstConfigRcPtr config);
enum OCIOMethod {
kOCIOFast,
kOCIOAccurate
};
static OCIOMethod GetOCIOMethodForMode(RenderMode::Mode mode);
static void SetOCIOMethodForMode(RenderMode::Mode mode, OCIOMethod method);
signals:
void ConfigChanged();
+11
View File
@@ -25,11 +25,22 @@
#include <QFloat16>
#include "common/define.h"
#include "core.h"
PixelService::PixelService()
{
}
PixelFormat::Format PixelService::GetConfiguredFormatForMode(RenderMode::Mode mode)
{
return static_cast<PixelFormat::Format>(Core::GetPreferenceForRenderMode(mode, QStringLiteral("PixelFormat")).toInt());
}
void PixelService::SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format)
{
Core::SetPreferenceForRenderMode(mode, QStringLiteral("PixelFormat"), format);
}
PixelFormat::Info PixelService::GetPixelFormatInfo(const PixelFormat::Format &format)
{
PixelFormat::Info info;
+7
View File
@@ -25,12 +25,19 @@
#include "codec/frame.h"
#include "pixelformat.h"
#include "render/rendermodes.h"
class PixelService : public QObject {
public:
PixelService();
/**
* @brief Returns the configured pixel format for a given mode
*/
static PixelFormat::Format GetConfiguredFormatForMode(RenderMode::Mode mode);
static void SetConfiguredFormatForMode(RenderMode::Mode mode, PixelFormat::Format format);
/**
* @brief Return a PixelFormatInfo containing information for a certain format
*
+9 -2
View File
@@ -31,6 +31,7 @@
#include "config/config.h"
#include "project/item/sequence/sequence.h"
#include "project/project.h"
#include "render/pixelservice.h"
ViewerWidget::ViewerWidget(QWidget *parent) :
QWidget(parent),
@@ -176,8 +177,14 @@ void ViewerWidget::ConnectViewerNode(ViewerOutput *node, ColorManager* color_man
qWarning() << "Failed to find a suitable color manager for the connected viewer node";
}
video_renderer_->SetParameters(VideoRenderingParams(viewer_node_->video_params(), PixelFormat::PIX_FMT_RGBA16F, RenderMode::kOffline, 2));
audio_renderer_->SetParameters(AudioRenderingParams(viewer_node_->audio_params(), SAMPLE_FMT_FLT));
RenderMode::Mode render_mode = RenderMode::kOffline;
video_renderer_->SetParameters(VideoRenderingParams(viewer_node_->video_params(),
PixelService::GetConfiguredFormatForMode(render_mode),
render_mode,
2));
audio_renderer_->SetParameters(AudioRenderingParams(viewer_node_->audio_params(),
SampleFormat::GetConfiguredFormatForMode(render_mode)));
// Reload cache into these renderers
// FIXME: Slow, rather than invalidate, we should probably serialize the cache into and out of files