From: Jean-Baptiste M. <jb...@kd...> - 2011-11-13 22:33:53
|
Git commit 3ee6e1d68029bc223f59341fafd376bd281bf60e by Jean-Baptiste Mardelle. Committed on 13/11/2011 at 23:33. Pushed by mardelle into branch 'v0.8.2'. Limit number of concurrent threads for proxy creation: http://kdenlive.org/mantis/view.php?id=2403 M +5 -0 src/kdenlivesettings.kcfg M +156 -155 src/projectlist.cpp M +57 -28 src/widgets/configenv_ui.ui http://commits.kde.org/kdenlive/3ee6e1d68029bc223f59341fafd376bd281bf60e diff --git a/src/kdenlivesettings.kcfg b/src/kdenlivesettings.kcfg index db295e1..a2a3cb8 100644 --- a/src/kdenlivesettings.kcfg +++ b/src/kdenlivesettings.kcfg @@ -248,6 +248,11 @@ <default>1</default> </entry> + <entry name="proxythreads" type="Int"> + <label>Proxy creation processing thread count.</label> + <default>2</default> + </entry> + <entry name="encodethreads" type="Int"> <label>FFmpeg encoding thread count.</label> <default>1</default> diff --git a/src/projectlist.cpp b/src/projectlist.cpp index f8d7dd8..484e769 100644 --- a/src/projectlist.cpp +++ b/src/projectlist.cpp @@ -2323,7 +2323,7 @@ void ProjectList::slotCreateProxy(const QString id) info.type = item->clipType(); info.exif = QString(item->referencedClip()->producerProperty("_exif_orientation")).toInt(); m_proxyList.append(info); - m_proxyThreads.addFuture(QtConcurrent::run(this, &ProjectList::slotGenerateProxy)); + if (m_proxyThreads.futures().isEmpty() || m_proxyThreads.futures().count() < KdenliveSettings::proxythreads()) m_proxyThreads.addFuture(QtConcurrent::run(this, &ProjectList::slotGenerateProxy)); } void ProjectList::slotAbortProxy(const QString id, const QString path) @@ -2340,79 +2340,183 @@ void ProjectList::slotAbortProxy(const QString id, const QString path) void ProjectList::slotGenerateProxy() { - if (m_proxyList.isEmpty() || m_abortAllProxies) return; - emit projectModified(); - PROXYINFO info = m_proxyList.takeFirst(); - if (m_abortProxy.contains(info.dest)) { - m_abortProxy.removeAll(info.dest); - return; - } + while (!m_proxyList.isEmpty() && !m_abortAllProxies) { + emit projectModified(); + PROXYINFO info = m_proxyList.takeFirst(); + if (m_abortProxy.contains(info.dest)) { + m_abortProxy.removeAll(info.dest); + return; + } - // Make sure proxy path is writable - QFile file(info.dest); - if (!file.open(QIODevice::WriteOnly)) { - setProxyStatus(info.dest, PROXYCRASHED); - m_processingProxy.removeAll(info.dest); - return; - } - file.close(); - QFile::remove(info.dest); + // Make sure proxy path is writable + QFile file(info.dest); + if (!file.open(QIODevice::WriteOnly)) { + setProxyStatus(info.dest, PROXYCRASHED); + m_processingProxy.removeAll(info.dest); + return; + } + file.close(); + QFile::remove(info.dest); - setProxyStatus(info.dest, CREATINGPROXY); + setProxyStatus(info.dest, CREATINGPROXY); - // Get the list of clips that will need to get progress info - QTreeWidgetItemIterator it(m_listView); - QList <ProjectItem *> processingItems; - while (*it && !m_abortAllProxies) { - if ((*it)->type() == PROJECTCLIPTYPE) { - ProjectItem *item = static_cast <ProjectItem *>(*it); - if (item->referencedClip()->getProperty("proxy") == info.dest) { - processingItems.append(item); + // Get the list of clips that will need to get progress info + QTreeWidgetItemIterator it(m_listView); + QList <ProjectItem *> processingItems; + while (*it && !m_abortAllProxies) { + if ((*it)->type() == PROJECTCLIPTYPE) { + ProjectItem *item = static_cast <ProjectItem *>(*it); + if (item->referencedClip()->getProperty("proxy") == info.dest) { + processingItems.append(item); + } } + ++it; } - ++it; - } - // Special case: playlist clips (.mlt or .kdenlive project files) - if (info.type == PLAYLIST) { - // change FFmpeg params to MLT format - QStringList parameters; - parameters << info.src; - parameters << "-consumer" << "avformat:" + info.dest; - QStringList params = m_doc->getDocumentProperty("proxyparams").simplified().split('-', QString::SkipEmptyParts); + // Special case: playlist clips (.mlt or .kdenlive project files) + if (info.type == PLAYLIST) { + // change FFmpeg params to MLT format + QStringList parameters; + parameters << info.src; + parameters << "-consumer" << "avformat:" + info.dest; + QStringList params = m_doc->getDocumentProperty("proxyparams").simplified().split('-', QString::SkipEmptyParts); - foreach(QString s, params) { - s = s.simplified(); - if (s.count(' ') == 0) { - s.append("=1"); + foreach(QString s, params) { + s = s.simplified(); + if (s.count(' ') == 0) { + s.append("=1"); + } + else s.replace(' ', '='); + parameters << s; } - 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(info.src); - parameters << "aspect=" + QString::number(display_ratio); + 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(info.src); + parameters << "aspect=" + QString::number(display_ratio); + + //kDebug()<<"TRANSCOD: "<<parameters; + QProcess myProcess; + myProcess.setProcessChannelMode(QProcess::MergedChannels); + myProcess.start(KdenliveSettings::rendererpath(), parameters); + myProcess.waitForStarted(); + int result = -1; + int duration = 0; + while (myProcess.state() != QProcess::NotRunning) { + // building proxy file + if (m_abortProxy.contains(info.dest) || m_abortAllProxies) { + myProcess.close(); + myProcess.waitForFinished(); + QFile::remove(info.dest); + m_abortProxy.removeAll(info.dest); + m_processingProxy.removeAll(info.dest); + setProxyStatus(info.dest, NOPROXY); + result = -2; + } + else { + QString log = QString(myProcess.readAll()); + processLogInfo(processingItems, &duration, log); + } + myProcess.waitForFinished(500); + } + myProcess.waitForFinished(); + m_processingProxy.removeAll(info.dest); + if (result == -1) result = myProcess.exitStatus(); + if (result == 0) { + // proxy successfully created + setProxyStatus(info.dest, PROXYDONE); + slotGotProxy(info.dest); + } + else if (result == 1) { + // Proxy process crashed + QFile::remove(info.dest); + setProxyStatus(info.dest, PROXYCRASHED); + } + continue; + } + + if (info.type == IMAGE) { + // Image proxy + QImage i(info.src); + if (i.isNull()) { + // Cannot load image + setProxyStatus(info.dest, PROXYCRASHED); + continue; + } + 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 (info.exif > 1) { + // Rotate image according to exif data + QImage processed; + QMatrix matrix; + + switch ( info.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; + } + processed = proxy.transformed( matrix ); + processed.save(info.dest); + } + else proxy.save(info.dest); + setProxyStatus(info.dest, PROXYDONE); + slotGotProxy(info.dest); + m_abortProxy.removeAll(info.dest); + m_processingProxy.removeAll(info.dest); + continue; + } - //kDebug()<<"TRANSCOD: "<<parameters; + QStringList parameters; + parameters << "-i" << info.src; + 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 << info.dest; QProcess myProcess; myProcess.setProcessChannelMode(QProcess::MergedChannels); - myProcess.start(KdenliveSettings::rendererpath(), parameters); + myProcess.start("ffmpeg", parameters); myProcess.waitForStarted(); int result = -1; int duration = 0; + while (myProcess.state() != QProcess::NotRunning) { // building proxy file if (m_abortProxy.contains(info.dest) || m_abortAllProxies) { myProcess.close(); myProcess.waitForFinished(); - QFile::remove(info.dest); m_abortProxy.removeAll(info.dest); m_processingProxy.removeAll(info.dest); - setProxyStatus(info.dest, NOPROXY); + QFile::remove(info.dest); + if (!m_abortAllProxies) setProxyStatus(info.dest, NOPROXY); result = -2; + } else { QString log = QString(myProcess.readAll()); @@ -2421,6 +2525,7 @@ void ProjectList::slotGenerateProxy() myProcess.waitForFinished(500); } myProcess.waitForFinished(); + m_abortProxy.removeAll(info.dest); m_processingProxy.removeAll(info.dest); if (result == -1) result = myProcess.exitStatus(); if (result == 0) { @@ -2433,110 +2538,6 @@ void ProjectList::slotGenerateProxy() QFile::remove(info.dest); setProxyStatus(info.dest, PROXYCRASHED); } - return; - } - - if (info.type == IMAGE) { - // Image proxy - QImage i(info.src); - if (i.isNull()) { - // Cannot load image - setProxyStatus(info.dest, 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 (info.exif > 1) { - // Rotate image according to exif data - QImage processed; - QMatrix matrix; - - switch ( info.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; - } - processed = proxy.transformed( matrix ); - processed.save(info.dest); - } - else proxy.save(info.dest); - setProxyStatus(info.dest, PROXYDONE); - slotGotProxy(info.dest); - m_abortProxy.removeAll(info.dest); - m_processingProxy.removeAll(info.dest); - return; - } - - QStringList parameters; - parameters << "-i" << info.src; - 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 << info.dest; - QProcess myProcess; - myProcess.setProcessChannelMode(QProcess::MergedChannels); - myProcess.start("ffmpeg", parameters); - myProcess.waitForStarted(); - int result = -1; - int duration = 0; - - while (myProcess.state() != QProcess::NotRunning) { - // building proxy file - if (m_abortProxy.contains(info.dest) || m_abortAllProxies) { - myProcess.close(); - myProcess.waitForFinished(); - m_abortProxy.removeAll(info.dest); - m_processingProxy.removeAll(info.dest); - QFile::remove(info.dest); - if (!m_abortAllProxies) setProxyStatus(info.dest, NOPROXY); - result = -2; - - } - else { - QString log = QString(myProcess.readAll()); - processLogInfo(processingItems, &duration, log); - } - myProcess.waitForFinished(500); - } - myProcess.waitForFinished(); - m_abortProxy.removeAll(info.dest); - m_processingProxy.removeAll(info.dest); - if (result == -1) result = myProcess.exitStatus(); - if (result == 0) { - // proxy successfully created - setProxyStatus(info.dest, PROXYDONE); - slotGotProxy(info.dest); - } - else if (result == 1) { - // Proxy process crashed - QFile::remove(info.dest); - setProxyStatus(info.dest, PROXYCRASHED); } } diff --git a/src/widgets/configenv_ui.ui b/src/widgets/configenv_ui.ui index b83442f..5456080 100644 --- a/src/widgets/configenv_ui.ui +++ b/src/widgets/configenv_ui.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>384</width> - <height>203</height> + <width>297</width> + <height>215</height> </rect> </property> <layout class="QGridLayout" name="gridLayout"> @@ -24,7 +24,7 @@ </property> </widget> </item> - <item row="1" column="0"> + <item row="2" column="0"> <widget class="QTabWidget" name="tabWidget"> <property name="currentIndex"> <number>0</number> @@ -33,7 +33,7 @@ <attribute name="title"> <string>MLT environment</string> </attribute> - <layout class="QGridLayout" name="gridLayout_4"> + <layout class="QGridLayout" name="gridLayout_3"> <item row="0" column="0"> <widget class="QLabel" name="label"> <property name="text"> @@ -41,7 +41,7 @@ </property> </widget> </item> - <item row="0" column="1" colspan="2"> + <item row="0" column="1" colspan="3"> <widget class="KUrlRequester" name="mltpathurl"/> </item> <item row="1" column="0"> @@ -51,22 +51,9 @@ </property> </widget> </item> - <item row="1" column="1" colspan="2"> + <item row="1" column="1" colspan="3"> <widget class="KUrlRequester" name="rendererpathurl"/> </item> - <item row="3" column="1"> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> <item row="2" column="0"> <widget class="QLabel" name="label_6"> <property name="text"> @@ -74,7 +61,7 @@ </property> </widget> </item> - <item row="2" column="1"> + <item row="2" column="1" colspan="2"> <widget class="QSpinBox" name="kcfg_mltthreads"> <property name="sizePolicy"> <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> @@ -87,7 +74,7 @@ </property> </widget> </item> - <item row="2" column="2"> + <item row="2" column="3"> <widget class="QLabel" name="label_7"> <property name="text"> <string>(>1 is experimental)</string> @@ -238,14 +225,55 @@ </widget> </widget> </item> + <item row="3" column="0"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Proxy clips</string> + </property> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string>Processing threads</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QSpinBox" name="kcfg_proxythreads"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimum"> + <number>1</number> + </property> + </widget> + </item> + </layout> + </widget> + </item> </layout> </widget> <customwidgets> <customwidget> - <class>KUrlRequester</class> - <extends>QFrame</extends> - <header>kurlrequester.h</header> - <container>1</container> + <class>KLineEdit</class> + <extends>QLineEdit</extends> + <header>klineedit.h</header> </customwidget> <customwidget> <class>KPushButton</class> @@ -253,9 +281,10 @@ <header>kpushbutton.h</header> </customwidget> <customwidget> - <class>KLineEdit</class> - <extends>QLineEdit</extends> - <header>klineedit.h</header> + <class>KUrlRequester</class> + <extends>QFrame</extends> + <header>kurlrequester.h</header> + <container>1</container> </customwidget> </customwidgets> <resources/> |