From 953722f2f4cf7279d4b2afc3a8299c0f5a8e2454 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Mardelle Date: Sun, 4 Dec 2011 21:41:03 +0100 Subject: [PATCH] Fix crash in thumbnails when deleting a clip --- src/clipitem.cpp | 9 +++++++++ src/clipitem.h | 2 ++ src/clipmanager.cpp | 12 ++++++------ src/clipmanager.h | 2 ++ src/customtrackview.cpp | 7 ++++--- src/docclipbase.cpp | 1 + src/kthumb.cpp | 3 ++- src/kthumb.h | 2 +- src/renderer.cpp | 1 + 9 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/clipitem.cpp b/src/clipitem.cpp index 086aa7c6..2c5fd7b9 100644 --- a/src/clipitem.cpp +++ b/src/clipitem.cpp @@ -124,6 +124,8 @@ ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, i ClipItem::~ClipItem() { blockSignals(true); + m_endThumbTimer.stop(); + m_startThumbTimer.stop(); if (scene()) scene()->removeItem(this); if (m_clipType == VIDEO || m_clipType == AV || m_clipType == SLIDESHOW || m_clipType == PLAYLIST) { //disconnect(m_clip->thumbProducer(), SIGNAL(thumbReady(int, QImage)), this, SLOT(slotThumbReady(int, QImage))); @@ -576,6 +578,13 @@ void ClipItem::slotFetchThumbs() if (!frames.isEmpty()) m_clip->slotExtractImage(frames); } +void ClipItem::stopThumbs() +{ + // Clip is about to be deleted, make sure we don't request thumbnails + disconnect(&m_startThumbTimer, SIGNAL(timeout()), this, SLOT(slotGetStartThumb())); + disconnect(&m_endThumbTimer, SIGNAL(timeout()), this, SLOT(slotGetEndThumb())); +} + void ClipItem::slotGetStartThumb() { m_startThumbRequested = true; diff --git a/src/clipitem.h b/src/clipitem.h index c5323905..5629743f 100644 --- a/src/clipitem.h +++ b/src/clipitem.h @@ -173,6 +173,8 @@ public: * Which producer is returned depends on the type of this clip (audioonly, videoonly, normal) */ Mlt::Producer *getProducer(int track, bool trackSpecific = true); void resetFrameWidth(int width); + /** @brief Clip is about to be deleted, block thumbs. */ + void stopThumbs(); protected: //virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event); diff --git a/src/clipmanager.cpp b/src/clipmanager.cpp index 43aa3227..dcd935a2 100644 --- a/src/clipmanager.cpp +++ b/src/clipmanager.cpp @@ -127,8 +127,7 @@ void ClipManager::requestThumbs(const QString id, QList frames) void ClipManager::stopThumbs(const QString &id) { - if (m_closing || (m_requestedThumbs.isEmpty() && m_audioThumbsQueue.isEmpty() && m_processingAudioThumbId != id)) return; - + if (m_closing || (m_requestedThumbs.isEmpty() && m_processingThumbId != id && m_audioThumbsQueue.isEmpty() && m_processingAudioThumbId != id)) return; // Abort video thumbs for this clip m_abortThumb = true; m_thumbsThread.waitForFinished(); @@ -162,12 +161,12 @@ void ClipManager::slotGetThumbs() while (!m_requestedThumbs.isEmpty() && !m_abortThumb) { m_thumbsMutex.lock(); i = m_requestedThumbs.constBegin(); - QString producerId = i.key(); - QList values = m_requestedThumbs.values(producerId); - m_requestedThumbs.remove(producerId); + m_processingThumbId = i.key(); + QList values = m_requestedThumbs.values(m_processingThumbId); + m_requestedThumbs.remove(m_processingThumbId); m_thumbsMutex.unlock(); qSort(values); - DocClipBase *clip = getClipById(producerId); + DocClipBase *clip = getClipById(m_processingThumbId); if (!clip) continue; max = m_requestedThumbs.size() + values.count(); while (!values.isEmpty() && clip->thumbProducer() && !m_abortThumb) { @@ -176,6 +175,7 @@ void ClipManager::slotGetThumbs() if (max > 3) emit displayMessage(i18n("Loading thumbnails"), 100 * done / max); } } + m_processingThumbId.clear(); emit displayMessage(QString(), -1); } diff --git a/src/clipmanager.h b/src/clipmanager.h index 169341a0..c7741b8f 100644 --- a/src/clipmanager.h +++ b/src/clipmanager.h @@ -149,6 +149,8 @@ private: // Private attributes QMap m_requestedThumbs; QMutex m_thumbsMutex; QFuture m_thumbsThread; + /** @brief The id of currently processed clip for thumbs creation. */ + QString m_processingThumbId; /** @brief If true, abort processing of clip thumbs before removing a clip. */ bool m_abortThumb; /** @brief We are about to delete the clip producer, stop processing thumbs. */ diff --git a/src/customtrackview.cpp b/src/customtrackview.cpp index 844b1d6e..2f56b5bf 100644 --- a/src/customtrackview.cpp +++ b/src/customtrackview.cpp @@ -3776,10 +3776,10 @@ void CustomTrackView::deleteClip(ItemInfo info, bool refresh) emit displayMessage(i18n("Error removing clip at %1 on track %2", m_document->timecode().getTimecodeFromFrames(info.startPos.frames(m_document->fps())), info.track), ErrorMessage); kDebug()<<"CANNOT REMOVE: "<fps())<<", TK: "<renderer()->saveSceneList(QString("/tmp/error%1.mlt").arg(m_ct), QDomElement()); - exit(1); return; } m_waitingThumbs.removeAll(item); + item->stopThumbs(); if (item->isSelected()) emit clipItemSelected(NULL); item->baseClip()->removeReference(); m_document->updateClip(item->baseClip()->getId()); @@ -4104,9 +4104,10 @@ void CustomTrackView::addClip(QDomElement xml, const QString &clipId, ItemInfo i emit displayMessage(i18n("Waiting for clip..."), InformationMessage); emit forceClipProcessing(clipId); qApp->processEvents(); - for (int i = 0; i < 3; i++) { + for (int i = 0; i < 10; i++) { if (baseclip->getProducer() == NULL) { - m_producerNotReady.wait(&m_mutex, 500 + 500 * i); + qApp->processEvents(); + m_producerNotReady.wait(&m_mutex, 200); } else break; } if (baseclip->getProducer() == NULL) { diff --git a/src/docclipbase.cpp b/src/docclipbase.cpp index d5fc2db9..96241c95 100644 --- a/src/docclipbase.cpp +++ b/src/docclipbase.cpp @@ -99,6 +99,7 @@ DocClipBase::~DocClipBase() { m_audioTimer.stop(); delete m_thumbProd; + m_thumbProd = NULL; qDeleteAll(m_toDeleteProducers); m_toDeleteProducers.clear(); qDeleteAll(m_baseTrackProducers); diff --git a/src/kthumb.cpp b/src/kthumb.cpp index 3ca94c6b..a87f654d 100644 --- a/src/kthumb.cpp +++ b/src/kthumb.cpp @@ -40,7 +40,7 @@ #include #include -KThumb::KThumb(ClipManager *clipManager, KUrl url, const QString &id, const QString &hash, QObject * parent, const char */*name*/) : +KThumb::KThumb(ClipManager *clipManager, KUrl url, const QString &id, const QString &hash, QObject * parent) : QObject(parent), m_url(url), m_thumbFile(), @@ -56,6 +56,7 @@ KThumb::KThumb(ClipManager *clipManager, KUrl url, const QString &id, const QStr KThumb::~KThumb() { if (m_producer) m_clipManager->stopThumbs(m_id); + m_producer = NULL; m_intraFramesQueue.clear(); m_intra.waitForFinished(); } diff --git a/src/kthumb.h b/src/kthumb.h index b85e0779..142bff41 100644 --- a/src/kthumb.h +++ b/src/kthumb.h @@ -56,7 +56,7 @@ class KThumb: public QObject Q_OBJECT public: - KThumb(ClipManager *clipManager, KUrl url, const QString &id, const QString &hash, QObject * parent = 0, const char *name = 0); + KThumb(ClipManager *clipManager, KUrl url, const QString &id, const QString &hash, QObject * parent = 0); ~KThumb(); void setProducer(Mlt::Producer *producer); bool hasProducer() const; diff --git a/src/renderer.cpp b/src/renderer.cpp index 272acaf5..72b8f46e 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -590,6 +590,7 @@ void Render::getFileProperties(const QDomElement &xml, const QString &clipId, in void Render::forceProcessing(const QString &id) { + if (m_processingClipId == id) return; m_infoMutex.lock(); for (int i = 0; i < m_requestList.count(); i++) { requestClipInfo info = m_requestList.at(i); -- 2.39.2