Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

intial detection and enabling of vaapi hardware encoders

parent b42add02
......@@ -5,10 +5,11 @@ MPEG=qscale=4 ab=192k vcodec=mpeg2video acodec=mp2 threads=%threads;mpg
[proxy]
x264=-vf scale=720:-2 -vcodec libx264 -g 1 -bf 0 -vb 0 -crf 20 -preset veryfast -acodec aac -ab 128k;mov
x264-VAAPI=-hwaccel vaapi -vaapi_device /dev/dri/renderD128 -i -vf format=nv12,hwupload,scale_vaapi=720:-2 -vcodec h264_vaapi -g 1 -bf 0 -vb 0 -crf 20 -acodec aac -ab 128k;mov
x264-NVENC=-hwaccel cuvid -c:v %nvcodec -i -filter:v scale_cuda=720:-2 -vcodec h264_nvenc -g 1 -bf 0 -vb 0 -acodec aac -ab 128k;mov
x264-vaapi=-hwaccel vaapi -vaapi_device /dev/dri/renderD128 -i -vf format=nv12,hwupload,scale_vaapi=720:-2 -vcodec h264_vaapi -g 1 -bf 0 -vb 0 -crf 20 -acodec aac -ab 128k;mov
x264-nvenc=-hwaccel cuvid -c:v %nvcodec -i -filter:v scale_cuda=720:-2 -vcodec h264_nvenc -g 1 -bf 0 -vb 0 -acodec aac -ab 128k;mov
MPEG2=-vf scale=720:-2 -g 1 -bf 0 -vb 0 -qscale 6 -ab 128k -vcodec mpeg2video -acodec ac3;mpg
MJPEG=-vf yadif,scale=720:-2 -qscale 3 -vcodec mjpeg -acodec pcm_s16le;mkv
MJPEG-vaapi=-hwaccel vaapi -vaapi_device /dev/dri/renderD128 -i -vf format=nv12,hwupload,scale_vaapi=720:-2 -vcodec mjpeg_vaapi -acodec copy;mkv
[screengrab]
X264 mute=-crf 25 -vcodec libx264 -preset veryfast -threads 0;mov
......
......@@ -149,15 +149,18 @@ void RenderJob::receivedStderr()
if (m_jobUiserver) {
m_jobUiserver->call(QStringLiteral("setPercent"), (uint)m_progress);
int seconds = m_startTime.secsTo(QTime::currentTime());
if (seconds < 0) {
// 1 day offset, add seconds in a day
seconds += 86400;
}
seconds = (int)(seconds * (100 - m_progress) / m_progress);
if (seconds == m_seconds) {
return;
}
if (seconds < 0) {
seconds += 24 * 60 * 60;
}
m_jobUiserver->call(QStringLiteral("setDescriptionField"), (uint)0, QString(),
tr("Remaining time: ") +
QTime(0, 0, 0).addSecs((int)(seconds * (100 - m_progress) / m_progress)).toString(QStringLiteral("hh:mm:ss")));
QTime(0, 0, 0).addSecs(seconds).toString(QStringLiteral("hh:mm:ss")));
//m_jobUiserver->call(QStringLiteral("setSpeed"), (frame - m_frame) / (seconds - m_seconds));
// m_jobUiserver->call("setSpeed", (frame - m_frame) / (seconds - m_seconds));
m_frame = frame;
m_seconds = seconds;
......
......@@ -1406,6 +1406,7 @@ void KdenliveSettingsDialog::loadEncodingProfiles()
m_configProject.kcfg_proxy_profile->clear();
KConfigGroup group4(&conf, "proxy");
values = group4.entryMap();
m_configProject.kcfg_proxy_profile->addItem(i18n("Automatic"));
QMapIterator<QString, QString> m(values);
while (m.hasNext()) {
m.next();
......
......@@ -46,6 +46,9 @@
#include <QStandardPaths>
#include <QTimer>
#include <QXmlStreamWriter>
#include <QTemporaryFile>
#include <QCheckBox>
#include <QPushButton>
// Recommended MLT version
const int mltVersionMajor = MLT_MIN_MAJOR_VERSION;
......@@ -102,6 +105,7 @@ Wizard::Wizard(bool autoClose, bool appImageCheck, QWidget *parent)
setButtonText(QWizard::FinishButton, i18n("OK"));
slotCheckMlt();
testHwEncoders();
if (!m_errors.isEmpty() || !m_warnings.isEmpty() || (!m_infos.isEmpty() && !appImageCheck)) {
QLabel *lab = new QLabel(this);
lab->setText(i18n("Startup error or warning, check our <a href='#'>online manual</a>."));
......@@ -119,6 +123,19 @@ Wizard::Wizard(bool autoClose, bool appImageCheck, QWidget *parent)
lab->setMessageType(KMessageWidget::Positive);
lab->setCloseButtonVisible(false);
m_startLayout->addWidget(lab);
// HW accel
QCheckBox *cb = new QCheckBox(i18n("VAAPI hardware acceleration"), this);
m_startLayout->addWidget(cb);
cb->setChecked(KdenliveSettings::vaapiEnabled());
QPushButton *pb = new QPushButton(i18n("Check hardware acceleration"), this);
connect(pb, &QPushButton::clicked, [&, cb, pb]() {
testHwEncoders();
pb->setEnabled(false);
cb->setChecked(KdenliveSettings::vaapiEnabled());
updateHwStatus();
pb->setEnabled(true);
});
m_startLayout->addWidget(pb);
setOption(QWizard::NoCancelButton, true);
return;
}
......@@ -883,3 +900,52 @@ void Wizard::slotUpdateDecklinkDevice(uint captureCard)
{
KdenliveSettings::setDecklink_capturedevice(captureCard);
}
void Wizard::testHwEncoders()
{
QProcess hwEncoders;
// Testing vaapi support
QTemporaryFile tmp(QDir::tempPath() + "/XXXXXX.mp4");
if (!tmp.open()) {
// Something went wrong
return;
}
tmp.close();
QStringList args{"-y","-vaapi_device","/dev/dri/renderD128","-f","lavfi","-i","smptebars=duration=5:size=1280x720:rate=25","-vf","format=nv12,hwupload","-c:v","h264_vaapi","-an","-f","mp4",tmp.fileName()};
qDebug()<<"// FFMPEG ARGS: "<<args;
hwEncoders.start(KdenliveSettings::ffmpegpath(), args);
bool vaapiSupported = false;
if (hwEncoders.waitForFinished()) {
if (hwEncoders.exitStatus() == QProcess::CrashExit) {
qDebug()<<"/// ++ VAAPI NOT SUPPORTED";
} else {
if (tmp.exists() && tmp.size() > 0) {
qDebug()<<"/// ++ VAAPI YES SUPPORTED ::::::";
// vaapi support enabled
vaapiSupported = true;
} else {
qDebug()<<"/// ++ VAAPI FAILED ::::::";
// vaapi support not enabled
}
}
}
KdenliveSettings::setVaapiEnabled(vaapiSupported);
qDebug()<<"_____ EXIT STATUS:\n"<<hwEncoders.exitStatus();
// ffmpegmlt -y -vaapi_device /dev/dri/renderD128 -f lavfi -i smptebars=duration=5:size=1280x720:rate=30 -vf 'format=nv12,hwupload' -c:v h264_vaapi -an -f null /dev/null
}
void Wizard::updateHwStatus()
{
auto *statusLabel = new KMessageWidget(this);
bool hwEnabled = KdenliveSettings::vaapiEnabled();
statusLabel->setMessageType(hwEnabled ? KMessageWidget::Positive : KMessageWidget::Information);
statusLabel->setWordWrap(true);
statusLabel->setText(KdenliveSettings::vaapiEnabled() ? i18n("VAAPI hardware encoders found and enabled") : i18n("No hardware encoders found"));
statusLabel->setCloseButtonVisible(false);
//errorLabel->setTimeout();
m_startLayout->addWidget(statusLabel);
statusLabel->animatedShow();
QTimer::singleShot(3000, statusLabel, &KMessageWidget::animatedHide);
}
......@@ -50,6 +50,7 @@ public:
void runUpdateMimeDatabase();
void adjustSettings();
bool isOk() const;
static void testHwEncoders();
private:
Ui::WizardStandard_UI m_standard;
......@@ -71,6 +72,7 @@ private:
void slotCheckPrograms();
void checkMltComponents();
void checkMissingCodecs();
void updateHwStatus();
private slots:
void slotCheckStandard();
......
......@@ -1149,12 +1149,16 @@ void KdenliveDoc::slotProxyCurrentItem(bool doProxy, QList<std::shared_ptr<Proje
// Error
return;
}
QString extension = QLatin1Char('.') + getDocumentProperty(QStringLiteral("proxyextension"));
QString params = getDocumentProperty(QStringLiteral("proxyparams"));
if (m_proxyExtension.isEmpty()) {
initProxySettings();
}
QString extension = QLatin1Char('.') + m_proxyExtension;
//getDocumentProperty(QStringLiteral("proxyextension"));
/*QString params = getDocumentProperty(QStringLiteral("proxyparams"));
if (params.contains(QStringLiteral("-s "))) {
QString proxySize = params.section(QStringLiteral("-s "), 1).section(QStringLiteral("x"), 0, 0);
extension.prepend(QStringLiteral("-") + proxySize);
}
}*/
// Prepare updated properties
QMap<QString, QString> newProps;
......@@ -1507,6 +1511,33 @@ void KdenliveDoc::selectPreviewProfile()
}
}
QString KdenliveDoc::getAutoProxyProfile()
{
if (m_proxyExtension.isEmpty() || m_proxyParams.isEmpty()) {
initProxySettings();
}
return m_proxyParams;
}
void KdenliveDoc::initProxySettings()
{
// Read preview profiles and find the best match
KConfig conf(QStringLiteral("encodingprofiles.rc"), KConfig::CascadeConfig, QStandardPaths::AppDataLocation);
KConfigGroup group(&conf, "proxy");
QString params;
QMap<QString, QString> values = group.entryMap();
// Select best proxy profile depending on hw encoder support
if (KdenliveSettings::nvencEnabled() && values.contains(QStringLiteral("MJPEG-nvenc"))) {
params = values.value(QStringLiteral("MJPEG-nvenc"));
} else if (KdenliveSettings::vaapiEnabled() && values.contains(QStringLiteral("MJPEG-vaapi"))) {
params = values.value(QStringLiteral("MJPEG-vaapi"));
} else {
params = values.value(QStringLiteral("MJPEG"));
}
m_proxyParams = params.section(QLatin1Char(';'), 0, 0);
m_proxyExtension = params.section(QLatin1Char(';'), 1);
}
void KdenliveDoc::checkPreviewStack()
{
// A command was pushed in the middle of the stack, remove all cached data from last undos
......
......@@ -157,6 +157,8 @@ public:
const QString documentRoot() const;
/** @brief Returns true if timeline preview settings changed*/
bool updatePreviewSettings(const QString &profile);
/** @brief Returns the recommanded proxy profile parameters */
QString getAutoProxyProfile();
private:
QUrl m_url;
......@@ -170,6 +172,12 @@ private:
/** @brief Tells whether the current document has been changed after being saved. */
bool m_modified;
/** @brief The default recommanded proxy extension */
QString m_proxyExtension;
/** @brief The default recommanded proxy params */
QString m_proxyParams;
/** @brief Tells whether the current document was modified by Kdenlive on opening, and a backup should be created on save. */
enum DOCSTATUS { CleanProject, ModifiedProject, UpgradedProject };
DOCSTATUS m_documentOpenStatus;
......@@ -195,6 +203,8 @@ private:
void loadDocumentProperties();
/** @brief update document properties to reflect a change in the current profile */
void updateProjectProfile(bool reloadProducers = false);
/** @brief initialize proxy settings based on hw status */
void initProxySettings();
public slots:
void slotCreateTextTemplateClip(const QString &group, const QString &groupId, QUrl path);
......
......@@ -210,6 +210,10 @@ bool ProxyJob::startJob()
m_jobDuration = (int) binClip->duration().seconds();
parameters << QStringLiteral("-y") << QStringLiteral("-v")<< QStringLiteral("quiet")<<QStringLiteral("-stats");
QString proxyParams = pCore->currentDoc()->getDocumentProperty(QStringLiteral("proxyparams")).simplified();
if (proxyParams.isEmpty()) {
// Automatic setting, decide based on hw support
proxyParams = pCore->currentDoc()->getAutoProxyProfile();
}
bool nvenc = proxyParams.contains(QStringLiteral("%nvcodec"));
if (nvenc) {
QString pix_fmt = binClip->videoCodecProperty(QStringLiteral("pix_fmt"));
......
......@@ -193,6 +193,14 @@
<label>default height for timeline preview resize.</label>
<default>600</default>
</entry>
<entry name="vaapiEnabled" type="Bool">
<label>Enables vaapi hw accel in encoders.</label>
<default>false</default>
</entry>
<entry name="nvencEnabled" type="Bool">
<label>Enables nvenc hw accel in encoders.</label>
<default>false</default>
</entry>
</group>
......
......@@ -541,6 +541,7 @@ void MainWindow::init()
// Populate encoding profiles
KConfig conf(QStringLiteral("encodingprofiles.rc"), KConfig::CascadeConfig, QStandardPaths::AppDataLocation);
/*KConfig conf(QStringLiteral("encodingprofiles.rc"), KConfig::CascadeConfig, QStandardPaths::AppDataLocation);
if (KdenliveSettings::proxyparams().isEmpty() || KdenliveSettings::proxyextension().isEmpty()) {
KConfigGroup group(&conf, "proxy");
QMap<QString, QString> values = group.entryMap();
......@@ -551,7 +552,7 @@ void MainWindow::init()
KdenliveSettings::setProxyparams(proxystring.section(QLatin1Char(';'), 0, 0));
KdenliveSettings::setProxyextension(proxystring.section(QLatin1Char(';'), 1, 1));
}
}
}*/
if (KdenliveSettings::v4l_parameters().isEmpty() || KdenliveSettings::v4l_extension().isEmpty()) {
KConfigGroup group(&conf, "video4linux");
QMap<QString, QString> values = group.entryMap();
......
......@@ -1318,7 +1318,7 @@ void GLWidget::onFrameDisplayed(const SharedFrame &frame)
m_sharedFrame = frame;
m_sendFrame = sendFrameForAnalysis;
m_mutex.unlock();
//update();
update();
}
void GLWidget::mouseReleaseEvent(QMouseEvent *event)
......
......@@ -743,22 +743,37 @@ void ProjectSettings::loadProxyProfiles()
QMapIterator<QString, QString> k(values);
int ix = -1;
proxy_profile->clear();
if (KdenliveSettings::vaapiEnabled() || KdenliveSettings::nvencEnabled()) {
proxy_profile->addItem(QIcon::fromTheme(QStringLiteral("speedometer")), i18n("Automatic"));
} else {
proxy_profile->addItem(i18n("Automatic"));
}
while (k.hasNext()) {
k.next();
if (!k.key().isEmpty()) {
QString params = k.value().section(QLatin1Char(';'), 0, 0);
QString extension = k.value().section(QLatin1Char(';'), 1, 1);
if (ix == -1 && ((params == m_proxyparameters && extension == m_proxyextension) || (m_proxyparameters.isEmpty() || m_proxyextension.isEmpty()))) {
if (ix == -1 && ((params == m_proxyparameters && extension == m_proxyextension))) {
// this is the current profile
ix = proxy_profile->count();
}
proxy_profile->addItem(k.key(), k.value());
if (params.contains(QLatin1String("vaapi"))) {
proxy_profile->addItem(KdenliveSettings::vaapiEnabled() ? QIcon::fromTheme(QStringLiteral("speedometer")) : QIcon::fromTheme(QStringLiteral("dialog-cancel")), k.key(), k.value());
} else if (params.contains(QLatin1String("nvenc"))) {
proxy_profile->addItem(KdenliveSettings::nvencEnabled() ?QIcon::fromTheme(QStringLiteral("speedometer")) : QIcon::fromTheme(QStringLiteral("dialog-cancel")), k.key(), k.value());
} else {
proxy_profile->addItem(k.key(), k.value());
}
}
}
if (ix == -1) {
// Current project proxy settings not found
ix = proxy_profile->count();
proxy_profile->addItem(i18n("Current Settings"), QString(m_proxyparameters + QLatin1Char(';') + m_proxyextension));
if (m_proxyparameters.isEmpty() && m_proxyextension.isEmpty()) {
ix = 0;
} else {
ix = proxy_profile->count();
proxy_profile->addItem(i18n("Current Settings"), QString(m_proxyparameters + QLatin1Char(';') + m_proxyextension));
}
}
proxy_profile->setCurrentIndex(ix);
slotUpdateProxyParams();
......@@ -782,7 +797,11 @@ void ProjectSettings::loadPreviewProfiles()
// this is the current profile
ix = preview_profile->count();
}
preview_profile->addItem(k.key(), k.value());
if (params.contains(QLatin1String("nvenc"))) {
preview_profile->addItem(KdenliveSettings::nvencEnabled() ? QIcon::fromTheme(QStringLiteral("speedometer")) : QIcon::fromTheme(QStringLiteral("dialog-cancel")), k.key(), k.value());
} else {
preview_profile->addItem(k.key(), k.value());
}
}
}
if (ix == -1) {
......@@ -790,9 +809,17 @@ void ProjectSettings::loadPreviewProfiles()
ix = preview_profile->count();
if (m_previewparams.isEmpty() && m_previewextension.isEmpty()) {
// Leave empty, will be automatically detected
preview_profile->addItem(i18n("Auto"));
if (KdenliveSettings::nvencEnabled()) {
preview_profile->addItem(QIcon::fromTheme(QStringLiteral("speedometer")), i18n("Automatic"));
} else {
preview_profile->addItem(i18n("Automatic"));
}
} else {
preview_profile->addItem(i18n("Current Settings"), QString(m_previewparams + QLatin1Char(';') + m_previewextension));
if (m_previewparams.contains(QLatin1String("nvenc"))) {
preview_profile->addItem(QIcon::fromTheme(QStringLiteral("speedometer")), i18n("Current Settings"), QString(m_previewparams + QLatin1Char(';') + m_previewextension));
} else {
preview_profile->addItem(i18n("Current Settings"), QString(m_previewparams + QLatin1Char(';') + m_previewextension));
}
}
}
preview_profile->setCurrentIndex(ix);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment