From 409f24be397c6fdffbd23936535ac84028e52a11 Mon Sep 17 00:00:00 2001 From: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Wed, 10 Aug 2022 11:37:24 -0700 Subject: [PATCH] exportdialog: allow restoring parameters --- app/codec/encoder.cpp | 60 +++++++++++- app/codec/encoder.h | 39 +++++++- app/codec/ffmpeg/ffmpegencoder.cpp | 4 +- app/common/qtutils.cpp | 10 ++ app/common/qtutils.h | 9 +- app/dialog/export/codec/cineformsection.cpp | 5 + app/dialog/export/codec/cineformsection.h | 2 + app/dialog/export/codec/codecsection.h | 2 + app/dialog/export/codec/h264section.cpp | 57 ++++++++++- app/dialog/export/codec/h264section.h | 6 ++ app/dialog/export/codec/imagesection.h | 5 + app/dialog/export/export.cpp | 101 ++++++++++++++++--- app/dialog/export/export.h | 10 +- app/dialog/export/exportsubtitlestab.h | 6 ++ app/dialog/export/exportvideotab.cpp | 14 ++- app/dialog/export/exportvideotab.h | 25 +++-- app/node/output/viewer/viewer.h | 6 ++ app/task/export/CMakeLists.txt | 2 - app/task/export/export.cpp | 16 +-- app/task/export/export.h | 6 +- app/task/export/exportparams.cpp | 103 -------------------- app/task/export/exportparams.h | 65 ------------ 22 files changed, 331 insertions(+), 222 deletions(-) delete mode 100644 app/task/export/exportparams.cpp delete mode 100644 app/task/export/exportparams.h diff --git a/app/codec/encoder.cpp b/app/codec/encoder.cpp index 8e6642449..b4ef307a3 100644 --- a/app/codec/encoder.cpp +++ b/app/codec/encoder.cpp @@ -93,7 +93,9 @@ EncodingParams::EncodingParams() : audio_enabled_(false), audio_bit_rate_(0), subtitles_enabled_(false), - subtitles_are_sidecar_(false) + subtitles_are_sidecar_(false), + video_scaling_method_(kStretch), + has_custom_range_(false) { } @@ -142,7 +144,14 @@ void EncodingParams::DisableSubtitles() void EncodingParams::Save(QXmlStreamWriter *writer) const { + writer->writeTextElement(QStringLiteral("version"), QString::number(kEncoderParamsVersion)); + writer->writeTextElement(QStringLiteral("filename"), filename_); + writer->writeTextElement(QStringLiteral("format"), QString::number(format_)); + + writer->writeTextElement(QStringLiteral("range"), QString::number(has_custom_range_)); + writer->writeTextElement(QStringLiteral("customrangein"), custom_range_.in().toString()); + writer->writeTextElement(QStringLiteral("customrangeout"), custom_range_.out().toString()); writer->writeStartElement(QStringLiteral("video")); @@ -156,10 +165,18 @@ void EncodingParams::Save(QXmlStreamWriter *writer) const writer->writeTextElement(QStringLiteral("timebase"), video_params_.time_base().toString()); writer->writeTextElement(QStringLiteral("divider"), QString::number(video_params_.divider())); writer->writeTextElement(QStringLiteral("bitrate"), QString::number(video_bit_rate_)); - writer->writeTextElement(QStringLiteral("minbitrate"), QString::number(video_max_bit_rate_)); + writer->writeTextElement(QStringLiteral("minbitrate"), QString::number(video_min_bit_rate_)); writer->writeTextElement(QStringLiteral("maxbitrate"), QString::number(video_max_bit_rate_)); writer->writeTextElement(QStringLiteral("bufsize"), QString::number(video_buffer_size_)); writer->writeTextElement(QStringLiteral("threads"), QString::number(video_threads_)); + writer->writeTextElement(QStringLiteral("pixfmt"), video_pix_fmt_); + writer->writeTextElement(QStringLiteral("imgseq"), QString::number(video_is_image_sequence_)); + + writer->writeStartElement(QStringLiteral("color")); + writer->writeTextElement(QStringLiteral("output"), color_transform_.output()); + writer->writeEndElement(); // colortransform + + writer->writeTextElement(QStringLiteral("vscale"), QString::number(video_scaling_method_)); if (!video_opts_.isEmpty()) { writer->writeStartElement(QStringLiteral("opts")); @@ -191,6 +208,19 @@ void EncodingParams::Save(QXmlStreamWriter *writer) const writer->writeTextElement(QStringLiteral("format"), QString::number(audio_params_.format())); } + writer->writeStartElement(QStringLiteral("subtitles")); + + writer->writeAttribute(QStringLiteral("enabled"), QString::number(subtitles_enabled_)); + + if (subtitles_enabled_) { + writer->writeTextElement(QStringLiteral("sidecar"), QString::number(subtitles_are_sidecar_)); + writer->writeTextElement(QStringLiteral("sidecarformat"), QString::number(subtitle_sidecar_fmt_)); + + writer->writeTextElement(QStringLiteral("codec"), QString::number(subtitles_codec_)); + } + + writer->writeEndElement(); // subtitles + writer->writeEndElement(); // audio } @@ -255,4 +285,30 @@ std::vector Encoder::GetSampleFormatsForCodec(ExportCodec:: return std::vector(); } +QMatrix4x4 EncodingParams::GenerateMatrix(EncodingParams::VideoScalingMethod method, + int source_width, int source_height, + int dest_width, int dest_height) +{ + QMatrix4x4 preview_matrix; + + if (method == EncodingParams::kStretch) { + return preview_matrix; + } + + float export_ar = static_cast(dest_width) / static_cast(dest_height); + float source_ar = static_cast(source_width) / static_cast(source_height); + + if (qFuzzyCompare(export_ar, source_ar)) { + return preview_matrix; + } + + if ((export_ar > source_ar) == (method == EncodingParams::kFit)) { + preview_matrix.scale(source_ar / export_ar, 1.0F); + } else { + preview_matrix.scale(1.0F, export_ar / source_ar); + } + + return preview_matrix; +} + } diff --git a/app/codec/encoder.h b/app/codec/encoder.h index 2982764ed..a8496065e 100644 --- a/app/codec/encoder.h +++ b/app/codec/encoder.h @@ -41,10 +41,22 @@ namespace olive { class Encoder; using EncoderPtr = std::shared_ptr; -class EncodingParams { +class EncodingParams +{ public: + enum VideoScalingMethod { + kFit, + kStretch, + kCrop + }; + EncodingParams(); + bool IsValid() const + { + return video_enabled_ || audio_enabled_ || subtitles_enabled_; + } + void SetFilename(const QString& filename) { filename_ = filename; } void EnableVideo(const VideoParams& video_params, const ExportCodec::Codec& vcodec); @@ -75,6 +87,8 @@ public: const ExportCodec::Codec& video_codec() const { return video_codec_; } const VideoParams& video_params() const { return video_params_; } const QHash& video_opts() const { return video_opts_; } + QString video_option(const QString &key) const { return video_opts_.value(key); } + bool has_video_opt(const QString &key) const { return video_opts_.contains(key); } const int64_t& video_bit_rate() const { return video_bit_rate_; } const int64_t& video_min_bit_rate() const { return video_min_bit_rate_; } const int64_t& video_max_bit_rate() const { return video_max_bit_rate_; } @@ -99,9 +113,26 @@ public: const rational& GetExportLength() const { return export_length_; } void SetExportLength(const rational& export_length) { export_length_ = export_length; } - virtual void Save(QXmlStreamWriter* writer) const; + void Save(QXmlStreamWriter* writer) const; + + bool has_custom_range() const { return has_custom_range_; } + const TimeRange& custom_range() const { return custom_range_; } + void set_custom_range(const TimeRange& custom_range) + { + has_custom_range_ = true; + custom_range_ = custom_range; + } + + const VideoScalingMethod& video_scaling_method() const { return video_scaling_method_; } + void set_video_scaling_method(const VideoScalingMethod& video_scaling_method) { video_scaling_method_ = video_scaling_method; } + + static QMatrix4x4 GenerateMatrix(VideoScalingMethod method, + int source_width, int source_height, + int dest_width, int dest_height); private: + static const int kEncoderParamsVersion = 1; + QString filename_; ExportFormat::Format format_; @@ -129,6 +160,10 @@ private: ExportCodec::Codec subtitles_codec_; rational export_length_; + VideoScalingMethod video_scaling_method_; + + bool has_custom_range_; + TimeRange custom_range_; }; diff --git a/app/codec/ffmpeg/ffmpegencoder.cpp b/app/codec/ffmpeg/ffmpegencoder.cpp index b532d0689..e989db229 100644 --- a/app/codec/ffmpeg/ffmpegencoder.cpp +++ b/app/codec/ffmpeg/ffmpegencoder.cpp @@ -638,7 +638,9 @@ bool FFmpegEncoder::InitializeStream(AVMediaType type, AVStream** stream_ptr, AV // Set custom options { for (auto i=params().video_opts().begin();i!=params().video_opts().end();i++) { - av_opt_set(codec_ctx->priv_data, i.key().toUtf8(), i.value().toUtf8(), AV_OPT_SEARCH_CHILDREN); + if (!i.key().startsWith(QStringLiteral("ove_"))) { + av_opt_set(codec_ctx->priv_data, i.key().toUtf8(), i.value().toUtf8(), AV_OPT_SEARCH_CHILDREN); + } } if (params().video_bit_rate() > 0) { diff --git a/app/common/qtutils.cpp b/app/common/qtutils.cpp index bb6c23de1..613f8a5e9 100644 --- a/app/common/qtutils.cpp +++ b/app/common/qtutils.cpp @@ -145,4 +145,14 @@ QStringList QtUtils::WordWrapString(const QString &s, const QFontMetrics &fm, in return list; } +void QtUtils::SetComboBoxData(QComboBox *cb, int data) +{ + for (int i=0; icount(); i++) { + if (cb->itemData(i).toInt() == data) { + cb->setCurrentIndex(i); + break; + } + } +} + } diff --git a/app/common/qtutils.h b/app/common/qtutils.h index 19e2ea68c..74ff4fcf8 100644 --- a/app/common/qtutils.h +++ b/app/common/qtutils.h @@ -21,12 +21,7 @@ #ifndef QTVERSIONABSTRACTION_H #define QTVERSIONABSTRACTION_H -/** - * - * A fairly simple header for reducing the amount of Qt version checks necessary throughout the code - * - */ - +#include #include #include #include @@ -58,6 +53,8 @@ public: static QStringList WordWrapString(const QString &s, const QFontMetrics &fm, int bounding_width); + static void SetComboBoxData(QComboBox *cb, int data); + template static T *GetParentOfType(const QObject *child) { diff --git a/app/dialog/export/codec/cineformsection.cpp b/app/dialog/export/codec/cineformsection.cpp index ba0071e6d..da83eabed 100644 --- a/app/dialog/export/codec/cineformsection.cpp +++ b/app/dialog/export/codec/cineformsection.cpp @@ -82,4 +82,9 @@ void CineformSection::AddOpts(EncodingParams *params) params->set_video_option(QStringLiteral("quality"), QString::number(quality_combobox_->currentIndex())); } +void CineformSection::SetOpts(const EncodingParams *p) +{ + quality_combobox_->setCurrentIndex(p->video_option(QStringLiteral("quality")).toInt()); +} + } diff --git a/app/dialog/export/codec/cineformsection.h b/app/dialog/export/codec/cineformsection.h index edbe8813a..8a3a08491 100644 --- a/app/dialog/export/codec/cineformsection.h +++ b/app/dialog/export/codec/cineformsection.h @@ -35,6 +35,8 @@ public: virtual void AddOpts(EncodingParams* params) override; + virtual void SetOpts(const EncodingParams *p) override; + private: QComboBox *quality_combobox_; diff --git a/app/dialog/export/codec/codecsection.h b/app/dialog/export/codec/codecsection.h index 24be8f1f8..93eebaa1d 100644 --- a/app/dialog/export/codec/codecsection.h +++ b/app/dialog/export/codec/codecsection.h @@ -35,6 +35,8 @@ public: virtual void AddOpts(EncodingParams* params){Q_UNUSED(params)} + virtual void SetOpts(const EncodingParams *p){Q_UNUSED(p)} + }; } diff --git a/app/dialog/export/codec/h264section.cpp b/app/dialog/export/codec/h264section.cpp index 8c015e0f8..732aef346 100644 --- a/app/dialog/export/codec/h264section.cpp +++ b/app/dialog/export/codec/h264section.cpp @@ -60,7 +60,7 @@ H264Section::H264Section(int default_crf, QWidget *parent) : preset_combobox_->addItem(tr("Slow")); preset_combobox_->addItem(tr("Slower")); preset_combobox_->addItem(tr("Very Slow")); - + //Default to "medium" preset_combobox_->setCurrentIndex(5); @@ -105,6 +105,10 @@ void H264Section::AddOpts(EncodingParams *params) CompressionMethod method = static_cast(compression_method_stack_->currentIndex()); + // This option is not used by the encoder (nor is anything with the ove_ prefix), it's to help us + // identify which option was chosen when params are restored + params->set_video_option(QStringLiteral("ove_compressionmethod"), QString::number(method)); + if (method == kConstantRateFactor) { // Simply set CRF value @@ -121,9 +125,12 @@ void H264Section::AddOpts(EncodingParams *params) max_rate = bitrate_section_->GetMaximumBitRate(); } else { // Calculate the bit rate from the file size divided by the sequence length in seconds (bits per second) - target_rate = qRound64(static_cast(filesize_section_->GetFileSize()) / params->GetExportLength().toDouble()); + int64_t target_fs = filesize_section_->GetFileSize(); + target_rate = qRound64(static_cast(target_fs) / params->GetExportLength().toDouble()); min_rate = target_rate; max_rate = target_rate; + + params->set_video_option(QStringLiteral("ove_targetfilesize"), QString::number(target_fs)); } // Disable CRF encoding @@ -135,10 +142,33 @@ void H264Section::AddOpts(EncodingParams *params) params->set_video_buffer_size(2000000); } - + params->set_video_option(QStringLiteral("preset"), QString::number(preset_combobox_->currentIndex())); } +void H264Section::SetOpts(const EncodingParams *p) +{ + CompressionMethod method = static_cast(p->video_option(QStringLiteral("ove_compressionmethod")).toInt()); + + compression_method_stack_->setCurrentIndex(method); + + if (method == kConstantRateFactor) { + crf_section_->SetValue(p->video_option(QStringLiteral("crf")).toInt()); + } else { + int64_t target_rate = p->video_bit_rate(); + int64_t max_rate = p->video_max_bit_rate(); + + if (method == kTargetBitRate) { + // Use user-supplied values for the bit rate + bitrate_section_->SetTargetBitRate(target_rate); + bitrate_section_->SetMaximumBitRate(max_rate); + } else { + // Calculate the bit rate from the file size divided by the sequence length in seconds (bits per second) + filesize_section_->SetFileSize(p->video_option(QStringLiteral("ove_targetfilesize")).toLongLong()); + } + } +} + H264CRFSection::H264CRFSection(int default_crf, QWidget *parent) : QWidget(parent) { @@ -168,6 +198,11 @@ int H264CRFSection::GetValue() const return crf_slider_->value(); } +void H264CRFSection::SetValue(int c) +{ + crf_slider_->setValue(c); +} + H264BitRateSection::H264BitRateSection(QWidget *parent) : QWidget(parent) { @@ -207,11 +242,21 @@ int64_t H264BitRateSection::GetTargetBitRate() const return qRound64(target_rate_->GetValue() * 1000000.0); } +void H264BitRateSection::SetTargetBitRate(int64_t b) +{ + target_rate_->SetValue(double(b) * 0.000001); +} + int64_t H264BitRateSection::GetMaximumBitRate() const { return qRound64(max_rate_->GetValue() * 1000000.0); } +void H264BitRateSection::SetMaximumBitRate(int64_t b) +{ + max_rate_->SetValue(double(b) * 0.000001); +} + H264FileSizeSection::H264FileSizeSection(QWidget *parent) : QWidget(parent) { @@ -243,6 +288,12 @@ int64_t H264FileSizeSection::GetFileSize() const return qRound64(file_size_->GetValue() * 1024.0 * 1024.0 * 8.0); } +void H264FileSizeSection::SetFileSize(int64_t f) +{ + // Convert bits back to megabytes + file_size_->SetValue(double(f) / 8.0 / 1024.0 / 1024.0); +} + H265Section::H265Section(QWidget *parent) : H264Section(H264CRFSection::kDefaultH265CRF, parent) { diff --git a/app/dialog/export/codec/h264section.h b/app/dialog/export/codec/h264section.h index 2ca0eaa59..9fd984ae5 100644 --- a/app/dialog/export/codec/h264section.h +++ b/app/dialog/export/codec/h264section.h @@ -37,6 +37,7 @@ public: H264CRFSection(int default_crf, QWidget* parent = nullptr); int GetValue() const; + void SetValue(int c); static const int kDefaultH264CRF = 18; static const int kDefaultH265CRF = 23; @@ -59,11 +60,13 @@ public: * @brief Get user-selected target bit rate (returns in BITS) */ int64_t GetTargetBitRate() const; + void SetTargetBitRate(int64_t b); /** * @brief Get user-selected maximum bit rate (returns in BITS) */ int64_t GetMaximumBitRate() const; + void SetMaximumBitRate(int64_t b); private: FloatSlider* target_rate_; @@ -82,6 +85,7 @@ public: * @brief Returns file size in BITS */ int64_t GetFileSize() const; + void SetFileSize(int64_t f); private: FloatSlider* file_size_; @@ -103,6 +107,8 @@ public: virtual void AddOpts(EncodingParams* params) override; + virtual void SetOpts(const EncodingParams *p) override; + private: QStackedWidget* compression_method_stack_; diff --git a/app/dialog/export/codec/imagesection.h b/app/dialog/export/codec/imagesection.h index b93f733a0..3575ea5a2 100644 --- a/app/dialog/export/codec/imagesection.h +++ b/app/dialog/export/codec/imagesection.h @@ -39,6 +39,11 @@ public: return image_sequence_checkbox_->isChecked(); } + void SetImageSequenceChecked(bool e) + { + image_sequence_checkbox_->setChecked(e); + } + void SetTimebase(const rational& r) { frame_slider_->SetTimebase(r); diff --git a/app/dialog/export/export.cpp b/app/dialog/export/export.cpp index 0968428f8..71b12e992 100644 --- a/app/dialog/export/export.cpp +++ b/app/dialog/export/export.cpp @@ -41,8 +41,10 @@ namespace olive { +#define super QDialog + ExportDialog::ExportDialog(ViewerOutput *viewer_node, QWidget *parent) : - QDialog(parent), + super(parent), viewer_node_(viewer_node) { QHBoxLayout* layout = new QHBoxLayout(this); @@ -255,6 +257,11 @@ ExportDialog::ExportDialog(ViewerOutput *viewer_node, QWidget *parent) : connect(subtitles_enabled_, &QCheckBox::toggled, subtitle_tab_, &QWidget::setEnabled); subtitles_enabled_->setChecked(has_subtitle_codecs); subtitles_enabled_->setEnabled(has_subtitle_codecs); + + // If the viewer already has cached params, use them + if (viewer_node_->GetLastUsedEncodingParams().IsValid()) { + SetParams(viewer_node_->GetLastUsedEncodingParams()); + } } rational ExportDialog::GetSelectedTimebase() const @@ -262,6 +269,11 @@ rational ExportDialog::GetSelectedTimebase() const return video_tab_->GetSelectedFrameRate().flipped(); } +void ExportDialog::SetSelectedTimebase(const rational &r) +{ + video_tab_->SetSelectedFrameRate(r.flipped()); +} + void ExportDialog::StartExport() { if (!video_enabled_->isChecked() && !audio_enabled_->isChecked() && !subtitles_enabled_->isChecked()) { @@ -390,13 +402,6 @@ void ExportDialog::ImageSequenceCheckBoxChanged(bool e) filename_edit_->setText(current_fileinfo.dir().filePath(basename)); } -void ExportDialog::closeEvent(QCloseEvent *e) -{ - preview_viewer_->ConnectViewerNode(nullptr); - - QDialog::closeEvent(e); -} - void ExportDialog::AddPreferencesTab(QWidget *inner_widget, const QString &title) { QScrollArea* scroll_area = new QScrollArea(); @@ -522,7 +527,7 @@ bool ExportDialog::SequenceHasSubtitles() const return false; } -ExportParams ExportDialog::GenerateParams() const +EncodingParams ExportDialog::GenerateParams() const { VideoParams video_render_params(static_cast(video_tab_->width_slider()->GetValue()), static_cast(video_tab_->height_slider()->GetValue()), @@ -537,7 +542,7 @@ ExportParams ExportDialog::GenerateParams() const audio_tab_->channel_layout_combobox()->GetChannelLayout(), audio_tab_->sample_format_combobox()->GetSampleFormat()); - ExportParams params; + EncodingParams params; params.set_format(format_combobox_->GetFormat()); params.SetFilename(filename_edit_->text().trimmed()); params.SetExportLength(viewer_node_->GetLength()); @@ -552,7 +557,7 @@ ExportParams ExportDialog::GenerateParams() const } if (video_tab_->scaling_method_combobox()->isEnabled()) { - params.set_video_scaling_method(static_cast(video_tab_->scaling_method_combobox()->currentData().toInt())); + params.set_video_scaling_method(static_cast(video_tab_->scaling_method_combobox()->currentData().toInt())); } if (video_enabled_->isChecked()) { @@ -596,6 +601,76 @@ ExportParams ExportDialog::GenerateParams() const return params; } +void ExportDialog::SetParams(const EncodingParams &e) +{ + format_combobox_->SetFormat(e.format()); + filename_edit_->setText(e.filename()); + + if (e.has_custom_range() && viewer_node_->GetWorkArea()->enabled()) { + range_combobox_->setCurrentIndex(kRangeInToOut); + } + + QtUtils::SetComboBoxData(video_tab_->scaling_method_combobox(), e.video_scaling_method()); + + video_enabled_->setChecked(e.video_enabled()); + if (e.video_enabled()) { + video_tab_->width_slider()->SetValue(e.video_params().width()); + video_tab_->height_slider()->SetValue(e.video_params().height()); + SetSelectedTimebase(e.video_params().time_base()); + video_tab_->pixel_format_field()->SetPixelFormat(e.video_params().format()); + video_tab_->pixel_aspect_combobox()->SetPixelAspectRatio(e.video_params().pixel_aspect_ratio()); + video_tab_->interlaced_combobox()->SetInterlaceMode(e.video_params().interlacing()); + + video_tab_->SetSelectedCodec(e.video_codec()); + + video_tab_->SetColorRange(e.video_params().color_range()); + + video_tab_->SetThreads(e.video_threads()); + + if (video_tab_->isVisible()) { + video_tab_->GetCodecSection()->SetOpts(&e); + } + + video_tab_->SetOCIOColorSpace(e.color_transform().output()); + + video_tab_->SetPixFmt(e.video_pix_fmt()); + + video_tab_->SetImageSequence(e.video_is_image_sequence()); + } + + audio_enabled_->setChecked(e.audio_enabled()); + if (e.audio_enabled()) { + audio_tab_->sample_rate_combobox()->SetSampleRate(e.audio_params().sample_rate()); + audio_tab_->channel_layout_combobox()->SetChannelLayout(e.audio_params().channel_layout()); + audio_tab_->sample_format_combobox()->SetSampleFormat(e.audio_params().format()); + + audio_tab_->SetCodec(e.audio_codec()); + + audio_tab_->bit_rate_slider()->SetValue(e.audio_bit_rate() / 1000); + } + + if (subtitles_enabled_->isEnabled()) { + subtitles_enabled_->setChecked(e.subtitles_enabled()); + subtitle_tab_->SetSidecarEnabled(e.subtitles_are_sidecar()); + if (e.subtitles_enabled()) { + subtitle_tab_->SetSubtitleCodec(e.subtitles_codec()); + if (e.subtitles_are_sidecar()) { + subtitle_tab_->SetSidecarFormat(e.subtitle_sidecar_fmt()); + } + } + } +} + +void ExportDialog::done(int r) +{ + qDebug() << "done???"; + preview_viewer_->ConnectViewerNode(nullptr); + + viewer_node_->SetLastUsedEncodingParams(GenerateParams()); + + super::done(r); +} + rational ExportDialog::GetExportLength() const { if (range_combobox_->currentIndex() == kRangeInToOut) { @@ -617,8 +692,8 @@ void ExportDialog::UpdateViewerDimensions() VideoParams vp = viewer_node_->GetVideoParams(); - QMatrix4x4 transform = ExportParams::GenerateMatrix( - static_cast(video_tab_->scaling_method_combobox()->currentData().toInt()), + QMatrix4x4 transform = EncodingParams::GenerateMatrix( + static_cast(video_tab_->scaling_method_combobox()->currentData().toInt()), vp.width(), vp.height(), static_cast(video_tab_->width_slider()->GetValue()), diff --git a/app/dialog/export/export.h b/app/dialog/export/export.h index 9cd7d274a..abf242575 100644 --- a/app/dialog/export/export.h +++ b/app/dialog/export/export.h @@ -45,6 +45,7 @@ public: ExportDialog(ViewerOutput* viewer_node, QWidget* parent = nullptr); rational GetSelectedTimebase() const; + void SetSelectedTimebase(const rational &r); void SetTime(const rational &time) { @@ -54,8 +55,11 @@ public: preview_viewer_->SetAudioScrubbingEnabled(true); } -protected: - virtual void closeEvent(QCloseEvent *e) override; + EncodingParams GenerateParams() const; + void SetParams(const EncodingParams &e); + +public slots: + virtual void done(int r) override; private: void AddPreferencesTab(QWidget *inner_widget, const QString &title); @@ -65,8 +69,6 @@ private: bool SequenceHasSubtitles() const; - ExportParams GenerateParams() const; - ViewerOutput* viewer_node_; ExportFormat::Format previously_selected_format_; diff --git a/app/dialog/export/exportsubtitlestab.h b/app/dialog/export/exportsubtitlestab.h index faa5d4bdf..dee62f93e 100644 --- a/app/dialog/export/exportsubtitlestab.h +++ b/app/dialog/export/exportsubtitlestab.h @@ -26,6 +26,7 @@ #include #include "codec/exportformat.h" +#include "common/qtutils.h" #include "dialog/export/exportformatcombobox.h" namespace olive { @@ -49,6 +50,11 @@ public: return static_cast(codec_combobox_->currentData().toInt()); } + void SetSubtitleCodec(ExportCodec::Codec c) + { + QtUtils::SetComboBoxData(codec_combobox_, c); + } + private: QCheckBox *sidecar_checkbox_; diff --git a/app/dialog/export/exportvideotab.cpp b/app/dialog/export/exportvideotab.cpp index fd175c8a0..56ecfcdfc 100644 --- a/app/dialog/export/exportvideotab.cpp +++ b/app/dialog/export/exportvideotab.cpp @@ -29,7 +29,6 @@ #include "core.h" #include "exportadvancedvideodialog.h" #include "node/color/colormanager/colormanager.h" -#include "task/export/exportparams.h" namespace olive { @@ -70,6 +69,13 @@ bool ExportVideoTab::IsImageSequenceSet() const return (img_section && img_section->IsImageSequenceChecked()); } +void ExportVideoTab::SetImageSequence(bool e) const +{ + if (ImageSection* img_section = dynamic_cast(codec_stack_->currentWidget())) { + img_section->SetImageSequenceChecked(e); + } +} + QWidget* ExportVideoTab::SetupResolutionSection() { int row = 0; @@ -107,9 +113,9 @@ QWidget* ExportVideoTab::SetupResolutionSection() scaling_method_combobox_ = new QComboBox(); scaling_method_combobox_->setEnabled(false); - scaling_method_combobox_->addItem(tr("Fit"), ExportParams::kFit); - scaling_method_combobox_->addItem(tr("Stretch"), ExportParams::kStretch); - scaling_method_combobox_->addItem(tr("Crop"), ExportParams::kCrop); + scaling_method_combobox_->addItem(tr("Fit"), EncodingParams::kFit); + scaling_method_combobox_->addItem(tr("Stretch"), EncodingParams::kStretch); + scaling_method_combobox_->addItem(tr("Crop"), EncodingParams::kCrop); layout->addWidget(scaling_method_combobox_, row, 1); // Automatically enable/disable the scaling method depending on maintain aspect ratio diff --git a/app/dialog/export/exportvideotab.h b/app/dialog/export/exportvideotab.h index f6f997ee2..1a23837f6 100644 --- a/app/dialog/export/exportvideotab.h +++ b/app/dialog/export/exportvideotab.h @@ -25,6 +25,7 @@ #include #include +#include "common/qtutils.h" #include "common/rational.h" #include "dialog/export/codec/cineformsection.h" #include "dialog/export/codec/codecstack.h" @@ -46,6 +47,7 @@ public: int SetFormat(ExportFormat::Format format); bool IsImageSequenceSet() const; + void SetImageSequence(bool e) const; rational GetStillImageTime() const { @@ -57,6 +59,11 @@ public: return static_cast(codec_combobox()->currentData().toInt()); } + void SetSelectedCodec(ExportCodec::Codec c) + { + QtUtils::SetComboBoxData(codec_combobox(), c); + } + QComboBox* codec_combobox() const { return codec_combobox_; @@ -98,6 +105,11 @@ public: return color_space_chooser_->input(); } + void SetOCIOColorSpace(const QString &s) + { + color_space_chooser_->set_input(s); + } + CodecSection* GetCodecSection() const { return static_cast(codec_stack_->currentWidget()); @@ -133,15 +145,16 @@ public: return threads_; } - const QString& pix_fmt() const + void SetThreads(int t) { - return pix_fmt_; + threads_ = t; } - VideoParams::ColorRange color_range() const - { - return color_range_; - } + const QString& pix_fmt() const { return pix_fmt_; } + void SetPixFmt(const QString &s) { pix_fmt_ = s; } + + VideoParams::ColorRange color_range() const { return color_range_; } + void SetColorRange(VideoParams::ColorRange c) { color_range_ = c; } public slots: void VideoCodecChanged(); diff --git a/app/node/output/viewer/viewer.h b/app/node/output/viewer/viewer.h index 8d26f4bd3..81e96f1d2 100644 --- a/app/node/output/viewer/viewer.h +++ b/app/node/output/viewer/viewer.h @@ -21,6 +21,7 @@ #ifndef VIEWER_H #define VIEWER_H +#include "codec/encoder.h" #include "common/rational.h" #include "node/node.h" #include "node/output/track/track.h" @@ -164,6 +165,9 @@ public: virtual void Value(const NodeValueRow& value, const NodeGlobals &globals, NodeValueTable *table) const override; + const EncodingParams &GetLastUsedEncodingParams() const { return last_used_encoding_params_; } + void SetLastUsedEncodingParams(const EncodingParams &p) { last_used_encoding_params_ = p; } + static const QString kVideoParamsInput; static const QString kAudioParamsInput; static const QString kSubtitleParamsInput; @@ -216,6 +220,8 @@ private: TimelineWorkArea *workarea_; TimelineMarkerList *markers_; + EncodingParams last_used_encoding_params_; + }; } diff --git a/app/task/export/CMakeLists.txt b/app/task/export/CMakeLists.txt index 5c1bb1f41..7a7fad1bc 100644 --- a/app/task/export/CMakeLists.txt +++ b/app/task/export/CMakeLists.txt @@ -18,7 +18,5 @@ set(OLIVE_SOURCES ${OLIVE_SOURCES} task/export/export.h task/export/export.cpp - task/export/exportparams.h - task/export/exportparams.cpp PARENT_SCOPE ) diff --git a/app/task/export/export.cpp b/app/task/export/export.cpp index 7688860d7..017fc59fb 100644 --- a/app/task/export/export.cpp +++ b/app/task/export/export.cpp @@ -27,7 +27,7 @@ namespace olive { ExportTask::ExportTask(ViewerOutput *viewer_node, ColorManager* color_manager, - const ExportParams& params) : + const EncodingParams& params) : color_manager_(color_manager), params_(params) { @@ -60,7 +60,7 @@ bool ExportTask::Run() // If we're exporting to a sidecar subtitle file, disable the subtitles in the main encoder bool subtitles_enabled = params_.subtitles_enabled(); - ExportParams sidecar_params = params_; + EncodingParams sidecar_params = params_; if (subtitles_enabled && params_.subtitles_are_sidecar()) { params_.DisableSubtitles(); } @@ -126,12 +126,12 @@ bool ExportTask::Run() || video_params().height() != params_.video_params().height()) { video_force_size = QSize(params_.video_params().width(), params_.video_params().height()); - if (params_.video_scaling_method() != ExportParams::kStretch) { - video_force_matrix = ExportParams::GenerateMatrix(params_.video_scaling_method(), - video_params().width(), - video_params().height(), - params_.video_params().width(), - params_.video_params().height()); + if (params_.video_scaling_method() != EncodingParams::kStretch) { + video_force_matrix = EncodingParams::GenerateMatrix(params_.video_scaling_method(), + video_params().width(), + video_params().height(), + params_.video_params().width(), + params_.video_params().height()); } } else { // Disables forcing size in the renderer diff --git a/app/task/export/export.h b/app/task/export/export.h index 4bed7cd8b..7dcd8cf99 100644 --- a/app/task/export/export.h +++ b/app/task/export/export.h @@ -21,7 +21,7 @@ #ifndef EXPORTTASK_H #define EXPORTTASK_H -#include "exportparams.h" +#include "codec/encoder.h" #include "node/output/viewer/viewer.h" #include "render/colorprocessor.h" #include "task/render/render.h" @@ -33,7 +33,7 @@ class ExportTask : public RenderTask { Q_OBJECT public: - ExportTask(ViewerOutput *viewer_node, ColorManager *color_manager, const ExportParams ¶ms); + ExportTask(ViewerOutput *viewer_node, ColorManager *color_manager, const EncodingParams ¶ms); protected: virtual bool Run() override; @@ -58,7 +58,7 @@ private: ColorManager* color_manager_; - ExportParams params_; + EncodingParams params_; std::shared_ptr encoder_; diff --git a/app/task/export/exportparams.cpp b/app/task/export/exportparams.cpp deleted file mode 100644 index f866f3cbd..000000000 --- a/app/task/export/exportparams.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/*** - - Olive - Non-Linear Video Editor - Copyright (C) 2022 Olive Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -***/ - -#include "exportparams.h" - -namespace olive { - -ExportParams::ExportParams() : - video_scaling_method_(kStretch), - has_custom_range_(false) -{ -} - -bool ExportParams::has_custom_range() const -{ - return has_custom_range_; -} - -const TimeRange &ExportParams::custom_range() const -{ - return custom_range_; -} - -void ExportParams::set_custom_range(const TimeRange &custom_range) -{ - has_custom_range_ = true; - custom_range_ = custom_range; -} - -const ExportParams::VideoScalingMethod &ExportParams::video_scaling_method() const -{ - return video_scaling_method_; -} - -void ExportParams::set_video_scaling_method(const ExportParams::VideoScalingMethod &video_scaling_method) -{ - video_scaling_method_ = video_scaling_method; -} - -QMatrix4x4 ExportParams::GenerateMatrix(ExportParams::VideoScalingMethod method, - int source_width, int source_height, - int dest_width, int dest_height) -{ - QMatrix4x4 preview_matrix; - - if (method == ExportParams::kStretch) { - return preview_matrix; - } - - float export_ar = static_cast(dest_width) / static_cast(dest_height); - float source_ar = static_cast(source_width) / static_cast(source_height); - - if (qFuzzyCompare(export_ar, source_ar)) { - return preview_matrix; - } - - if ((export_ar > source_ar) == (method == ExportParams::kFit)) { - preview_matrix.scale(source_ar / export_ar, 1.0F); - } else { - preview_matrix.scale(1.0F, export_ar / source_ar); - } - - return preview_matrix; -} - -void ExportParams::Save(QXmlStreamWriter *writer) const -{ - writer->writeStartElement(QStringLiteral("export")); - - writer->writeTextElement(QStringLiteral("vscale"), QString::number(video_scaling_method_)); - - writer->writeTextElement(QStringLiteral("range"), QString::number(has_custom_range_)); - - writer->writeTextElement(QStringLiteral("customrangein"), custom_range_.in().toString()); - - writer->writeTextElement(QStringLiteral("customrangeout"), custom_range_.out().toString()); - - // FIXME: Change this when color chains are implemented - writer->writeTextElement(QStringLiteral("color"), color_transform().output()); - - EncodingParams::Save(writer); - - writer->writeEndElement(); // export -} - -} diff --git a/app/task/export/exportparams.h b/app/task/export/exportparams.h deleted file mode 100644 index 437271eab..000000000 --- a/app/task/export/exportparams.h +++ /dev/null @@ -1,65 +0,0 @@ -/*** - - Olive - Non-Linear Video Editor - Copyright (C) 2022 Olive Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -***/ - -#ifndef EXPORTPARAMS_H -#define EXPORTPARAMS_H - -#include - -#include "codec/encoder.h" -#include "node/output/viewer/viewer.h" -#include "render/colortransform.h" - -namespace olive { - -class ExportParams : public EncodingParams { -public: - enum VideoScalingMethod { - kFit, - kStretch, - kCrop - }; - - ExportParams(); - - bool has_custom_range() const; - const TimeRange& custom_range() const; - void set_custom_range(const TimeRange& custom_range); - - const VideoScalingMethod& video_scaling_method() const; - void set_video_scaling_method(const VideoScalingMethod& video_scaling_method); - - static QMatrix4x4 GenerateMatrix(ExportParams::VideoScalingMethod method, - int source_width, int source_height, - int dest_width, int dest_height); - - virtual void Save(QXmlStreamWriter* writer) const override; - -private: - VideoScalingMethod video_scaling_method_; - - bool has_custom_range_; - TimeRange custom_range_; - -}; - -} - -#endif // EXPORTPARAMS_H