Initial support for externally created proxy clips through a pattern

Should work with Sony PXW camcorder proxy clips
parent e997a3be
......@@ -14,6 +14,7 @@ endif()
install(FILES
banner.png
encodingprofiles.rc
externalproxies.rc
metadata.properties
meta_ffmpeg.png
meta_libav.png
......
# This lists patterns for camcorder proxy clips. a ';' separated list with
# * relative path
# * prefix
# * suffix
[proxy]
Sony PXW=../Sub;;S03.MP4
......@@ -158,6 +158,7 @@ ki18n_wrap_ui(kdenlive_UIS
ui/configjogshuttle_ui.ui
ui/configmisc_ui.ui
ui/configproject_ui.ui
ui/configproxy_ui.ui
ui/configsdl_ui.ui
ui/configtimeline_ui.ui
ui/configtranscode_ui.ui
......
This diff is collapsed.
......@@ -29,6 +29,7 @@
#include "ui_configjogshuttle_ui.h"
#include "ui_configmisc_ui.h"
#include "ui_configproject_ui.h"
#include "ui_configproxy_ui.h"
#include "ui_configsdl_ui.h"
#include "ui_configtimeline_ui.h"
#include "ui_configtranscode_ui.h"
......@@ -83,6 +84,7 @@ private slots:
void slotEditVideo4LinuxProfile();
void slotReloadBlackMagic();
void slotReloadShuttleDevices();
void loadExternalProxyProfiles();
private:
KPageWidgetItem *m_page1;
......@@ -101,6 +103,7 @@ private:
Ui::ConfigSdl_UI m_configSdl;
Ui::ConfigTranscode_UI m_configTranscode;
Ui::ConfigProject_UI m_configProject;
Ui::ConfigProxy_UI m_configProxy;
ProfileWidget *m_pw;
KProcess m_readProcess;
bool m_modified;
......
......@@ -1362,7 +1362,6 @@ bool DocumentValidator::upgrade(double version, const double currentVersion)
originalProd.removeAttribute(QStringLiteral("file_hash"));
originalProd.removeAttribute(QStringLiteral("file_size"));
originalProd.removeAttribute(QStringLiteral("frame_size"));
originalProd.removeAttribute(QStringLiteral("proxy_out"));
originalProd.removeAttribute(QStringLiteral("zone_out"));
originalProd.removeAttribute(QStringLiteral("zone_in"));
originalProd.removeAttribute(QStringLiteral("name"));
......
......@@ -100,6 +100,8 @@ KdenliveDoc::KdenliveDoc(const QUrl &url, const QString &projectFolder, QUndoGro
m_documentProperties[QStringLiteral("proxyextension")] = KdenliveSettings::proxyextension();
m_documentProperties[QStringLiteral("previewparameters")] = KdenliveSettings::previewparams();
m_documentProperties[QStringLiteral("previewextension")] = KdenliveSettings::previewextension();
m_documentProperties[QStringLiteral("externalproxyparams")] = KdenliveSettings::externalProxyProfile();
m_documentProperties[QStringLiteral("enableexternalproxy")] = QString::number((int)KdenliveSettings::externalproxy());
m_documentProperties[QStringLiteral("generateproxy")] = QString::number((int)KdenliveSettings::generateproxy());
m_documentProperties[QStringLiteral("proxyminsize")] = QString::number(KdenliveSettings::proxyminsize());
m_documentProperties[QStringLiteral("generateimageproxy")] = QString::number((int)KdenliveSettings::generateimageproxy());
......@@ -407,6 +409,11 @@ bool KdenliveDoc::useProxy() const
return m_documentProperties.value(QStringLiteral("enableproxy")).toInt() != 0;
}
bool KdenliveDoc::useExternalProxy() const
{
return m_documentProperties.value(QStringLiteral("enableexternalproxy")).toInt() != 0;
}
bool KdenliveDoc::autoGenerateProxy(int width) const
{
return (m_documentProperties.value(QStringLiteral("generateproxy")).toInt() != 0) &&
......@@ -1174,6 +1181,7 @@ void KdenliveDoc::slotProxyCurrentItem(bool doProxy, QList<std::shared_ptr<Proje
}
// Parse clips
QStringList externalProxyParams = m_documentProperties.value(QStringLiteral("externalproxyparams")).split(QLatin1Char(';'));
for (int i = 0; i < clipList.count(); ++i) {
std::shared_ptr<ProjectClip> item = clipList.at(i);
ClipType::ProducerType t = item->clipType();
......@@ -1188,9 +1196,30 @@ void KdenliveDoc::slotProxyCurrentItem(bool doProxy, QList<std::shared_ptr<Proje
if (doProxy) {
newProps.clear();
QString path = dir.absoluteFilePath(item->hash() + (t == ClipType::Image ? QStringLiteral(".png") : extension));
// insert required duration for proxy
newProps.insert(QStringLiteral("proxy_out"), item->getProducerProperty(QStringLiteral("out")));
QString path;
if (useExternalProxy() && item->hasLimitedDuration()) {
if (externalProxyParams.count() == 3) {
QFileInfo info(item->url());
QDir clipDir = info.absoluteDir();
if (clipDir.cd(externalProxyParams.at(0))) {
// Find correct file
QString fileName = info.fileName();
if (!externalProxyParams.at(1).isEmpty()) {
fileName.prepend(externalProxyParams.at(1));
}
if (!externalProxyParams.at(2).isEmpty()) {
fileName = fileName.section(QLatin1Char('.'), 0, -2);
fileName.append(externalProxyParams.at(2));
}
if (clipDir.exists(fileName)) {
path = clipDir.absoluteFilePath(fileName);
}
}
}
}
if (path.isEmpty()) {
path = dir.absoluteFilePath(item->hash() + (t == ClipType::Image ? QStringLiteral(".png") : extension));
}
newProps.insert(QStringLiteral("kdenlive:proxy"), path);
// We need to insert empty proxy so that undo will work
// TODO: how to handle clip properties
......
......@@ -122,6 +122,7 @@ public:
/** @brief Get all document properties that need to be saved */
QMap<QString, QString> documentProperties();
bool useProxy() const;
bool useExternalProxy() const;
bool autoGenerateProxy(int width) const;
bool autoGenerateImageProxy(int width) const;
/** @brief Saves effects embedded in project file. */
......
......@@ -131,11 +131,26 @@
<default>false</default>
</entry>
<entry name="externalproxy" type="Bool">
<label>Enable proxy clips.</label>
<default>false</default>
</entry>
<entry name="generateproxy" type="Bool">
<label>Auto generate proxy for new clips.</label>
<default>false</default>
</entry>
<entry name="external_proxy_profile" type="Int">
<label>index for the external proxy clips combo.</label>
<default></default>
</entry>
<entry name="externalProxyProfile" type="String">
<label>Pattern to find external proxy clips.</label>
<default></default>
</entry>
<entry name="generateimageproxy" type="Bool">
<label>Auto generate proxy for new image clips.</label>
<default>false</default>
......
......@@ -1621,6 +1621,17 @@ void MainWindow::slotEditProjectSettings()
pCore->bin()->rebuildProxies();
}
}
if (project->getDocumentProperty(QStringLiteral("externalproxyparams")) != w->externalProxyParams()) {
modified = true;
project->setDocumentProperty(QStringLiteral("externalproxyparams"), w->externalProxyParams());
if (pCore->projectItemModel()->clipsCount() > 0 &&
KMessageBox::questionYesNo(this, i18n("You have changed the proxy parameters. Do you want to recreate all proxy clips for this project?")) ==
KMessageBox::Yes) {
pCore->bin()->rebuildProxies();
}
}
if (project->getDocumentProperty(QStringLiteral("generateproxy")) != QString::number((int)w->generateProxy())) {
modified = true;
project->setDocumentProperty(QStringLiteral("generateproxy"), QString::number((int)w->generateProxy()));
......@@ -1646,6 +1657,10 @@ void MainWindow::slotEditProjectSettings()
modified = true;
slotUpdateProxySettings();
}
if (QString::number((int)w->useExternalProxy()) != project->getDocumentProperty(QStringLiteral("enableexternalproxy"))) {
project->setDocumentProperty(QStringLiteral("enableexternalproxy"), QString::number((int)w->useExternalProxy()));
modified = true;
}
if (w->metadata() != project->metadata()) {
project->setMetadata(w->metadata());
}
......
......@@ -100,10 +100,12 @@ ProjectSettings::ProjectSettings(KdenliveDoc *doc, QMap<QString, QString> metada
generate_proxy->setChecked(doc->getDocumentProperty(QStringLiteral("generateproxy")).toInt() != 0);
proxy_minsize->setValue(doc->getDocumentProperty(QStringLiteral("proxyminsize")).toInt());
m_proxyparameters = doc->getDocumentProperty(QStringLiteral("proxyparams"));
m_initialExternalProxyProfile = doc->getDocumentProperty(QStringLiteral("externalproxyparams"));
generate_imageproxy->setChecked(doc->getDocumentProperty(QStringLiteral("generateimageproxy")).toInt() != 0);
proxy_imageminsize->setValue(doc->getDocumentProperty(QStringLiteral("proxyimageminsize")).toInt());
proxy_imagesize->setValue(doc->getDocumentProperty(QStringLiteral("proxyimagesize")).toInt());
m_proxyextension = doc->getDocumentProperty(QStringLiteral("proxyextension"));
external_proxy->setChecked(doc->getDocumentProperty(QStringLiteral("enableexternalproxy")).toInt() != 0);
m_previewparams = doc->getDocumentProperty(QStringLiteral("previewparameters"));
m_previewextension = doc->getDocumentProperty(QStringLiteral("previewextension"));
QString storageFolder = doc->getDocumentProperty(QStringLiteral("storagefolder"));
......@@ -118,6 +120,9 @@ ProjectSettings::ProjectSettings(KdenliveDoc *doc, QMap<QString, QString> metada
} else {
currentProf = KdenliveSettings::default_profile();
enable_proxy->setChecked(KdenliveSettings::enableproxy());
external_proxy->setChecked(KdenliveSettings::externalproxy());
qDebug()<<"//// INITIAL REPORT; ENABLE EXT PROCY: "<<KdenliveSettings::externalproxy()<<"\n++++++++";
m_initialExternalProxyProfile = KdenliveSettings::externalProxyProfile();
generate_proxy->setChecked(KdenliveSettings::generateproxy());
proxy_minsize->setValue(KdenliveSettings::proxyminsize());
m_proxyparameters = KdenliveSettings::proxyparams();
......@@ -137,6 +142,7 @@ ProjectSettings::ProjectSettings(KdenliveDoc *doc, QMap<QString, QString> metada
loadProxyProfiles();
loadPreviewProfiles();
loadExternalProxyProfiles();
// Proxy GUI stuff
proxy_showprofileinfo->setIcon(QIcon::fromTheme(QStringLiteral("help-about")));
......@@ -147,11 +153,13 @@ ProjectSettings::ProjectSettings(KdenliveDoc *doc, QMap<QString, QString> metada
connect(proxy_manageprofile, &QAbstractButton::clicked, this, &ProjectSettings::slotManageEncodingProfile);
proxy_profile->setToolTip(i18n("Select default proxy profile"));
connect(proxy_profile, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdateProxyParams()));
connect(proxy_profile, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ProjectSettings::slotUpdateProxyParams);
proxyparams->setVisible(false);
proxyparams->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 5);
connect(proxy_showprofileinfo, &QAbstractButton::clicked, proxyparams, &QWidget::setVisible);
external_proxy_profile->setToolTip(i18n("Select camcorder profile"));
// Preview GUI stuff
preview_showprofileinfo->setIcon(QIcon::fromTheme(QStringLiteral("help-about")));
preview_showprofileinfo->setToolTip(i18n("Show default profile parameters"));
......@@ -161,7 +169,7 @@ ProjectSettings::ProjectSettings(KdenliveDoc *doc, QMap<QString, QString> metada
connect(preview_manageprofile, &QAbstractButton::clicked, this, &ProjectSettings::slotManagePreviewProfile);
preview_profile->setToolTip(i18n("Select default preview profile"));
connect(preview_profile, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdatePreviewParams()));
connect(preview_profile, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ProjectSettings::slotUpdatePreviewParams);
previewparams->setVisible(false);
previewparams->setMaximumHeight(QFontMetrics(font()).lineSpacing() * 5);
connect(preview_showprofileinfo, &QAbstractButton::clicked, previewparams, &QWidget::setVisible);
......@@ -477,6 +485,11 @@ bool ProjectSettings::useProxy() const
return enable_proxy->isChecked();
}
bool ProjectSettings::useExternalProxy() const
{
return external_proxy->isChecked();
}
bool ProjectSettings::generateProxy() const
{
return generate_proxy->isChecked();
......@@ -502,15 +515,21 @@ int ProjectSettings::proxyImageSize() const
return proxy_imagesize->value();
}
QString ProjectSettings::externalProxyParams() const
{
return external_proxy_profile->currentData().toString();
}
QString ProjectSettings::proxyParams() const
{
QString params = proxy_profile->itemData(proxy_profile->currentIndex()).toString();
QString params = proxy_profile->currentData().toString();
return params.section(QLatin1Char(';'), 0, 0);
}
QString ProjectSettings::proxyExtension() const
{
QString params = proxy_profile->itemData(proxy_profile->currentIndex()).toString();
QString params = proxy_profile->currentData().toString();
return params.section(QLatin1Char(';'), 1, 1);
}
......@@ -649,13 +668,13 @@ void ProjectSettings::slotExportToText()
void ProjectSettings::slotUpdateProxyParams()
{
QString params = proxy_profile->itemData(proxy_profile->currentIndex()).toString();
QString params = proxy_profile->currentData().toString();
proxyparams->setPlainText(params.section(QLatin1Char(';'), 0, 0));
}
void ProjectSettings::slotUpdatePreviewParams()
{
QString params = preview_profile->itemData(preview_profile->currentIndex()).toString();
QString params = preview_profile->currentData().toString();
previewparams->setPlainText(params.section(QLatin1Char(';'), 0, 0));
}
......@@ -756,6 +775,36 @@ void ProjectSettings::loadProxyProfiles()
slotUpdateProxyParams();
}
void ProjectSettings::loadExternalProxyProfiles()
{
// load proxy profiles
KConfig conf(QStringLiteral("externalproxies.rc"), KConfig::CascadeConfig, QStandardPaths::AppDataLocation);
KConfigGroup group(&conf, "proxy");
QMap<QString, QString> values = group.entryMap();
QMapIterator<QString, QString> k(values);
int ix = -1;
external_proxy_profile->clear();
while (k.hasNext()) {
k.next();
if (!k.key().isEmpty()) {
if (ix == -1 && k.value() == m_initialExternalProxyProfile) {
// this is the current profile
ix = external_proxy_profile->count();
}
if (k.value().contains(QLatin1Char(';'))) {
external_proxy_profile->addItem(k.key(), k.value());
}
}
}
if (ix == -1 && !m_initialExternalProxyProfile.isEmpty()) {
// Current project proxy settings not found
ix = external_proxy_profile->count();
external_proxy_profile->addItem(i18n("Current Settings"), m_initialExternalProxyProfile);
}
external_proxy_profile->setCurrentIndex(ix);
}
void ProjectSettings::loadPreviewProfiles()
{
// load proxy profiles
......
......@@ -41,11 +41,13 @@ public:
bool enableVideoThumbs() const;
bool enableAudioThumbs() const;
bool useProxy() const;
bool useExternalProxy() const;
bool generateProxy() const;
int proxyMinSize() const;
bool generateImageProxy() const;
int proxyImageMinSize() const;
int proxyImageSize() const;
QString externalProxyParams() const;
QString proxyParams() const;
QString proxyExtension() const;
const QMap<QString, QString> metadata() const;
......@@ -90,8 +92,11 @@ private:
QDir m_previewDir;
/** @brief Fill the proxy profiles combobox. */
void loadProxyProfiles();
/** @brief Fill the external proxy profiles combobox. */
void loadExternalProxyProfiles();
QString m_previewparams;
QString m_previewextension;
QString m_initialExternalProxyProfile;
/** @brief Fill the proxy profiles combobox. */
void loadPreviewProfiles();
......
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ConfigProxy_UI</class>
<widget class="QWidget" name="ConfigProxy_UI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>665</width>
<height>440</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QCheckBox" name="kcfg_enableproxy">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Enable proxy clips</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="proxy_box">
<property name="enabled">
<bool>false</bool>
</property>
<property name="flat">
<bool>true</bool>
</property>
<property name="checkable">
<bool>false</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="2" colspan="3">
<widget class="QSpinBox" name="kcfg_proxyminsize">
<property name="suffix">
<string>pixels</string>
</property>
<property name="maximum">
<number>10000</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="kcfg_externalproxy">
<property name="text">
<string>Use external proxy clips</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QToolButton" name="proxy_manageprofile">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="5">
<widget class="QPlainTextEdit" name="proxyparams">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_24">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Encoding profile</string>
</property>
</widget>
</item>
<item row="4" column="2" colspan="3">
<widget class="QSpinBox" name="kcfg_proxyimagesize">
<property name="enabled">
<bool>false</bool>
</property>
<property name="suffix">
<string>pixels</string>
</property>
<property name="minimum">
<number>200</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="value">
<number>800</number>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QToolButton" name="proxy_showprofileinfo">
<property name="text">
<string>...</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="kcfg_generateimageproxy">
<property name="text">
<string>Generate for images larger than</string>
</property>
</widget>
</item>
<item row="7" 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="0" column="0" colspan="2">
<widget class="QCheckBox" name="kcfg_generateproxy">
<property name="text">
<string>Generate for videos larger than</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="image_label">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Proxy image size</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="KComboBox" name="kcfg_proxy_profile">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="3" column="2" colspan="3">
<widget class="QSpinBox" name="kcfg_proxyimageminsize">
<property name="suffix">
<string>pixels</string>
</property>
<property name="minimum">
<number>500</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="value">
<number>2000</number>
</property>
</widget>
</item>
<item row="6" column="1" colspan="4">
<widget class="QComboBox" name="kcfg_external_proxy_profile"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KComboBox</class>
<extends>QComboBox</extends>
<header>kcombobox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>kcfg_enableproxy</sender>
<signal>toggled(bool)</signal>
<receiver>proxy_box</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>137</x>
<y>40</y>
</hint>
<hint type="destinationlabel">
<x>346</x>
<y>280</y>
</hint>
</hints>
</connection>
</connections>
</ui>
This diff is collapsed.
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