]> git.sesse.net Git - kdenlive/blobdiff - src/renderer.cpp
Prevent crash when deleting a clip while playing:
[kdenlive] / src / renderer.cpp
index 310a4ed1f8c81de62c918c4e328a744012452a91..b96f1f6be913fc5ecc1e7bf4a7a16df2bf8c64c1 100644 (file)
@@ -133,9 +133,11 @@ Render::~Render()
 
 
 void Render::closeMlt()
-{
+{       
     //delete m_osdTimer;
-    if (m_mltProducer) {
+    if (m_mltConsumer) delete m_mltConsumer;
+    if (m_mltProducer) delete m_mltProducer;
+    /*if (m_mltProducer) {
         Mlt::Service service(m_mltProducer->parent().get_service());
         mlt_service_lock(service.get_service());
 
@@ -158,21 +160,14 @@ void Render::closeMlt()
                 resource = mlt_properties_get(properties, "mlt_service");
             }
 
-            for (int trackNb = tractor.count() - 1; trackNb >= 0; --trackNb) {
-                Mlt::Producer trackProducer(tractor.track(trackNb));
-                Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
-                if (trackPlaylist.type() == playlist_type) trackPlaylist.clear();
-            }
             delete field;
             field = NULL;
         }
         mlt_service_unlock(service.get_service());
-    }
+    }*/
 
     kDebug() << "// // // CLOSE RENDERER " << m_name;
-    delete m_mltConsumer;
-    delete m_mltProducer;
-    delete m_blackClip;
+    if (m_blackClip) delete m_blackClip;
     //delete m_osdInfo;
 }
 
@@ -571,7 +566,7 @@ void Render::getFileProperties(const QDomElement xml, const QString &clipId, int
         proxyProducer = false;
     }
 
-    KUrl url = KUrl(path);
+    KUrl url(path);
     Mlt::Producer *producer = NULL;
     CLIPTYPE type = (CLIPTYPE)xml.attribute("type").toInt();
     //kDebug() << "PROFILE WIDT: "<< xml.attribute("mlt_service") << ": "<< m_mltProfile->width() << "\n...................\n\n";
@@ -595,12 +590,12 @@ void Render::getFileProperties(const QDomElement xml, const QString &clipId, int
         play.appendChild(doc.importNode(xml, true));
         producer = new Mlt::Producer(*m_mltProfile, "xml-string", doc.toString().toUtf8().constData());
     } else {
-        producer = new Mlt::Producer(*m_mltProfile, url.path().toUtf8().constData());
+        producer = new Mlt::Producer(*m_mltProfile, path.toUtf8().constData());
     }
 
 
     if (producer == NULL || producer->is_blank() || !producer->is_valid()) {
-        kDebug() << " / / / / / / / / ERROR / / / / // CANNOT LOAD PRODUCER: ";
+        kDebug() << " / / / / / / / / ERROR / / / / // CANNOT LOAD PRODUCER: "<<path;
         if (proxyProducer) {
             // Proxy file is corrupted
             emit removeInvalidProxy(clipId, false);
@@ -696,6 +691,10 @@ void Render::getFileProperties(const QDomElement xml, const QString &clipId, int
 
     if ((!replaceProducer && xml.hasAttribute("file_hash")) || xml.hasAttribute("proxy")) {
         // Clip  already has all properties
+        if (replaceProducer) emit blockClipMonitor(clipId);
+        // Querying a frame is required by MLT, otherwise the producer is not correctly initialised
+        Mlt::Frame *frame = producer->get_frame();
+        delete frame;
         emit replyGetFileProperties(clipId, producer, QMap < QString, QString >(), QMap < QString, QString >(), replaceProducer, selectClip);
         return;
     }
@@ -885,6 +884,7 @@ void Render::getFileProperties(const QDomElement xml, const QString &clipId, int
             metadataPropertyMap[ name.section('.', 0, -2)] = value;
     }
     producer->seek(0);
+    if (replaceProducer) emit blockClipMonitor(clipId);
     emit replyGetFileProperties(clipId, producer, filePropertyMap, metadataPropertyMap, replaceProducer, selectClip);
     // FIXME: should delete this to avoid a leak...
     //delete producer;
@@ -931,13 +931,18 @@ void Render::initSceneList()
 
 int Render::setProducer(Mlt::Producer *producer, int position)
 {
+    QMutexLocker locker(&m_mutex);
     if (m_winid == -1) return -1;
-
     if (m_mltConsumer) {
-        m_mltConsumer->stop();
-    } else return -1;
+        if (!m_mltConsumer->is_stopped()) {
+            m_mltConsumer->stop();
+        }
+        m_mltConsumer->set("refresh", 0);
+    }
+    else {
+        return -1;
+    }
 
-    m_mltConsumer->purge();
     m_isBlocked = true;
     if (m_mltProducer) {
         m_mltProducer->set_speed(0);
@@ -945,7 +950,8 @@ int Render::setProducer(Mlt::Producer *producer, int position)
         m_mltProducer = NULL;
         emit stopped();
     }
-    if (producer) {
+    blockSignals(true);
+    if (producer && producer->is_valid()) {
         m_mltProducer = new Mlt::Producer(producer->get_producer());
     } else m_mltProducer = m_blackClip->cut(0, 50);
 
@@ -956,6 +962,7 @@ int Render::setProducer(Mlt::Producer *producer, int position)
     int volume = KdenliveSettings::volume();
     m_mltProducer->set("meta.volume", (double)volume / 100);
     m_fps = m_mltProducer->get_fps();
+    blockSignals(false);
     int error = connectPlaylist();
 
     if (position != -1) {
@@ -977,7 +984,7 @@ int Render::setSceneList(QString playlist, int position)
     m_isBlocked = true;
     int error = 0;
 
-    //kDebug() << "//////  RENDER, SET SCENE LIST: " << playlist;
+    //kDebug() << "//////  RENDER, SET SCENE LIST:\n" << playlist <<"\n..........:::.";
 
     // Remove previous profile info
     QDomDocument doc;
@@ -1000,7 +1007,7 @@ int Render::setSceneList(QString playlist, int position)
         m_mltProducer->set_speed(0);
         //if (KdenliveSettings::osdtimecode() && m_osdInfo) m_mltProducer->detach(*m_osdInfo);
 
-        Mlt::Service service(m_mltProducer->parent().get_service());
+        /*Mlt::Service service(m_mltProducer->parent().get_service());
         mlt_service_lock(service.get_service());
 
         if (service.type() == tractor_type) {
@@ -1030,7 +1037,7 @@ int Render::setSceneList(QString playlist, int position)
             }
             delete field;
         }
-        mlt_service_unlock(service.get_service());
+        mlt_service_unlock(service.get_service());*/
 
         qDeleteAll(m_slowmotionProducers.values());
         m_slowmotionProducers.clear();
@@ -1041,11 +1048,11 @@ int Render::setSceneList(QString playlist, int position)
     }
 
     blockSignals(true);
-    // TODO: Better way to do this
-    if (KdenliveSettings::projectloading_avformatnovalidate())
+    // WARNING: disabled because it caused crashes (see Kdenlive bug #2205 and #2206) - jbm
+    /*if (KdenliveSettings::projectloading_avformatnovalidate())
         playlist.replace(">avformat</property>", ">avformat-novalidate</property>");
     else
-        playlist.replace(">avformat-novalidate</property>", ">avformat</property>");
+        playlist.replace(">avformat-novalidate</property>", ">avformat</property>");*/
     m_mltProducer = new Mlt::Producer(*m_mltProfile, "xml-string", playlist.toUtf8().constData());
     if (!m_mltProducer || !m_mltProducer->is_valid()) {
         kDebug() << " WARNING - - - - -INVALID PLAYLIST: " << playlist.toUtf8().constData();
@@ -1643,7 +1650,7 @@ Mlt::Producer *Render::checkSlowMotionProducer(Mlt::Producer *prod, QDomElement
     if (!slowprod || slowprod->get_producer() == NULL) {
         slowprod = new Mlt::Producer(*m_mltProfile, 0, ("framebuffer:" + url).toUtf8().constData());
         if (strobe > 1) slowprod->set("strobe", strobe);
-        QString id = prod->get("id");
+        QString id = prod->parent().get("id");
         if (id.contains('_')) id = id.section('_', 0, 0);
         QString producerid = "slowmotion:" + id + ':' + QString::number(speed);
         if (strobe > 1) producerid.append(':' + QString::number(strobe));
@@ -2555,6 +2562,11 @@ bool Render::mltAddEffect(Mlt::Service service, EffectsParameterList params, int
             return false;
         }
         params.removeParam("kdenlive_id");
+        if (params.hasParam("_sync_in_out")) {
+            // This effect must sync in / out with parent clip
+            params.removeParam("_sync_in_out");
+            filter->set_in_and_out(service.get_int("in"), service.get_int("out"));
+        }
 
         for (int j = 0; j < params.count(); j++) {
             filter->set((prefix + params.at(j).name()).toUtf8().constData(), params.at(j).value().toUtf8().constData());
@@ -2576,10 +2588,6 @@ bool Render::mltAddEffect(Mlt::Service service, EffectsParameterList params, int
             filter->set("effect", effectArgs.simplified().toUtf8().constData());
         }
 
-        if (params.paramValue("id") == "pan_zoom") {
-            filter->set_in_and_out(service.get_int("in"), service.get_int("out") + 1);
-        }
-
         // attach filter to the clip
         service.attach(*filter);
     }
@@ -2704,13 +2712,15 @@ bool Render::mltEditEffect(int track, GenTime position, EffectsParameterList par
     QString prefix;
     QString ser = filter->get("mlt_service");
     if (ser == "region") prefix = "filter0.";
+    if (params.hasParam("_sync_in_out")) {
+        // This effect must sync in / out with parent clip
+        params.removeParam("_sync_in_out");
+        filter->set_in_and_out(clip->get_in(), clip->get_out());
+    }
     mlt_service_lock(service.get_service());
     for (int j = 0; j < params.count(); j++) {
         filter->set((prefix + params.at(j).name()).toUtf8().constData(), params.at(j).value().toUtf8().constData());
-    }
-
-    if (params.paramValue("id") == "pan_zoom")
-        filter->set_in_and_out(clip->get_in(), clip->get_out() + 1);
+    }   
 
     delete clip;
     mlt_service_unlock(service.get_service());
@@ -3188,7 +3198,6 @@ bool Render::mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod)
         kDebug() << "// Warning, CLIP on track " << track << ", at: " << pos << " is invalid, cannot update it!!!";
         return false;
     }
-    kDebug() << "NEW PROD ID: " << prod->get("id");
     m_isBlocked++;
     kDebug() << "// TRYING TO UPDATE CLIP at: " << pos << ", TK: " << track;
     Mlt::Service service(m_mltProducer->parent().get_service());
@@ -3843,13 +3852,14 @@ const QList <Mlt::Producer *> Render::producersList()
         int clipNb = trackPlaylist.count();
         for (int i = 0; i < clipNb; i++) {
             Mlt::Producer *c = trackPlaylist.get_clip(i);
-            Mlt::Producer *nprod = new Mlt::Producer(c->get_parent());
-            if (nprod) {
-                QString prodId = nprod->get("id");
-                if (!prodId.startsWith("slowmotion") && !prodId.isEmpty() && !nprod->is_blank() && !ids.contains(prodId)) {
-                    ids.append(nprod->get("id"));
+            if (c == NULL) continue;
+            QString prodId = c->parent().get("id");
+            if (!c->is_blank() && !ids.contains(prodId) && !prodId.startsWith("slowmotion") && !prodId.isEmpty()) {
+                Mlt::Producer *nprod = new Mlt::Producer(c->get_parent());
+                if (nprod) {
+                    ids.append(prodId);
                     prods.append(nprod);
-                } else delete nprod;
+                }
             }
             delete c;
         }
@@ -3876,7 +3886,7 @@ void Render::fillSlowMotionProducers()
             Mlt::Producer *c = trackPlaylist.get_clip(i);
             Mlt::Producer *nprod = new Mlt::Producer(c->get_parent());
             if (nprod) {
-                QString id = nprod->get("id");
+                QString id = nprod->parent().get("id");
                 if (id.startsWith("slowmotion:") && !nprod->is_blank()) {
                     // this is a slowmotion producer, add it to the list
                     QString url = QString::fromUtf8(nprod->get("resource"));