]> git.sesse.net Git - kdenlive/commitdiff
Try to fix the concurrency issues causing crash in the avformat producer
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Sat, 22 Oct 2011 16:56:43 +0000 (16:56 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Sat, 22 Oct 2011 16:56:43 +0000 (16:56 +0000)
svn path=/trunk/kdenlive/; revision=5976

12 files changed:
src/customtrackview.cpp
src/docclipbase.cpp
src/docclipbase.h
src/kthumb.cpp
src/mainwindow.cpp
src/mainwindow.h
src/monitor.cpp
src/monitor.h
src/projectlist.cpp
src/projectlist.h
src/renderer.cpp
src/renderer.h

index 428612df4ece540b243863d1d2098c9e7564fa1b..f00f7ad69846910b54c92c08e2c21ed564692259 100644 (file)
@@ -4200,12 +4200,9 @@ void CustomTrackView::slotUpdateClip(const QString &clipId, bool reload)
             }
         }
     }
-    m_document->renderer()->unlockService(tractor);
     for (int i = 0; i < clipList.count(); i++)
         clipList.at(i)->refreshClip(true, true);
-    if (baseClip) {
-        baseClip->cleanupProducers();
-    }
+    m_document->renderer()->unlockService(tractor);
 }
 
 ClipItem *CustomTrackView::getClipItemAtEnd(GenTime pos, int track)
index 171392ddff4db9d22cb753cc8b9338a6b4feb587..68ab905615a158ca3161aaaab618ad7166913b8e 100644 (file)
@@ -624,6 +624,25 @@ Mlt::Producer *DocClipBase::videoProducer()
     return m_videoOnlyProducer;
 }
 
+Mlt::Producer *DocClipBase::getCloneProducer(Mlt::Producer *source)
+{
+    QMutexLocker locker(&m_producerMutex);
+    if (source == NULL) {
+        for (int i = 0; i < m_baseTrackProducers.count(); i++) {
+            if (m_baseTrackProducers.at(i) != NULL) {
+                source = m_baseTrackProducers.at(i);
+                break;
+            }
+        }
+    }
+    if (source) {
+        Mlt::Producer *prod = cloneProducer(source);
+        adjustProducerProperties(prod, getId() + "_monitor", false, false);
+        return prod;
+    }
+    return NULL;
+}
+
 Mlt::Producer *DocClipBase::getProducer(int track)
 {
     QMutexLocker locker(&m_producerMutex);
index edccd3c4d4220f43d573fa7fccbfcb3df32a502f..9d8a59b4e0e55a14b4b4e6a309ea8956ffe9a58a 100644 (file)
@@ -120,6 +120,8 @@ Q_OBJECT public:
     void setProducer(Mlt::Producer *producer, bool reset = false, bool readPropertiesFromProducer = false);
     /** Retrieve a producer for a track */
     Mlt::Producer *getProducer(int track = -1);
+    /** Get a copy of the producer, for use in the clip monitor */
+    Mlt::Producer *getCloneProducer(Mlt::Producer *source = NULL);
     /** Retrieve the producer that shows only video */
     Mlt::Producer *videoProducer();
     /** Retrieve the producer that shows only audio */
index ac232e66c62124611d23fe969ff3664905c27e10..71f2bfc96dc37d5a20d75f9a2110c28ee7377ff6 100644 (file)
@@ -222,13 +222,14 @@ QImage KThumb::getFrame(Mlt::Frame *frame, int frameWidth, int displayWidth, int
     int ow = frameWidth;
     int oh = height;
     mlt_image_format format = mlt_image_rgb24a;
-    uint8_t *data = frame->get_image(format, ow, oh, 0);
-    QImage image((uchar *)data, ow, oh, QImage::Format_ARGB32_Premultiplied);
+    
+    const uchar* imagedata = frame->get_image(format, ow, oh);
+    QImage image(imagedata, ow, oh, QImage::Format_ARGB32_Premultiplied);
+    
     if (!image.isNull()) {
         if (ow > (2 * displayWidth)) {
             // there was a scaling problem, do it manually
-            QImage scaled = image.scaled(displayWidth, height);
-            image = scaled.rgbSwapped();
+            image = image.scaled(displayWidth, height).rgbSwapped();
         } else {
             image = image.scaled(displayWidth, height, Qt::IgnoreAspectRatio).rgbSwapped();
         }
index 30616e1cf6eb979a27e1e6cfbe6cf6730f3e52b4..0c4376c5d61615bb401bd100b0a6d9cdea7e2cff 100644 (file)
@@ -208,7 +208,8 @@ MainWindow::MainWindow(const QString &MltPath, const KUrl & Url, const QString &
     m_clipMonitorDock->setObjectName("clip_monitor");
     m_clipMonitor = new Monitor("clip", m_monitorManager, QString(), m_timelineArea);
     m_clipMonitorDock->setWidget(m_clipMonitor);
-    connect(m_projectList, SIGNAL(clipSelected(DocClipBase *, QPoint)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *, QPoint)));
+    connect(m_projectList, SIGNAL(clipSelected(DocClipBase *, QPoint)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint)));
+    connect(m_projectList, SIGNAL(raiseClipMonitor()), m_clipMonitor, SLOT(activateMonitor()));
     
     m_projectMonitorDock = new QDockWidget(i18n("Project Monitor"), this);
     m_projectMonitorDock->setObjectName("project_monitor");
@@ -839,23 +840,28 @@ void MainWindow::slotAddEffect(const QDomElement effect)
 void MainWindow::slotUpdateClip(const QString &id)
 {
     if (!m_activeDocument) return;
-    m_activeTimeline->projectView()->slotUpdateClip(id);
+    DocClipBase *clip = m_activeDocument->clipManager()->getClipById(id);
+    if (clip->numReferences() > 0) m_activeTimeline->projectView()->slotUpdateClip(id);
+    if (m_clipMonitor->activeClip() && m_clipMonitor->activeClip()->getId() == id) {
+        if (clip) m_clipMonitor->updateClipProducer(clip->getCloneProducer());
+    }
+    if (clip) {
+        clip->cleanupProducers();
+    }
 }
 
 void MainWindow::slotConnectMonitors()
 {
     m_projectList->setRenderer(m_projectMonitor->render);
-    //connect(m_projectList, SIGNAL(receivedClipDuration(const QString &)), this, SLOT(slotUpdateClip(const QString &)));
     connect(m_projectList, SIGNAL(deleteProjectClips(QStringList, QMap<QString, QString>)), this, SLOT(slotDeleteProjectClips(QStringList, QMap<QString, QString>)));
     connect(m_projectList, SIGNAL(showClipProperties(DocClipBase *)), this, SLOT(slotShowClipProperties(DocClipBase *)));
     connect(m_projectList, SIGNAL(showClipProperties(QList <DocClipBase *>, QMap<QString, QString>)), this, SLOT(slotShowClipProperties(QList <DocClipBase *>, QMap<QString, QString>)));
     connect(m_projectMonitor->render, SIGNAL(replyGetImage(const QString &, const QString &, int, int)), m_projectList, SLOT(slotReplyGetImage(const QString &, const QString &, int, int)));
     connect(m_projectMonitor->render, SIGNAL(replyGetImage(const QString &, const QImage &)), m_projectList, SLOT(slotReplyGetImage(const QString &, const QImage &)));
-    connect(m_projectMonitor->render, SIGNAL(replyGetFileProperties(const QString &, Mlt::Producer*, const stringMap &, const stringMap &, bool, bool)), m_projectList, SLOT(slotReplyGetFileProperties(const QString &, Mlt::Producer*, const stringMap &, const stringMap &, bool, bool)));
+    connect(m_projectMonitor->render, SIGNAL(replyGetFileProperties(const QString &, Mlt::Producer*, const stringMap &, const stringMap &, bool, bool)), this, SLOT(slotReplyGetFileProperties(const QString &, Mlt::Producer*, const stringMap &, const stringMap &, bool, bool)));
 
     connect(m_projectMonitor->render, SIGNAL(removeInvalidClip(const QString &, bool)), m_projectList, SLOT(slotRemoveInvalidClip(const QString &, bool)));
     
-    connect(m_projectMonitor->render, SIGNAL(blockClipMonitor(const QString)), this, SLOT(slotBlockClipMonitor(const QString)));
     connect(m_projectMonitor->render, SIGNAL(removeInvalidProxy(const QString &, bool)), m_projectList, SLOT(slotRemoveInvalidProxy(const QString &, bool)));
 
     connect(m_clipMonitor, SIGNAL(refreshClipThumbnail(const QString &, bool)), m_projectList, SLOT(slotRefreshClipThumbnail(const QString &, bool)));
@@ -1867,7 +1873,7 @@ bool MainWindow::closeCurrentDocument(bool saveChanges)
             break;
         }
     }
-    m_clipMonitor->slotSetXml(NULL);
+    m_clipMonitor->slotSetClipProducer(NULL);
     m_timelineArea->removeTab(m_timelineArea->indexOf(w));
     if (m_timelineArea->count() == 1) {
         m_timelineArea->setTabBarHidden(true);
@@ -2279,7 +2285,7 @@ void MainWindow::slotUpdateProjectProfile(const QString &profile)
     // Deselect current effect / transition
     m_effectStack->slotClipItemSelected(NULL, 0);
     m_transitionConfig->slotTransitionItemSelected(NULL, 0, QPoint(), false);
-    m_clipMonitor->slotSetXml(NULL);
+    m_clipMonitor->slotSetClipProducer(NULL);
     bool updateFps = m_activeDocument->setProfilePath(profile);
     KdenliveSettings::setCurrent_profile(profile);
     KdenliveSettings::setProject_fps(m_activeDocument->fps());
@@ -2424,7 +2430,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
             disconnect(m_activeTimeline->projectView(), SIGNAL(transitionItemSelected(Transition*, int, QPoint, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(Transition*)));
             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, const int)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *, QPoint, const int)));
+            disconnect(m_activeTimeline->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, const int)));
             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)));
@@ -2444,7 +2450,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
             disconnect(m_projectList, SIGNAL(loadingIsOver()), m_activeTimeline->projectView(), SLOT(slotUpdateAllThumbs()));
             disconnect(m_projectList, SIGNAL(displayMessage(const QString&, int)), this, SLOT(slotGotProgressInfo(const QString&, int)));
             disconnect(m_projectList, SIGNAL(updateRenderStatus()), this, SLOT(slotCheckRenderStatus()));
-            disconnect(m_projectList, SIGNAL(clipNeedsReload(const QString&, bool)), m_activeTimeline->projectView(), SLOT(slotUpdateClip(const QString &, bool)));
+            disconnect(m_projectList, SIGNAL(clipNeedsReload(const QString&)), this, SLOT(slotUpdateClip(const QString &)));
             disconnect(m_projectList, SIGNAL(refreshClip(const QString &)), m_activeTimeline->projectView(), SLOT(slotRefreshThumbs(const QString &)));
             m_effectStack->clear();
         }
@@ -2460,7 +2466,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
     m_effectStack->updateProjectFormat(doc->mltProfile(), doc->timecode());
     connect(m_projectList, SIGNAL(refreshClip(const QString &, bool)), m_monitorManager, SLOT(slotRefreshCurrentMonitor()));
     connect(m_projectList, SIGNAL(refreshClip(const QString &, bool)), trackView->projectView(), SLOT(slotRefreshThumbs(const QString &, bool)));
-    connect(m_projectList, SIGNAL(clipNeedsReload(const QString&, bool)), trackView->projectView(), SLOT(slotUpdateClip(const QString &, bool)));
+    connect(m_projectList, SIGNAL(clipNeedsReload(const QString&)),this, SLOT(slotUpdateClip(const QString &)));
 
     connect(m_projectList, SIGNAL(projectModified()), doc, SLOT(setModified()));
     connect(m_projectList, SIGNAL(updateProfile(const QString &)), this, SLOT(slotUpdateProjectProfile(const QString &)));
@@ -2510,7 +2516,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc)   //cha
     connect(trackView, SIGNAL(setZoom(int)), this, SLOT(slotSetZoom(int)));
     connect(trackView->projectView(), SIGNAL(displayMessage(const QString&, MessageType)), m_messageLabel, SLOT(setMessage(const QString&, MessageType)));
 
-    connect(trackView->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, const int)), m_clipMonitor, SLOT(slotSetXml(DocClipBase *, QPoint, const int)));
+    connect(trackView->projectView(), SIGNAL(showClipFrame(DocClipBase *, QPoint, const int)), m_clipMonitor, SLOT(slotSetClipProducer(DocClipBase *, QPoint, const int)));
     connect(trackView->projectView(), SIGNAL(playMonitor()), m_projectMonitor, SLOT(slotPlay()));
 
     connect(trackView->projectView(), SIGNAL(clipItemSelected(ClipItem*, int, bool)), m_projectMonitor, SLOT(slotSetSelectedClip(ClipItem*)));
@@ -4379,9 +4385,9 @@ void MainWindow::slotOpenBackupDialog(const KUrl url)
     delete dia;
 }
 
-void MainWindow::slotBlockClipMonitor(const QString id)
+void MainWindow::slotReplyGetFileProperties(const QString &clipId, Mlt::Producer *producer, const stringMap &properties, const stringMap &metadata, bool replace, bool refreshThumbnail)
 {
-    if (m_clipMonitor->activeClip() && m_clipMonitor->activeClip()->getId() == id) m_clipMonitor->slotSetXml(NULL);
+    m_projectList->slotReplyGetFileProperties(clipId, producer, properties, metadata, replace, refreshThumbnail);
 }
 
 
index 7bec3fc84af0d01e043fa3fb8adf270192f0e9ea..bcd9b5a0fb87ff1e0dc14d90d85e63140936c878 100644 (file)
@@ -544,8 +544,8 @@ private slots:
     void slotInsertNotesTimecode();
     /** @brief Open the project's backupdialog. */
     void slotOpenBackupDialog(const KUrl url = KUrl());
-    /** @brief Make sure to block clip monitor before deleting a clip's producer. */
-    void slotBlockClipMonitor(const QString id);
+    /** @brief Make sure to update clip monitor before deleting a clip's producer. */
+    void slotReplyGetFileProperties(const QString &clipId, Mlt::Producer *producer, const stringMap &properties, const stringMap &metadata, bool replace, bool refreshThumbnail);
     /** @brief Disable proxies for this project. */
     void slotDisableProxies();
 
index b22c2cacaaf7ebdf47a8bb4d10c8ac1581e5d699..b446886ec3304d31030b0f017df0413db7c2a1b5 100644 (file)
@@ -59,7 +59,6 @@ Monitor::Monitor(QString name, MonitorManager *manager, QString profile, QWidget
     m_selectedClip(NULL),
     m_loopClipTransition(true),
     m_editMarker(NULL)
-
 {
     QVBoxLayout *layout = new QVBoxLayout;
     layout->setContentsMargins(0, 0, 0, 0);
@@ -804,10 +803,17 @@ void Monitor::slotLoopClip()
     m_playAction->setIcon(m_pauseIcon);
 }
 
-void Monitor::slotSetXml(DocClipBase *clip, QPoint zone, const int position)
+void Monitor::updateClipProducer(Mlt::Producer *prod)
+{
+    if (render == NULL) return;
+    render->setProducer(prod, render->seekFramePosition());
+}
+
+void Monitor::slotSetClipProducer(DocClipBase *clip, QPoint zone, int position)
 {
     if (render == NULL) return;
     if (clip == NULL && m_currentClip != NULL) {
+        kDebug()<<"// SETTING NULL CLIP MONITOR";
         m_currentClip = NULL;
         m_length = -1;
         render->setProducer(NULL, -1);
@@ -817,13 +823,18 @@ void Monitor::slotSetXml(DocClipBase *clip, QPoint zone, const int position)
         m_currentClip = clip;
         if (m_currentClip) activateMonitor();
         updateMarkers(clip);
-        if (render->setProducer(clip->getProducer(), position) == -1) {
+        Mlt::Producer *prod = NULL;
+        if (clip) prod = clip->getCloneProducer();
+        if (render->setProducer(prod, position) == -1) {
             // MLT CONSUMER is broken
             kDebug(QtWarningMsg) << "ERROR, Cannot start monitor";
         }
     } else {
-        if (m_currentClip) activateMonitor();
-        if (position != -1) render->seek(position);
+        if (m_currentClip) {
+            activateMonitor();
+            if (position == -1) position = render->seekFramePosition();
+            render->seek(position);
+        }
     }
     if (!zone.isNull()) {
         m_ruler->setZone(zone.x(), zone.y());
index 45f0179a823fe8e8ba924a281a04fb3ff3eda74e..5dc9113d2b3f4e98761088d5f03644ef958cf629 100644 (file)
@@ -176,6 +176,7 @@ private:
     /** true if selected clip is transition, false = selected clip is clip.
      *  Necessary because sometimes we get two signals, e.g. we get a clip and we get selected transition = NULL. */
     bool m_loopClipTransition;
+
 #if defined(Q_WS_MAC) || defined(USE_OPEN_GL)
     VideoGLWidget *m_glWidget;
     bool createOpenGlWidget(QWidget *parent, const QString profile);
@@ -207,7 +208,8 @@ private slots:
 
 public slots:
     void slotOpenFile(const QString &);
-    void slotSetXml(DocClipBase *clip, QPoint zone = QPoint(), const int position = -1);
+    void slotSetClipProducer(DocClipBase *clip, QPoint zone = QPoint(), int position = -1);
+    void updateClipProducer(Mlt::Producer *prod);
     void refreshMonitor(bool visible);
     void refreshMonitor();
     void slotSeek(int pos);
index 2b0999539d55621a67033f08dce024fc68b5d169..e798466b56dc2623949d3f37b5b5f297c62646d6 100644 (file)
@@ -160,7 +160,7 @@ ProjectList::ProjectList(QWidget *parent) :
     connect(this, SIGNAL(processNextThumbnail()), this, SLOT(slotProcessNextThumbnail()));
     connect(m_listView, SIGNAL(projectModified()), this, SIGNAL(projectModified()));
     connect(m_listView, SIGNAL(itemSelectionChanged()), this, SLOT(slotClipSelected()));
-    connect(m_listView, SIGNAL(focusMonitor()), this, SLOT(slotClipSelected()));
+    connect(m_listView, SIGNAL(focusMonitor()), this, SIGNAL(raiseClipMonitor()));
     connect(m_listView, SIGNAL(pauseMonitor()), this, SLOT(slotPauseMonitor()));
     connect(m_listView, SIGNAL(requestMenu(const QPoint &, QTreeWidgetItem *)), this, SLOT(slotContextMenu(const QPoint &, QTreeWidgetItem *)));
     connect(m_listView, SIGNAL(addClip()), this, SLOT(slotAddClip()));
@@ -500,8 +500,8 @@ void ProjectList::slotReloadClip(const QString &id)
         item = static_cast <ProjectItem *>(selected.at(i));
         if (item && !item->isProxyRunning()) {
             DocClipBase *clip = item->referencedClip();
-            if (!clip->isClean()) {
-                // The clip is currently under processing (replacement in timeline), we cannot reload it now.
+            if (!clip || !clip->isClean() || m_render->isProcessing(item->clipId())) {
+                kDebug()<<"//// TRYING TO RELOAD: "<<item->clipId()<<", but it is busy";
                 continue;
             }
             CLIPTYPE t = item->clipType();
@@ -523,10 +523,8 @@ void ProjectList::slotReloadClip(const QString &id)
                     e.setAttribute("length", length);
                 }
             }
-            if (clip) {
-                clip->clearThumbProducer();
-            }
             m_render->getFileProperties(e, item->clipId(), m_listView->iconSize().height(), true);
+            resetThumbsProducer(clip);
         }
     }
 }
@@ -579,7 +577,7 @@ void ProjectList::slotMissingClip(const QString &id)
             }
             item->referencedClip()->setProducer(newProd, true);
             item->slotSetToolTip();
-            emit clipNeedsReload(id, true);
+            emit clipNeedsReload(id);
         }
     }
     update();
@@ -1087,8 +1085,8 @@ void ProjectList::slotAddClip(DocClipBase *clip, bool getProperties)
         m_listView->processLayout();
         QDomElement e = clip->toXML().cloneNode().toElement();
         e.removeAttribute("file_hash");
-        clip->clearThumbProducer();
         m_render->getFileProperties(e, clip->getId(), m_listView->iconSize().height(), true);
+        resetThumbsProducer(clip);
     }
     else if (item->hasProxy() && !item->isProxyRunning()) {
         slotCreateProxy(clip->getId());
@@ -1145,11 +1143,6 @@ void ProjectList::slotGotProxy(ProjectItem *item)
 {
     if (item == NULL || !m_refreshed) return;
     DocClipBase *clip = item->referencedClip();
-    if (!clip->isClean()) {
-        //WARNING: might result in clip said marked as proxy but not using proxy?
-        // The clip is currently under processing (replacement in timeline), we cannot reload it now.
-        return;
-    }
     // Proxy clip successfully created
     QDomElement e = clip->toXML().cloneNode().toElement();
 
@@ -1161,7 +1154,6 @@ void ProjectList::slotGotProxy(ProjectItem *item)
             e.setAttribute("length", length);
         }
     }
-    clip->clearThumbProducer();
     m_render->getFileProperties(e, clip->getId(), m_listView->iconSize().height(), true);
 }
 
@@ -1245,8 +1237,8 @@ void ProjectList::updateAllClips(bool displayRatioChanged, bool fpsChanged)
                         xml.removeAttribute("proxy_out");
                     }
                     bool replace = xml.attribute("replace") == "1";
-                    if (replace) clip->clearThumbProducer();
                     m_render->getFileProperties(xml, clip->getId(), m_listView->iconSize().height(), replace);
+                    if (replace) resetThumbsProducer(clip);
                 }
                 else {
                     item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDropEnabled);
@@ -1645,6 +1637,13 @@ void ProjectList::requestClipThumbnail(const QString id)
     slotProcessNextThumbnail();
 }
 
+void ProjectList::resetThumbsProducer(DocClipBase *clip)
+{
+    if (!clip) return;
+    clip->clearThumbProducer();
+    m_thumbnailQueue.removeAll(clip->getId());
+}
+
 void ProjectList::slotProcessNextThumbnail()
 {
     if (m_render->processingItems() > 0) {
@@ -1725,7 +1724,7 @@ void ProjectList::slotRefreshMonitor()
         if (m_listView->currentItem() && m_listView->currentItem()->type() != PROJECTFOLDERTYPE) {
             ProjectItem *item = static_cast <ProjectItem*>(m_listView->currentItem());
             DocClipBase *clip = item->referencedClip();
-            if (clip && clip->isClean()) emit clipSelected(clip);
+            if (clip && clip->isClean() && !m_render->isProcessing(item->clipId())) emit clipSelected(clip);
         }
     }
 }
@@ -1749,8 +1748,8 @@ void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Produce
             }
             item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsDropEnabled);
         }
-        clip->setProducer(producer, replace);
         item->setProperties(properties, metadata);
+        clip->setProducer(producer, replace);
         clip->askForAudioThumbs();
         if (refreshThumbnail) getCachedThumbnail(item);
         // Proxy stuff
@@ -1808,18 +1807,17 @@ void ProjectList::slotReplyGetFileProperties(const QString &clipId, Mlt::Produce
         processNextThumbnail();
     }
     if (replace && item) {
-        if (item->numReferences() > 0) toReload = clipId;
-        else item->referencedClip()->cleanupProducers();
+        toReload = clipId;
         // update clip in clip monitor
-        if (queue == 0 && item->isSelected() && m_listView->selectedItems().count() == 1)
-            m_refreshMonitorTimer.start();
+        /*if (queue == 0 && item->isSelected() && m_listView->selectedItems().count() == 1)
+            m_refreshMonitorTimer.start();*/
     }
     if (!item) {
         // no item for producer, delete it
         delete producer;
     }
     if (!toReload.isEmpty())
-        emit clipNeedsReload(toReload, true);
+        emit clipNeedsReload(toReload);
 }
 
 bool ProjectList::adjustProjectProfileToItem(ProjectItem *item)
@@ -2601,12 +2599,15 @@ void ProjectList::slotProxyCurrentItem(bool doProxy)
             CLIPTYPE t = item->clipType();
             if ((t == VIDEO || t == AV || t == UNKNOWN || t == IMAGE || t == PLAYLIST) && item->referencedClip()) {
                 if ((doProxy && item->hasProxy()) || (!doProxy && !item->hasProxy())) continue;
-                oldProps = item->referencedClip()->properties();
+                DocClipBase *clip = item->referencedClip();
+                if (!clip->isClean() || m_render->isProcessing(item->clipId())) continue;
+                resetThumbsProducer(clip);
+                oldProps = clip->properties();
                 if (doProxy) {
                     newProps.clear();
-                    QString path = proxydir + item->referencedClip()->getClipHash() + "." + (t == IMAGE ? "png" : m_doc->getDocumentProperty("proxyextension"));
+                    QString path = proxydir + clip->getClipHash() + "." + (t == IMAGE ? "png" : m_doc->getDocumentProperty("proxyextension"));
                     // insert required duration for proxy
-                    newProps.insert("proxy_out", item->referencedClip()->producerProperty("out"));
+                    newProps.insert("proxy_out", clip->producerProperty("out"));
                     newProps.insert("proxy", path);
                     // We need to insert empty proxy so that undo will work
                     oldProps.insert("proxy", QString());
index 1803c3627665f5f4fc879ee35d9010e906b8aacb..fbebd9f69f45578d956342b28a982af595ca9d63 100644 (file)
@@ -341,6 +341,8 @@ private:
     void setThumbnail(const QString &clipId, const QPixmap &pix);
     /** @brief Get cached thumbnail for a project's clip or create it if no cache. */
     void getCachedThumbnail(ProjectItem *item);
+    /** @brief The clip is about to be reloaded, cancel thumbnail requests. */
+    void resetThumbsProducer(DocClipBase *clip);
 
 private slots:
     void slotClipSelected();
@@ -393,7 +395,7 @@ signals:
     void loadingIsOver();
     void displayMessage(const QString, int progress);
     void clipNameChanged(const QString, const QString);
-    void clipNeedsReload(const QString&, bool);
+    void clipNeedsReload(const QString&);
     /** @brief A property affecting display was changed, so we need to update monitors and thumbnails
      *  @param id: The clip's id string
      *  @param resetThumbs Should we recreate the timeline thumbnails. */
@@ -404,6 +406,8 @@ signals:
     /** @brief Request a profile change for current document. */
     void updateProfile(const QString &);
     void processNextThumbnail();
+    /** @brief Activate the clip monitor. */
+    void raiseClipMonitor();
 };
 
 #endif
index 16078ff1d138384611f665eafc256d1d428c2e35..183fa2f180080b857d62912208ee419aede252fa 100644 (file)
@@ -565,8 +565,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);
 }
@@ -595,6 +597,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;
@@ -603,7 +620,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") != "-") {
@@ -644,6 +661,7 @@ void Render::processFileProperties()
             }
             else emit removeInvalidClip(info.clipId, info.replaceProducer);
             delete producer;
+            m_processingClipId.clear();
             continue;
         }
 
@@ -654,6 +672,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;
             }
         }
@@ -734,6 +753,7 @@ void Render::processFileProperties()
         if ((!info.replaceProducer && info.xml.hasAttribute("file_hash")) || proxyProducer) {
             // Clip  already has all properties
             emit replyGetFileProperties(info.clipId, producer, stringMap(), stringMap(), info.replaceProducer, true);
+            m_processingClipId.clear();
             continue;
         }
 
@@ -830,6 +850,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) {
@@ -837,7 +858,6 @@ void Render::processFileProperties()
                 filePropertyMap["type"] = "audio";
             }
         }
-        delete frame;
         // Retrieve audio / video codec name
 
         // If there is a
@@ -909,6 +929,7 @@ void Render::processFileProperties()
         producer->seek(0);
         emit replyGetFileProperties(info.clipId, producer, filePropertyMap, metadataPropertyMap, info.replaceProducer);
     }
+    m_processingClipId.clear();
 }
 
 
@@ -952,10 +973,12 @@ void Render::initSceneList()
 
 int Render::setProducer(Mlt::Producer *producer, int position)
 {
-    kDebug()<<"//////////\n SET CLIP PRODUCER  \n//////////";
     QMutexLocker locker(&m_mutex);
+    QString currentId;
+    int consumerPosition = 0;
     if (m_winid == -1) return -1;
     if (m_mltConsumer) {
+        consumerPosition = m_mltConsumer->position();
         if (!m_mltConsumer->is_stopped()) {
             m_mltConsumer->stop();
             m_mltConsumer->purge();
@@ -967,6 +990,7 @@ int Render::setProducer(Mlt::Producer *producer, int position)
     }
 
     if (m_mltProducer) {
+        currentId = m_mltProducer->get("id");
         m_mltProducer->set_speed(0);
         delete m_mltProducer;
         m_mltProducer = NULL;
@@ -974,13 +998,15 @@ int Render::setProducer(Mlt::Producer *producer, int position)
     }
     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();
@@ -990,10 +1016,7 @@ int Render::setProducer(Mlt::Producer *producer, int position)
         return error;
     }
 
-    if (position != -1) {
-        m_mltProducer->seek(position);
-        emit rendererPosition(position);
-    } else emit rendererPosition((int) m_mltProducer->position());
+    emit rendererPosition((int) m_mltProducer->position());
     return error;
 }
 
@@ -1280,6 +1303,7 @@ void Render::start()
         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."));
@@ -1338,8 +1362,8 @@ void Render::switchPlay(bool play)
         m_mltProducer->set_speed(1.0);
     } else if (!play) {
         m_mltConsumer->set("refresh", 0);
-        stop();
         m_mltProducer->seek(m_mltConsumer->position());
+        stop();
         //emitConsumerStopped();
         /*m_mltConsumer->set("refresh", 0);
         m_mltConsumer->stop();
@@ -1477,7 +1501,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;
 }
 
@@ -1827,7 +1852,9 @@ Mlt::Tractor *Render::lockService()
 
 void Render::unlockService(Mlt::Tractor *tractor)
 {
-    if (tractor) delete tractor;
+    if (tractor) {
+        delete tractor;
+    }
     if (!m_mltProducer) return;
     Mlt::Service service(m_mltProducer->parent().get_service());
     if (service.type() != tractor_type) {
index f6298504f3a9816a26c5bd297d079e15c8aa77fa..a8de89ea711acb77f1565e0e81867f81de9fea76 100644 (file)
@@ -106,7 +106,6 @@ Q_OBJECT public:
     void seek(GenTime time);
     void seek(int time);
     void seekToFrameDiff(int diff);
-    int m_isBlocked;
 
     QPixmap getImageThumbnail(KUrl url, int width, int height);
 
@@ -285,6 +284,8 @@ Q_OBJECT public:
     int processingItems() const;
     /** @brief Force processing of clip with selected id. */
     void forceProcessing(const QString &id);
+    /** @brief Are we currently processing clip with selected id. */
+    bool isProcessing(const QString &id);
 
     /** @brief Requests the file properties for the specified URL (will be put in a queue list)
         @param xml The xml parameters for the clip
@@ -342,6 +343,8 @@ private:
     void mltPasteEffects(Mlt::Producer *source, Mlt::Producer *dest);
     QMap<QString, QString> mltGetTransitionParamsFromXml(QDomElement xml);
     QMap<QString, Mlt::Producer *> m_slowmotionProducers;
+    /** @brief The id of the clip that is currently being loaded for info query */
+    QString m_processingClipId;
 
     /** @brief Build the MLT Consumer object with initial settings.
      *  @param profileName The MLT profile to use for the consumer */
@@ -397,9 +400,6 @@ signals:
      */
     void removeInvalidProxy(const QString &id, bool durationError);
     void refreshDocumentProducers(bool displayRatioChanged, bool fpsChanged);
-    
-    /** @brief If we will delete the producer, make sure to pause the monitor */
-    void blockClipMonitor(const QString &);
 
     /** @brief A frame's image has to be shown.
      *