aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Baptiste Mardelle <[email protected]>2015-07-23 14:44:29 +0200
committerJean-Baptiste Mardelle <[email protected]>2015-07-26 15:40:18 +0200
commit25ce7a7bc0047383ad97fde5d319af230d74e9d8 (patch)
treedbd6c0b3b2e4697b12e6d6b6c7f863e02f6975d3
parent95d8a82d81570663725a03252f3960cc2be602d2 (diff)
Various fixes to slowmotion, and remove dev stuff for beta release
-rw-r--r--src/bin/projectclip.cpp2
-rw-r--r--src/doc/documentchecker.cpp3
-rw-r--r--src/doc/kdenlivedoc.cpp7
-rw-r--r--src/mltcontroller/clipcontroller.cpp3
-rw-r--r--src/mltcontroller/clipcontroller.h6
-rw-r--r--src/mltcontroller/clippropertiescontroller.cpp8
-rw-r--r--src/monitor/glwidget.cpp2
-rw-r--r--src/project/projectmanager.cpp1
-rw-r--r--src/renderer.cpp279
-rw-r--r--src/renderer.h14
-rw-r--r--src/timeline/customtrackview.cpp4
-rw-r--r--src/timeline/timeline.cpp25
-rw-r--r--src/timeline/timeline.h1
-rw-r--r--src/timeline/track.cpp194
-rw-r--r--src/timeline/track.h10
15 files changed, 267 insertions, 292 deletions
diff --git a/src/bin/projectclip.cpp b/src/bin/projectclip.cpp
index 890794f..7ef966c 100644
--- a/src/bin/projectclip.cpp
+++ b/src/bin/projectclip.cpp
@@ -484,7 +484,7 @@ void ProjectClip::setProperties(QMap <QString, QString> properties, bool refresh
bool reload = false;
// Some properties also need to be passed to track producers
QStringList timelineProperties;
- timelineProperties << "force_aspect_ratio" << "video_index" << "audio_index" << "full_luma" <<"threads" <<"force_colorspace"<<"force_tff"<<"force_progressive"<<"force_fps";
+ timelineProperties << "force_aspect_ratio" << "video_index" << "audio_index" << "set.force_full_luma"<< "full_luma" <<"threads" <<"force_colorspace"<<"force_tff"<<"force_progressive"<<"force_fps";
QStringList keys;
keys << "luma_duration" << "luma_file" << "fade" << "ttl" << "softness" << "crop" << "animation";
while (i.hasNext()) {
diff --git a/src/doc/documentchecker.cpp b/src/doc/documentchecker.cpp
index 1623928..db73c09 100644
--- a/src/doc/documentchecker.cpp
+++ b/src/doc/documentchecker.cpp
@@ -106,7 +106,6 @@ bool DocumentChecker::hasErrorInClips()
// Don't check same url twice (for example track producers)
continue;
}
- qDebug()<<" / / /Checking resource: "<<resource;
if (e.hasAttribute("proxy")) {
QString proxyresource = e.attribute("proxy");
if (!proxyresource.isEmpty() && proxyresource != "-") {
@@ -176,7 +175,7 @@ bool DocumentChecker::hasErrorInClips()
e = m_missingClips.at(i).toElement();
QString clipType;
QString service = EffectsList::property(e, "mlt_service");
- if (service == "avformat" || service == "avformat-novalidate") {
+ if (service == "avformat" || service == "avformat-novalidate" || service == "framebuffer") {
clipType = i18n("Video clip");
} else if (service == "qimage" || service == "pixbuf") {
clipType = i18n("Image clip");
diff --git a/src/doc/kdenlivedoc.cpp b/src/doc/kdenlivedoc.cpp
index e089faf..9eb2634 100644
--- a/src/doc/kdenlivedoc.cpp
+++ b/src/doc/kdenlivedoc.cpp
@@ -1652,7 +1652,12 @@ void KdenliveDoc::loadDocumentProperties()
}
}
}
- m_projectFolder = QUrl::fromLocalFile(m_documentProperties.value("projectfolder"));
+ QString path = m_documentProperties.value("projectfolder");
+ if (!path.startsWith('/')) {
+ QDir dir = QDir::home();
+ path = dir.absoluteFilePath(path);
+ }
+ m_projectFolder = QUrl::fromLocalFile(path);
list = m_document.elementsByTagName("profile");
if (!list.isEmpty()) {
m_profile = ProfilesDialog::getVideoProfileFromXml(list.at(0).toElement());
diff --git a/src/mltcontroller/clipcontroller.cpp b/src/mltcontroller/clipcontroller.cpp
index 7941935..fff24e9 100644
--- a/src/mltcontroller/clipcontroller.cpp
+++ b/src/mltcontroller/clipcontroller.cpp
@@ -192,7 +192,8 @@ const QString ClipController::clipId()
return property("id");
}
-const char *ClipController::getPassPropertiesList() const
+// static
+const char *ClipController::getPassPropertiesList()
{
return "kdenlive:proxy,kdenlive:originalurl,force_aspect_num,force_aspect_den,force_aspect_ratio,force_fps,force_progressive,force_tff,threads,force_colorspace,set.force_full_luma,templatetext,file_hash";
}
diff --git a/src/mltcontroller/clipcontroller.h b/src/mltcontroller/clipcontroller.h
index 10ac336..f3fba35 100644
--- a/src/mltcontroller/clipcontroller.h
+++ b/src/mltcontroller/clipcontroller.h
@@ -179,6 +179,9 @@ public:
/** @brief Returns true if audio thumbnails for this clip are cached */
bool audioThumbCreated;
Mlt::Profile *profile();
+ /** @brief When replacing a producer, it is important that we keep some properties, for exemple force_ stuff and url for proxies
+ * this method returns a list of properties that we want to keep when replacing a producer . */
+ static const char *getPassPropertiesList();
private:
Mlt::Producer *m_masterProducer;
@@ -194,9 +197,6 @@ private:
BinController *m_binController;
/** @brief A list of snap markers; these markers are added to a clips snap-to points, and are displayed as necessary. */
QList < CommentedTime > m_snapMarkers;
- /** @brief When replacing a producer, it is important that we keep some properties, for exemple force_ stuff and url for proxies
- * this method returns a list of properties that we want to keep when replacing a producer . */
- const char *getPassPropertiesList() const;
void getInfoForProducer();
void rebuildEffectList();
};
diff --git a/src/mltcontroller/clippropertiescontroller.cpp b/src/mltcontroller/clippropertiescontroller.cpp
index 80529cc..28634e4 100644
--- a/src/mltcontroller/clippropertiescontroller.cpp
+++ b/src/mltcontroller/clippropertiescontroller.cpp
@@ -371,12 +371,12 @@ ClipPropertiesController::ClipPropertiesController(Timecode tc, ClipController *
vbox->addLayout(hlay);
//Full luma
- QString force_luma = m_properties.get("full_luma");
- m_originalProperties.insert("full_luma", force_luma);
+ QString force_luma = m_properties.get("set.force_full_luma");
+ m_originalProperties.insert("set.force_full_luma", force_luma);
hlay = new QHBoxLayout;
box = new QCheckBox(i18n("Full luma range"), this);
connect(box, SIGNAL(stateChanged(int)), this, SLOT(slotEnableForce(int)));
- box->setObjectName("full_luma");
+ box->setObjectName("set.force_full_luma");
box->setChecked(!force_luma.isEmpty());
hlay->addWidget(box);
vbox->addLayout(hlay);
@@ -498,7 +498,7 @@ void ClipPropertiesController::slotEnableForce(int state)
if (!combo) return;
properties.insert(param, QString::number(combo->currentData().toInt()));
}
- else if (param == "kdenlive:transparency" || param == "full_luma") {
+ else if (param == "kdenlive:transparency" || param == "set.force_full_luma") {
properties.insert(param, "1");
}
else if (param == "force_ar") {
diff --git a/src/monitor/glwidget.cpp b/src/monitor/glwidget.cpp
index 7747230..16751dc 100644
--- a/src/monitor/glwidget.cpp
+++ b/src/monitor/glwidget.cpp
@@ -819,7 +819,7 @@ void GLWidget::resetProfile(MltVideoProfile profile)
m_consumer->stop();
m_consumer->purge();
}
- //m_monitorProfile->get_profile()->description = profile.description.toUtf8().data();
+ m_monitorProfile->get_profile()->description = qstrdup(profile.description.toUtf8().constData());
m_monitorProfile->set_colorspace(profile.colorspace);
m_monitorProfile->set_frame_rate(profile.frame_rate_num, profile.frame_rate_den);
m_monitorProfile->set_height(profile.height);
diff --git a/src/project/projectmanager.cpp b/src/project/projectmanager.cpp
index 6795302..af5cd39 100644
--- a/src/project/projectmanager.cpp
+++ b/src/project/projectmanager.cpp
@@ -281,7 +281,6 @@ bool ProjectManager::saveFile()
qDebug()<<"SaveFile called without project";
return false;
}
- KMessageBox::information(pCore->window(), "Warning, development version for testing only. we are currently working on core functionnalities,\ndo not save any project or your project files might be corrupted.");
if (m_project->url().isEmpty()) {
return saveFileAs();
} else {
diff --git a/src/renderer.cpp b/src/renderer.cpp
index 08309b1..99beacd 100644
--- a/src/renderer.cpp
+++ b/src/renderer.cpp
@@ -1203,7 +1203,6 @@ int Render::setSceneList(const QDomDocument &list, int position)
int Render::setSceneList(QString playlist, int position)
{
- //qDebug() << "////// RENDER, SET SCENE LIST:\n" << playlist <<"\n..........:::.";
requestedSeekPosition = SEEK_INACTIVE;
m_refreshTimer.stop();
QMutexLocker locker(&m_mutex);
@@ -1301,6 +1300,7 @@ int Render::setSceneList(QString playlist, int position)
}
blockSignals(false);
Mlt::Tractor tractor(service);
+ qDebug()<<"****************************** BUILDING PLAYLIST ***********************";
Mlt::Properties retainList((mlt_properties) tractor.get_data("xml_retain"));
if (retainList.is_valid() && retainList.get_data(m_binController->binPlaylistId().toUtf8().constData())) {
Mlt::Playlist playlist((mlt_playlist) retainList.get_data(m_binController->binPlaylistId().toUtf8().constData()));
@@ -2001,30 +2001,6 @@ void Render::mltCheckLength(Mlt::Tractor *tractor)
}
}
-Mlt::Producer *Render::checkSlowMotionProducer(Mlt::Producer *prod, QDomElement element)
-{
- if (element.attribute("speed", "1.0").toDouble() == 1.0 && element.attribute("strobe", "1").toInt() == 1) return prod;
- QLocale locale;
- locale.setNumberOptions(QLocale::OmitGroupSeparator);
- // We want a slowmotion producer
- double speed = element.attribute("speed", "1.0").toDouble();
- int strobe = element.attribute("strobe", "1").toInt();
- QString url = QString::fromUtf8(prod->get("resource"));
- url.append('?' + locale.toString(speed));
- if (strobe > 1) url.append("&strobe=" + QString::number(strobe));
- Mlt::Producer *slowprod = m_slowmotionProducers.value(url);
- if (!slowprod || slowprod->get_producer() == NULL) {
- slowprod = new Mlt::Producer(*m_qmlView->profile(), 0, ("framebuffer:" + url).toUtf8().constData());
- if (strobe > 1) slowprod->set("strobe", strobe);
- QString id = prod->parent().get("id");
- if (id.contains('_')) id = id.section('_', 0, 0);
- QString producerid = "slowmotion:" + id + ':' + locale.toString(speed);
- if (strobe > 1) producerid.append(':' + QString::number(strobe));
- slowprod->set("id", producerid.toUtf8().constData());
- m_slowmotionProducers.insert(url, slowprod);
- }
- return slowprod;
-}
int Render::mltInsertClip(ItemInfo info, const QString &clipId, bool overwrite, bool push)
{
@@ -2230,55 +2206,6 @@ void Render::unlockService(Mlt::Tractor *tractor)
service.unlock();
}
-bool Render::mltUpdateClip(Mlt::Tractor *tractor, ItemInfo info, QDomElement element, Mlt::Producer *prod)
-{
- // TODO: optimize
- if (prod == NULL || tractor == NULL) {
- //qDebug() << "Cannot update clip with null producer //////";
- return false;
- }
-
- Mlt::Producer trackProducer(tractor->track(tractor->count() - 1 - info.track));
- Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
- int startPos = info.startPos.frames(m_fps);
- int clipIndex = trackPlaylist.get_clip_index_at(startPos);
- if (trackPlaylist.is_blank(clipIndex)) {
- //qDebug() << "// WARNING, TRYING TO REMOVE A BLANK: " << startPos;
- return false;
- }
- Mlt::Producer *clip = trackPlaylist.get_clip(clipIndex);
- // keep effects
- QList <Mlt::Filter *> filtersList;
- Mlt::Service sourceService(clip->get_service());
- int ct = 0;
- Mlt::Filter *filter = sourceService.filter(ct);
- while (filter) {
- if (filter->get_int("kdenlive_ix") != 0) {
- filtersList.append(filter);
- }
- ct++;
- filter = sourceService.filter(ct);
- }
- delete clip;
- clip = trackPlaylist.replace_with_blank(clipIndex);
- delete clip;
- prod = checkSlowMotionProducer(prod, element);
- if (prod == NULL || !prod->is_valid()) {
- return false;
- }
-
- Mlt::Producer *clip2 = prod->cut(info.cropStart.frames(m_fps), (info.cropDuration + info.cropStart).frames(m_fps) - 1);
- trackPlaylist.insert_at(info.startPos.frames(m_fps), clip2, 1);
- Mlt::Service destService(clip2->get_service());
- delete clip2;
-
- if (!filtersList.isEmpty()) {
- for (int i = 0; i < filtersList.count(); ++i)
- destService.attach(*(filtersList.at(i)));
- }
- qDeleteAll(filtersList);
- return true;
-}
int Render::mltGetSpaceLength(const GenTime &pos, int track, bool fromBlankStart)
{
@@ -2485,195 +2412,6 @@ void Render::mltPasteEffects(Mlt::Producer *source, Mlt::Producer *dest)
}
}
-int Render::mltChangeClipSpeed(ItemInfo info, ItemInfo speedIndependantInfo, double speed, double /*oldspeed*/, int strobe, Mlt::Producer *prod)
-{
- int newLength = 0;
- Mlt::Service service(m_mltProducer->parent().get_service());
- if (service.type() != tractor_type) {
- qWarning() << "// TRACTOR PROBLEM";
- return -1;
- }
-
- ////qDebug() << "Changing clip speed, set in and out: " << info.cropStart.frames(m_fps) << " to " << (info.endPos - info.startPos).frames(m_fps) - 1;
- Mlt::Tractor tractor(service);
- Mlt::Producer trackProducer(tractor.track(tractor.count() - info.track - 1));
- Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
- int startPos = info.startPos.frames(m_fps);
- int clipIndex = trackPlaylist.get_clip_index_at(startPos);
- int clipLength = trackPlaylist.clip_length(clipIndex);
-
- Mlt::Producer *original = trackPlaylist.get_clip(clipIndex);
- if (original == NULL) {
- qDebug()<<"// No clip to apply effect";
- return -1;
- }
- if (!original->is_valid() || original->is_blank()) {
- // invalid clip
- delete original;
- qDebug()<<"// Invalid clip to apply effect";
- return -1;
- }
- Mlt::Producer clipparent = original->parent();
- if (!clipparent.is_valid() || clipparent.is_blank()) {
- // invalid clip
- qDebug()<<"// Invalid parent to apply effect";
- delete original;
- return -1;
- }
-
- QString serv = clipparent.get("mlt_service");
- QString id = clipparent.get("id");
- id = id.section("_", 0, 0);
- if (speed <= 0 && speed > -1) speed = 1.0;
- //qDebug() << "SLOWMO CLIP SERVICE: " << serv;
- if ((serv == "avformat" || serv == "avformat-novalidate") && (speed != 1.0 || strobe > 1)) {
- service.lock();
- QString url = QString::fromUtf8(clipparent.get("resource"));
- url.append('?' + m_locale.toString(speed));
- if (strobe > 1) url.append("&strobe=" + QString::number(strobe));
- Mlt::Producer *slowprod = m_slowmotionProducers.value(url);
- if (!slowprod || slowprod->get_producer() == NULL) {
- slowprod = new Mlt::Producer(*m_qmlView->profile(), 0, ("framebuffer:" + url).toUtf8().constData());
- if (!slowprod->is_valid()) {
- qDebug()<<"++++ FAILED TO CREATE SLOWMO PROD";
- }
- if (strobe > 1) slowprod->set("strobe", strobe);
- QString producerid = "slowmotion:" + id + ':' + m_locale.toString(speed);
- if (strobe > 1) producerid.append(':' + QString::number(strobe));
- slowprod->set("id", producerid.toUtf8().constData());
- // copy producer props
- double ar = original->parent().get_double("force_aspect_ratio");
- if (ar != 0.0) slowprod->set("force_aspect_ratio", ar);
- double fps = original->parent().get_double("force_fps");
- if (fps != 0.0) slowprod->set("force_fps", fps);
- int threads = original->parent().get_int("threads");
- if (threads != 0) slowprod->set("threads", threads);
- if (original->parent().get("force_progressive"))
- slowprod->set("force_progressive", original->parent().get_int("force_progressive"));
- if (original->parent().get("force_tff"))
- slowprod->set("force_tff", original->parent().get_int("force_tff"));
- int ix = original->parent().get_int("video_index");
- if (ix != 0) slowprod->set("video_index", ix);
- int colorspace = original->parent().get_int("force_colorspace");
- if (colorspace != 0) slowprod->set("force_colorspace", colorspace);
- int full_luma = original->parent().get_int("set.force_full_luma");
- if (full_luma != 0) slowprod->set("set.force_full_luma", full_luma);
- m_slowmotionProducers.insert(url, slowprod);
- }
- Mlt::Producer *clip = trackPlaylist.replace_with_blank(clipIndex);
- trackPlaylist.consolidate_blanks(0);
-
- // Check that the blank space is long enough for our new duration
- clipIndex = trackPlaylist.get_clip_index_at(startPos);
- int blankEnd = trackPlaylist.clip_start(clipIndex) + trackPlaylist.clip_length(clipIndex);
- Mlt::Producer *cut;
- if (clipIndex + 1 < trackPlaylist.count() && (startPos + clipLength / speed > blankEnd)) {
- GenTime maxLength = GenTime(blankEnd, m_fps) - info.startPos;
- cut = slowprod->cut((int)(info.cropStart.frames(m_fps) / speed), (int)(info.cropStart.frames(m_fps) / speed + maxLength.frames(m_fps) - 1));
- } else cut = slowprod->cut((int)(info.cropStart.frames(m_fps) / speed), (int)((info.cropStart.frames(m_fps) + clipLength) / speed - 1));
-
- // move all effects to the correct producer
- mltPasteEffects(clip, cut);
- trackPlaylist.insert_at(startPos, cut, 1);
- delete cut;
- delete clip;
- clipIndex = trackPlaylist.get_clip_index_at(startPos);
- newLength = trackPlaylist.clip_length(clipIndex);
- service.unlock();
- } else if (speed == 1.0 && strobe < 2) {
- if (!prod || !prod->is_valid()) {
- qDebug()<<"// Something is wrong with original slowmo producer";
- return -1;
- }
- service.lock();
-
- Mlt::Producer *clip = trackPlaylist.replace_with_blank(clipIndex);
- trackPlaylist.consolidate_blanks(0);
-
- // Check that the blank space is long enough for our new duration
- clipIndex = trackPlaylist.get_clip_index_at(startPos);
- int blankEnd = trackPlaylist.clip_start(clipIndex) + trackPlaylist.clip_length(clipIndex);
-
- Mlt::Producer *cut;
- int originalStart = (int)(speedIndependantInfo.cropStart.frames(m_fps));
- if (clipIndex + 1 < trackPlaylist.count() && (info.startPos + speedIndependantInfo.cropDuration).frames(m_fps) > blankEnd) {
- GenTime maxLength = GenTime(blankEnd, m_fps) - info.startPos;
- cut = prod->cut(originalStart, (int)(originalStart + maxLength.frames(m_fps) - 1));
- } else cut = prod->cut(originalStart, (int)(originalStart + speedIndependantInfo.cropDuration.frames(m_fps)) - 1);
-
- // move all effects to the correct producer
- mltPasteEffects(clip, cut);
-
- trackPlaylist.insert_at(startPos, cut, 1);
- delete cut;
- delete clip;
- clipIndex = trackPlaylist.get_clip_index_at(startPos);
- newLength = trackPlaylist.clip_length(clipIndex);
- service.unlock();
-
- } else if (serv == "framebuffer") {
- service.lock();
- QString url = QString::fromUtf8(clipparent.get("resource"));
- url = url.section('?', 0, 0);
- url.append('?' + m_locale.toString(speed));
- if (strobe > 1) url.append("&strobe=" + QString::number(strobe));
- Mlt::Producer *slowprod = m_slowmotionProducers.value(url);
- if (!slowprod || slowprod->get_producer() == NULL) {
- slowprod = new Mlt::Producer(*m_qmlView->profile(), 0, ("framebuffer:" + url).toUtf8().constData());
- slowprod->set("strobe", strobe);
- QString producerid = "slowmotion:" + id.section(':', 1, 1) + ':' + m_locale.toString(speed);
- if (strobe > 1) producerid.append(':' + QString::number(strobe));
- slowprod->set("id", producerid.toUtf8().constData());
- // copy producer props
- double ar = original->parent().get_double("force_aspect_ratio");
- if (ar != 0.0) slowprod->set("force_aspect_ratio", ar);
- double fps = original->parent().get_double("force_fps");
- if (fps != 0.0) slowprod->set("force_fps", fps);
- if (original->parent().get("force_progressive"))
- slowprod->set("force_progressive", original->parent().get_int("force_progressive"));
- if (original->parent().get("force_tff"))
- slowprod->set("force_tff", original->parent().get_int("force_tff"));
- int threads = original->parent().get_int("threads");
- if (threads != 0) slowprod->set("threads", threads);
- int ix = original->parent().get_int("video_index");
- if (ix != 0) slowprod->set("video_index", ix);
- int colorspace = original->parent().get_int("force_colorspace");
- if (colorspace != 0) slowprod->set("force_colorspace", colorspace);
- int full_luma = original->parent().get_int("set.force_full_luma");
- if (full_luma != 0) slowprod->set("set.force_full_luma", full_luma);
- m_slowmotionProducers.insert(url, slowprod);
- }
- Mlt::Producer *clip = trackPlaylist.replace_with_blank(clipIndex);
- trackPlaylist.consolidate_blanks(0);
-
- GenTime duration = speedIndependantInfo.cropDuration / speed;
- int originalStart = (int)(speedIndependantInfo.cropStart.frames(m_fps) / speed);
-
- // Check that the blank space is long enough for our new duration
- clipIndex = trackPlaylist.get_clip_index_at(startPos);
- int blankEnd = trackPlaylist.clip_start(clipIndex) + trackPlaylist.clip_length(clipIndex);
-
- Mlt::Producer *cut;
- if (clipIndex + 1 < trackPlaylist.count() && (info.startPos + duration).frames(m_fps) > blankEnd) {
- GenTime maxLength = GenTime(blankEnd, m_fps) - info.startPos;
- cut = slowprod->cut(originalStart, (int)(originalStart + maxLength.frames(m_fps) - 1));
- } else cut = slowprod->cut(originalStart, (int)(originalStart + duration.frames(m_fps)) - 1);
-
- // move all effects to the correct producer
- mltPasteEffects(clip, cut);
-
- trackPlaylist.insert_at(startPos, cut, 1);
- delete cut;
- delete clip;
- clipIndex = trackPlaylist.get_clip_index_at(startPos);
- newLength = trackPlaylist.clip_length(clipIndex);
-
- service.unlock();
- }
- delete original;
- if (clipIndex + 1 == trackPlaylist.count()) mltCheckLength(&tractor);
- return newLength;
-}
bool Render::mltRemoveTrackEffect(int track, int index, bool updateIndex)
{
@@ -4489,3 +4227,18 @@ void Render::setVolume(double volume)
}
}
}
+
+void Render::storeSlowmotionProducer(const QString &url, Mlt::Producer *prod)
+{
+ if (!m_slowmotionProducers.contains(url)) {
+ m_slowmotionProducers.insert(url, prod);
+ }
+}
+
+Mlt::Producer *Render::getSlowmotionProducer(const QString &url)
+{
+ if (m_slowmotionProducers.contains(url)) {
+ return m_slowmotionProducers.value(url);
+ }
+ return NULL;
+}
diff --git a/src/renderer.h b/src/renderer.h
index b403d30..df8bf3f 100644
--- a/src/renderer.h
+++ b/src/renderer.h
@@ -201,9 +201,8 @@ class Render: public AbstractRender
* Playlist manipulation.
*/
void mltCheckLength(Mlt::Tractor *tractor);
- Mlt::Producer *checkSlowMotionProducer(Mlt::Producer *prod, QDomElement element);
+ Mlt::Producer *getSlowmotionProducer(const QString &url);
int mltInsertClip(ItemInfo info, const QString &clipId, bool overwrite = false, bool push = false);
- bool mltUpdateClip(Mlt::Tractor *tractor, ItemInfo info, QDomElement element, Mlt::Producer *prod);
void mltInsertSpace(QMap <int, int> trackClipStartList, QMap <int, int> trackTransitionStartList, int track, const GenTime &duration, const GenTime &timeOffset);
int mltGetSpaceLength(const GenTime &pos, int track, bool fromBlankStart);
@@ -264,16 +263,6 @@ class Render: public AbstractRender
void mltPlantTransition(Mlt::Field *field, Mlt::Transition &tr, int a_track, int b_track);
Mlt::Producer *invalidProducer(const QString &id);
- /** @brief Changes the speed of a clip in MLT's playlist.
- *
- * It creates a new "framebuffer" producer, which must have its "resource"
- * property set to "video.mpg?0.6", where "video.mpg" is the path to the
- * clip and "0.6" is the speed in percentage. The newly created producer
- * will have its "id" property set to "slowmotion:parentid:speed", where
- * "parentid" is the id of the original clip in the ClipManager list and
- * "speed" is the current speed. */
- int mltChangeClipSpeed(ItemInfo info, ItemInfo speedIndependantInfo, double speed, double oldspeed, int strobe, Mlt::Producer *prod);
-
const QList <Mlt::Producer *> producersList();
void setDropFrames(bool show);
/** @brief Sets an MLT consumer property. */
@@ -498,6 +487,7 @@ public slots:
void getFileProperties(const QDomElement &xml, const QString &clipId, int imageHeight, bool replaceProducer = true);
/** @brief Renderer moved to a new frame, check seeking */
void checkFrameNumber(int pos);
+ void storeSlowmotionProducer(const QString &url, Mlt::Producer *prod);
void seek(int time);
};
diff --git a/src/timeline/customtrackview.cpp b/src/timeline/customtrackview.cpp
index 032e318..f06fd6e 100644
--- a/src/timeline/customtrackview.cpp
+++ b/src/timeline/customtrackview.cpp
@@ -4272,15 +4272,13 @@ void CustomTrackView::deleteSelectedClips()
void CustomTrackView::doChangeClipSpeed(ItemInfo info, const ItemInfo &speedIndependantInfo, const double speed, const double oldspeed, int strobe, const QString &id)
{
- Q_UNUSED(id)
- qDebug()<<" / / /CHANGING CLIP SPEED: "<<id<<" = "<<speed;
ClipItem *item = getClipItemAtStart(info.startPos, info.track);
if (!item) {
//qDebug() << "ERROR: Cannot find clip for speed change";
emit displayMessage(i18n("Cannot find clip for speed change"), ErrorMessage);
return;
}
- int endPos = m_document->renderer()->mltChangeClipSpeed(info, speedIndependantInfo, speed, oldspeed, strobe, m_document->renderer()->getTrackProducer(item->getBinId(), info.track));
+ int endPos = m_timeline->changeClipSpeed(info, speedIndependantInfo, speed, strobe, m_document->renderer()->getBinProducer(id));
if (endPos >= 0) {
item->setSpeed(speed, strobe);
item->updateRectGeometry();
diff --git a/src/timeline/timeline.cpp b/src/timeline/timeline.cpp
index c9ca3cc..e869fd8 100644
--- a/src/timeline/timeline.cpp
+++ b/src/timeline/timeline.cpp
@@ -28,6 +28,7 @@
#include "customruler.h"
#include "customtrackview.h"
#include "dialogs/profilesdialog.h"
+#include "mltcontroller/clipcontroller.h"
#include "kdenlivesettings.h"
#include "mainwindow.h"
@@ -221,6 +222,7 @@ int Timeline::getTracks() {
if (playlist.filter_count()) getEffects(playlist, NULL, 0);
++trackIndex;
connect(m_tracks[0], &Track::newTrackDuration, this, &Timeline::checkDuration);
+ connect(m_tracks[0], SIGNAL(storeSlowMotion(QString,Mlt::Producer *)), m_doc->renderer(), SLOT(storeSlowmotionProducer(QString,Mlt::Producer *)));
}
checkTrackHeight();
return duration;
@@ -767,6 +769,7 @@ int Timeline::addTrack(int ix, Mlt::Playlist &playlist) {
int in = clip->get_in();
int out = clip->get_out();
QString idString = clip->parent().get("id");
+ qDebug()<<"***** LOADING: "<<idString<<"\n"<<clip->get("id")<<"\n**********";
if (in >= out || m_invalidProducers.contains(idString)) {
m_documentErrors.append(i18n("Invalid clip removed from track %1 at %2\n", ix, position));
playlist.remove(i);
@@ -787,6 +790,8 @@ int Timeline::addTrack(int ix, Mlt::Playlist &playlist) {
speed = locale.toDouble(idString.section(':', 2, 2));
strobe = idString.section(':', 3, 3).toInt();
if (strobe == 0) strobe = 1;
+ // Slowmotion producer, store it for reuse
+ m_doc->renderer()->storeSlowmotionProducer(idString, &clip->parent());
}
id = id.section('_', 0, 0);
ProjectClip *binclip = m_doc->getBinClip(id);
@@ -799,6 +804,7 @@ int Timeline::addTrack(int ix, Mlt::Playlist &playlist) {
clipinfo.cropStart = GenTime(in, fps);
clipinfo.cropDuration = GenTime(length, fps);
clipinfo.track = ix;
+ qDebug()<<"// Loading clip: "<<idString<<" / SPEED: "<<speed<<"\n++++++++++++++++++++++++";
ClipItem *item = new ClipItem(binclip, clipinfo, fps, speed, strobe, m_trackview->getFrameWidth(), true);
item->updateState(idString);
m_scene->addItem(item);
@@ -1286,3 +1292,22 @@ void Timeline::updateClipProperties(const QString &id, QMap <QString, QString> p
track(i)->updateClipProperties(id, properties);
}
}
+
+int Timeline::changeClipSpeed(ItemInfo info, ItemInfo speedIndependantInfo, double speed, int strobe, Mlt::Producer *originalProd)
+{
+ Mlt::Producer *prod;
+ QLocale locale;
+ if (speed == 1) {
+ prod = originalProd;
+ }
+ else {
+ QString url = QString::fromUtf8(originalProd->get("resource"));
+ url.append('?' + locale.toString(speed));
+ if (strobe > 1) url.append("&strobe=" + QString::number(strobe));
+ prod = m_doc->renderer()->getSlowmotionProducer(url);
+ }
+ Mlt::Properties passProperties;
+ Mlt::Properties original(originalProd->get_properties());
+ passProperties.pass_list(original, ClipController::getPassPropertiesList());
+ return track(info.track)->changeClipSpeed(info, speedIndependantInfo, speed, strobe, prod, passProperties);
+}
diff --git a/src/timeline/timeline.h b/src/timeline/timeline.h
index 333c59e..01b28ca 100644
--- a/src/timeline/timeline.h
+++ b/src/timeline/timeline.h
@@ -114,6 +114,7 @@ public:
* Returns -1 if track is shorter, 0 if not blank and > 0 for blank length */
int getTrackSpaceLength(int trackIndex, int pos, bool fromBlankStart);
void updateClipProperties(const QString &id, QMap <QString, QString> properties);
+ int changeClipSpeed(ItemInfo info, ItemInfo speedIndependantInfo, double speed, int strobe, Mlt::Producer *originalProd);
int getTracks();
void getTransitions();
diff --git a/src/timeline/track.cpp b/src/timeline/track.cpp
index 06da50c..f5ed588 100644
--- a/src/timeline/track.cpp
+++ b/src/timeline/track.cpp
@@ -485,3 +485,197 @@ void Track::updateClipProperties(const QString &id, QMap <QString, QString> prop
}
}
+int Track::changeClipSpeed(ItemInfo info, ItemInfo speedIndependantInfo, double speed, int strobe, Mlt::Producer *prod, Mlt::Properties passProps)
+{
+ int newLength = 0;
+ int startPos = info.startPos.frames(m_fps);
+ int clipIndex = m_playlist.get_clip_index_at(startPos);
+ int clipLength = m_playlist.clip_length(clipIndex);
+
+ Mlt::Producer *original = m_playlist.get_clip(clipIndex);
+ if (original == NULL) {
+ qDebug()<<"// No clip to apply effect";
+ return -1;
+ }
+ if (!original->is_valid() || original->is_blank()) {
+ // invalid clip
+ delete original;
+ qDebug()<<"// Invalid clip to apply effect";
+ return -1;
+ }
+ Mlt::Producer clipparent = original->parent();
+ if (!clipparent.is_valid() || clipparent.is_blank()) {
+ // invalid clip
+ qDebug()<<"// Invalid parent to apply effect";
+ delete original;
+ return -1;
+ }
+
+ QString serv = clipparent.get("mlt_service");
+ QString id = clipparent.get("id");
+ QLocale locale;
+ id = id.section("_", 0, 0);
+ if (speed <= 0 && speed > -1) speed = 1.0;
+ //qDebug() << "SLOWMO CLIP SERVICE: " << serv;
+
+ if ((serv == "avformat" || serv == "avformat-novalidate") && (speed != 1.0 || strobe > 1)) {
+ m_playlist.lock();
+ QString url = QString::fromUtf8(clipparent.get("resource"));
+ url.append('?' + locale.toString(speed));
+ if (strobe > 1) url.append("&strobe=" + QString::number(strobe));
+ if (!prod || !prod->is_valid()) {
+ prod = new Mlt::Producer(*m_playlist.profile(), 0, ("framebuffer:" + url).toUtf8().constData());
+ if (!prod->is_valid()) {
+ qDebug()<<"++++ FAILED TO CREATE SLOWMO PROD";
+ }
+ if (strobe > 1) prod->set("strobe", strobe);
+ QString producerid = "slowmotion:" + id + ':' + locale.toString(speed);
+ if (strobe > 1) producerid.append(':' + QString::number(strobe));
+ prod->set("id", producerid.toUtf8().constData());
+ // copy producer props
+ for (int i = 0; i < passProps.count(); i++) {
+ prod->set(passProps.get_name(i), passProps.get(i));
+ }
+
+ /*
+ double ar = original->parent().get_double("force_aspect_ratio");
+ if (ar != 0.0) slowprod->set("force_aspect_ratio", ar);
+ double fps = original->parent().get_double("force_fps");
+ if (fps != 0.0) slowprod->set("force_fps", fps);
+ int threads = original->parent().get_int("threads");
+ if (threads != 0) slowprod->set("threads", threads);
+ if (original->parent().get("force_progressive"))
+ slowprod->set("force_progressive", original->parent().get_int("force_progressive"));
+ if (original->parent().get("force_tff"))
+ slowprod->set("force_tff", original->parent().get_int("force_tff"));
+ int ix = original->parent().get_int("video_index");
+ if (ix != 0) slowprod->set("video_index", ix);
+ int colorspace = original->parent().get_int("force_colorspace");
+ if (colorspace != 0) slowprod->set("force_colorspace", colorspace);
+ int full_luma = original->parent().get_int("set.force_full_luma");
+ if (full_luma != 0) slowprod->set("set.force_full_luma", full_luma);*/
+ emit storeSlowMotion(url, prod);
+ //m_slowmotionProducers.insert(url, slowprod);
+ }
+ Mlt::Producer *clip = m_playlist.replace_with_blank(clipIndex);
+ m_playlist.consolidate_blanks(0);
+
+ // Check that the blank space is long enough for our new duration
+ clipIndex = m_playlist.get_clip_index_at(startPos);
+ int blankEnd = m_playlist.clip_start(clipIndex) + m_playlist.clip_length(clipIndex);
+ Mlt::Producer *cut;
+ if (clipIndex + 1 < m_playlist.count() && (startPos + clipLength / speed > blankEnd)) {
+ GenTime maxLength = GenTime(blankEnd, m_fps) - info.startPos;
+ cut = prod->cut((int)(info.cropStart.frames(m_fps) / speed), (int)(info.cropStart.frames(m_fps) / speed + maxLength.frames(m_fps) - 1));
+ } else cut = prod->cut((int)(info.cropStart.frames(m_fps) / speed), (int)((info.cropStart.frames(m_fps) + clipLength) / speed - 1));
+
+ // move all effects to the correct producer
+ Clip(*cut).addEffects(*clip);
+ m_playlist.insert_at(startPos, cut, 1);
+ delete cut;
+ delete clip;
+ clipIndex = m_playlist.get_clip_index_at(startPos);
+ newLength = m_playlist.clip_length(clipIndex);
+ m_playlist.unlock();
+ } else if (speed == 1.0 && strobe < 2) {
+ if (!prod || !prod->is_valid()) {
+ qDebug()<<"// Something is wrong with original slowmo producer";
+ return -1;
+ }
+ m_playlist.unlock();
+
+ Mlt::Producer *clip = m_playlist.replace_with_blank(clipIndex);
+ m_playlist.consolidate_blanks(0);
+
+ // Check that the blank space is long enough for our new duration
+ clipIndex = m_playlist.get_clip_index_at(startPos);
+ int blankEnd = m_playlist.clip_start(clipIndex) + m_playlist.clip_length(clipIndex);
+
+ Mlt::Producer *cut;
+ Mlt::Producer *trackProd = clipProducer(prod, PlaylistState::Original);
+ int originalStart = (int)(speedIndependantInfo.cropStart.frames(m_fps));
+ if (clipIndex + 1 < m_playlist.count() && (info.startPos + speedIndependantInfo.cropDuration).frames(m_fps) > blankEnd) {
+ GenTime maxLength = GenTime(blankEnd, m_fps) - info.startPos;
+ cut = trackProd->cut(originalStart, (int)(originalStart + maxLength.frames(m_fps) - 1));
+ } else cut = trackProd->cut(originalStart, (int)(originalStart + speedIndependantInfo.cropDuration.frames(m_fps)) - 1);
+
+ // move all effects to the correct producer
+ Clip(*cut).addEffects(*clip);
+
+ m_playlist.insert_at(startPos, cut, 1);
+ delete cut;
+ delete clip;
+ clipIndex = m_playlist.get_clip_index_at(startPos);
+ newLength = m_playlist.clip_length(clipIndex);
+ m_playlist.unlock();
+
+ } else if (serv == "framebuffer") {
+ m_playlist.lock();
+ QString url = QString::fromUtf8(clipparent.get("resource"));
+ url = url.section('?', 0, 0);
+ url.append('?' + locale.toString(speed));
+ if (strobe > 1) url.append("&strobe=" + QString::number(strobe));
+ if (!prod || !prod->is_valid()) {
+ prod = new Mlt::Producer(*m_playlist.profile(), 0, ("framebuffer:" + url).toUtf8().constData());
+ prod->set("strobe", strobe);
+ QString producerid = "slowmotion:" + id.section(':', 1, 1) + ':' + locale.toString(speed);
+ if (strobe > 1) producerid.append(':' + QString::number(strobe));
+ prod->set("id", producerid.toUtf8().constData());
+ // copy producer props
+ for (int i = 0; i < passProps.count(); i++) {
+ prod->set(passProps.get_name(i), passProps.get(i));
+ }
+
+
+ /*double ar = original->parent().get_double("force_aspect_ratio");
+ if (ar != 0.0) slowprod->set("force_aspect_ratio", ar);
+ double fps = original->parent().get_double("force_fps");
+ if (fps != 0.0) slowprod->set("force_fps", fps);
+ if (original->parent().get("force_progressive"))
+ slowprod->set("force_progressive", original->parent().get_int("force_progressive"));
+ if (original->parent().get("force_tff"))
+ slowprod->set("force_tff", original->parent().get_int("force_tff"));
+ int threads = original->parent().get_int("threads");
+ if (threads != 0) slowprod->set("threads", threads);
+ int ix = original->parent().get_int("video_index");
+ if (ix != 0) slowprod->set("video_index", ix);
+ int colorspace = original->parent().get_int("force_colorspace");
+ if (colorspace != 0) slowprod->set("force_colorspace", colorspace);
+ int full_luma = original->parent().get_int("set.force_full_luma");
+ if (full_luma != 0) slowprod->set("set.force_full_luma", full_luma);
+ m_slowmotionProducers.insert(url, slowprod);*/
+ emit storeSlowMotion(url, prod);
+ }
+ Mlt::Producer *clip = m_playlist.replace_with_blank(clipIndex);
+ m_playlist.consolidate_blanks(0);
+
+ GenTime duration = speedIndependantInfo.cropDuration / speed;
+ int originalStart = (int)(speedIndependantInfo.cropStart.frames(m_fps) / speed);
+
+ // Check that the blank space is long enough for our new duration
+ clipIndex = m_playlist.get_clip_index_at(startPos);
+ int blankEnd = m_playlist.clip_start(clipIndex) + m_playlist.clip_length(clipIndex);
+
+ Mlt::Producer *cut;
+ if (clipIndex + 1 < m_playlist.count() && (info.startPos + duration).frames(m_fps) > blankEnd) {
+ GenTime maxLength = GenTime(blankEnd, m_fps) - info.startPos;
+ cut = prod->cut(originalStart, (int)(originalStart + maxLength.frames(m_fps) - 1));
+ } else cut = prod->cut(originalStart, (int)(originalStart + duration.frames(m_fps)) - 1);
+
+ // move all effects to the correct producer
+ Clip(*cut).addEffects(*clip);
+
+ m_playlist.insert_at(startPos, cut, 1);
+ delete cut;
+ delete clip;
+ clipIndex = m_playlist.get_clip_index_at(startPos);
+ newLength = m_playlist.clip_length(clipIndex);
+
+ m_playlist.unlock();
+ }
+ delete original;
+ //if (clipIndex + 1 == m_playlist.count()) mltCheckLength(&tractor);
+ return newLength;
+}
+
+
diff --git a/src/timeline/track.h b/src/timeline/track.h
index 9bd76c5..7daf481 100644
--- a/src/timeline/track.h
+++ b/src/timeline/track.h
@@ -129,6 +129,15 @@ public:
* @param forceCreation if true, we do not attempt to re-use existing track producer but recreate it
* @return producer cut for this track */
Mlt::Producer *clipProducer(Mlt::Producer *parent, PlaylistState::ClipState state, bool forceCreation = false);
+ /** @brief Changes the speed of a clip in MLT's playlist.
+ *
+ * It creates a new "framebuffer" producer, which must have its "resource"
+ * property set to "video.mpg?0.6", where "video.mpg" is the path to the
+ * clip and "0.6" is the speed in percentage. The newly created producer
+ * will have its "id" property set to "slowmotion:parentid:speed", where
+ * "parentid" is the id of the original clip in the ClipManager list and
+ * "speed" is the current speed. */
+ int changeClipSpeed(ItemInfo info, ItemInfo speedIndependantInfo, double speed, int strobe, Mlt::Producer *prod, Mlt::Properties passProps);
/** @brief Returns true if there is a clip with audio on this track */
bool hasAudio();
void setProperty(const QString &name, const QString &value);
@@ -153,6 +162,7 @@ signals:
/** @brief notify track length change to update background
* @param duration is the new length */
void newTrackDuration(int duration);
+ void storeSlowMotion(const QString &url, Mlt::Producer *prod);
private:
/** MLT playlist behind the scene */