]> git.sesse.net Git - kdenlive/blobdiff - src/renderer.cpp
Do not uselessly switch monitors at startup
[kdenlive] / src / renderer.cpp
index 3e1001c437a9747043d3e990b7f22fdeac3cdb86..ebee863cd116ae0142af6eed8f44df8ae2a5874c 100644 (file)
@@ -64,9 +64,9 @@ static void kdenlive_callback(void* /*ptr*/, int level, const char* fmt, va_list
 static void consumer_frame_show(mlt_consumer, Render * self, mlt_frame frame_ptr)
 {
     // detect if the producer has finished playing. Is there a better way to do it?
+    self->emitFrameNumber();
     Mlt::Frame frame(frame_ptr);
     if (!frame.is_valid()) return;
-    self->emitFrameNumber(mlt_frame_get_position(frame_ptr));
     if (self->sendFrameForAnalysis && frame_ptr->convert_image) {
         self->emitFrameUpdated(frame);
     }
@@ -107,7 +107,6 @@ Render::Render(const QString & rendererName, int winid, QString profile, QWidget
     m_mltConsumer(NULL),
     m_mltProducer(NULL),
     m_mltProfile(NULL),
-    m_framePosition(0),
     m_externalConsumer(false),
     m_isZoneMode(false),
     m_isLoopMode(false),
@@ -188,7 +187,6 @@ void Render::buildConsumer(const QString &profileName)
     setenv("MLT_PROFILE", tmp, 1);
     m_mltProfile = new Mlt::Profile(tmp);
     m_mltProfile->set_explicit(true);
-    kDebug()<<"// *********  PROFILE AR: "<<m_mltProfile->dar();
     delete[] tmp;
 
     m_blackClip = new Mlt::Producer(*m_mltProfile, "colour", "black");
@@ -209,7 +207,6 @@ void Render::buildConsumer(const QString &profileName)
                     m_externalConsumer = true;
                     m_mltConsumer->listen("consumer-frame-show", this, (mlt_listener) consumer_frame_show);
                     m_mltConsumer->set("terminate_on_pause", 0);
-                    m_mltConsumer->set("buffer", 12);
                     m_mltConsumer->set("deinterlace_method", "onefield");
                     m_mltConsumer->set("real_time", KdenliveSettings::mltthreads());
                     mlt_log_set_callback(kdenlive_callback);
@@ -291,10 +288,13 @@ Mlt::Producer *Render::invalidProducer(const QString &id)
     return clip;
 }
 
+bool Render::hasProfile(const QString &profileName) const
+{
+    return m_activeProfile == profileName;
+}
+
 int Render::resetProfile(const QString &profileName, bool dropSceneList)
 {
-    QString scene;
-    if (!dropSceneList) scene = sceneList();
     if (m_mltConsumer) {
         if (m_externalConsumer == KdenliveSettings::external_display()) {
             if (KdenliveSettings::external_display() && m_activeProfile == profileName) return 1;
@@ -315,6 +315,8 @@ int Render::resetProfile(const QString &profileName, bool dropSceneList)
         delete m_mltConsumer;
         m_mltConsumer = NULL;
     }
+    QString scene;
+    if (!dropSceneList) scene = sceneList();
     int pos = 0;
     double current_fps = m_mltProfile->fps();
     double current_dar = m_mltProfile->dar();
@@ -360,16 +362,22 @@ void Render::seek(GenTime time)
 {
     if (!m_mltProducer)
         return;
+
     m_mltProducer->seek((int)(time.frames(m_fps)));
-    refresh();
+    if (m_mltProducer->get_speed() == 0) {
+        refresh();
+    }
 }
 
 void Render::seek(int time)
 {
     if (!m_mltProducer)
         return;
+
     m_mltProducer->seek(time);
-    refresh();
+    if (m_mltProducer->get_speed() == 0) {
+        refresh();
+    }
 }
 
 //static
@@ -561,8 +569,10 @@ void Render::getFileProperties(const QDomElement &xml, const QString &clipId, in
     info.imageHeight = imageHeight;
     info.replaceProducer = replaceProducer;
     // Make sure we don't request the info for same clip twice
+    m_infoMutex.lock();
     m_requestList.removeAll(info);
     m_requestList.append(info);
+    m_infoMutex.unlock();
     if (!m_infoThread.isRunning())
         m_infoThread = QtConcurrent::run(this, &Render::processFileProperties);
 }
@@ -591,6 +601,21 @@ int Render::processingItems() const
     return count;
 }
 
+bool Render::isProcessing(const QString &id)
+{
+    if (m_processingClipId == id) return true;
+    m_infoMutex.lock();
+    for (int i = 0; i < m_requestList.count(); i++) {
+        requestClipInfo info = m_requestList.at(i);
+        if (info.clipId == id) {
+            m_infoMutex.unlock();
+            return true;
+        }
+    }
+    m_infoMutex.unlock();
+    return false;
+}
+
 void Render::processFileProperties()
 {
     requestClipInfo info;
@@ -599,7 +624,7 @@ void Render::processFileProperties()
         m_infoMutex.lock();
         info = m_requestList.takeFirst();
         m_infoMutex.unlock();
-        if (info.replaceProducer) emit blockClipMonitor(info.clipId);
+        m_processingClipId = info.clipId;
         QString path;
         bool proxyProducer;
         if (info.xml.hasAttribute("proxy") && info.xml.attribute("proxy") != "-") {
@@ -640,6 +665,7 @@ void Render::processFileProperties()
             }
             else emit removeInvalidClip(info.clipId, info.replaceProducer);
             delete producer;
+            m_processingClipId.clear();
             continue;
         }
 
@@ -650,6 +676,7 @@ void Render::processFileProperties()
                 // Proxy file length is different than original clip length, this will corrupt project so disable this proxy clip
                 emit removeInvalidProxy(info.clipId, true);
                 delete producer;
+                m_processingClipId.clear();
                 continue;
             }
         }
@@ -726,19 +753,30 @@ void Render::processFileProperties()
 
         if (info.xml.hasAttribute("templatetext"))
             producer->set("templatetext", info.xml.attribute("templatetext").toUtf8().constData());
+
+        int imageWidth = (int)((double) info.imageHeight * m_mltProfile->width() / m_mltProfile->height() + 0.5);
+        int fullWidth = (int)((double) info.imageHeight * m_mltProfile->dar() + 0.5);
+        int frameNumber = info.xml.attribute("thumbnail", "-1").toInt();
         
         if ((!info.replaceProducer && info.xml.hasAttribute("file_hash")) || proxyProducer) {
             // Clip  already has all properties
-            emit replyGetFileProperties(info.clipId, producer, stringMap(), stringMap(), info.replaceProducer, true);
+            if (proxyProducer) {
+                // Recreate clip thumb
+                if (frameNumber > 0) producer->seek(frameNumber);
+                Mlt::Frame *frame = producer->get_frame();
+                if (frame && frame->is_valid()) {
+                    QImage img = KThumb::getFrame(frame, imageWidth, fullWidth, info.imageHeight);
+                    delete frame;
+                    emit replyGetImage(info.clipId, img);
+                }
+            }
+            emit replyGetFileProperties(info.clipId, producer, stringMap(), stringMap(), info.replaceProducer);
+            m_processingClipId.clear();
             continue;
         }
 
-        int imageWidth = (int)((double) info.imageHeight * m_mltProfile->width() / m_mltProfile->height() + 0.5);
-        int fullWidth = (int)((double) info.imageHeight * m_mltProfile->dar() + 0.5);
         stringMap filePropertyMap;
         stringMap metadataPropertyMap;
-
-        int frameNumber = info.xml.attribute("thumbnail", "-1").toInt();
         if (frameNumber > 0) producer->seek(frameNumber);
         
         duration = duration > 0 ? duration : producer->get_playtime();
@@ -826,6 +864,7 @@ void Render::processFileProperties()
                         variance = -1;
                     }
                 } while (variance == -1);
+                delete frame;
                 if (frameNumber > -1) filePropertyMap["thumbnail"] = frameNumber;
                 emit replyGetImage(info.clipId, img);
             } else if (frame->get_int("test_audio") == 0) {
@@ -833,7 +872,6 @@ void Render::processFileProperties()
                 filePropertyMap["type"] = "audio";
             }
         }
-        delete frame;
         // Retrieve audio / video codec name
 
         // If there is a
@@ -905,6 +943,7 @@ void Render::processFileProperties()
         producer->seek(0);
         emit replyGetFileProperties(info.clipId, producer, filePropertyMap, metadataPropertyMap, info.replaceProducer);
     }
+    m_processingClipId.clear();
 }
 
 
@@ -948,48 +987,50 @@ void Render::initSceneList()
 
 int Render::setProducer(Mlt::Producer *producer, int position)
 {
-    kDebug()<<"//////////\n SET CLIP PRODUCER  \n//////////";
     QMutexLocker locker(&m_mutex);
-    if (m_winid == -1) return -1;
-    if (m_mltConsumer) {
-        if (!m_mltConsumer->is_stopped()) {
-            m_mltConsumer->stop();
-            m_mltConsumer->purge();
-        }
-        m_mltConsumer->set("refresh", 0);
-    }
-    else {
-        return -1;
+    QString currentId;
+    int consumerPosition = 0;
+    if (m_winid == -1 || !m_mltConsumer) return -1;
+    m_mltConsumer->set("refresh", 0);
+    if (!m_mltConsumer->is_stopped()) {
+        m_mltConsumer->stop();
     }
+    m_mltConsumer->purge();
+    consumerPosition = m_mltConsumer->position();
 
     if (m_mltProducer) {
         m_mltProducer->set_speed(0);
+        currentId = m_mltProducer->get("id");
         delete m_mltProducer;
         m_mltProducer = NULL;
         emit stopped();
     }
+
     blockSignals(true);
     if (producer && producer->is_valid()) {
-        m_mltProducer = new Mlt::Producer(producer->get_producer());
+        m_mltProducer = producer;
     } else m_mltProducer = m_blackClip->cut(0, 1);
 
     if (!m_mltProducer || !m_mltProducer->is_valid()) {
         kDebug() << " WARNING - - - - -INVALID PLAYLIST: ";
         return -1;
     }
+    if (position == -1 && m_mltProducer->get("id") == currentId) position = consumerPosition;
+    if (position != -1) m_mltProducer->seek(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 (producer == NULL) {
-        return error;
-    }
 
-    if (position != -1) {
-        m_mltProducer->seek(position);
-        emit rendererPosition(position);
-    } else emit rendererPosition((int) m_mltProducer->position());
+    position = m_mltProducer->position();
+    m_mltConsumer->set("refresh", 1);
+    // Make sure the first frame is displayed, otherwise if we change producer too fast
+    // We can crash the avformat producer
+    Mlt::Event *ev = m_mltConsumer->setup_wait_for("consumer-frame-show");
+    m_mltConsumer->wait_for(ev);
+    delete ev;
+    emit rendererPosition(position);
     return error;
 }
 
@@ -1000,6 +1041,7 @@ int Render::setSceneList(QDomDocument list, int position)
 
 int Render::setSceneList(QString playlist, int position)
 {
+    QMutexLocker locker(&m_mutex);
     if (m_winid == -1) return -1;
     int error = 0;
 
@@ -1217,7 +1259,6 @@ double Render::fps() const
 int Render::connectPlaylist()
 {
     if (!m_mltConsumer) return -1;
-    //m_mltConsumer->set("refresh", "0");
     m_mltConsumer->connect(*m_mltProducer);
     m_mltProducer->set_speed(0);
     if (m_mltConsumer->start() == -1) {
@@ -1229,28 +1270,8 @@ int Render::connectPlaylist()
     }
     emit durationChanged(m_mltProducer->get_playtime());
     return 0;
-    //refresh();
 }
 
-void Render::refreshDisplay()
-{
-
-    if (!m_mltProducer) return;
-    //m_mltConsumer->set("refresh", 0);
-
-    //mlt_properties properties = MLT_PRODUCER_PROPERTIES(m_mltProducer->get_producer());
-    /*if (KdenliveSettings::osdtimecode()) {
-        mlt_properties_set_int( properties, "meta.attr.timecode", 1);
-        mlt_properties_set( properties, "meta.attr.timecode.markup", "#timecode#");
-        m_osdInfo->set("dynamic", "1");
-        m_mltProducer->attach(*m_osdInfo);
-    }
-    else {
-        m_mltProducer->detach(*m_osdInfo);
-        m_osdInfo->set("dynamic", "0");
-    }*/
-    refresh();
-}
 
 int Render::volume() const
 {
@@ -1291,41 +1312,41 @@ void Render::slotOsdTimeout()
 
 void Render::start()
 {
+    QMutexLocker locker(&m_mutex);
     if (m_winid == -1) {
         kDebug() << "-----  BROKEN MONITOR: " << m_name << ", RESTART";
         return;
     }
+
     if (m_mltConsumer && m_mltConsumer->is_stopped()) {
         if (m_mltConsumer->start() == -1) {
             //KMessageBox::error(qApp->activeWindow(), i18n("Could not create the video preview window.\nThere is something wrong with your Kdenlive install or your driver settings, please fix it."));
             kDebug(QtWarningMsg) << "/ / / / CANNOT START MONITOR";
         } else {
-            refresh();
+            m_mltConsumer->purge();
+            m_mltConsumer->set("refresh", 1);
         }
     }
 }
 
 void Render::stop()
 {
+    QMutexLocker locker(&m_mutex);
     if (m_mltProducer == NULL) return;
     if (m_mltConsumer && !m_mltConsumer->is_stopped()) {
-        //kDebug() << "/////////////   RENDER STOPPED: " << m_name;
-        //m_mltConsumer->set("refresh", 0);
         m_mltConsumer->stop();
-        // delete m_mltConsumer;
-        // m_mltConsumer = NULL;
+        m_mltConsumer->purge();
     }
 
     if (m_mltProducer) {
         if (m_isZoneMode) resetZoneMode();
         m_mltProducer->set_speed(0.0);
-        //m_mltProducer->set("out", m_mltProducer->get_length() - 1);
-        //kDebug() << m_mltProducer->get_length();
     }
 }
 
 void Render::stop(const GenTime & startTime)
 {
+    QMutexLocker locker(&m_mutex);
     if (m_mltProducer) {
         if (m_isZoneMode) resetZoneMode();
         m_mltProducer->set_speed(0.0);
@@ -1342,28 +1363,30 @@ void Render::pause()
     if (m_isZoneMode) resetZoneMode();
     m_mltConsumer->set("refresh", 0);
     m_mltProducer->set_speed(0.0);
-    /*
-    The 2 lines below create a flicker loop
-    emit rendererPosition(m_framePosition);
-    m_mltProducer->seek(m_framePosition);*/
     m_mltConsumer->purge();
 }
 
 void Render::switchPlay(bool play)
 {
+    QMutexLocker locker(&m_mutex);
     if (!m_mltProducer || !m_mltConsumer)
         return;
     if (m_isZoneMode) resetZoneMode();
     if (play && m_mltProducer->get_speed() == 0.0) {
-        if (m_name == "clip" && m_framePosition == (int) m_mltProducer->get_out()) m_mltProducer->seek(0);
+        if (m_name == "clip" && m_mltConsumer->position() == m_mltProducer->get_out()) m_mltProducer->seek(0);
+        if (m_mltConsumer->is_stopped()) {
+            m_mltConsumer->start();
+        }
+        m_mltConsumer->set("refresh", "1");
         m_mltProducer->set_speed(1.0);
-        m_mltConsumer->set("refresh", 1);
-        if (m_mltConsumer->is_stopped()) m_mltConsumer->start();
     } else if (!play) {
-        stop();
-        m_mltConsumer->set("refresh", "0");
-        m_framePosition++;
-        m_mltProducer->seek(m_framePosition);
+        m_mltProducer->set_speed(0.0);
+        m_mltConsumer->set("refresh", 0);
+        m_mltProducer->seek(m_mltConsumer->position());
+        if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop();
+        if (m_isZoneMode) resetZoneMode();
+        
+        //emitConsumerStopped();
         /*m_mltConsumer->set("refresh", 0);
         m_mltConsumer->stop();
         m_mltConsumer->purge();
@@ -1431,9 +1454,12 @@ void Render::seekToFrame(int pos)
 {
     if (!m_mltProducer)
         return;
+    
     resetZoneMode();
     m_mltProducer->seek(pos);
-    refresh();
+    if (m_mltProducer->get_speed() == 0) {
+        refresh();
+    }
 }
 
 void Render::seekToFrameDiff(int diff)
@@ -1448,6 +1474,7 @@ void Render::seekToFrameDiff(int diff)
 void Render::doRefresh()
 {
     // Use a Timer so that we don't refresh too much
+    QMutexLocker locker(&m_mutex);
     if (m_mltConsumer) {
         if (m_mltConsumer->is_stopped()) m_mltConsumer->start();
         m_mltConsumer->set("refresh", 1);
@@ -1456,16 +1483,19 @@ void Render::doRefresh()
 
 void Render::refresh()
 {
+    QMutexLocker locker(&m_mutex);
     if (!m_mltProducer)
         return;
     if (m_mltConsumer) {
-        m_mltConsumer->set("refresh", 1);
         if (m_mltConsumer->is_stopped()) m_mltConsumer->start();
+        m_mltConsumer->purge();
+        m_mltConsumer->set("refresh", 1);
     }
 }
 
 void Render::setDropFrames(bool show)
 {
+    QMutexLocker locker(&m_mutex);
     if (m_mltConsumer) {
         int dropFrames = KdenliveSettings::mltthreads();
         if (show == false) dropFrames = -dropFrames;
@@ -1496,7 +1526,8 @@ GenTime Render::seekPosition() const
 
 int Render::seekFramePosition() const
 {
-    if (m_mltProducer) return (int) m_mltProducer->position();
+    //if (m_mltProducer) return (int) m_mltProducer->position();
+    if (m_mltConsumer) return (int) m_mltConsumer->position();
     return 0;
 }
 
@@ -1516,11 +1547,9 @@ void Render::emitFrameUpdated(Mlt::Frame& frame)
     emit frameUpdated(qimage);
 }
 
-void Render::emitFrameNumber(double position)
+void Render::emitFrameNumber()
 {
-    kDebug()<<"+++++++++++++++++++++++++++++++++++++++\n   "<<m_name<<" GOT POSITION: "<<position<<"\n++++++++++++++++++++++++++";
-    m_framePosition = position;
-    emit rendererPosition((int) position);
+    if (m_mltConsumer) emit rendererPosition((int) m_mltConsumer->position());
 }
 
 void Render::emitConsumerStopped()
@@ -1568,8 +1597,7 @@ void Render::exportCurrentFrame(KUrl url, bool /*notify*/)
 
 void Render::showFrame(Mlt::Frame& frame)
 {
-    m_framePosition = qMax(frame.get_int("_position"), 0);
-    emit rendererPosition((int) m_framePosition);
+    emit rendererPosition((int) m_mltConsumer->position());
     mlt_image_format format = mlt_image_rgb24a;
     int width = 0;
     int height = 0;
@@ -1645,6 +1673,7 @@ void Render::mltCheckLength(Mlt::Tractor *tractor)
         }
 
         if (blackclip == NULL || blackTrackPlaylist.count() != 1) {
+            if (blackclip) delete blackclip;
             blackTrackPlaylist.clear();
             m_blackClip->set("length", duration + 1);
             m_blackClip->set("out", duration);
@@ -1833,19 +1862,30 @@ void Render::mltCutClip(int track, GenTime position)
 
 }
 
-void Render::lock()
+Mlt::Tractor *Render::lockService()
 {
-    if (!m_mltProducer) return;
+    // we are going to replace some clips, purge consumer
+    QMutexLocker locker(&m_mutex);
+    if (!m_mltProducer) return NULL;
+    if (m_mltConsumer) {
+        if (!m_mltConsumer->is_stopped()) m_mltConsumer->stop();
+        m_mltConsumer->purge();
+    }
     Mlt::Service service(m_mltProducer->parent().get_service());
     if (service.type() != tractor_type) {
         kWarning() << "// TRACTOR PROBLEM";
-        return;
+        return NULL;
     }
     service.lock();
+    return new Mlt::Tractor(service);
+    
 }
 
-void Render::unlock()
+void Render::unlockService(Mlt::Tractor *tractor)
 {
+    if (tractor) {
+        delete tractor;
+    }
     if (!m_mltProducer) return;
     Mlt::Service service(m_mltProducer->parent().get_service());
     if (service.type() != tractor_type) {
@@ -1855,21 +1895,15 @@ void Render::unlock()
     service.unlock();
 }
 
-bool Render::mltUpdateClip(ItemInfo info, QDomElement element, Mlt::Producer *prod)
+bool Render::mltUpdateClip(Mlt::Tractor *tractor, ItemInfo info, QDomElement element, Mlt::Producer *prod)
 {
     // TODO: optimize
-    if (prod == NULL) {
+    if (prod == NULL || tractor == NULL) {
         kDebug() << "Cannot update clip with null producer //////";
         return false;
     }
 
-    Mlt::Service service(m_mltProducer->parent().get_service());
-    if (service.type() != tractor_type) {
-        kWarning() << "// TRACTOR PROBLEM";
-        return false;
-    }
-    Mlt::Tractor tractor(service);
-    Mlt::Producer trackProducer(tractor.track(tractor.count() - 1 - info.track));
+    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);
@@ -1881,7 +1915,6 @@ bool Render::mltUpdateClip(ItemInfo info, QDomElement element, Mlt::Producer *pr
     // keep effects
     QList <Mlt::Filter *> filtersList;
     Mlt::Service sourceService(clip->get_service());
-    sourceService.lock();
     int ct = 0;
     Mlt::Filter *filter = sourceService.filter(ct);
     while (filter) {
@@ -1891,8 +1924,8 @@ bool Render::mltUpdateClip(ItemInfo info, QDomElement element, Mlt::Producer *pr
         ct++;
         filter = sourceService.filter(ct);
     }
-
-    trackPlaylist.replace_with_blank(clipIndex);
+    delete clip;
+    clip = trackPlaylist.replace_with_blank(clipIndex);
     delete clip;
     prod = checkSlowMotionProducer(prod, element);
     if (prod == NULL || !prod->is_valid()) {
@@ -3186,35 +3219,26 @@ bool Render::mltMoveClip(int startTrack, int endTrack, GenTime moveStart, GenTim
 }
 
 
-bool Render::mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod)
+bool Render::mltUpdateClipProducer(Mlt::Tractor *tractor, int track, int pos, Mlt::Producer *prod)
 {
-    if (prod == NULL || !prod->is_valid()) {
+    if (prod == NULL || !prod->is_valid() || tractor == NULL || !tractor->is_valid()) {
         kDebug() << "// Warning, CLIP on track " << track << ", at: " << pos << " is invalid, cannot update it!!!";
         return false;
     }
-    //kDebug() << "// TRYING TO UPDATE CLIP at: " << pos << ", TK: " << track;
-    Mlt::Service service(m_mltProducer->parent().get_service());
-    if (service.type() != tractor_type) {
-        kWarning() << "// TRACTOR PROBLEM";
-        return false;
-    }
-    service.lock();
-    Mlt::Tractor tractor(service);
-    Mlt::Producer trackProducer(tractor.track(track));
+
+    Mlt::Producer trackProducer(tractor->track(track));
     Mlt::Playlist trackPlaylist((mlt_playlist) trackProducer.get_service());
     int clipIndex = trackPlaylist.get_clip_index_at(pos);
     Mlt::Producer *clipProducer = trackPlaylist.replace_with_blank(clipIndex);
     if (clipProducer == NULL || clipProducer->is_blank()) {
         kDebug() << "// ERROR UPDATING CLIP PROD";
         delete clipProducer;
-        service.unlock();
         return false;
     }
     Mlt::Producer *clip = prod->cut(clipProducer->get_in(), clipProducer->get_out());
     if (!clip || !clip->is_valid()) {
         if (clip) delete clip;
         delete clipProducer;
-        service.unlock();
         return false;
     }
     // move all effects to the correct producer
@@ -3222,7 +3246,6 @@ bool Render::mltUpdateClipProducer(int track, int pos, Mlt::Producer *prod)
     trackPlaylist.insert_at(pos, clip, 1);
     delete clip;
     delete clipProducer;
-    service.unlock();
     return true;
 }
 
@@ -3996,7 +4019,7 @@ void Render::mltDeleteTrack(int ix)
     }
     tractor.removeChild(track);
     //kDebug() << "/////////// RESULT SCENE: \n" << doc.toString();
-    setSceneList(doc.toString(), m_framePosition);
+    setSceneList(doc.toString(), m_mltConsumer->position());
     emit refreshDocumentProducers(false, false);
 }
 
@@ -4006,6 +4029,7 @@ void Render::updatePreviewSettings()
     kDebug() << "////// RESTARTING CONSUMER";
     if (!m_mltConsumer || !m_mltProducer) return;
     if (m_mltProducer->get_playtime() == 0) return;
+    QMutexLocker locker(&m_mutex);
     Mlt::Service service(m_mltProducer->parent().get_service());
     if (service.type() != tractor_type) return;