File indexing completed on 2024-03-24 04:54:10
0001 /* 0002 SPDX-FileCopyrightText: 2008 Jean-Baptiste Mardelle <jb@kdenlive.org> 0003 0004 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "proxytest.h" 0008 0009 #include "core.h" 0010 #include "doc/kdenlivedoc.h" 0011 #include "kdenlivesettings.h" 0012 0013 #include "kdenlive_debug.h" 0014 #include <QDialogButtonBox> 0015 #include <QFontDatabase> 0016 #include <QPushButton> 0017 #include <QTreeWidget> 0018 #include <QWheelEvent> 0019 #include <QtConcurrent> 0020 0021 #include "klocalizedstring.h" 0022 #include <kio/directorysizejob.h> 0023 0024 ProxyTest::ProxyTest(QWidget *parent) 0025 : QDialog(parent) 0026 , m_closing(false) 0027 { 0028 setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont)); 0029 setupUi(this); 0030 setWindowTitle(i18nc("@title:window", "Compare Proxy Profile")); 0031 buttonBox->button(QDialogButtonBox::Apply)->setText(i18n("Test Proxy Profiles")); 0032 infoWidget->hide(); 0033 paramBox->setVisible(false); 0034 m_failedProfiles = new MyTreeWidgetItem(resultList, {i18n("Failing profiles")}); 0035 resultList->addTopLevelItem(m_failedProfiles); 0036 m_failedProfiles->setExpanded(false); 0037 m_failedProfiles->setHidden(true); 0038 connect(resultList, &QTreeWidget::itemSelectionChanged, resultList, [&]() { 0039 QTreeWidgetItem *item = resultList->currentItem(); 0040 if (item) { 0041 paramBox->setPlainText(item->data(0, Qt::UserRole).toString()); 0042 paramBox->setVisible(true); 0043 } else { 0044 paramBox->clear(); 0045 paramBox->setVisible(false); 0046 } 0047 }); 0048 connect(buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, this, [this]() { 0049 infoWidget->setText(i18n("Starting process")); 0050 infoWidget->animatedShow(); 0051 resultList->setCursor(Qt::BusyCursor); 0052 buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); 0053 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0054 QtConcurrent::run(this, &ProxyTest::startTest); 0055 #else 0056 QtConcurrent::run(&ProxyTest::startTest, this); 0057 #endif 0058 }); 0059 } 0060 0061 void ProxyTest::addAnalysis(const QStringList &data) 0062 { 0063 QStringList itemData = data; 0064 QString params = itemData.takeFirst(); 0065 if (itemData.size() == 1) { 0066 // This proxy profile failed 0067 MyTreeWidgetItem *item = new MyTreeWidgetItem(m_failedProfiles, itemData); 0068 item->setData(0, Qt::UserRole, params); 0069 item->setIcon(0, QIcon::fromTheme(QStringLiteral("window-close"))); 0070 m_failedProfiles->setHidden(false); 0071 // m_failedProfiles->addChild(item); 0072 } else { 0073 MyTreeWidgetItem *item = new MyTreeWidgetItem(resultList, itemData); 0074 qDebug() << "=== ADDING ANALYSIS: " << itemData; 0075 item->setData(0, Qt::UserRole, params); 0076 item->setData(1, Qt::UserRole, itemData.at(1).toInt()); 0077 QTime t = QTime(0, 0).addMSecs(itemData.at(1).toInt()); 0078 qDebug() << "TIME: " << itemData.at(1).toInt() << " = " << t.toString(QStringLiteral("mm:ss:z")); 0079 item->setText(1, t.toString(QStringLiteral("mm:ss:z"))); 0080 item->setText(2, KIO::convertSize(itemData.at(2).toInt())); 0081 item->setData(2, Qt::UserRole, itemData.at(2).toInt()); 0082 // resultList->addTopLevelItem(item); 0083 } 0084 } 0085 0086 void ProxyTest::showMessage(const QString &message) 0087 { 0088 infoWidget->setText(message); 0089 if (!message.isEmpty()) { 0090 infoWidget->animatedShow(); 0091 } else { 0092 // Tests finished 0093 infoWidget->animatedHide(); 0094 resultList->setCursor(Qt::ArrowCursor); 0095 } 0096 } 0097 0098 ProxyTest::~ProxyTest() 0099 { 0100 m_closing = true; 0101 Q_EMIT jobCanceled(); 0102 // Wait until concurrent tread is finished 0103 QMutexLocker lk(&m_locker); 0104 } 0105 0106 void ProxyTest::startTest() 0107 { 0108 // load proxy profiles 0109 KConfig conf(QStringLiteral("encodingprofiles.rc"), KConfig::CascadeConfig, QStandardPaths::AppDataLocation); 0110 KConfigGroup group(&conf, "proxy"); 0111 QMap<QString, QString> values = group.entryMap(); 0112 QMapIterator<QString, QString> k(values); 0113 int proxyResize = pCore->currentDoc()->getDocumentProperty(QStringLiteral("proxyresize")).toInt(); 0114 QElapsedTimer timer; 0115 QTemporaryFile src(QDir::temp().absoluteFilePath(QString("XXXXXX.mov"))); 0116 if (!src.open()) { 0117 // Something went wrong 0118 QMetaObject::invokeMethod(this, "showMessage", Qt::QueuedConnection, Q_ARG(QString, i18n("Cannot create temporary files"))); 0119 return; 0120 } 0121 QMutexLocker lk1(&m_locker); 0122 m_process.reset(new QProcess()); 0123 connect(this, &ProxyTest::jobCanceled, m_process.get(), &QProcess::kill, Qt::DirectConnection); 0124 QMetaObject::invokeMethod(this, "showMessage", Qt::QueuedConnection, Q_ARG(QString, i18n("Generating a 60 seconds test video %1", src.fileName()))); 0125 QStringList source = {QStringLiteral("-y"), 0126 QStringLiteral("-f"), 0127 QStringLiteral("lavfi"), 0128 QStringLiteral("-i"), 0129 QStringLiteral("testsrc=duration=60:size=1920x1080:rate=25"), 0130 QStringLiteral("-c:v"), 0131 QStringLiteral("libx264"), 0132 QStringLiteral("-pix_fmt"), 0133 QStringLiteral("yuv420p"), 0134 src.fileName()}; 0135 m_process->start(KdenliveSettings::ffmpegpath(), source); 0136 m_process->waitForStarted(); 0137 if (m_closing) { 0138 return; 0139 } 0140 m_process->waitForFinished(-1); 0141 if (m_closing) { 0142 return; 0143 } 0144 0145 while (k.hasNext() && !m_closing) { 0146 k.next(); 0147 if (!k.key().isEmpty()) { 0148 QMetaObject::invokeMethod(this, "showMessage", Qt::QueuedConnection, Q_ARG(QString, i18n("Processing %1", k.key()))); 0149 QString params = k.value().section(QLatin1Char(';'), 0, 0); 0150 QString extension = k.value().section(QLatin1Char(';'), 1, 1); 0151 // Testing vaapi support 0152 QTemporaryFile tmp(QDir::temp().absoluteFilePath(QString("XXXXXX.%1").arg(extension))); 0153 if (!tmp.open()) { 0154 // Something went wrong 0155 QMetaObject::invokeMethod(this, "showMessage", Qt::QueuedConnection, Q_ARG(QString, i18n("Cannot create temporary files"))); 0156 return; 0157 } 0158 tmp.close(); 0159 params.replace(QStringLiteral("%width"), QString::number(proxyResize)); 0160 if (params.contains(QStringLiteral("%frameSize"))) { 0161 int w = proxyResize; 0162 int h = w * 1080 / 1920; 0163 params.replace(QStringLiteral("%frameSize"), QString("%1x%2").arg(w).arg(h)); 0164 } 0165 params.replace(QStringLiteral("%nvcodec"), QStringLiteral("h264_cuvid")); 0166 m_process.reset(new QProcess()); 0167 connect(this, &ProxyTest::jobCanceled, m_process.get(), &QProcess::kill, Qt::DirectConnection); 0168 QStringList parameters = {QStringLiteral("-hide_banner"), QStringLiteral("-y"), QStringLiteral("-stats"), QStringLiteral("-v"), 0169 QStringLiteral("error")}; 0170 if (params.contains(QLatin1String("-i "))) { 0171 // we have some pre-filename parameters, filename will be inserted later 0172 } else { 0173 parameters << QStringLiteral("-i") << src.fileName(); 0174 } 0175 QStringList paramList = params.split(QLatin1Char(' '), Qt::SkipEmptyParts); 0176 for (const QString &s : qAsConst(paramList)) { 0177 QString t = s.simplified(); 0178 if (t != QLatin1String("-noautorotate")) { 0179 parameters << t; 0180 if (t == QLatin1String("-i")) { 0181 parameters << src.fileName(); 0182 } 0183 } 0184 } 0185 parameters << tmp.fileName(); 0186 qDebug() << "==== STARTING TEST PROFILE : " << k.key() << " = " << parameters; 0187 m_process->start(KdenliveSettings::ffmpegpath(), parameters); 0188 m_process->waitForStarted(); 0189 timer.start(); 0190 bool success = false; 0191 QStringList results = {params}; 0192 if (m_process->waitForFinished(-1)) { 0193 if (m_closing) { 0194 return; 0195 } 0196 qint64 elapsed = timer.elapsed(); 0197 qint64 size = tmp.size(); 0198 if (size > 0) { 0199 success = true; 0200 results << QStringList({k.key(), QString::number(elapsed), QString::number(size)}); 0201 } 0202 } 0203 if (!success) { 0204 if (m_closing) { 0205 return; 0206 } 0207 qDebug() << "==== PROFILE FAILED: " << k.key() << " !!!!!!!!!!!!"; 0208 results << QStringList({k.key()}); 0209 } 0210 QMetaObject::invokeMethod(this, "addAnalysis", Qt::QueuedConnection, Q_ARG(QStringList, results)); 0211 } 0212 } 0213 if (m_closing) { 0214 return; 0215 } 0216 QMetaObject::invokeMethod(this, "showMessage", Qt::QueuedConnection, Q_ARG(QString, QString())); 0217 }