Commit bfdcee54 authored by Jean-Baptiste Mardelle's avatar Jean-Baptiste Mardelle
Browse files

Audio cut task: detect incompatible encoders to prevent losing audio or video...

Audio cut task: detect incompatible encoders to prevent losing audio or video on stream copy attempt
parent 33360d8e
Pipeline #63740 passed with stage
in 9 minutes and 4 seconds
......@@ -36,6 +36,8 @@
#include <QProcess>
#include <KIO/RenameDialog>
#include <KLineEdit>
#include <QComboBox>
#include <QObject>
#include <klocalizedstring.h>
CutTask::CutTask(const ObjectId &owner, const QString &destination, const QStringList encodingParams, int in, int out, bool addToProject, QObject* object)
......@@ -58,28 +60,113 @@ void CutTask::start(const ObjectId &owner, int in , int out, QObject* object, bo
return;
}
const QString source = binClip->url();
QString videoCodec = binClip->codec(false);
QString audioCodec = binClip->codec(true);
// Check if the audio/video codecs are supported for encoding (required for the codec copy feature)
QProcess checkProcess;
QStringList params = {QStringLiteral("-codecs")};
checkProcess.start(KdenliveSettings::ffmpegpath(), params);
checkProcess.waitForFinished(); // sets current thread to sleep and waits for pingProcess end
QString output(checkProcess.readAllStandardOutput());
QString line;
QTextStream stream(&output);
bool videoOk = videoCodec.isEmpty();
bool audioOk = audioCodec.isEmpty();
while (stream.readLineInto(&line)) {
if (!videoOk && line.contains(videoCodec)) {
if (line.simplified().section(QLatin1Char(' '), 0, 0).contains(QLatin1Char('E'))) {
videoOk = true;
}
} else if (!audioOk && line.contains(audioCodec)) {
if (line.simplified().section(QLatin1Char(' '), 0, 0).contains(QLatin1Char('E'))) {
audioOk = true;
}
}
if (audioOk && videoOk) {
break;
}
}
QString warnMessage;
if (!videoOk) {
warnMessage = i18n("Cannot copy video codec %1, will re-encode.", videoCodec);
}
if (!audioOk) {
if (!videoOk) {
warnMessage.append(QLatin1Char('\n'));
}
warnMessage.append(i18n("Cannot copy audio codec %1, will re-encode.", audioCodec));
}
QString transcoderExt = source.section(QLatin1Char('.'), -1);
transcoderExt.prepend(QLatin1Char('.'));
QFileInfo finfo(source);
QString fileName = finfo.fileName().section(QLatin1Char('.'), 0, -2);
QDir dir = finfo.absoluteDir();
QString inString = QString::number(int(GenTime(in, pCore->getCurrentFps()).seconds()));
QString outString = QString::number(int(GenTime(out, pCore->getCurrentFps()).seconds()));
QString path = dir.absoluteFilePath(fileName + QString("-%1-%2.").arg(inString, outString) + transcoderExt);
QString path = dir.absoluteFilePath(fileName + QString("-%1-%2").arg(inString, outString) + transcoderExt);
QPointer<QDialog> d = new QDialog(QApplication::activeWindow());
Ui::CutJobDialog_UI ui;
ui.setupUi(d);
ui.extra_params->setVisible(false);
ui.message->setText(warnMessage);
ui.message->setVisible(!warnMessage.isEmpty());
if (videoCodec.isEmpty()) {
ui.video_codec->setText(i18n("none"));
ui.vcodec->setEnabled(false);
} else {
ui.video_codec->setText(videoCodec);
ui.vcodec->addItem(i18n("Copy stream"), QStringLiteral("copy"));
ui.vcodec->addItem(i18n("X264 encoding"), QStringLiteral("libx264"));
}
if (audioCodec.isEmpty()) {
ui.audio_codec->setText(i18n("none"));
ui.acodec->setEnabled(false);
} else {
ui.audio_codec->setText(audioCodec);
ui.acodec->addItem(i18n("Copy stream"), QStringLiteral("copy"));
ui.acodec->addItem(i18n("PCM encoding"), QStringLiteral("pcm_s24le"));
ui.acodec->addItem(i18n("AAC encoding"), QStringLiteral("aac"));
}
ui.audio_codec->setText(audioCodec);
ui.add_clip->setChecked(KdenliveSettings::add_new_clip());
ui.file_url->setMode(KFile::File);
ui.extra_params->setMaximumHeight(QFontMetrics(QApplication::font()).lineSpacing() * 5);
ui.file_url->setUrl(QUrl::fromLocalFile(path));
QObject::connect(ui.acodec, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), d.data(), [&ui, transcoderExt]() {
ui.extra_params->setPlainText(QString("-c:a %1 -c:v %2").arg(ui.acodec->currentData().toString()).arg(ui.vcodec->currentData().toString()));
QString path = ui.file_url->url().toLocalFile();
QString fileName = path.section(QLatin1Char('.'), 0, -2);
if (ui.acodec->currentData() == QLatin1String("copy") && ui.vcodec->currentData() == QLatin1String("copy")) {
fileName.append(transcoderExt);
} else {
fileName.append(QStringLiteral(".mov"));
}
ui.file_url->setUrl(QUrl::fromLocalFile(fileName));
});
QObject::connect(ui.vcodec, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), d.data(), [&ui, transcoderExt]() {
ui.extra_params->setPlainText(QString("-c:a %1 -c:v %2").arg(ui.acodec->currentData().toString()).arg(ui.vcodec->currentData().toString()));
QString path = ui.file_url->url().toLocalFile();
QString fileName = path.section(QLatin1Char('.'), 0, -2);
if (ui.acodec->currentData() == QLatin1String("copy") && ui.vcodec->currentData() == QLatin1String("copy")) {
fileName.append(transcoderExt);
} else {
fileName.append(QStringLiteral(".mov"));
}
ui.file_url->setUrl(QUrl::fromLocalFile(fileName));
});
QFontMetrics fm = ui.file_url->lineEdit()->fontMetrics();
ui.file_url->setMinimumWidth(int(fm.boundingRect(ui.file_url->text().left(50)).width() * 1.4));
ui.button_more->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
ui.extra_params->setPlainText(QStringLiteral("-acodec copy -vcodec copy"));
ui.extra_params->setPlainText(QStringLiteral("-c:a copy -c:v copy"));
QString mess = i18n("Extracting %1 out of %2", Timecode::getStringTimecode(out - in, pCore->getCurrentFps(), true), binClip->getStringDuration());
ui.info_label->setText(mess);
if (!videoOk) {
ui.vcodec->setCurrentIndex(1);
}
if (!audioOk) {
ui.acodec->setCurrentIndex(1);
}
if (d->exec() != QDialog::Accepted) {
delete d;
return;
......@@ -141,11 +228,12 @@ void CutTask::run()
pCore->taskManager.taskDone(m_owner.second, this);
return;
}
QStringList params = {QStringLiteral("-y"),QStringLiteral("-stats"),QStringLiteral("-v"),QStringLiteral("error"),QStringLiteral("-noaccurate_seek"),QStringLiteral("-ss"),QString::number(m_inPoint.seconds()),QStringLiteral("-i"),url, QStringLiteral("-t"), QString::number((m_outPoint-m_inPoint).seconds()),QStringLiteral("-avoid_negative_ts"),QStringLiteral("make_zero")};
QStringList params = {QStringLiteral("-y"),QStringLiteral("-stats"),QStringLiteral("-v"),QStringLiteral("error"),QStringLiteral("-noaccurate_seek"),QStringLiteral("-ss"),QString::number(m_inPoint.seconds()),QStringLiteral("-i"),url, QStringLiteral("-t"), QString::number((m_outPoint-m_inPoint).seconds()),QStringLiteral("-avoid_negative_ts"),QStringLiteral("make_zero"),QStringLiteral("-sn"),QStringLiteral("-dn"),QStringLiteral("-map"),QStringLiteral("0")};
params << m_encodingParams << m_destination;
m_jobProcess = std::make_unique<QProcess>(new QProcess);
connect(m_jobProcess.get(), &QProcess::readyReadStandardError, this, &CutTask::processLogInfo);
connect(this, &CutTask::jobCanceled, m_jobProcess.get(), &QProcess::kill, Qt::DirectConnection);
qDebug()<<"=== STARTING CUT JOB: "<<params;
m_jobProcess->start(KdenliveSettings::ffmpegpath(), params, QIODevice::ReadOnly);
m_jobProcess->waitForFinished(-1);
bool result = m_jobProcess->exitStatus() == QProcess::NormalExit;
......
......@@ -6,71 +6,59 @@
<rect>
<x>0</x>
<y>0</y>
<width>270</width>
<height>244</height>
<width>318</width>
<height>323</height>
</rect>
</property>
<property name="windowTitle">
<string>Cut Clip</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="3">
<item row="2" column="2" colspan="3">
<widget class="QComboBox" name="vcodec"/>
</item>
<item row="0" column="0" colspan="4">
<widget class="QLabel" name="info_label">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QToolButton" name="button_more">
<property name="toolTip">
<string>Configure job</string>
</property>
<item row="2" column="1">
<widget class="QLabel" name="video_codec">
<property name="text">
<string>...</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>false</bool>
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="destination_label">
<item row="5" column="0" colspan="5">
<widget class="QTextEdit" name="extra_params">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Save to</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="3">
<widget class="KUrlRequester" name="file_url" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="3" column="1">
<widget class="QLabel" name="audio_codec">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="4">
<widget class="QTextEdit" name="extra_params">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<item row="3" column="2" colspan="3">
<widget class="QComboBox" name="acodec"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Audio</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="7" column="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
......@@ -83,7 +71,64 @@
</property>
</spacer>
</item>
<item row="4" column="2" colspan="2">
<item row="0" column="4">
<widget class="QToolButton" name="button_more">
<property name="toolTip">
<string>Configure job</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="autoRaise">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="0" colspan="5">
<widget class="QCheckBox" name="add_clip">
<property name="text">
<string>Add clip to project</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Video</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="5">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="destination_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Save to</string>
</property>
</widget>
</item>
<item>
<widget class="KUrlRequester" name="file_url">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item row="7" column="3" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
......@@ -93,10 +138,10 @@
</property>
</widget>
</item>
<item row="2" column="0" colspan="4">
<widget class="QCheckBox" name="add_clip">
<property name="text">
<string>Add clip to project</string>
<item row="6" column="0" colspan="5">
<widget class="KMessageWidget" name="message">
<property name="messageType">
<enum>KMessageWidget::Information</enum>
</property>
</widget>
</item>
......@@ -109,6 +154,11 @@
<header>kurlrequester.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>KMessageWidget</class>
<extends>QFrame</extends>
<header>kmessagewidget.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
......
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