#include <KDebug>
#include <KLocale>
-ProxyJob::ProxyJob(JOBTYPE type, CLIPTYPE cType, const QString &id, QStringList parameters) : AbstractClipJob(type, cType, id, parameters)
+ProxyJob::ProxyJob(CLIPTYPE cType, const QString &id, QStringList parameters) : AbstractClipJob(PROXYJOB, cType, id, parameters),
+ m_jobDuration(0),
+ m_isFfmpegJob(true)
{
+ jobStatus = JOBWAITING;
description = i18n("proxy");
m_dest = parameters.at(0);
m_src = parameters.at(1);
m_proxyParams = parameters.at(3);
m_renderWidth = parameters.at(4).toInt();
m_renderHeight = parameters.at(5).toInt();
+ replaceClip = true;
}
-QProcess *ProxyJob::startJob(bool *ok)
+void ProxyJob::startJob()
{
// Special case: playlist clips (.mlt or .kdenlive project files)
+ m_jobDuration = 0;
if (clipType == PLAYLIST) {
// change FFmpeg params to MLT format
+ m_isFfmpegJob = false;
QStringList mltParameters;
- mltParameters << m_src;
- mltParameters << "-consumer" << "avformat:" + m_dest;
- QStringList params = m_proxyParams.split('-', QString::SkipEmptyParts);
+ mltParameters << m_src;
+ mltParameters << "-consumer" << "avformat:" + m_dest;
+ QStringList params = m_proxyParams.split('-', QString::SkipEmptyParts);
- foreach(QString s, params) {
- s = s.simplified();
- if (s.count(' ') == 0) {
- s.append("=1");
- }
- else s.replace(' ', '=');
- mltParameters << s;
- }
+ foreach(QString s, params) {
+ s = s.simplified();
+ if (s.count(' ') == 0) {
+ s.append("=1");
+ }
+ else s.replace(' ', '=');
+ mltParameters << s;
+ }
- mltParameters.append(QString("real_time=-%1").arg(KdenliveSettings::mltthreads()));
+ mltParameters.append(QString("real_time=-%1").arg(KdenliveSettings::mltthreads()));
- //TODO: currently, when rendering an xml file through melt, the display ration is lost, so we enforce it manualy
- double display_ratio = KdenliveDoc::getDisplayRatio(m_src);
- mltParameters << "aspect=" + QString::number(display_ratio);
+ //TODO: currently, when rendering an xml file through melt, the display ration is lost, so we enforce it manualy
+ double display_ratio = KdenliveDoc::getDisplayRatio(m_src);
+ mltParameters << "aspect=" + QString::number(display_ratio);
+
+ // Ask for progress reporting
+ mltParameters << "progress=1";
- QProcess *myProcess = new QProcess;
- myProcess->setProcessChannelMode(QProcess::MergedChannels);
- myProcess->start(KdenliveSettings::rendererpath(), mltParameters);
- myProcess->waitForStarted();
- return myProcess;
+ m_jobProcess = new QProcess;
+ m_jobProcess->setProcessChannelMode(QProcess::MergedChannels);
+ m_jobProcess->start(KdenliveSettings::rendererpath(), mltParameters);
+ m_jobProcess->waitForStarted();
}
else if (clipType == IMAGE) {
+ m_isFfmpegJob = false;
// Image proxy
QImage i(m_src);
if (i.isNull()) {
- *ok = false;
- return NULL;
+ m_errorMessage.append(i18n("Cannot load image %1.", m_src));
+ setStatus(JOBCRASHED);
+ return;
}
QImage proxy;
processed.save(m_dest);
}
else proxy.save(m_dest);
- *ok = true;
- return NULL;
+ setStatus(JOBDONE);
+ return;
}
else {
+ m_isFfmpegJob = true;
QStringList parameters;
parameters << "-i" << m_src;
QString params = m_proxyParams;
- foreach(QString s, params.split(' '))
- parameters << s;
+ foreach(const QString &s, params.split(' '))
+ parameters << s;
// Make sure we don't block when proxy file already exists
parameters << "-y";
parameters << m_dest;
- QProcess *myProcess = new QProcess;
- myProcess->setProcessChannelMode(QProcess::MergedChannels);
- myProcess->start("ffmpeg", parameters);
- myProcess->waitForStarted();
- return myProcess;
+ m_jobProcess = new QProcess;
+ m_jobProcess->setProcessChannelMode(QProcess::MergedChannels);
+ m_jobProcess->start("ffmpeg", parameters, QIODevice::ReadOnly);
+ m_jobProcess->waitForStarted();
+ }
+ while (m_jobProcess->state() != QProcess::NotRunning) {
+ processLogInfo();
+ if (jobStatus == JOBABORTED) {
+ emit cancelRunningJob(m_clipId, cancelProperties());
+ m_jobProcess->close();
+ m_jobProcess->waitForFinished();
+ QFile::remove(m_dest);
+ }
+ m_jobProcess->waitForFinished(400);
+ }
+
+ if (jobStatus != JOBABORTED) {
+ int result = m_jobProcess->exitStatus();
+ if (result == QProcess::NormalExit) {
+ if (QFileInfo(m_dest).size() == 0) {
+ // File was not created
+ processLogInfo();
+ m_errorMessage.append(i18n("Failed to create proxy clip."));
+ setStatus(JOBCRASHED);
+ }
+ else setStatus(JOBDONE);
+ }
+ else if (result == QProcess::CrashExit) {
+ // Proxy process crashed
+ QFile::remove(m_dest);
+ setStatus(JOBCRASHED);
+ }
+ }
+
+ delete m_jobProcess;
+ return;
+}
+
+void ProxyJob::processLogInfo()
+{
+ if (!m_jobProcess || jobStatus == JOBABORTED) return;
+ QString log = m_jobProcess->readAll();
+ if (!log.isEmpty()) m_logDetails.append(log + '\n');
+ else return;
+ int progress;
+ if (m_isFfmpegJob) {
+ // Parse FFmpeg output
+ if (m_jobDuration == 0) {
+ if (log.contains("Duration:")) {
+ QString data = log.section("Duration:", 1, 1).section(',', 0, 0).simplified();
+ QStringList numbers = data.split(':');
+ m_jobDuration = (int) (numbers.at(0).toInt() * 3600 + numbers.at(1).toInt() * 60 + numbers.at(2).toDouble());
+ }
+ }
+ else if (log.contains("time=")) {
+ QString time = log.section("time=", 1, 1).simplified().section(' ', 0, 0);
+ if (time.contains(':')) {
+ QStringList numbers = time.split(':');
+ progress = numbers.at(0).toInt() * 3600 + numbers.at(1).toInt() * 60 + numbers.at(2).toDouble();
+ }
+ else progress = (int) time.toDouble();
+ emit jobProgress(m_clipId, (int) (100.0 * progress / m_jobDuration), jobType);
+ }
+ }
+ else {
+ // Parse MLT output
+ if (log.contains("percentage:")) {
+ progress = log.section(':', -1).simplified().toInt();
+ emit jobProgress(m_clipId, progress, jobType);
+ }
}
}
return props;
}
+const QString ProxyJob::statusMessage()
+{
+ QString statusInfo;
+ switch (jobStatus) {
+ case JOBWORKING:
+ statusInfo = i18n("Creating proxy");
+ break;
+ case JOBWAITING:
+ statusInfo = i18n("Waiting - proxy");
+ break;
+ default:
+ break;
+ }
+ return statusInfo;
+}