]> git.sesse.net Git - kdenlive/blobdiff - src/renderer.cpp
Fix broken producer incorrectly handled when using proxy, corrupting project:
[kdenlive] / src / renderer.cpp
index 3e18730174c408034b15898a708d2a7d5a72019b..bc8e14c89ba0c6d494b0fccdc0b233c8dc9f541d 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;
 }
 
@@ -183,18 +178,17 @@ void Render::slotSwitchFullscreen()
 
 void Render::buildConsumer(const QString profileName)
 {
-    m_activeProfile = profileName;
-    char *tmp = qstrdup(m_activeProfile.toUtf8().constData());
-    setenv("MLT_PROFILE", tmp, 1);
     delete m_blackClip;
     m_blackClip = NULL;
 
     //TODO: uncomment following line when everything is clean
     // uncommented Feb 2011 --Granjow
     if (m_mltProfile) delete m_mltProfile;
-
+    m_activeProfile = profileName;
+    char *tmp = qstrdup(m_activeProfile.toUtf8().constData());
+    setenv("MLT_PROFILE", tmp, 1);
     m_mltProfile = new Mlt::Profile(tmp);
-    m_mltProfile->get_profile()->is_explicit = 1;
+    m_mltProfile->set_explicit(true);
     delete[] tmp;
 
     m_blackClip = new Mlt::Producer(*m_mltProfile, "colour", "black");
@@ -282,15 +276,25 @@ void Render::buildConsumer(const QString profileName)
 
 Mlt::Producer *Render::invalidProducer(const QString &id)
 {
-    Mlt::Producer *clip = new Mlt::Producer(*m_mltProfile, "colour", "red");
+    Mlt::Producer *clip;
+    QString txt = "+" + i18n("Missing clip") + ".txt";
+    char *tmp = qstrdup(txt.toUtf8().constData());
+    clip = new Mlt::Producer(*m_mltProfile, tmp);
+    delete[] tmp;
+    if (clip == NULL) clip = new Mlt::Producer(*m_mltProfile, "colour", "red");
+    else {
+        clip->set("bgcolour", "0xff0000ff");
+        clip->set("pad", "10");
+    }
     clip->set("id", id.toUtf8().constData());
     clip->set("mlt_type", "producer");
     return clip;
 }
 
-int Render::resetProfile(const QString profileName)
+int Render::resetProfile(const QString profileName, bool dropSceneList)
 {
-    QString scene = sceneList();
+    QString scene;
+    if (!dropSceneList) scene = sceneList();
     if (m_mltConsumer) {
         if (m_externalConsumer == KdenliveSettings::external_display()) {
             if (KdenliveSettings::external_display() && m_activeProfile == profileName) return 1;
@@ -336,31 +340,17 @@ int Render::resetProfile(const QString profileName)
     buildConsumer(profileName);
     double new_fps = m_mltProfile->fps();
     double new_dar = m_mltProfile->dar();
-    if (current_fps != new_fps) {
-        // fps changed, we must update the scenelist positions
-        scene = updateSceneListFps(current_fps, new_fps, scene);
+    
+    if (!dropSceneList) {
+        // We need to recover our playlist
+        if (current_fps != new_fps) {
+            // fps changed, we must update the scenelist positions
+            scene = updateSceneListFps(current_fps, new_fps, scene);
+        }
+        setSceneList(scene, pos);
+        // producers have changed (different profile), so reset them...
+        emit refreshDocumentProducers(new_dar != current_dar, current_fps != new_fps);
     }
-    //kDebug() << "//RESET WITHSCENE: " << scene;
-    setSceneList(scene, pos);
-    // producers have changed (different profile), so reset them...
-    emit refreshDocumentProducers(new_dar != current_dar);
-    /*Mlt::Producer *producer = new Mlt::Producer(*m_mltProfile , "xml-string", scene.toUtf8().constData());
-    m_mltProducer = producer;
-    m_blackClip = new Mlt::Producer(*m_mltProfile , "colour", "black");
-    m_mltProducer->optimise();
-    m_mltProducer->set_speed(0);
-    connectPlaylist();*/
-
-    //delete m_mltProfile;
-    // mlt_properties properties = MLT_CONSUMER_PROPERTIES(m_mltConsumer->get_consumer());
-    //mlt_profile prof = m_mltProfile->get_profile();
-    //mlt_properties_set_data(properties, "_profile", prof, 0, (mlt_destructor)mlt_profile_close, NULL);
-    //mlt_properties_set(properties, "profile", "hdv_1080_50i");
-    //m_mltConsumer->set("profile", (char *) profile.toUtf8().data());
-    //m_mltProfile = new Mlt::Profile((char*) profile.toUtf8().data());
-
-    //apply_profile_properties( m_mltProfile, m_mltConsumer->get_consumer(), properties );
-    //refresh();
     return 1;
 }
 
@@ -576,8 +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";
@@ -601,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);
@@ -617,6 +606,7 @@ void Render::getFileProperties(const QDomElement xml, const QString &clipId, int
     }
 
     if (proxyProducer && xml.hasAttribute("proxy_out")) {
+        producer->set("length", xml.attribute("proxy_out").toInt() + 1);
         producer->set("out", xml.attribute("proxy_out").toInt());
         if (producer->get_out() != xml.attribute("proxy_out").toInt()) {
             // Proxy file length is different than original clip length, this will corrupt project so disable this proxy clip
@@ -701,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;
     }
@@ -890,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;
@@ -936,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);
@@ -950,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);
 
@@ -961,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) {
@@ -982,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;
@@ -1005,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) {
@@ -1035,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();
@@ -1046,12 +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();
@@ -3512,7 +3513,6 @@ void Render::mltUpdateTransitionParams(QString type, int a_track, int b_track, G
         int currentOut = (int) mlt_transition_get_out(tr);
 
         // kDebug()<<"Looking for transition : " << currentIn <<'x'<<currentOut<< ", OLD oNE: "<<in_pos<<'x'<<out_pos;
-
         if (resource == type && b_track == currentTrack && currentIn == in_pos && currentOut == out_pos) {
             QMap<QString, QString> map = mltGetTransitionParamsFromXml(xml);
             QMap<QString, QString>::Iterator it;
@@ -3800,6 +3800,8 @@ bool Render::mltAddTransition(QString tag, int a_track, int b_track, GenTime in,
     //kDebug() << " ------  ADDING TRANSITION PARAMs: " << args.count();
     if (xml.hasAttribute("id"))
         transition->set("kdenlive_id", xml.attribute("id").toUtf8().constData());
+    if (xml.hasAttribute("force_track"))
+        transition->set("force_track", xml.attribute("force_track").toInt());
 
     for (it = args.begin(); it != args.end(); ++it) {
         key = it.key();
@@ -3852,7 +3854,7 @@ const QList <Mlt::Producer *> Render::producersList()
             if (nprod) {
                 QString prodId = nprod->get("id");
                 if (!prodId.startsWith("slowmotion") && !prodId.isEmpty() && !nprod->is_blank() && !ids.contains(prodId)) {
-                    ids.append(nprod->get("id"));
+                    ids.append(prodId);
                     prods.append(nprod);
                 } else delete nprod;
             }
@@ -4022,7 +4024,7 @@ void Render::mltDeleteTrack(int ix)
     tractor.removeChild(track);
     //kDebug() << "/////////// RESULT SCENE: \n" << doc.toString();
     setSceneList(doc.toString(), m_framePosition);
-    emit refreshDocumentProducers(false);
+    emit refreshDocumentProducers(false, false);
 }