Introduce MLT clip analysis, can now be used for getting auto normalize data in sox gain effect

parent 175a3d51
......@@ -3,7 +3,10 @@
<name>Sox Gain</name>
<description>Sox gain audio effect</description>
<author>http://sox.sourceforge.net</author>
<parameter type="constant" name="gain" max="50" min="-50" default="5">
<parameter type="double" name="gain" max="50" min="-50" default="5.00" decimals="2">
<name>Gain</name>
</parameter>
<parameter type="filterjob" filtertag="sox:analysis" filterparams="" consumer="null" consumerparams="video_off=1 all=1" wantedproperties="gain" finalfilter="sox_gain">
<name>Normalize</name>
</parameter>
</effect>
......@@ -1896,7 +1896,7 @@ void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement insertedE
return;
}
QDomElement effect = insertedEffect.cloneNode().toElement();
//kDebug() << "// update effect ix: " << effect.attribute("kdenlive_ix")<<", TRACK: "<<track;
//kDebug() << "// update effect ix: " << effect.attribute("kdenlive_ix")<<", GAIN: "<<EffectsList::parameter(effect, "gain");
if (pos < GenTime()) {
// editing a track effect
EffectsParameterList effectParams = getEffectArgs(effect);
......@@ -1964,6 +1964,7 @@ void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement insertedE
emit clipItemSelected(clip, ix);
}
}
else emit displayMessage(i18n("Cannot find clip to update effect"), ErrorMessage);
setDocumentModified();
}
......@@ -6748,3 +6749,28 @@ void CustomTrackView::adjustEffects(ClipItem* item, ItemInfo oldInfo, QUndoComma
}
void CustomTrackView::slotGotFilterJobResults(const QString &id, int startPos, int track, const QString &filter, stringMap filterParams)
{
ClipItem *clip = getClipItemAt(GenTime(startPos, m_document->fps()), track);
if (clip == NULL) {
emit displayMessage(i18n("Cannot find clip for effect update %1.", filter), ErrorMessage);
return;
}
QDomElement newEffect;
QDomElement effect = clip->getEffectAt(clip->selectedEffectIndex());
if (effect.attribute("id") == filter) {
newEffect = effect.cloneNode().toElement();
QMap<QString, QString>::const_iterator i = filterParams.constBegin();
while (i != filterParams.constEnd()) {
EffectsList::setParameter(newEffect, i.key(), i.value());
kDebug()<<"// RESULT FILTER: "<<i.key()<<"="<< i.value();
++i;
}
EditEffectCommand *command = new EditEffectCommand(this, m_document->tracksCount() - clip->track(), clip->startPos(), effect, newEffect, clip->selectedEffectIndex(), true);
m_commandStack->push(command);
emit clipItemSelected(clip, clip->selectedEffectIndex());
}
}
......@@ -451,6 +451,8 @@ private slots:
* @param id The clip's Id string.
* @param resetThumbs Should we recreate the timeline thumbnails. */
void slotRefreshThumbs(const QString &id, bool resetThumbs);
/** @brief A Filter job producer results. */
void slotGotFilterJobResults(const QString &id, int startPos, int track, const QString &filter, stringMap filterParams);
signals:
void cursorMoved(int, int);
......
......@@ -910,7 +910,7 @@ void EffectStackEdit::slotStartFilterJobAction()
QDomElement pa = namenode.item(i).toElement();
QString type = pa.attribute("type");
if (type == "filterjob") {
emit startFilterJob(pa.attribute("filtertag"), pa.attribute("filterparams"), pa.attribute("consumer"), pa.attribute("consumerparams"), pa.attribute("wantedproperties"));
emit startFilterJob(pa.attribute("filtertag"), pa.attribute("filterparams"), pa.attribute("finalfilter"), pa.attribute("consumer"), pa.attribute("consumerparams"), pa.attribute("wantedproperties"));
kDebug()<<" - - -PROPS:\n"<<pa.attribute("filtertag")<<"-"<< pa.attribute("filterparams")<<"-"<< pa.attribute("consumer")<<"-"<< pa.attribute("consumerparams")<<"-"<< pa.attribute("wantedproperties");
break;
}
......
......@@ -109,7 +109,7 @@ signals:
void showComments(bool show);
void effectStateChanged(bool enabled);
/** @brief Start an MLT filter job on this clip. */
void startFilterJob(const QString &filterName, const QString &filterParams, const QString &consumer, const QString &consumerParams, const QString &properties);
void startFilterJob(const QString &filterName, const QString &filterParams, const QString &finalFilterName, const QString &consumer, const QString &consumerParams, const QString &properties);
};
#endif
......@@ -92,10 +92,11 @@ EffectStackView::EffectStackView(Monitor *monitor, QWidget *parent) :
connect(m_ui.checkAll, SIGNAL(stateChanged(int)), this, SLOT(slotCheckAll(int)));
connect(m_ui.buttonShowComments, SIGNAL(clicked()), this, SLOT(slotShowComments()));
connect(m_effectedit, SIGNAL(parameterChanged(const QDomElement &, const QDomElement &)), this , SLOT(slotUpdateEffectParams(const QDomElement &, const QDomElement &)));
connect(m_effectedit, SIGNAL(startFilterJob(QString,QString,QString,QString,QString)), this , SLOT(slotStartFilterJob(QString,QString,QString,QString,QString)));
connect(m_effectedit, SIGNAL(startFilterJob(QString,QString,QString,QString,QString,QString)), this , SLOT(slotStartFilterJob(QString,QString,QString,QString,QString,QString)));
connect(m_effectedit, SIGNAL(seekTimeline(int)), this , SLOT(slotSeekTimeline(int)));
connect(m_effectedit, SIGNAL(displayMessage(const QString&, int)), this, SIGNAL(displayMessage(const QString&, int)));
connect(m_effectedit, SIGNAL(checkMonitorPosition(int)), this, SLOT(slotCheckMonitorPosition(int)));
connect(monitor, SIGNAL(renderPosition(int)), this, SLOT(slotRenderPos(int)));
connect(this, SIGNAL(showComments(bool)), m_effectedit, SIGNAL(showComments(bool)));
m_effectLists["audio"] = &MainWindow::audioEffects;
......@@ -529,10 +530,10 @@ void EffectStackView::slotShowComments()
emit showComments(m_ui.buttonShowComments->isChecked());
}
void EffectStackView::slotStartFilterJob(const QString&filterName, const QString&filterParams, const QString&consumer, const QString&consumerParams, const QString&properties)
void EffectStackView::slotStartFilterJob(const QString&filterName, const QString&filterParams, const QString&finalFilterName, const QString&consumer, const QString&consumerParams, const QString&properties)
{
if (!m_clipref) return;
emit startFilterJob(m_clipref->clipProducer(), filterName, filterParams, consumer, consumerParams, properties);
emit startFilterJob(m_clipref->info(), m_clipref->clipProducer(), filterName, filterParams, finalFilterName, consumer, consumerParams, properties);
}
#include "effectstackview.moc"
......@@ -143,7 +143,7 @@ private slots:
void slotShowComments();
/** @brief Triggers a filter job on this clip. */
void slotStartFilterJob(const QString&filterName, const QString&filterParams, const QString&consumer, const QString&consumerParams, const QString&properties);
void slotStartFilterJob(const QString&filterName, const QString&filterParams, const QString&finalFilterName, const QString&consumer, const QString&consumerParams, const QString&properties);
signals:
void removeEffect(ClipItem*, int, QDomElement);
......@@ -164,7 +164,7 @@ signals:
void updateClipRegion(ClipItem*, int, QString);
void displayMessage(const QString&, int);
void showComments(bool show);
void startFilterJob(const QString &clipId, const QString &filterName, const QString &filterParams, const QString &consumer, const QString &consumerParams, const QString &properties);
void startFilterJob(ItemInfo info, const QString &clipId, const QString &filterName, const QString &filterParams, const QString&finalFilterName, const QString &consumer, const QString &consumerParams, const QString &properties);
};
#endif
......@@ -269,7 +269,7 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
m_effectStack = new EffectStackView(m_projectMonitor);
m_effectStackDock->setWidget(m_effectStack);
addDockWidget(Qt::TopDockWidgetArea, m_effectStackDock);
connect(m_effectStack, SIGNAL(startFilterJob(const QString&,const QString&,const QString&,const QString&,const QString&,const QString&)), m_projectList, SLOT(slotStartFilterJob(const QString&,const QString&,const QString&,const QString&,const QString&,const QString&)));
connect(m_effectStack, SIGNAL(startFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QString&)), m_projectList, SLOT(slotStartFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QString&)));
m_transitionConfigDock = new QDockWidget(i18n("Transition"), this);
m_transitionConfigDock->setObjectName("transition");
......@@ -2488,6 +2488,8 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha
disconnect(m_activeTimeline->projectView(), SIGNAL(playMonitor()), m_projectMonitor, SLOT(slotPlay()));
disconnect(m_activeTimeline->projectView(), SIGNAL(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType)));
disconnect(m_activeTimeline->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, bool, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, bool, const int)));
disconnect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap)), m_activeTimeline->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap)));
disconnect(m_activeTimeline, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(activateMonitor()));
disconnect(m_activeTimeline, SIGNAL(insertTrack(int)), this, SLOT(slotInsertTrack(int)));
disconnect(m_activeTimeline, SIGNAL(deleteTrack(int)), this, SLOT(slotDeleteTrack(int)));
......@@ -2568,6 +2570,8 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) //cha
connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(ClipItem*)));
connect(trackView->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(Transition*)));
connect(m_projectList, SIGNAL(gotFilterJobResults(const QString &, int, int, const QString &, stringMap)), trackView->projectView(), SLOT(slotGotFilterJobResults(const QString &, int, int, const QString &, stringMap)));
connect(m_effectStack, SIGNAL(updateEffect(ClipItem*, int, QDomElement, QDomElement, int)), trackView->projectView(), SLOT(slotUpdateClipEffect(ClipItem*, int, QDomElement, QDomElement, int)));
connect(m_effectStack, SIGNAL(updateClipRegion(ClipItem*, int, QString)), trackView->projectView(), SLOT(slotUpdateClipRegion(ClipItem*, int, QString)));
......
......@@ -2832,6 +2832,7 @@ void ProjectList::slotProcessJobs()
}
connect(job, SIGNAL(jobProgress(QString, int, int)), this, SIGNAL(processLog(QString, int, int)));
connect(job, SIGNAL(cancelRunningJob(const QString, stringMap)), this, SIGNAL(cancelRunningJob(const QString, stringMap)));
connect(job, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap)), this, SIGNAL(gotFilterJobResults(QString,int, int, QString,stringMap)));
if (job->jobType == MLTJOB) {
MeltJob *jb = static_cast<MeltJob *> (job);
......@@ -3247,13 +3248,13 @@ void ProjectList::discardJobs(const QString &id, JOBTYPE type) {
}
}
void ProjectList::slotStartFilterJob(const QString&id, const QString&filterName, const QString&filterParams, const QString&consumer, const QString&consumerParams, const QString&properties)
void ProjectList::slotStartFilterJob(ItemInfo info, const QString&id, const QString&filterName, const QString&filterParams, const QString&finalFilterName, const QString&consumer, const QString&consumerParams, const QString&properties)
{
ProjectItem *item = getItemById(id);
if (!item) return;
QStringList jobParams;
jobParams << filterName << filterParams << consumer << consumerParams << properties;
kDebug()<<"// STARTING JOB: "<<jobParams;
jobParams << QString::number(info.cropStart.frames(m_fps)) << QString::number((info.cropStart + info.cropDuration).frames(m_fps));
jobParams << filterName << filterParams << consumer << consumerParams << properties << QString::number(info.startPos.frames(m_fps)) << QString::number(info.track) << finalFilterName;
MeltJob *job = new MeltJob(item->clipType(), id, jobParams);
if (job->isExclusive() && hasPendingJob(item, job->jobType)) {
delete job;
......
......@@ -303,7 +303,7 @@ public slots:
void slotCutClipJob(const QString &id, QPoint zone);
void slotTranscodeClipJob(QStringList ids, QString params, QString desc);
/** @brief Start an MLT process job. */
void slotStartFilterJob(const QString&,const QString&,const QString&,const QString&,const QString&,const QString&);
void slotStartFilterJob(ItemInfo, const QString&,const QString&,const QString&,const QString&,const QString&,const QString&,const QString&);
private:
ProjectListView *m_listView;
......@@ -483,6 +483,8 @@ signals:
void updateJobStatus(const QString, int, int, const QString &label = QString(), const QString &actionName = QString(), const QString details = QString());
void gotProxy(const QString);
void checkJobProcess();
/** @brief A Filter Job produced results, send them back to the clip. */
void gotFilterJobResults(const QString &id, int startPos, int track, const QString &filterName, stringMap params);
};
#endif
......
......@@ -59,6 +59,7 @@ protected:
signals:
void jobProgress(QString, int, int);
void cancelRunningJob(const QString, stringMap);
void gotFilterJobResults(const QString &id, int startPos, int track, const QString &filterName, stringMap params);
};
......
......@@ -57,11 +57,25 @@ void MeltJob::startJob()
setStatus(JOBCRASHED);
return;
}
int in = m_params.takeFirst().toInt();
int out = m_params.takeFirst().toInt();
QString filter = m_params.takeFirst();
QString filterParams = m_params.takeFirst();
QString consumer = m_params.takeFirst();
QString consumerParams = m_params.takeFirst();
QString properties = m_params.takeFirst();
int startPos = m_params.takeFirst().toInt();
int track = m_params.takeFirst().toInt();
QString finalFilter;
if (!m_params.isEmpty()) finalFilter = m_params.takeFirst();
else finalFilter = filter;
if (out <= in) {
m_errorMessage.append(i18n("Clip zone undefined (%1 - %2).", in, out));
setStatus(JOBCRASHED);
return;
}
Mlt::Producer *prod = m_producer->cut(in, out);
m_profile = m_producer->profile();
m_consumer = new Mlt::Consumer(*m_profile, consumer.toUtf8().constData());
if (!m_consumer || !m_consumer->is_valid()) {
......@@ -88,25 +102,29 @@ void MeltJob::startJob()
mltFilter.set(data.section('=', 0, 0).toUtf8().constData(), data.section('=', 1, 1).toUtf8().constData());
}
}
m_producer->attach(mltFilter);
m_length = m_producer->get_length();
m_consumer->connect(*m_producer);
m_producer->set_speed(0);
m_producer->seek(0);
prod->attach(mltFilter);
m_length = prod->get_length();
m_consumer->connect(*prod);
prod->set_speed(0);
prod->seek(0);
m_showFrameEvent = m_consumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_render);
m_consumer->start();
m_producer->set_speed(1);
prod->set_speed(1);
while (jobStatus != JOBABORTED && !m_consumer->is_stopped()) {
}
m_consumer->stop();
QStringList wanted = properties.split(',', QString::SkipEmptyParts);
stringMap jobResults;
foreach(const QString key, wanted) {
QString value = mltFilter.get(key.toUtf8().constData());
jobResults.insert(key, value);
kDebug()<<"RESULT: "<<key<<" = "<< value;
}
if (!jobResults.isEmpty()) emit gotFilterJobResults(m_clipId, startPos, track, finalFilter, jobResults);
setStatus(JOBDONE);
delete m_consumer;
delete prod;
return;
}
......
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