X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fprojecttree%2Fproxyclipjob.cpp;h=fe3b77c85c9cd045bd6c7fddc87b9b2ca29e797d;hb=f69a24d18f8134c93e407ea485967ac31187da47;hp=31a67bbf681252f522b13ae660f52306e2983c31;hpb=dd604e8fc559277a2fc42a161feb0de91d3515a5;p=kdenlive diff --git a/src/projecttree/proxyclipjob.cpp b/src/projecttree/proxyclipjob.cpp index 31a67bbf..fe3b77c8 100644 --- a/src/projecttree/proxyclipjob.cpp +++ b/src/projecttree/proxyclipjob.cpp @@ -21,14 +21,18 @@ #include "proxyclipjob.h" #include "kdenlivesettings.h" #include "kdenlivedoc.h" +#include + #include -#include +#include -ProxyJob::ProxyJob(CLIPTYPE cType, const QString &id, QStringList parameters) : AbstractClipJob(PROXYJOB, cType, id, parameters), - m_jobDuration(0), - m_isFfmpegJob(true) +ProxyJob::ProxyJob(ClipType cType, const QString &id, const QStringList& parameters) + : AbstractClipJob(PROXYJOB, cType, id, parameters), + m_jobDuration(0), + m_isFfmpegJob(true) { + m_jobStatus = JobWaiting; description = i18n("proxy"); m_dest = parameters.at(0); m_src = parameters.at(1); @@ -36,55 +40,58 @@ ProxyJob::ProxyJob(CLIPTYPE cType, const QString &id, QStringList parameters) : 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) { + 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); - - foreach(QString s, params) { - s = s.simplified(); - if (s.count(' ') == 0) { - s.append("=1"); - } - else s.replace(' ', '='); - mltParameters << s; - } + mltParameters << m_src; + mltParameters << QLatin1String("-consumer") << QLatin1String("avformat:") + m_dest; + QStringList params = m_proxyParams.split(QLatin1Char('-'), QString::SkipEmptyParts); + + foreach(const QString &s, params) { + QString t = s.simplified(); + if (t.count(QLatin1Char(' ')) == 0) { + t.append(QLatin1String("=1")); + } + else t.replace(QLatin1Char(' '), QLatin1String("=")); + mltParameters << t; + } - 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); - - // Ask for progress reporting - mltParameters << "progress=1"; - - m_jobProcess = new QProcess; - m_jobProcess->setProcessChannelMode(QProcess::MergedChannels); - m_jobProcess->start(KdenliveSettings::rendererpath(), mltParameters); - m_jobProcess->waitForStarted(); - return m_jobProcess; + mltParameters.append(QString::fromLatin1("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; + if (m_src.startsWith(QLatin1String("consumer:"))) display_ratio = KdenliveDoc::getDisplayRatio(m_src.section(QLatin1String(":"), 1)); + else display_ratio = KdenliveDoc::getDisplayRatio(m_src); + mltParameters << QLatin1String("aspect=") + QLocale().toString(display_ratio); + + // Ask for progress reporting + mltParameters << QLatin1String("progress=1"); + + m_jobProcess = new QProcess; + m_jobProcess->setProcessChannelMode(QProcess::MergedChannels); + m_jobProcess->start(KdenliveSettings::rendererpath(), mltParameters); + m_jobProcess->waitForStarted(); } - else if (clipType == IMAGE) { + 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; - // Images are scaled to profile size. + // Images are scaled to profile size. //TODO: Make it be configurable? if (i.width() > i.height()) proxy = i.scaledToWidth(m_renderWidth); else proxy = i.scaledToHeight(m_renderHeight); @@ -94,91 +101,122 @@ QProcess *ProxyJob::startJob(bool *ok) QMatrix matrix; switch ( m_exif ) { - case 2: - matrix.scale( -1, 1 ); - break; - case 3: - matrix.rotate( 180 ); - break; - case 4: - matrix.scale( 1, -1 ); - break; - case 5: - matrix.rotate( 270 ); - matrix.scale( -1, 1 ); - break; - case 6: - matrix.rotate( 90 ); - break; - case 7: - matrix.rotate( 90 ); - matrix.scale( -1, 1 ); - break; - case 8: - matrix.rotate( 270 ); - break; + case 2: + matrix.scale( -1, 1 ); + break; + case 3: + matrix.rotate( 180 ); + break; + case 4: + matrix.scale( 1, -1 ); + break; + case 5: + matrix.rotate( 270 ); + matrix.scale( -1, 1 ); + break; + case 6: + matrix.rotate( 90 ); + break; + case 7: + matrix.rotate( 90 ); + matrix.scale( -1, 1 ); + break; + case 8: + matrix.rotate( 270 ); + break; } processed = proxy.transformed( matrix ); processed.save(m_dest); + } else { + proxy.save(m_dest); } - else proxy.save(m_dest); - *ok = true; - return NULL; - } - else { + setStatus(JobDone); + return; + } else { m_isFfmpegJob = true; - QStringList parameters; - parameters << "-i" << m_src; + QStringList parameters; + parameters << QLatin1String("-i") << m_src; QString params = m_proxyParams; - foreach(const QString &s, params.split(' ')) + foreach(const QString &s, params.split(QLatin1Char(' '))) parameters << s; // Make sure we don't block when proxy file already exists - parameters << "-y"; + parameters << QLatin1String("-y"); parameters << m_dest; m_jobProcess = new QProcess; m_jobProcess->setProcessChannelMode(QProcess::MergedChannels); - m_jobProcess->start("ffmpeg", parameters); + m_jobProcess->start(KdenliveSettings::ffmpegpath(), parameters, QIODevice::ReadOnly); m_jobProcess->waitForStarted(); - QString log = m_jobProcess->readAll(); - if (!log.isEmpty()) m_errorMessage.append(log + '\n'); - return m_jobProcess; } + while (m_jobProcess->state() != QProcess::NotRunning) { + processLogInfo(); + if (m_jobStatus == JobAborted) { + emit cancelRunningJob(m_clipId, cancelProperties()); + m_jobProcess->close(); + m_jobProcess->waitForFinished(); + QFile::remove(m_dest); + } + m_jobProcess->waitForFinished(400); + } + + if (m_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; } -int ProxyJob::processLogInfo() +void ProxyJob::processLogInfo() { - if (!m_jobProcess) return -1; - QString log = m_jobProcess->readAll(); - if (!log.isEmpty()) m_errorMessage.append(log + '\n'); + if (!m_jobProcess || m_jobStatus == JobAborted) return; + QString log = QString::fromUtf8(m_jobProcess->readAll()); + if (!log.isEmpty()) + m_logDetails.append(log + QLatin1Char('\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(':'); + if (log.contains(QLatin1String("Duration:"))) { + QString data = log.section(QLatin1String("Duration:"), 1, 1).section(QLatin1Char(','), 0, 0).simplified(); + QStringList numbers = data.split(QLatin1Char(':')); 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(':'); + else if (log.contains(QLatin1String("time="))) { + QString time = log.section(QLatin1String("time="), 1, 1).simplified().section(QLatin1Char(' '), 0, 0); + if (time.contains(QLatin1Char(':'))) { + QStringList numbers = time.split(QLatin1Char(':')); progress = numbers.at(0).toInt() * 3600 + numbers.at(1).toInt() * 60 + numbers.at(2).toDouble(); } else progress = (int) time.toDouble(); - return (int) (100.0 * progress / m_jobDuration); + 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(); - return progress; + if (log.contains(QLatin1String("percentage:"))) { + progress = log.section(QLatin1String("percentage:"), 1).simplified().section(QLatin1Char(' '), 0, 0).toInt(); + emit jobProgress(m_clipId, progress, jobType); } } - return -1; } ProxyJob::~ProxyJob() @@ -193,8 +231,25 @@ const QString ProxyJob::destination() const stringMap ProxyJob::cancelProperties() { QMap props; - props.insert("proxy", "-"); + props.insert(QLatin1String("proxy"), QLatin1String("-")); return props; } +const QString ProxyJob::statusMessage() +{ + QString statusInfo; + switch (m_jobStatus) { + case JobWorking: + statusInfo = i18n("Creating proxy"); + break; + case JobWaiting: + statusInfo = i18n("Waiting - proxy"); + break; + default: + break; + } + return statusInfo; +} + +#include "proxyclipjob.moc"