+void ProjectList::slotCreateProxy(const QString id)
+{
+ ProjectItem *item = getItemById(id);
+ if (!item || item->isProxyRunning() || item->referencedClip()->isPlaceHolder()) return;
+ QString path = item->referencedClip()->getProperty("proxy");
+ if (path.isEmpty()) {
+ setProxyStatus(path, PROXYCRASHED);
+ return;
+ }
+ setProxyStatus(path, PROXYWAITING);
+ if (m_abortProxy.contains(path)) m_abortProxy.removeAll(path);
+ if (m_processingProxy.contains(path)) {
+ // Proxy is already being generated
+ return;
+ }
+ if (QFile::exists(path)) {
+ // Proxy already created
+ setProxyStatus(path, PROXYDONE);
+ slotGotProxy(path);
+ return;
+ }
+ m_processingProxy.append(path);
+ QtConcurrent::run(this, &ProjectList::slotGenerateProxy, path, item->clipUrl().path(), item->clipType(), QString(item->referencedClip()->producerProperty("_exif_orientation")).toInt());
+}
+
+void ProjectList::slotAbortProxy(const QString id, const QString path)
+{
+ QTreeWidgetItemIterator it(m_listView);
+ ProjectItem *item = getItemById(id);
+ setProxyStatus(item, NOPROXY);
+ slotGotProxy(item);
+ if (!path.isEmpty() && m_processingProxy.contains(path)) {
+ m_abortProxy << path;
+ setProxyStatus(path, NOPROXY);
+ }
+}
+
+void ProjectList::slotGenerateProxy(const QString destPath, const QString sourcePath, int clipType, int exif_orientation)
+{
+ emit projectModified();
+ // Make sure proxy path is writable
+ QFile file(destPath);
+ if (!file.open(QIODevice::WriteOnly)) {
+ setProxyStatus(destPath, PROXYCRASHED);
+ m_processingProxy.removeAll(destPath);
+ return;
+ }
+ file.close();
+ QFile::remove(destPath);
+
+ setProxyStatus(destPath, CREATINGPROXY);
+
+ // Special case: playlist clips (.mlt or .kdenlive project files)
+ if (clipType == PLAYLIST) {
+ // change FFmpeg params to MLT format
+ QStringList parameters;
+ parameters << sourcePath;
+ parameters << "-consumer" << "avformat:" + destPath;
+ QStringList params = m_doc->getDocumentProperty("proxyparams").simplified().split('-', QString::SkipEmptyParts);
+
+ foreach(QString s, params) {
+ s = s.simplified();
+ if (s.count(' ') == 0) {
+ s.append("=1");
+ }
+ else s.replace(' ', '=');
+ parameters << s;
+ }
+
+ parameters.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(sourcePath);
+ parameters << "aspect=" + QString::number(display_ratio);
+
+ //kDebug()<<"TRANSCOD: "<<parameters;
+ QProcess myProcess;
+ myProcess.start(KdenliveSettings::rendererpath(), parameters);
+ myProcess.waitForStarted();
+ int result = -1;
+ while (myProcess.state() != QProcess::NotRunning) {
+ // building proxy file
+ if (m_abortProxy.contains(destPath)) {
+ myProcess.close();
+ myProcess.waitForFinished();
+ m_abortProxy.removeAll(destPath);
+ m_processingProxy.removeAll(destPath);
+ QFile::remove(destPath);
+ setProxyStatus(destPath, NOPROXY);
+ result = -2;
+
+ }
+ myProcess.waitForFinished(500);
+ }
+ myProcess.waitForFinished();
+ m_processingProxy.removeAll(destPath);
+ if (result == -1) result = myProcess.exitStatus();
+ if (result == 0) {
+ // proxy successfully created
+ setProxyStatus(destPath, PROXYDONE);
+ slotGotProxy(destPath);
+ }
+ else if (result == 1) {
+ // Proxy process crashed
+ QFile::remove(destPath);
+ setProxyStatus(destPath, PROXYCRASHED);
+ }
+
+ }
+
+ if (clipType == IMAGE) {
+ // Image proxy
+ QImage i(sourcePath);
+ if (i.isNull()) {
+ // Cannot load image
+ setProxyStatus(destPath, PROXYCRASHED);
+ return;
+ }
+ QImage proxy;
+ // Images are scaled to profile size.
+ //TODO: Make it be configurable?
+ if (i.width() > i.height()) proxy = i.scaledToWidth(m_render->frameRenderWidth());
+ else proxy = i.scaledToHeight(m_render->renderHeight());
+ if (exif_orientation > 1) {
+ // Rotate image according to exif data
+ QImage processed;
+ QMatrix matrix;
+
+ switch ( exif_orientation ) {
+ 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(destPath);
+ }
+ else proxy.save(destPath);
+ setProxyStatus(destPath, PROXYDONE);
+ slotGotProxy(destPath);
+ m_abortProxy.removeAll(destPath);
+ m_processingProxy.removeAll(destPath);
+ return;
+ }
+
+ QStringList parameters;
+ parameters << "-i" << sourcePath;
+ QString params = m_doc->getDocumentProperty("proxyparams").simplified();
+ foreach(QString s, params.split(' '))
+ parameters << s;
+
+ // Make sure we don't block when proxy file already exists
+ parameters << "-y";
+ parameters << destPath;
+ kDebug()<<"// STARTING PROXY GEN: "<<parameters;
+ QProcess myProcess;
+ myProcess.start("ffmpeg", parameters);
+ myProcess.waitForStarted();
+ int result = -1;
+ while (myProcess.state() != QProcess::NotRunning) {
+ // building proxy file
+ if (m_abortProxy.contains(destPath)) {
+ myProcess.close();
+ myProcess.waitForFinished();
+ m_abortProxy.removeAll(destPath);
+ m_processingProxy.removeAll(destPath);
+ QFile::remove(destPath);
+ setProxyStatus(destPath, NOPROXY);
+ result = -2;
+
+ }
+ myProcess.waitForFinished(500);
+ }
+ myProcess.waitForFinished();
+ if (result == -1) result = myProcess.exitStatus();
+ if (result == 0) {
+ // proxy successfully created
+ setProxyStatus(destPath, PROXYDONE);
+ slotGotProxy(destPath);
+ }
+ else if (result == 1) {
+ // Proxy process crashed
+ QFile::remove(destPath);
+ setProxyStatus(destPath, PROXYCRASHED);
+ }
+ m_abortProxy.removeAll(destPath);
+ m_processingProxy.removeAll(destPath);
+}
+