mirror of
https://invent.kde.org/multimedia/kdenlive
synced 2025-12-06 08:20:01 +01:00
Compare commits
1 Commits
work/embed
...
work/avfil
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0adacfd5fa |
@@ -12,6 +12,7 @@ avfilter_alimiter.xml
|
||||
avfilter_allpass.xml
|
||||
avfilter_aphaser.xml
|
||||
avfilter_apulsator.xml
|
||||
avfilter_arnndn.xml
|
||||
avfilter_atadenoise.xml
|
||||
avfilter_avgblur.xml
|
||||
avfilter_bandpass.xml
|
||||
|
||||
13
data/effects/avfilter/avfilter_arnndn.xml
Normal file
13
data/effects/avfilter/avfilter_arnndn.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE kpartgui>
|
||||
<effect tag="avfilter.arnndn" id="avfilter.arnndn" type="audio">
|
||||
<name>Reduce Noise From Speech</name>
|
||||
<description>Noise reduction using neural models</description>
|
||||
<author>libavfilter</author>
|
||||
<parameter type="fixed" name="av.m" value="%avfiltermodels/mp.rnnn">
|
||||
<paramdependencies files="%avfiltermodels/mp.rnnn" >Required model files for Noise Reduction Models not found in <a href="file://%folder">models folder</a>. Check our <a href="https://docs.kdenlive.org/en/effects_and_compositions/effect_groups/alpha_manipulation/motion_tracker.html?highlight=motion%20tracker#id2">manual</a> for instructions.</paramdependencies>
|
||||
</parameter>
|
||||
<parameter type="constant" name="av.mix" default="1" min="-1" max="1" decimals="3">
|
||||
<name>Mix level</name>
|
||||
</parameter>
|
||||
</effect>
|
||||
@@ -78,7 +78,7 @@
|
||||
<group list="avfilter.flanger,avfilter.aphaser,avfilter.apulsator,sox_flanger,sox_phaser,avfilter.treble,avfilter.vibrato"><text>Modulators</text>
|
||||
</group>
|
||||
|
||||
<group list="ladspa.9354877"><text>Noise Reduction and Audio Restoration</text>
|
||||
<group list="ladspa.9354877,avfilter.arnndn"><text>Noise Reduction and Audio Restoration</text>
|
||||
</group>
|
||||
|
||||
<group list="panner,audiomap,channelswap,mono,channelcopy,channelswap,swapchannels,audiobalance,audiopan">
|
||||
|
||||
@@ -113,6 +113,10 @@ AssetParameterModel::AssetParameterModel(std::unique_ptr<Mlt::Properties> asset,
|
||||
}
|
||||
bool isFixed = (type == QLatin1String("fixed"));
|
||||
if (isFixed) {
|
||||
if (value.contains(QLatin1Char('%'))) {
|
||||
value.replace(QLatin1String("%avfiltermodels"),
|
||||
QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/avfiltermodels")).absolutePath());
|
||||
}
|
||||
m_fixedParams[name] = value;
|
||||
} else if (currentRow.type == ParamType::Position) {
|
||||
int val = value.toInt();
|
||||
|
||||
@@ -205,11 +205,14 @@ bool EffectsRepository::isPreferred(const QString &effectId) const
|
||||
return m_preferred_list.contains(effectId);
|
||||
}
|
||||
|
||||
std::unique_ptr<Mlt::Filter> EffectsRepository::getEffect(const QString &effectId) const
|
||||
std::unique_ptr<Mlt::Properties> EffectsRepository::getEffect(const QString &effectId) const
|
||||
{
|
||||
Q_ASSERT(exists(effectId));
|
||||
QString service_name = m_assets.at(effectId).mltId;
|
||||
// We create the Mlt element from its name
|
||||
if (effectId.startsWith(QStringLiteral("avfilter."))) {
|
||||
return std::make_unique<Mlt::Link>(service_name.toLatin1().constData());
|
||||
}
|
||||
auto filter = std::make_unique<Mlt::Filter>(pCore->getProjectProfile(), service_name.toLatin1().constData(), nullptr);
|
||||
return filter;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
static std::unique_ptr<EffectsRepository> &get();
|
||||
|
||||
/** @brief returns a fresh instance of the given effect */
|
||||
std::unique_ptr<Mlt::Filter> getEffect(const QString &effectId) const;
|
||||
std::unique_ptr<Mlt::Properties> getEffect(const QString &effectId) const;
|
||||
/** @brief returns true if an effect exists in MLT (bypasses the blacklist/metadata parsing) */
|
||||
bool hasInternalEffect(const QString &effectId) const;
|
||||
QPair<QString, QString> reloadCustom(const QString &path);
|
||||
|
||||
@@ -92,7 +92,13 @@ std::shared_ptr<EffectItemModel> EffectItemModel::construct(std::unique_ptr<Mlt:
|
||||
void EffectItemModel::plant(const std::weak_ptr<Mlt::Service> &service)
|
||||
{
|
||||
if (auto ptr = service.lock()) {
|
||||
int ret = ptr->attach(filter());
|
||||
int ret = 0;
|
||||
if (isLink()) {
|
||||
Mlt::Chain fromChain(static_cast<Mlt::Producer *>(ptr.get())->parent());
|
||||
ret = fromChain.attach(getLink());
|
||||
} else {
|
||||
ret = ptr->attach(getFilter());
|
||||
}
|
||||
Q_ASSERT(ret == 0);
|
||||
} else {
|
||||
qDebug() << "Error : Cannot plant effect because parent service is not available anymore";
|
||||
@@ -141,7 +147,13 @@ void EffectItemModel::plantClone(const std::weak_ptr<Mlt::Service> &service)
|
||||
ptr->set("_childid", childId);
|
||||
}
|
||||
m_childEffects.insert(childId, effect);
|
||||
int ret = ptr->attach(effect->filter());
|
||||
int ret = 0;
|
||||
if (isLink()) {
|
||||
Mlt::Chain fromChain(static_cast<Mlt::Producer *>(ptr.get())->parent());
|
||||
ret = fromChain.attach(effect->getLink());
|
||||
} else {
|
||||
ret = ptr->attach(effect->getFilter());
|
||||
}
|
||||
Q_ASSERT(ret == 0);
|
||||
return;
|
||||
}
|
||||
@@ -153,7 +165,13 @@ void EffectItemModel::plantClone(const std::weak_ptr<Mlt::Service> &service)
|
||||
void EffectItemModel::unplant(const std::weak_ptr<Mlt::Service> &service)
|
||||
{
|
||||
if (auto ptr = service.lock()) {
|
||||
int ret = ptr->detach(filter());
|
||||
int ret = 0;
|
||||
if (isLink()) {
|
||||
Mlt::Chain fromChain(static_cast<Mlt::Producer *>(ptr.get())->parent());
|
||||
ret = fromChain.detach(getLink());
|
||||
} else {
|
||||
ret = ptr->detach(getFilter());
|
||||
}
|
||||
Q_ASSERT(ret == 0);
|
||||
} else {
|
||||
qDebug() << "Error : Cannot plant effect because parent service is not available anymore";
|
||||
@@ -167,12 +185,23 @@ void EffectItemModel::unplantClone(const std::weak_ptr<Mlt::Service> &service)
|
||||
return;
|
||||
}
|
||||
if (auto ptr = service.lock()) {
|
||||
int ret = ptr->detach(filter());
|
||||
int ret = 0;
|
||||
if (isLink()) {
|
||||
Mlt::Chain fromChain(static_cast<Mlt::Producer *>(ptr.get())->parent());
|
||||
ret = fromChain.detach(getLink());
|
||||
} else {
|
||||
ret = ptr->detach(getFilter());
|
||||
}
|
||||
Q_ASSERT(ret == 0);
|
||||
int childId = ptr->get_int("_childid");
|
||||
auto effect = m_childEffects.take(childId);
|
||||
if (effect && effect->isValid()) {
|
||||
ptr->detach(effect->filter());
|
||||
if (effect->isLink()) {
|
||||
Mlt::Chain fromChain(static_cast<Mlt::Producer *>(ptr.get())->parent());
|
||||
ret = fromChain.detach(effect->getLink());
|
||||
} else {
|
||||
ret = ptr->detach(effect->getFilter());
|
||||
}
|
||||
effect.reset();
|
||||
}
|
||||
} else {
|
||||
@@ -181,11 +210,26 @@ void EffectItemModel::unplantClone(const std::weak_ptr<Mlt::Service> &service)
|
||||
}
|
||||
}
|
||||
|
||||
Mlt::Filter &EffectItemModel::filter() const
|
||||
Mlt::Properties &EffectItemModel::filter() const
|
||||
{
|
||||
return *(m_asset.get());
|
||||
}
|
||||
|
||||
Mlt::Filter &EffectItemModel::getFilter() const
|
||||
{
|
||||
return *static_cast<Mlt::Filter *>(m_asset.get());
|
||||
}
|
||||
|
||||
Mlt::Link &EffectItemModel::getLink() const
|
||||
{
|
||||
return *static_cast<Mlt::Link *>(m_asset.get());
|
||||
}
|
||||
|
||||
bool EffectItemModel::isLink() const
|
||||
{
|
||||
return m_assetId.startsWith(QLatin1String("avfilter."));
|
||||
}
|
||||
|
||||
bool EffectItemModel::isValid() const
|
||||
{
|
||||
return m_asset && m_asset->is_valid();
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "abstractmodel/treeitem.hpp"
|
||||
#include "assets/model/assetparametermodel.hpp"
|
||||
#include <mlt++/MltFilter.h>
|
||||
#include <mlt++/MltLink.h>
|
||||
|
||||
class EffectStackModel;
|
||||
/** @brief This represents an effect of the effectstack
|
||||
@@ -37,7 +38,10 @@ public:
|
||||
void unplant(const std::weak_ptr<Mlt::Service> &service) override;
|
||||
void unplantClone(const std::weak_ptr<Mlt::Service> &service) override;
|
||||
|
||||
Mlt::Filter &filter() const;
|
||||
Mlt::Properties &filter() const;
|
||||
Mlt::Filter &getFilter() const;
|
||||
Mlt::Link &getLink() const;
|
||||
bool isLink() const;
|
||||
|
||||
/** @brief Return true if the effect applies only to audio */
|
||||
bool isAudio() const override;
|
||||
|
||||
@@ -367,7 +367,7 @@ bool EffectStackModel::fromXml(const QDomElement &effectsXml, Fun &undo, Fun &re
|
||||
connect(effect.get(), &AssetParameterModel::showEffectZone, this, &EffectStackModel::updateEffectZones);
|
||||
if (effectId.startsWith(QLatin1String("fadein")) || effectId.startsWith(QLatin1String("fade_from_"))) {
|
||||
m_fadeIns.insert(effect->getId());
|
||||
int duration = effect->filter().get_length() - 1;
|
||||
int duration = effect->getFilter().get_length() - 1;
|
||||
effect->filter().set("in", currentIn);
|
||||
effect->filter().set("out", currentIn + duration);
|
||||
if (effectId.startsWith(QLatin1String("fade_"))) {
|
||||
@@ -380,7 +380,7 @@ bool EffectStackModel::fromXml(const QDomElement &effectsXml, Fun &undo, Fun &re
|
||||
}
|
||||
} else if (effectId.startsWith(QLatin1String("fadeout")) || effectId.startsWith(QLatin1String("fade_to_"))) {
|
||||
m_fadeOuts.insert(effect->getId());
|
||||
int duration = effect->filter().get_length() - 1;
|
||||
int duration = effect->getFilter().get_length() - 1;
|
||||
int filterOut = pCore->getItemIn(m_ownerId) + pCore->getItemDuration(m_ownerId) - 1;
|
||||
effect->filter().set("in", filterOut - duration);
|
||||
effect->filter().set("out", filterOut);
|
||||
@@ -451,14 +451,14 @@ bool EffectStackModel::copyEffect(const std::shared_ptr<AbstractEffectItem> &sou
|
||||
QVector<int> roles = {TimelineModel::EffectNamesRole};
|
||||
if (effectId.startsWith(QLatin1String("fadein")) || effectId.startsWith(QLatin1String("fade_from_"))) {
|
||||
m_fadeIns.insert(effect->getId());
|
||||
int duration = effect->filter().get_length() - 1;
|
||||
int duration = effect->getFilter().get_length() - 1;
|
||||
int in = pCore->getItemIn(m_ownerId);
|
||||
effect->filter().set("in", in);
|
||||
effect->filter().set("out", in + duration);
|
||||
roles << TimelineModel::FadeInRole;
|
||||
} else if (effectId.startsWith(QLatin1String("fadeout")) || effectId.startsWith(QLatin1String("fade_to_"))) {
|
||||
m_fadeOuts.insert(effect->getId());
|
||||
int duration = effect->filter().get_length() - 1;
|
||||
int duration = effect->getFilter().get_length() - 1;
|
||||
int out = pCore->getItemIn(m_ownerId) + pCore->getItemDuration(m_ownerId) - 1;
|
||||
effect->filter().set("in", out - duration);
|
||||
effect->filter().set("out", out);
|
||||
@@ -524,7 +524,7 @@ bool EffectStackModel::appendEffect(const QString &effectId, bool makeCurrent)
|
||||
int inFades = 0;
|
||||
int outFades = 0;
|
||||
if (effectId.startsWith(QLatin1String("fadein")) || effectId.startsWith(QLatin1String("fade_from_"))) {
|
||||
int duration = effect->filter().get_length() - 1;
|
||||
int duration = effect->getFilter().get_length() - 1;
|
||||
int in = pCore->getItemIn(m_ownerId);
|
||||
effect->filter().set("in", in);
|
||||
effect->filter().set("out", in + duration);
|
||||
@@ -590,10 +590,10 @@ bool EffectStackModel::adjustStackLength(bool adjustFromEnd, int oldIn, int oldD
|
||||
std::shared_ptr<EffectItemModel> effect = std::static_pointer_cast<EffectItemModel>(leaf);
|
||||
if (fadeInDuration > 0 && m_fadeIns.count(leaf->getId()) > 0) {
|
||||
// Adjust fade in
|
||||
int oldEffectIn = qMax(0, effect->filter().get_in());
|
||||
int oldEffectOut = effect->filter().get_out();
|
||||
int oldEffectIn = qMax(0, effect->getFilter().get_in());
|
||||
int oldEffectOut = effect->getFilter().get_out();
|
||||
qDebug() << "--previous effect: " << oldEffectIn << "-" << oldEffectOut;
|
||||
int effectDuration = qMin(effect->filter().get_length() - 1, duration);
|
||||
int effectDuration = qMin(effect->getFilter().get_length() - 1, duration);
|
||||
if (!adjustFromEnd && (oldIn != newIn || duration != oldDuration)) {
|
||||
// Clip start was resized, adjust effect in / out
|
||||
Fun operation = [effect, newIn, effectDuration, logUndo]() {
|
||||
@@ -687,7 +687,7 @@ bool EffectStackModel::adjustStackLength(bool adjustFromEnd, int oldIn, int oldD
|
||||
qDebug() << "// NULL Keyframes---------";
|
||||
}
|
||||
if (m_ownerId.type == ObjectType::TimelineTrack && !hasZone) {
|
||||
int oldEffectOut = effect->filter().get_out();
|
||||
int oldEffectOut = effect->getFilter().get_out();
|
||||
Fun operation = [effect, out, logUndo]() {
|
||||
effect->setParameter(QStringLiteral("out"), out, logUndo);
|
||||
return true;
|
||||
@@ -705,12 +705,12 @@ bool EffectStackModel::adjustStackLength(bool adjustFromEnd, int oldIn, int oldD
|
||||
PUSH_LAMBDA(reverse, undo);
|
||||
}
|
||||
} else if (m_ownerId.type == ObjectType::TimelineClip && effect->data(QModelIndex(), AssetParameterModel::RequiresInOut).toBool() == true) {
|
||||
int oldEffectIn = qMax(0, effect->filter().get_in());
|
||||
int oldEffectOut = effect->filter().get_out();
|
||||
int oldEffectIn = qMax(0, effect->getFilter().get_in());
|
||||
int oldEffectOut = effect->getFilter().get_out();
|
||||
int newIn = pCore->getItemIn(m_ownerId);
|
||||
int newOut = newIn + pCore->getItemDuration(m_ownerId) - 1;
|
||||
Fun operation = [effect, newIn, newOut]() {
|
||||
effect->filter().set_in_and_out(newIn, newOut);
|
||||
effect->getFilter().set_in_and_out(newIn, newOut);
|
||||
qDebug() << "--new effect: " << newIn << "-" << newOut;
|
||||
return true;
|
||||
};
|
||||
@@ -719,7 +719,7 @@ bool EffectStackModel::adjustStackLength(bool adjustFromEnd, int oldIn, int oldD
|
||||
return false;
|
||||
}
|
||||
Fun reverse = [effect, oldEffectIn, oldEffectOut]() {
|
||||
effect->filter().set_in_and_out(oldEffectIn, oldEffectOut);
|
||||
effect->getFilter().set_in_and_out(oldEffectIn, oldEffectOut);
|
||||
return true;
|
||||
};
|
||||
PUSH_LAMBDA(operation, redo);
|
||||
@@ -754,7 +754,7 @@ bool EffectStackModel::adjustFadeLength(int duration, bool fromStart, bool audio
|
||||
if (m_fadeIns.count(std::static_pointer_cast<TreeItem>(rootItem->child(i))->getId()) > 0) {
|
||||
std::shared_ptr<EffectItemModel> effect = std::static_pointer_cast<EffectItemModel>(rootItem->child(i));
|
||||
if (oldDuration == -1) {
|
||||
oldDuration = effect->filter().get_length();
|
||||
oldDuration = effect->getFilter().get_length();
|
||||
}
|
||||
effect->filter().set("in", in);
|
||||
duration = qMin(pCore->getItemDuration(m_ownerId), duration);
|
||||
@@ -803,7 +803,7 @@ bool EffectStackModel::adjustFadeLength(int duration, bool fromStart, bool audio
|
||||
if (m_fadeOuts.count(std::static_pointer_cast<TreeItem>(rootItem->child(i))->getId()) > 0) {
|
||||
std::shared_ptr<EffectItemModel> effect = std::static_pointer_cast<EffectItemModel>(rootItem->child(i));
|
||||
if (oldDuration == -1) {
|
||||
oldDuration = effect->filter().get_length();
|
||||
oldDuration = effect->getFilter().get_length();
|
||||
}
|
||||
effect->filter().set("out", out);
|
||||
duration = qMin(itemDuration, duration);
|
||||
@@ -843,7 +843,7 @@ int EffectStackModel::getFadePosition(bool fromStart)
|
||||
for (int i = 0; i < rootItem->childCount(); ++i) {
|
||||
if (*(m_fadeIns.begin()) == std::static_pointer_cast<TreeItem>(rootItem->child(i))->getId()) {
|
||||
std::shared_ptr<EffectItemModel> effect = std::static_pointer_cast<EffectItemModel>(rootItem->child(i));
|
||||
return effect->filter().get_length() - 1;
|
||||
return effect->getFilter().get_length() - 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -853,7 +853,7 @@ int EffectStackModel::getFadePosition(bool fromStart)
|
||||
for (int i = 0; i < rootItem->childCount(); ++i) {
|
||||
if (*(m_fadeOuts.begin()) == std::static_pointer_cast<TreeItem>(rootItem->child(i))->getId()) {
|
||||
std::shared_ptr<EffectItemModel> effect = std::static_pointer_cast<EffectItemModel>(rootItem->child(i));
|
||||
return effect->filter().get_length() - 1;
|
||||
return effect->getFilter().get_length() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -908,7 +908,7 @@ void EffectStackModel::registerItem(const std::shared_ptr<TreeItem> &item)
|
||||
if (effectItem->data(QModelIndex(), AssetParameterModel::RequiresInOut).toBool() == true) {
|
||||
int in = pCore->getItemIn(m_ownerId);
|
||||
int out = in + pCore->getItemDuration(m_ownerId) - 1;
|
||||
effectItem->filter().set_in_and_out(in, out);
|
||||
effectItem->getFilter().set_in_and_out(in, out);
|
||||
}
|
||||
if (!m_loadingExisting) {
|
||||
// qDebug() << "$$$$$$$$$$$$$$$$$$$$$ Planting effect in " << m_childServices.size();
|
||||
@@ -1078,7 +1078,7 @@ void EffectStackModel::importEffects(const std::weak_ptr<Mlt::Service> &service,
|
||||
effect = EffectItemModel::construct(std::move(filter), shared_from_this(), originalDecimalPoint);
|
||||
} else {
|
||||
// duplicate effect
|
||||
std::unique_ptr<Mlt::Filter> asset = EffectsRepository::get()->getEffect(effectId);
|
||||
std::unique_ptr<Mlt::Properties> asset = EffectsRepository::get()->getEffect(effectId);
|
||||
asset->inherit(*(filter));
|
||||
effect = EffectItemModel::construct(std::move(asset), shared_from_this(), originalDecimalPoint);
|
||||
}
|
||||
@@ -1109,7 +1109,7 @@ void EffectStackModel::importEffects(const std::weak_ptr<Mlt::Service> &service,
|
||||
m_fadeIns.insert(effect->getId());
|
||||
if (effect->filter().get_int("in") != clipIn) {
|
||||
// Broken fade, fix
|
||||
int filterLength = effect->filter().get_length() - 1;
|
||||
int filterLength = effect->getFilter().get_length() - 1;
|
||||
effect->filter().set("in", clipIn);
|
||||
effect->filter().set("out", clipIn + filterLength);
|
||||
}
|
||||
@@ -1117,7 +1117,7 @@ void EffectStackModel::importEffects(const std::weak_ptr<Mlt::Service> &service,
|
||||
m_fadeOuts.insert(effect->getId());
|
||||
if (effect->filter().get_int("out") != clipOut) {
|
||||
// Broken fade, fix
|
||||
int filterLength = effect->filter().get_length() - 1;
|
||||
int filterLength = effect->getFilter().get_length() - 1;
|
||||
effect->filter().set("in", clipOut - filterLength);
|
||||
effect->filter().set("out", clipOut);
|
||||
}
|
||||
|
||||
@@ -44,8 +44,7 @@ ClipStabilize::ClipStabilize(const std::vector<QString> &binIds, QString filterN
|
||||
if (m_filtername == QLatin1String("vidstab")) {
|
||||
m_view = std::make_unique<AssetParameterView>(this);
|
||||
qDebug() << "// Fetching effect: " << m_filtername;
|
||||
std::unique_ptr<Mlt::Filter> asset = EffectsRepository::get()->getEffect(m_filtername);
|
||||
auto prop = std::make_unique<Mlt::Properties>(asset->get_properties());
|
||||
std::unique_ptr<Mlt::Properties> prop = EffectsRepository::get()->getEffect(m_filtername);
|
||||
QDomElement xml = EffectsRepository::get()->getXml(m_filtername);
|
||||
m_assetModel.reset(new AssetParameterModel(std::move(prop), xml, m_filtername, ObjectId()));
|
||||
QDir dir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/effects/presets/"));
|
||||
|
||||
Reference in New Issue
Block a user