File indexing completed on 2024-04-21 04:51:22
0001 /* 0002 SPDX-FileCopyrightText: 2022 Julius Künzel <jk.kdedev@smartlab.uber.space> 0003 0004 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "renderpresetdialog.h" 0008 0009 #include "core.h" 0010 #include "kdenlivesettings.h" 0011 #include "monitor/monitormanager.h" 0012 #include "profiles/profilemodel.hpp" 0013 #include "renderpresets/renderpresetmodel.hpp" 0014 #include "renderpresets/renderpresetrepository.hpp" 0015 0016 #include <KMessageBox> 0017 #include <QPushButton> 0018 #include <QScrollBar> 0019 0020 // TODO replace this by std::gcd ones why require C++17 or greater 0021 static int gcd(int a, int b) 0022 { 0023 for (;;) { 0024 if (a == 0) return b; 0025 b %= a; 0026 if (b == 0) return a; 0027 a %= b; 0028 } 0029 } 0030 0031 RenderPresetDialog::RenderPresetDialog(QWidget *parent, RenderPresetModel *preset, Mode mode) 0032 : QDialog(parent) 0033 , m_saveName(preset ? preset->name() : "") 0034 , m_monitor(nullptr) 0035 , m_fixedResRatio(1.) 0036 , m_manualPreset(false) 0037 { 0038 setupUi(this); 0039 if (preset) { 0040 m_manualPreset = preset->isManual(); 0041 } 0042 m_uiParams.append({QStringLiteral("f"), 0043 QStringLiteral("acodec"), 0044 QStringLiteral("vcodec"), 0045 QStringLiteral("width"), 0046 QStringLiteral("height"), 0047 QStringLiteral("s"), 0048 QStringLiteral("r"), 0049 QStringLiteral("frame_rate_num"), 0050 QStringLiteral("frame_rate_den"), 0051 QStringLiteral("crf"), 0052 QStringLiteral("color_range"), 0053 QStringLiteral("vb"), 0054 QStringLiteral("vminrate"), 0055 QStringLiteral("vmaxrate"), 0056 QStringLiteral("vglobal_quality"), 0057 QStringLiteral("vq"), 0058 QStringLiteral("rc"), 0059 QStringLiteral("g"), 0060 QStringLiteral("bf"), 0061 QStringLiteral("progressive"), 0062 QStringLiteral("top_field_first"), 0063 QStringLiteral("qscale"), 0064 QStringLiteral("vbufsize"), 0065 QStringLiteral("qmin"), 0066 QStringLiteral("qp_i"), 0067 QStringLiteral("qp_p"), 0068 QStringLiteral("qp_b"), 0069 QStringLiteral("ab"), 0070 QStringLiteral("aq"), 0071 QStringLiteral("compression_level"), 0072 QStringLiteral("vbr"), 0073 QStringLiteral("ar"), 0074 QStringLiteral("display_aspect_num"), 0075 QStringLiteral("display_aspect_den"), 0076 QStringLiteral("sample_aspect_num"), 0077 QStringLiteral("sample_aspect_den"), 0078 QStringLiteral("aspect"), 0079 QStringLiteral("sc_threshold"), 0080 QStringLiteral("strict_gop"), 0081 QStringLiteral("keyint_min"), 0082 QStringLiteral("channels")}); 0083 0084 formatCombo->addItems(RenderPresetRepository::supportedFormats()); 0085 vCodecCombo->addItems(RenderPresetRepository::vcodecs()); 0086 aCodecCombo->addItems(RenderPresetRepository::acodecs()); 0087 0088 aRateControlCombo->addItem(i18n("(Not set)")); 0089 aRateControlCombo->addItem(i18n("Average Bitrate")); 0090 aRateControlCombo->addItem(i18n("CBR – Constant Bitrate")); 0091 aRateControlCombo->addItem(i18n("VBR – Variable Bitrate")); 0092 0093 audioChannels->addItem(i18n("1 (mono)"), 1); 0094 audioChannels->addItem(i18n("2 (stereo)"), 2); 0095 audioChannels->addItem(i18n("4"), 4); 0096 audioChannels->addItem(i18n("6"), 6); 0097 0098 QValidator *validator = new QIntValidator(this); 0099 audioSampleRate->setValidator(validator); 0100 0101 // Add some common pixel aspect ratios: 0102 // The following code works, because setting a yet 0103 // unknown ratio will add it to the combo box. 0104 setPixelAspectRatio(1, 1); 0105 setPixelAspectRatio(10, 11); 0106 setPixelAspectRatio(12, 11); 0107 setPixelAspectRatio(59, 54); 0108 setPixelAspectRatio(4, 3); 0109 setPixelAspectRatio(64, 45); 0110 setPixelAspectRatio(11, 9); 0111 setPixelAspectRatio(118, 81); 0112 0113 // 0114 QPushButton *helpButton = buttonBox->button(QDialogButtonBox::Help); 0115 helpButton->setText(QString()); 0116 helpButton->setIcon(QIcon::fromTheme(QStringLiteral("settings-configure"))); 0117 helpButton->setToolTip(i18n("Edit Render Preset")); 0118 helpButton->setCheckable(true); 0119 helpButton->setChecked(KdenliveSettings::showRenderTextParameters()); 0120 parameters->setVisible(KdenliveSettings::showRenderTextParameters()); 0121 connect(helpButton, &QPushButton::toggled, [this](bool checked) { 0122 parameters->setVisible(checked); 0123 KdenliveSettings::setShowRenderTextParameters(checked); 0124 }); 0125 0126 connect(vRateControlCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this](int index) { 0127 switch (index) { 0128 case RenderPresetParams::RateControl::Average: 0129 default_vbitrate->setEnabled(true); 0130 default_vquality->setEnabled(false); 0131 vquality_label->setEnabled(false); 0132 vBuffer->setEnabled(false); 0133 break; 0134 case RenderPresetParams::RateControl::Constant: 0135 default_vbitrate->setEnabled(true); 0136 default_vquality->setEnabled(false); 0137 vquality_label->setEnabled(false); 0138 vBuffer->setEnabled(true); 0139 break; 0140 case RenderPresetParams::RateControl::Constrained: 0141 default_vbitrate->setEnabled(true); 0142 default_vquality->setEnabled(true); 0143 vquality_label->setEnabled(true); 0144 vBuffer->setEnabled(true); 0145 break; 0146 case RenderPresetParams::RateControl::Quality: 0147 default_vbitrate->setEnabled(false); 0148 default_vquality->setEnabled(true); 0149 vquality_label->setEnabled(true); 0150 vBuffer->setEnabled(false); 0151 break; 0152 default: 0153 default_vbitrate->setEnabled(false); 0154 default_vquality->setEnabled(false); 0155 vquality_label->setEnabled(false); 0156 vBuffer->setEnabled(false); 0157 break; 0158 }; 0159 slotUpdateParams(); 0160 }); 0161 0162 vRateControlCombo->addItem(i18n("(Not set)")); 0163 vRateControlCombo->addItem(i18n("Average Bitrate")); 0164 vRateControlCombo->addItem(i18n("CBR – Constant Bitrate")); 0165 vRateControlCombo->addItem(i18n("VBR – Variable Bitrate")); 0166 vRateControlCombo->addItem(i18n("Constrained VBR")); 0167 0168 connect(scanningCombo, &QComboBox::currentTextChanged, this, [&]() { 0169 fieldOrderCombo->setEnabled(scanningCombo->currentIndex() != 1); 0170 cField->setEnabled(scanningCombo->currentIndex() != 1); 0171 slotUpdateParams(); 0172 }); 0173 connect(gopSpinner, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [&](int value) { 0174 fixedGop->setEnabled(value > 1); 0175 bFramesSpinner->setEnabled(value > 1); 0176 bFramesLabel->setEnabled(value > 1); 0177 if (value <= 1) { 0178 fixedGop->blockSignals(true); 0179 fixedGop->setChecked(false); 0180 fixedGop->blockSignals(false); 0181 bFramesSpinner->blockSignals(true); 0182 bFramesSpinner->setValue(-1); 0183 bFramesSpinner->blockSignals(false); 0184 } else { 0185 bFramesSpinner->setMaximum(value - 1); 0186 } 0187 slotUpdateParams(); 0188 }); 0189 0190 groupName->addItems(RenderPresetRepository::get()->groupNames()); 0191 0192 std::unique_ptr<ProfileModel> &projectProfile = pCore->getCurrentProfile(); 0193 int parNum = projectProfile->sample_aspect_num(); 0194 int parDen = projectProfile->sample_aspect_den(); 0195 connect(button_manual, &QPushButton::clicked, [this, helpButton]() { 0196 if (m_manualPreset) { 0197 return; 0198 } 0199 tabWidget->setVisible(false); 0200 label_container->setEnabled(false); 0201 formatCombo->setEnabled(false); 0202 parameters->setVisible(true); 0203 parameters->setReadOnly(false); 0204 helpButton->setEnabled(false); 0205 m_manualPreset = true; 0206 }); 0207 if (preset) { 0208 groupName->setCurrentText(preset->groupName()); 0209 if (mode != Mode::New) { 0210 preset_name->setText(preset->name()); 0211 } 0212 preset_name->setFocus(); 0213 if (m_manualPreset) { 0214 tabWidget->setVisible(false); 0215 label_container->setEnabled(false); 0216 formatCombo->setEnabled(false); 0217 parameters->setVisible(true); 0218 parameters->setPlainText(preset->params().toString()); 0219 parameters->setReadOnly(false); 0220 helpButton->setEnabled(false); 0221 preset_extension->setText(preset->extension()); 0222 } else { 0223 formatCombo->setCurrentText(preset->getParam(QStringLiteral("f"))); 0224 preset_extension->setText(preset->extension()); 0225 QString width = preset->getParam(QStringLiteral("width")); 0226 QString height = preset->getParam(QStringLiteral("height")); 0227 QString size = preset->getParam(QStringLiteral("s")); 0228 0229 if (!(width.isEmpty() && height.isEmpty())) { 0230 resWidth->setValue(width.toInt()); 0231 resHeight->setValue(height.toInt()); 0232 cResolution->setChecked(true); 0233 } else if (!size.isEmpty()) { 0234 QStringList list = size.split(QStringLiteral("x")); 0235 if (list.count() == 2) { 0236 resWidth->setValue(list.at(0).toInt()); 0237 resHeight->setValue(list.at(1).toInt()); 0238 cResolution->setChecked(true); 0239 } 0240 } else { 0241 resWidth->setValue(projectProfile->width()); 0242 resHeight->setValue(projectProfile->height()); 0243 } 0244 0245 // video tab 0246 if (preset->hasParam(QStringLiteral("vbufsize"))) { 0247 bool ok = false; 0248 int vbufsize = preset->getParam(QStringLiteral("vbufsize")).toInt(&ok); 0249 if (ok) { 0250 vBuffer->setValue(vbufsize / 1024 / 8); 0251 } 0252 } 0253 QString vqParam = preset->getParam(QStringLiteral("vq")); 0254 QString vbParam = preset->getParam(QStringLiteral("vb")); 0255 if (vqParam.isEmpty()) { 0256 vqParam = preset->getParam(QStringLiteral("vqp")); 0257 } 0258 if (vqParam.isEmpty()) { 0259 vqParam = preset->getParam(QStringLiteral("vglobal_quality")); 0260 } 0261 if (vqParam.isEmpty()) { 0262 vqParam = preset->getParam(QStringLiteral("qscale")); 0263 } 0264 if (vqParam.isEmpty()) { 0265 vqParam = preset->getParam(QStringLiteral("crf")); 0266 } 0267 if (vqParam == QStringLiteral("%quality")) { 0268 default_vquality->setValue(preset->defaultVQuality().toInt()); 0269 } else { 0270 default_vquality->setValue(vqParam.toInt()); 0271 } 0272 0273 vRateControlCombo->setCurrentIndex(preset->params().videoRateControl()); 0274 0275 if (vbParam.isEmpty()) { 0276 vbParam = preset->getParam(QStringLiteral("vmaxrate")); 0277 } 0278 if (vbParam.contains(QStringLiteral("%bitrate"))) { 0279 default_vbitrate->setValue(preset->defaultVBitrate().toInt()); 0280 } else if (!vbParam.isEmpty()) { 0281 default_vbitrate->setValue(vbParam.replace('k', "").replace('M', "000").toInt()); 0282 } 0283 0284 QString sampAspNum = preset->getParam(QStringLiteral("sample_aspect_num")); 0285 QString sampAspDen = preset->getParam(QStringLiteral("sample_aspect_den")); 0286 QString sampAsp = preset->getParam(QStringLiteral("aspect")); 0287 0288 if (!(sampAspNum.isEmpty() && sampAspDen.isEmpty())) { 0289 parNum = sampAspNum.toInt(); 0290 parDen = sampAspDen.toInt(); 0291 cPar->setChecked(true); 0292 } else if (!sampAsp.isEmpty()) { 0293 QStringList list = sampAsp.split(QStringLiteral("/")); 0294 if (list.count() == 2) { 0295 parNum = list.at(0).toInt(); 0296 parDen = list.at(1).toInt(); 0297 cPar->setChecked(true); 0298 } 0299 } 0300 0301 if (preset->hasParam(QStringLiteral("display_aspect_num")) && preset->hasParam(QStringLiteral("display_aspect_den"))) { 0302 displayAspectNum->setValue(preset->getParam(QStringLiteral("display_aspect_num")).toInt()); 0303 displayAspectDen->setValue(preset->getParam(QStringLiteral("display_aspect_den")).toInt()); 0304 cDar->setChecked(true); 0305 } else { 0306 displayAspectNum->setValue(projectProfile->display_aspect_num()); 0307 displayAspectDen->setValue(projectProfile->display_aspect_den()); 0308 } 0309 0310 vCodecCombo->setCurrentText(preset->getParam(QStringLiteral("vcodec"))); 0311 if (preset->hasParam(QStringLiteral("r"))) { 0312 cFps->setChecked(true); 0313 double val = preset->getParam(QStringLiteral("r")).toDouble(); 0314 if (val == 23.98 || val == 23.976 || val == (24000 / 1001)) { 0315 framerateNum->setValue(24000); 0316 framerateDen->setValue(1001); 0317 } else if (val == 29.97 || val == (30000 / 1001)) { 0318 framerateNum->setValue(30000); 0319 framerateDen->setValue(1001); 0320 } else if (val == 47.95 || val == (48000 / 1001)) { 0321 framerateNum->setValue(48000); 0322 framerateDen->setValue(1001); 0323 } else if (val == 59.94 || val == (60000 / 1001)) { 0324 framerateNum->setValue(60000); 0325 framerateDen->setValue(1001); 0326 } else { 0327 framerateNum->setValue(qRound(val * 1000)); 0328 framerateDen->setValue(1000); 0329 } 0330 } else if (preset->hasParam(QStringLiteral("frame_rate_num")) && preset->hasParam(QStringLiteral("frame_rate_den"))) { 0331 framerateNum->setValue(preset->getParam(QStringLiteral("frame_rate_num")).toInt()); 0332 framerateDen->setValue(preset->getParam(QStringLiteral("frame_rate_den")).toInt()); 0333 cFps->setChecked(true); 0334 } else { 0335 framerateNum->setValue(projectProfile->frame_rate_num()); 0336 framerateDen->setValue(projectProfile->frame_rate_den()); 0337 } 0338 if (preset->hasParam(QStringLiteral("progressive"))) { 0339 scanningCombo->setCurrentIndex(preset->getParam(QStringLiteral("progressive")).toInt()); 0340 cScanning->setChecked(true); 0341 } 0342 if (preset->hasParam(QStringLiteral("top_field_first"))) { 0343 fieldOrderCombo->setCurrentIndex(preset->getParam(QStringLiteral("top_field_first")).toInt()); 0344 cField->setChecked(true); 0345 } 0346 int gopVal = -1; 0347 if (preset->hasParam(QStringLiteral("g"))) { 0348 gopVal = preset->getParam(QStringLiteral("g")).toInt(); 0349 gopSpinner->setValue(gopVal); 0350 } 0351 if (preset->hasParam(QStringLiteral("sc_threshold"))) 0352 fixedGop->setChecked(preset->getParam(QStringLiteral("sc_threshold")).toInt() == 0); 0353 else if (preset->hasParam(QStringLiteral("keyint_min"))) 0354 fixedGop->setChecked(preset->getParam(QStringLiteral("keyint_min")).toInt() == gopVal); 0355 else if (preset->hasParam(QStringLiteral("strict_gop"))) { 0356 fixedGop->setChecked(preset->getParam(QStringLiteral("strict_gop")).toInt() == 1); 0357 } else { 0358 fixedGop->setChecked(false); 0359 } 0360 bFramesSpinner->setValue(preset->getParam(QStringLiteral("bf")).toInt()); 0361 0362 // audio tab 0363 if (preset->hasParam(QStringLiteral("channels"))) { 0364 int ix = audioChannels->findData(preset->getParam(QStringLiteral("channels")).toInt()); 0365 audioChannels->setCurrentIndex(ix); 0366 cChannels->setChecked(true); 0367 } else { 0368 int ix = audioChannels->findData(2); 0369 audioChannels->setCurrentIndex(ix); 0370 } 0371 aRateControlCombo->setCurrentIndex(preset->audioRateControl()); 0372 0373 if (preset->hasParam(QStringLiteral("channels"))) { 0374 audioSampleRate->setCurrentText(preset->getParam(QStringLiteral("ar"))); 0375 cSampleR->setChecked(true); 0376 } else { 0377 audioSampleRate->setCurrentText(QStringLiteral("44100")); 0378 } 0379 0380 QString aqParam = preset->getParam(QStringLiteral("aq")); 0381 if (aqParam.isEmpty()) { 0382 aqParam = preset->getParam(QStringLiteral("compression_level")); 0383 } 0384 if (aqParam.contains(QStringLiteral("%audioquality"))) { 0385 aQuality->setValue(preset->defaultAQuality().toInt()); 0386 } else { 0387 aQuality->setValue(aqParam.toInt()); 0388 } 0389 QString abParam = preset->getParam(QStringLiteral("ab")); 0390 if (abParam.contains(QStringLiteral("%audiobitrate"))) { 0391 aBitrate->setValue(preset->defaultABitrate().toInt()); 0392 } else { 0393 aBitrate->setValue(abParam.replace('k', "").replace('M', "000").toInt()); 0394 } 0395 0396 aCodecCombo->setCurrentText(preset->getParam(QStringLiteral("acodec"))); 0397 0398 // general tab 0399 speeds_list->setText(preset->speeds().join('\n')); 0400 additionalParams->setPlainText(preset->params(m_uiParams).toString()); 0401 } 0402 } else { 0403 resHeight->setValue(projectProfile->height()); 0404 resWidth->setValue(projectProfile->width()); 0405 framerateNum->setValue(projectProfile->frame_rate_num()); 0406 framerateDen->setValue(projectProfile->frame_rate_den()); 0407 parNum = projectProfile->sample_aspect_num(); 0408 parDen = projectProfile->sample_aspect_den(); 0409 displayAspectNum->setValue(projectProfile->display_aspect_num()); 0410 displayAspectDen->setValue(projectProfile->display_aspect_den()); 0411 scanningCombo->setCurrentIndex(projectProfile->progressive() ? 1 : 0); 0412 } 0413 0414 setPixelAspectRatio(parNum, parDen); 0415 0416 if (groupName->currentText().isEmpty()) { 0417 groupName->setCurrentText(i18nc("Group Name", "Custom")); 0418 } 0419 0420 if (mode == Mode::Edit) { 0421 setWindowTitle(i18n("Edit Render Preset")); 0422 } 0423 0424 connect(preset_name, &QLineEdit::textChanged, this, [&](const QString &text) { buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty()); }); 0425 0426 connect(buttonBox, &QDialogButtonBox::accepted, this, [&, preset, mode]() { 0427 QString oldName; 0428 if (preset) { 0429 oldName = preset->name(); 0430 } 0431 QString newPresetName = preset_name->text().simplified(); 0432 if (newPresetName.isEmpty()) { 0433 KMessageBox::error(this, i18n("The preset name can't be empty")); 0434 return; 0435 } 0436 QString newGroupName = groupName->currentText().simplified(); 0437 if (newGroupName.isEmpty()) { 0438 newGroupName = i18nc("Group Name", "Custom"); 0439 } 0440 QString speeds_list_str = speeds_list->toPlainText().replace('\n', ';').simplified(); 0441 0442 std::unique_ptr<RenderPresetModel> newPreset(new RenderPresetModel(newPresetName, newGroupName, parameters->toPlainText().simplified(), 0443 preset_extension->text().simplified(), QString::number(default_vbitrate->value()), 0444 QString::number(default_vquality->value()), QString::number(aBitrate->value()), 0445 QString::number(aQuality->value()), speeds_list_str, m_manualPreset)); 0446 0447 m_saveName = RenderPresetRepository::get()->savePreset(newPreset.get(), mode == Mode::Edit); 0448 if ((mode == Mode::Edit) && !m_saveName.isEmpty() && (oldName != m_saveName)) { 0449 RenderPresetRepository::get()->deletePreset(oldName); 0450 } 0451 accept(); 0452 }); 0453 0454 connect(formatCombo, &QComboBox::currentTextChanged, [this](const QString &format) { 0455 if (format == QLatin1String("matroska")) { 0456 preset_extension->setText(QStringLiteral("mkv")); 0457 } else { 0458 preset_extension->setText(format); 0459 } 0460 slotUpdateParams(); 0461 }); 0462 connect(vCodecCombo, &QComboBox::currentTextChanged, this, &RenderPresetDialog::slotUpdateParams); 0463 0464 connect(fieldOrderCombo, &QComboBox::currentTextChanged, this, &RenderPresetDialog::slotUpdateParams); 0465 connect(aCodecCombo, &QComboBox::currentTextChanged, this, &RenderPresetDialog::slotUpdateParams); 0466 connect(linkResoultion, &QToolButton::clicked, this, [&]() { m_fixedResRatio = double(resWidth->value()) / double(resHeight->value()); }); 0467 connect(resWidth, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [&](int value) { 0468 if (linkResoultion->isChecked()) { 0469 resHeight->blockSignals(true); 0470 resHeight->setValue(qRound(value / m_fixedResRatio)); 0471 resHeight->blockSignals(false); 0472 } 0473 updateDisplayAspectRatio(); 0474 }); 0475 connect(resHeight, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [&](int value) { 0476 if (linkResoultion->isChecked()) { 0477 resWidth->blockSignals(true); 0478 resWidth->setValue(qRound(value * m_fixedResRatio)); 0479 resWidth->blockSignals(false); 0480 } 0481 updateDisplayAspectRatio(); 0482 }); 0483 connect(parCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &RenderPresetDialog::updateDisplayAspectRatio); 0484 auto update_par = [&]() { 0485 int parNum = displayAspectNum->value() * resHeight->value(); 0486 int parDen = displayAspectDen->value() * resWidth->value(); 0487 setPixelAspectRatio(parNum, parDen); 0488 slotUpdateParams(); 0489 }; 0490 connect(displayAspectNum, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, update_par); 0491 connect(displayAspectDen, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, update_par); 0492 connect(framerateNum, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [&](int value) { 0493 if (value == 0) { 0494 framerateDen->blockSignals(true); 0495 framerateDen->setValue(0); 0496 framerateDen->blockSignals(false); 0497 } 0498 slotUpdateParams(); 0499 }); 0500 connect(framerateDen, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [&](int value) { 0501 if (value == 0) { 0502 framerateNum->blockSignals(true); 0503 framerateNum->setValue(0); 0504 framerateNum->blockSignals(false); 0505 } 0506 slotUpdateParams(); 0507 }); 0508 connect(fixedGop, &QCheckBox::stateChanged, this, &RenderPresetDialog::slotUpdateParams); 0509 connect(bFramesSpinner, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &RenderPresetDialog::slotUpdateParams); 0510 connect(additionalParams, &QPlainTextEdit::textChanged, this, &RenderPresetDialog::slotUpdateParams); 0511 0512 connect(aRateControlCombo, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &RenderPresetDialog::slotUpdateParams); 0513 connect(aBitrate, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &RenderPresetDialog::slotUpdateParams); 0514 connect(aQuality, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &RenderPresetDialog::slotUpdateParams); 0515 connect(audioChannels, &QComboBox::currentTextChanged, this, &RenderPresetDialog::slotUpdateParams); 0516 connect(audioSampleRate, &QComboBox::currentTextChanged, this, &RenderPresetDialog::slotUpdateParams); 0517 0518 linkResoultion->setChecked(true); 0519 slotUpdateParams(); 0520 connect(cResolution, &QCheckBox::toggled, this, &RenderPresetDialog::slotUpdateParams); 0521 connect(cPar, &QCheckBox::toggled, this, &RenderPresetDialog::slotUpdateParams); 0522 connect(cDar, &QCheckBox::toggled, this, &RenderPresetDialog::slotUpdateParams); 0523 connect(cFps, &QCheckBox::toggled, this, &RenderPresetDialog::slotUpdateParams); 0524 connect(cScanning, &QCheckBox::toggled, this, &RenderPresetDialog::slotUpdateParams); 0525 connect(cField, &QCheckBox::toggled, this, &RenderPresetDialog::slotUpdateParams); 0526 connect(cChannels, &QCheckBox::toggled, this, &RenderPresetDialog::slotUpdateParams); 0527 connect(cSampleR, &QCheckBox::toggled, this, &RenderPresetDialog::slotUpdateParams); 0528 0529 for (QSpinBox *sp : findChildren<QSpinBox *>()) { 0530 sp->installEventFilter(this); 0531 sp->setFocusPolicy(Qt::StrongFocus); 0532 } 0533 for (QComboBox *sp : findChildren<QComboBox *>()) { 0534 sp->installEventFilter(this); 0535 sp->setFocusPolicy(Qt::StrongFocus); 0536 } 0537 0538 // TODO 0539 if (false && m_monitor == nullptr) { 0540 // QString profile = DvdWizardVob::getDvdProfile(format); 0541 /*m_monitor = new Monitor(Kdenlive::RenderMonitor, pCore->monitorManager(), this); 0542 m_monitor->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); 0543 mainBox->addWidget(m_monitor); 0544 pCore->monitorManager()->appendMonitor(m_monitor); 0545 // m_monitor->setCustomProfile(profile, m_tc); 0546 pCore->monitorManager()->activateMonitor(Kdenlive::RenderMonitor); 0547 m_monitor->start();*/ 0548 } 0549 } 0550 0551 RenderPresetDialog::~RenderPresetDialog() 0552 { 0553 if (m_monitor) { 0554 m_monitor->stop(); 0555 pCore->monitorManager()->removeMonitor(m_monitor); 0556 delete m_monitor; 0557 } 0558 } 0559 0560 bool RenderPresetDialog::eventFilter(QObject *o, QEvent *e) 0561 { 0562 if (e->type() == QEvent::Wheel && (qobject_cast<QComboBox *>(o) || qobject_cast<QAbstractSpinBox *>(o))) { 0563 if (scrollArea->verticalScrollBar()->isVisible() && !qobject_cast<QWidget *>(o)->hasFocus()) { 0564 e->ignore(); 0565 return true; 0566 } else { 0567 e->accept(); 0568 return false; 0569 } 0570 } 0571 return QWidget::eventFilter(o, e); 0572 } 0573 0574 void RenderPresetDialog::slotUpdateParams() 0575 { 0576 if (m_manualPreset) { 0577 return; 0578 } 0579 QStringList params; 0580 QString vcodec = vCodecCombo->currentText(); 0581 params.append(QStringLiteral("f=%1").arg(formatCombo->currentText())); 0582 // video tab 0583 params.append(QStringLiteral("vcodec=%1").arg(vcodec)); 0584 if (cResolution->isChecked()) { 0585 if (resWidth->value() > 0) { 0586 params.append(QStringLiteral("width=%1").arg(resWidth->value())); 0587 } 0588 if (resHeight->value() > 0) { 0589 params.append(QStringLiteral("height=%1").arg(resHeight->value())); 0590 } 0591 } 0592 if (cPar->isChecked()) { 0593 QStringList par = parCombo->currentData().toString().split(QStringLiteral(":")); 0594 if (par.length() >= 2 && par.at(0).toInt() > 0 && par.at(1).toInt() > 0) { 0595 params.append(QStringLiteral("sample_aspect_num=%1 sample_aspect_den=%2").arg(par.at(0).toInt()).arg(par.at(1).toInt())); 0596 } 0597 } 0598 if (cDar->isChecked() && displayAspectNum->value() > 0 && displayAspectDen->value() > 0) { 0599 params.append(QStringLiteral("display_aspect_num=%1 display_aspect_den=%2").arg(displayAspectNum->value()).arg(displayAspectDen->value())); 0600 } 0601 0602 if (cFps->isChecked() && framerateNum->value() > 0 && framerateDen->value() > 0) { 0603 params.append(QStringLiteral("frame_rate_num=%1").arg(framerateNum->value())); 0604 params.append(QStringLiteral("frame_rate_den=%1").arg(framerateDen->value())); 0605 frameRateDisplay->setText(QString::number(double(framerateNum->value()) / double(framerateDen->value()), 'g', 10)); 0606 frameRateDisplay->show(); 0607 } else { 0608 frameRateDisplay->hide(); 0609 } 0610 0611 // Adjust scanning 0612 if (cScanning->isChecked()) { 0613 params.append(QStringLiteral("progressive=%1").arg(scanningCombo->currentIndex())); 0614 if (cField->isChecked() && scanningCombo->currentIndex() == 0) { 0615 params.append(QStringLiteral("top_field_first=%1").arg(fieldOrderCombo->currentIndex())); 0616 } 0617 } 0618 if (vcodec == "libx265") { 0619 // Most x265 parameters must be supplied through x265-params. 0620 switch (vRateControlCombo->currentIndex()) { 0621 case RenderPresetParams::RateControl::Average: 0622 params.append(QStringLiteral("vb=%bitrate+'k'")); 0623 break; 0624 case RenderPresetParams::RateControl::Constant: { 0625 // x265 does not expect bitrate suffixes and requires Kb/s 0626 params.append(QStringLiteral("vb=%bitrate")); 0627 params.append(QStringLiteral("vbufsize=%1").arg(vBuffer->value() * 8 * 1024)); 0628 break; 0629 } 0630 case RenderPresetParams::RateControl::Quality: { 0631 params.append(QStringLiteral("crf=%quality")); 0632 break; 0633 } 0634 case RenderPresetParams::RateControl::Constrained: { 0635 params.append(QStringLiteral("crf=%quality")); 0636 params.append(QStringLiteral("vbufsize=%1").arg(vBuffer->value() * 8 * 1024)); 0637 params.append(QStringLiteral("vmaxrate=%bitrate+'k'")); 0638 break; 0639 } 0640 } 0641 if (fixedGop->isEnabled() && fixedGop->isChecked()) { 0642 params.append(QStringLiteral("sc_threshold=0")); 0643 } 0644 } else if (vcodec.contains("nvenc")) { 0645 switch (vRateControlCombo->currentIndex()) { 0646 case RenderPresetParams::RateControl::Average: 0647 params.append(QStringLiteral("vb=%bitrate+'k'")); 0648 break; 0649 case RenderPresetParams::RateControl::Constant: { 0650 params.append(QStringLiteral("cbr=1 ")); 0651 params.append(QStringLiteral("vb=%bitrate+'k'")); 0652 params.append(QStringLiteral("vminrate=%bitrate+'k'")); 0653 params.append(QStringLiteral("vmaxrate=%bitrate+'k'")); 0654 params.append(QStringLiteral("vbufsize=%1").arg(vBuffer->value() * 8 * 1024)); 0655 break; 0656 } 0657 case RenderPresetParams::RateControl::Quality: { 0658 params.append(QStringLiteral("rc=constqp")); 0659 params.append(QStringLiteral("vqp=%quality")); 0660 params.append(QStringLiteral("vq=%quality")); 0661 break; 0662 } 0663 case RenderPresetParams::RateControl::Constrained: { 0664 params.append(QStringLiteral("qmin=%quality")); 0665 params.append(QStringLiteral("vb=%cvbr")); // setIfNotSet(p, "vb", qRound(cvbr)); 0666 params.append(QStringLiteral("vmaxrate=%bitrate+'k'")); 0667 params.append(QStringLiteral("vbufsize=%1").arg(vBuffer->value() * 8 * 1024)); 0668 break; 0669 } 0670 } 0671 /*if (ui->dualPassCheckbox->isChecked()) 0672 setIfNotSet(p, "v2pass", 1); 0673 */ 0674 if (fixedGop->isEnabled() && fixedGop->isChecked()) { 0675 params.append(QStringLiteral("sc_threshold=0 strict_gop=1")); 0676 } 0677 } else if (vcodec.endsWith("_amf")) { 0678 switch (vRateControlCombo->currentIndex()) { 0679 case RenderPresetParams::RateControl::Average: 0680 params.append(QStringLiteral("vb=%bitrate+'k'")); 0681 break; 0682 case RenderPresetParams::RateControl::Constant: { 0683 params.append(QStringLiteral("rc=cbr ")); 0684 params.append(QStringLiteral("vb=%bitrate+'k'")); 0685 params.append(QStringLiteral("vminrate=%bitrate+'k'")); 0686 params.append(QStringLiteral("vmaxrate=%bitrate+'k'")); 0687 params.append(QStringLiteral("vbufsize=%1 ").arg(vBuffer->value() * 8 * 1024)); 0688 break; 0689 } 0690 case RenderPresetParams::RateControl::Quality: { 0691 params.append(QStringLiteral("rc=cqp")); 0692 params.append(QStringLiteral("qp_i=%quality")); 0693 params.append(QStringLiteral("qp_p=%quality")); 0694 params.append(QStringLiteral("qp_b=%quality")); 0695 params.append(QStringLiteral("vq=%quality")); 0696 break; 0697 } 0698 case RenderPresetParams::RateControl::Constrained: { 0699 params.append(QStringLiteral("rc=vbr_peak")); 0700 params.append(QStringLiteral("qmin=%quality")); 0701 params.append(QStringLiteral("vb=%cvbr")); // setIfNotSet(p, "vb", qRound(cvbr)); 0702 params.append(QStringLiteral("vmaxrate=%bitrate+'k'")); 0703 params.append(QStringLiteral("vbufsize=%1").arg(vBuffer->value() * 8 * 1024)); 0704 break; 0705 } 0706 } 0707 /*if (ui->dualPassCheckbox->isChecked()) 0708 setIfNotSet(p, "v2pass", 1); 0709 */ 0710 if (fixedGop->isEnabled() && fixedGop->isChecked()) { 0711 params.append(QStringLiteral("sc_threshold=0 strict_gop=1")); 0712 } 0713 } else { 0714 switch (vRateControlCombo->currentIndex()) { 0715 case RenderPresetParams::RateControl::Average: 0716 params.append(QStringLiteral("vb=%bitrate+'k'")); 0717 break; 0718 case RenderPresetParams::RateControl::Constant: { 0719 // const QString& b = ui->videoBitrateCombo->currentText(); 0720 params.append(QStringLiteral("vb=%bitrate+'k'")); 0721 params.append(QStringLiteral("vminrate=%bitrate+'k'")); 0722 params.append(QStringLiteral("vmaxrate=%bitrate+'k'")); 0723 params.append(QStringLiteral("vbufsize=%1").arg(vBuffer->value() * 8 * 1024)); 0724 break; 0725 } 0726 case RenderPresetParams::RateControl::Quality: { 0727 if (vcodec.startsWith("libx264")) { 0728 params.append(QStringLiteral("crf=%quality")); 0729 } else if (vcodec.startsWith("libvpx") || vcodec.startsWith("libaom-")) { 0730 params.append(QStringLiteral("crf=%quality")); 0731 params.append(QStringLiteral("vb=0")); // VP9 needs this to prevent constrained quality mode. 0732 } else if (vcodec.endsWith("_vaapi")) { 0733 params.append(QStringLiteral("vglobal_quality=%quality")); 0734 params.append(QStringLiteral("vq=%quality")); 0735 } else { 0736 params.append(QStringLiteral("qscale=%quality")); 0737 } 0738 break; 0739 } 0740 case RenderPresetParams::RateControl::Constrained: { 0741 if (vcodec.startsWith("libx264") || vcodec.startsWith("libvpx") || vcodec.startsWith("libaom-")) { 0742 params.append(QStringLiteral("crf=%quality")); 0743 } else if (vcodec.endsWith("_qsv") || vcodec.endsWith("_videotoolbox")) { 0744 params.append(QStringLiteral("vb=%cvbr")); // setIfNotSet(p, "vb", qRound(cvbr)); 0745 } else if (vcodec.endsWith("_vaapi")) { 0746 params.append(QStringLiteral("vb=%bitrate+'k'")); 0747 params.append(QStringLiteral("vglobal_quality=%quality")); 0748 params.append(QStringLiteral("vq=%quality")); 0749 } else { 0750 params.append(QStringLiteral("qscale=%quality")); 0751 } 0752 params.append(QStringLiteral("vmaxrate=%bitrate+'k'")); 0753 params.append(QStringLiteral("vbufsize=%1").arg(vBuffer->value() * 8 * 1024)); 0754 break; 0755 } 0756 } 0757 if (fixedGop->isEnabled() && fixedGop->isChecked()) { 0758 if (vcodec.startsWith("libvpx") || vcodec.startsWith("libaom-")) { 0759 params.append(QStringLiteral("keyint_min=%1").arg(gopSpinner->value())); 0760 } else { 0761 params.append(QStringLiteral("sc_threshold=0")); 0762 } 0763 } 0764 /* 0765 if (vcodec.endsWith("_videotoolbox")) { 0766 setIfNotSet(p, "pix_fmt", "nv12"); 0767 } else if (vcodec.endsWith("_vaapi")) { 0768 setIfNotSet(p, "vprofile", "main"); 0769 setIfNotSet(p, "connection_type", "x11"); 0770 }*/ 0771 } 0772 if (gopSpinner->value() > 0) { 0773 params.append(QStringLiteral("g=%1").arg(gopSpinner->value())); 0774 if (bFramesSpinner->value() >= 0) { 0775 params.append(QStringLiteral("bf=%1").arg(bFramesSpinner->value())); 0776 } 0777 } 0778 0779 // audio tab 0780 QString acodec = aCodecCombo->currentText(); 0781 params.append(QStringLiteral("acodec=%1").arg(acodec)); 0782 0783 if (cChannels->isChecked() && audioChannels->currentData().toInt() > 0) { 0784 params.append(QStringLiteral("channels=%1").arg(audioChannels->currentData().toInt())); 0785 } 0786 if (cSampleR->isChecked() && audioSampleRate->currentText().toInt() > 0) { 0787 params.append(QStringLiteral("ar=%1").arg(audioSampleRate->currentText().toInt())); 0788 } 0789 if (acodec.startsWith(QStringLiteral("pcm_"))) { 0790 aRateControlCombo->setEnabled(false); 0791 aBitrate->setEnabled(false); 0792 aQuality->setEnabled(false); 0793 } else { 0794 aRateControlCombo->setEnabled(true); 0795 switch (aRateControlCombo->currentIndex()) { 0796 case RenderPresetParams::RateControl::Unknown: 0797 aBitrate->setEnabled(false); 0798 aQuality->setEnabled(false); 0799 break; 0800 case RenderPresetParams::RateControl::Average: 0801 case RenderPresetParams::RateControl::Constant: 0802 aBitrate->setEnabled(true); 0803 aQuality->setEnabled(false); 0804 break; 0805 case RenderPresetParams::RateControl::Quality: 0806 default: 0807 aBitrate->setEnabled(false); 0808 aQuality->setEnabled(true); 0809 break; 0810 }; 0811 switch (aRateControlCombo->currentIndex()) { 0812 case RenderPresetParams::RateControl::Average: 0813 case RenderPresetParams::RateControl::Constant: { 0814 params.append(QStringLiteral("ab=%audiobitrate+'k'")); 0815 if (acodec == "libopus") { 0816 if (aRateControlCombo->currentIndex() == RenderPresetParams::RateControl::Constant) { 0817 params.append(QStringLiteral("vbr=off")); 0818 } else { 0819 params.append(QStringLiteral("vbr=constrained")); 0820 } 0821 } 0822 break; 0823 } 0824 case RenderPresetParams::RateControl::Quality: { 0825 if (acodec == "libopus") { 0826 params.append(QStringLiteral("vbr=on")); 0827 params.append(QStringLiteral("compression_level=%audioquality")); 0828 } else { 0829 params.append(QStringLiteral("aq=%audioquality")); 0830 } 0831 } 0832 default: 0833 break; 0834 } 0835 } 0836 0837 QString addionalParams = additionalParams->toPlainText().simplified(); 0838 0839 QStringList removed; 0840 for (const auto &p : qAsConst(m_uiParams)) { 0841 QString store = addionalParams; 0842 if (store != addionalParams.remove(QRegularExpression(QStringLiteral("((^|\\s)%1=\\S*)").arg(p)))) { 0843 removed.append(p); 0844 } 0845 } 0846 if (!removed.isEmpty()) { 0847 overrideParamsWarning->setText( 0848 xi18nc("@info", 0849 "The following parameters will not have an effect, because they get overwritten by the equivalent user interface options: <icode>%1</icode>", 0850 removed.join(", "))); 0851 overrideParamsWarning->show(); 0852 } else { 0853 overrideParamsWarning->hide(); 0854 } 0855 addionalParams = addionalParams.simplified().prepend(params.join(QStringLiteral(" ")) + QStringLiteral(" ")); 0856 parameters->setPlainText(addionalParams.simplified()); 0857 } 0858 0859 void RenderPresetDialog::setPixelAspectRatio(int num, int den) 0860 { 0861 parCombo->blockSignals(true); 0862 if (num < 1) num = 1; 0863 if (den < 1) den = 1; 0864 int gcdV = gcd(num, den); 0865 QString data = QStringLiteral("%1:%2").arg(num / gcdV).arg(den / gcdV); 0866 int ix = parCombo->findData(data); 0867 if (ix < 0) { 0868 parCombo->addItem(QStringLiteral("%L1 (%2:%3)").arg(double(num) / double(den), 0, 'g', 8).arg(num / gcdV).arg(den / gcdV), data); 0869 ix = parCombo->count() - 1; 0870 } 0871 parCombo->setCurrentIndex(ix); 0872 parCombo->blockSignals(false); 0873 } 0874 0875 void RenderPresetDialog::updateDisplayAspectRatio() 0876 { 0877 displayAspectNum->blockSignals(true); 0878 displayAspectDen->blockSignals(true); 0879 QStringList par = parCombo->currentData().toString().split(QStringLiteral(":")); 0880 int parNum = resWidth->value(); 0881 int parDen = resHeight->value(); 0882 if (par.length() >= 2 && par.at(0).toInt() > 0 && par.at(1).toInt() > 0) { 0883 parNum *= par.at(0).toInt(); 0884 parDen *= par.at(1).toInt(); 0885 } 0886 int gcdV = gcd(parNum, parDen); 0887 displayAspectNum->setValue(parNum / gcdV); 0888 displayAspectDen->setValue(parDen / gcdV); 0889 displayAspectNum->blockSignals(false); 0890 displayAspectDen->blockSignals(false); 0891 slotUpdateParams(); 0892 }; 0893 0894 QString RenderPresetDialog::saveName() 0895 { 0896 return m_saveName; 0897 }