]> git.sesse.net Git - kdenlive/commitdiff
Rewrite generation of timeline thumbnails when zooming at frame level, using separate...
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Tue, 28 Jun 2011 10:37:23 +0000 (10:37 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Tue, 28 Jun 2011 10:37:23 +0000 (10:37 +0000)
svn path=/trunk/kdenlive/; revision=5740

src/clipitem.cpp
src/clipitem.h
src/clipmanager.cpp
src/clipmanager.h
src/customtrackview.cpp
src/customtrackview.h
src/docclipbase.cpp
src/kthumb.cpp
src/kthumb.h

index 07878af299d7df5c41f776fbbee05167c310f351..d59a562d7015f8d4eeb2a177ea0519255379edce 100644 (file)
@@ -756,11 +756,28 @@ void ClipItem::paint(QPainter *painter,
             QLineF l2(mapped.left() + m_startPix.width(), mapped.top(), mapped.left() + m_startPix.width(), mapped.bottom());
             painter->drawLine(l2);
         }
-        if (painter->matrix().m11() == FRAME_SIZE) {
+        if (painter->matrix().m11() == FRAME_SIZE && m_clip->thumbProducer() && clipType() != COLOR && clipType() != AUDIO && !m_audioOnly) {
             int offset = (m_info.startPos - m_info.cropStart).frames(m_fps);
-            int left = qMax((int) m_info.startPos.frames(m_fps) + 1, (int) mapToScene(exposed.left(), 0).x());
-            int right = qMin((int)(m_info.startPos + m_info.cropDuration).frames(m_fps) - 1, (int) mapToScene(exposed.right(), 0).x());
-            doGetIntraThumbs(painter, mapped.topLeft(), m_info.cropStart.frames(m_fps), left - offset, right - offset);
+            int left = qMax((int) m_info.startPos.frames(m_fps) + 1, (int) mapToScene(exposed.left(), 0).x()) - offset;
+            int right = qMin((int)(m_info.startPos + m_info.cropDuration).frames(m_fps) - 1, (int) mapToScene(exposed.right(), 0).x()) - offset;
+            QPointF startPos = mapped.topLeft();
+            int twidth = FRAME_SIZE;
+            int startOffset = m_info.cropStart.frames(m_fps);
+            if (clipType() == IMAGE || clipType() == TEXT) {
+                for (int i = left; i <= right; i++) {
+                    painter->drawPixmap(startPos + QPointF(twidth *(i - startOffset), 0), m_startPix);
+                }
+            }
+            else {
+#if KDE_IS_VERSION(4,5,0)
+                m_clip->thumbProducer()->queryIntraThumbs(left, right);
+                connect(m_clip->thumbProducer(), SIGNAL(thumbsCached()), this, SLOT(slotGotThumbsCache()));
+                QString path = m_clip->fileURL().path() + "%";
+                for (int i = left; i <= right; i++) {
+                    painter->drawImage(startPos + QPointF(twidth *(i - startOffset), 0), m_clip->thumbProducer()->findCachedThumb(path + QString::number(i)));
+                }
+#endif
+            }
         }
         painter->setPen(Qt::black);
     }
@@ -1707,35 +1724,27 @@ void ClipItem::updateKeyframes(QDomElement effect)
     if (!m_keyframes.contains(m_selectedKeyframe)) m_selectedKeyframe = -1;
 }
 
-void ClipItem::doGetIntraThumbs(QPainter *painter, const QPointF startPos, int offset, int start, int end)
+/*void ClipItem::slotGetIntraThumbs(CustomTrackView *view, int start, int end)
 {
-    if (!m_clip->thumbProducer() || clipType() == COLOR) return;
-    if (scene() && scene()->views().isEmpty()) return;
-    CustomTrackView *view = (CustomTrackView *) scene()->views()[0];
-    if (view == NULL) return;
     const int theight = KdenliveSettings::trackheight();
     const int twidth = FRAME_SIZE;
-
-    if (clipType() == IMAGE || clipType() == TEXT) {
-        for (int i = start; i <= end; i++)
-            painter->drawPixmap(startPos + QPointF(twidth *(i - offset), 0), m_startPix);
-    }
+    QString path = m_clip->fileURL().path() + "%";
     QPixmap p;
     for (int i = start; i <= end; i++) {
 #if KDE_IS_VERSION(4,5,0)
-        if (!view->m_pixmapCache->findPixmap(m_clip->fileURL().path() + "%" + QString::number(i), &p)) {
+        if (!view->m_pixmapCache->contains(path + QString::number(i))) {
             p = m_clip->extractImage(i, twidth, theight);
-            view->m_pixmapCache->insertPixmap(m_clip->fileURL().path() + "%" + QString::number(i), p);
+            view->m_pixmapCache->insertPixmap(path + QString::number(i), p);
         }
 #else
-        if (!view->m_pixmapCache->find(m_clip->fileURL().path() + "%" + QString::number(i), p)) {
+        if (!view->m_pixmapCache->find(path + QString::number(i), p)) {
             p = m_clip->extractImage(i, twidth, theight);
-            view->m_pixmapCache->insert(m_clip->fileURL().path() + "%" + QString::number(i), p);
+            view->m_pixmapCache->insert(path + QString::number(i), p);
         }
 #endif
-        painter->drawPixmap(startPos + QPointF(twidth *(i - offset), 0), p);
     }
-}
+    update();
+}*/
 
 QList <int> ClipItem::updatePanZoom(int width, int height, int cut)
 {
@@ -1930,4 +1939,10 @@ void ClipItem::updateGeometryKeyframes(QDomElement effect, int paramIndex, int w
     param.setAttribute("value", geometry.serialise(cropStart().frames(m_fps), (cropStart() + cropDuration()).frames(m_fps) - 1));
 }
 
+void ClipItem::slotGotThumbsCache()
+{
+    disconnect(m_clip->thumbProducer(), SIGNAL(thumbsCached()), this, SLOT(slotGotThumbsCache()));
+    update();
+}
+
 #include "clipitem.moc"
index 87b9baa665d7b70b4881b4a09257cfa7282f3188..7e49dfdbae47159ae50036be77cbc35f26ff0a1f 100644 (file)
@@ -226,7 +226,6 @@ private:
 
     QPixmap m_videoPix;
     QPixmap m_audioPix;
-    void doGetIntraThumbs(QPainter *painter, const QPointF startPos, int offset, int start, int end);
 
 private slots:
     void slotGetStartThumb();
@@ -237,6 +236,8 @@ private slots:
     void slotSetStartThumb(QImage img);
     void slotSetEndThumb(QImage img);
     void slotThumbReady(int frame, QImage img);
+    /** @brief The thumbnailer has finished to cache all required thumbs. */
+    void slotGotThumbsCache();
 
 public slots:
     void slotFetchThumbs();
index a1ebafcb7f97ac29b08882b95d162b3e3b47716a..2a4187d63cd74b30d460f35070d9c9c7789d7f2b 100644 (file)
@@ -52,6 +52,10 @@ ClipManager::ClipManager(KdenliveDoc *doc) :
     connect(&m_fileWatcher, SIGNAL(deleted(const QString &)), this, SLOT(slotClipMissing(const QString &)));
     connect(&m_fileWatcher, SIGNAL(created(const QString &)), this, SLOT(slotClipAvailable(const QString &)));
     connect(&m_modifiedTimer, SIGNAL(timeout()), this, SLOT(slotProcessModifiedClips()));
+
+#if KDE_IS_VERSION(4,5,0)
+    pixmapCache = new KImageCache("kdenlive-thumbs", 1000000);
+#endif
 }
 
 ClipManager::~ClipManager()
@@ -60,6 +64,9 @@ ClipManager::~ClipManager()
     m_generatingAudioId.clear();
     qDeleteAll(m_clipList);
     m_clipList.clear();
+#if KDE_IS_VERSION(4,5,0)
+    delete pixmapCache;
+#endif
 }
 
 void ClipManager::clear()
@@ -71,6 +78,9 @@ void ClipManager::clear()
     m_clipList.clear();
     m_clipIdCounter = 1;
     m_folderIdCounter = 1;
+#if KDE_IS_VERSION(4,5,0)
+    pixmapCache->clear();
+#endif
 }
 
 void ClipManager::checkAudioThumbs()
index b9374d2156cc04ae3c128e9cdee3571b7010007b..f9ac1722b27b2b56e0be1e91e1c852e9bb25b3dd 100644 (file)
 #include <KUndoStack>
 #include <KDirWatch>
 #include <klocale.h>
+#include <kdeversion.h>
+
+#if KDE_IS_VERSION(4,5,0)
+#include <KImageCache>
+#endif
+
 
 #include "gentime.h"
 #include "definitions.h"
@@ -104,6 +110,10 @@ Q_OBJECT public:
     QDomElement groupsXml() const;
     int clipsCount() const;
 
+#if KDE_IS_VERSION(4,5,0)
+    KImageCache* pixmapCache;
+#endif
+
 private slots:
     /** A clip was externally modified, monitor for more changes and prepare for reload */
     void slotClipModified(const QString &path);
index 1f8cc7aadebfaeb29e0012f69cf8d0f9a79bb665..766dc2470abb33c09cdb0ed4051f5b3a43c25d2f 100644 (file)
@@ -142,12 +142,6 @@ CustomTrackView::CustomTrackView(KdenliveDoc *doc, CustomTrackScene* projectscen
 
     m_activeTrackBrush = KStatefulBrush(KColorScheme::View, KColorScheme::ActiveBackground, KSharedConfig::openConfig(KdenliveSettings::colortheme()));
 
-#if KDE_IS_VERSION(4,5,0)
-    m_pixmapCache = new KImageCache("kdenlive-thumbs", 1000000);
-#else
-    m_pixmapCache = new KPixmapCache("kdenlive-thumbs");
-#endif
-
     m_animationTimer = new QTimeLine(800);
     m_animationTimer->setFrameRange(0, 5);
     m_animationTimer->setUpdateInterval(100);
@@ -192,7 +186,6 @@ CustomTrackView::~CustomTrackView()
     qDeleteAll(m_guides);
     m_guides.clear();
     m_waitingThumbs.clear();
-    delete m_pixmapCache;
     delete m_animationTimer;
 }
 
index a88286fe51c29dbba64169bff99aa94c01f30f9f..9312566c6469034bd0dbfc2132aa75c57817da21 100644 (file)
 #define CUSTOMTRACKVIEW_H
 
 #include <kdeversion.h>
-#if KDE_IS_VERSION(4,5,0)
-#include <KImageCache>
-#else
-#include <KPixmapCache>
-#endif
-
 #include <KColorScheme>
 
 #include <QGraphicsView>
@@ -184,11 +178,6 @@ public:
     void clearSelection();
     void editItemDuration();
     void buildGuidesMenu(QMenu *goMenu) const;
-#if KDE_IS_VERSION(4,5,0)
-    KImageCache* m_pixmapCache;
-#else
-    KPixmapCache* m_pixmapCache;
-#endif
     /** update the timeline objects when palette changes */
     void updatePalette();
     /** @brief Returns true if a track has audio data on it.
index 677eee7e692d9a2c030ec55ccd6a23667c413f21..cb63298a47439f406021c4d10dcb0b4b80312c43 100644 (file)
@@ -1183,3 +1183,5 @@ QPixmap DocClipBase::extractImage(int frame, int width, int height)
     return p;
 }
 
+
+
index 3208ea4d404b8125902e931f3f3476d374798e00..29ac0f0670071f6bc18703a84b380b8db63c5691 100644 (file)
@@ -57,18 +57,22 @@ KThumb::KThumb(ClipManager *clipManager, KUrl url, const QString &id, const QStr
 KThumb::~KThumb()
 {
     m_requestedThumbs.clear();
+    m_intraFramesQueue.clear();
     if (m_audioThumbProducer.isRunning()) {
         m_stopAudioThumbs = true;
         m_audioThumbProducer.waitForFinished();
         slotAudioThumbOver();
     }
     m_future.waitForFinished();
+    m_intra.waitForFinished();
 }
 
 void KThumb::setProducer(Mlt::Producer *producer)
 {
     m_requestedThumbs.clear();
+    m_intraFramesQueue.clear();
     m_future.waitForFinished();
+    m_intra.waitForFinished();
     m_producer = producer;
     // FIXME: the profile() call leaks an object, but trying to free
     // it leads to a double-free in Profile::~Profile()
@@ -148,7 +152,6 @@ QPixmap KThumb::getImage(KUrl url, int frame, int width, int height)
     return pix;
 }
 
-
 //static
 QImage KThumb::getFrame(Mlt::Producer *producer, int framepos, int width, int height)
 {
@@ -445,6 +448,40 @@ void KThumb::askForAudioThumbs(const QString &id)
     m_clipManager->askForAudioThumb(id);
 }
 
+#if KDE_IS_VERSION(4,5,0)
+void KThumb::queryIntraThumbs(int start, int end)
+{
+    for (int i = start; i <= end; i++) {
+        if (!m_intraFramesQueue.contains(i)) m_intraFramesQueue.append(i);
+    }
+    qSort(m_intraFramesQueue);
+    if (!m_intra.isRunning()) m_intra = QtConcurrent::run(this, &KThumb::slotGetIntraThumbs);
+}
+
+void KThumb::slotGetIntraThumbs()
+{
+    int theight = KdenliveSettings::trackheight();
+    int twidth = FRAME_SIZE;
+    QString path = m_url.path() + "%";
+    QImage img;
+
+    while (!m_intraFramesQueue.isEmpty()) {
+        int pos = m_intraFramesQueue.takeFirst();
+        if (!m_clipManager->pixmapCache->contains(path + QString::number(pos))) {
+            m_clipManager->pixmapCache->insertImage(path + QString::number(pos), getFrame(m_producer, pos, twidth, theight));
+        }
+        m_intraFramesQueue.removeAll(pos);
+    }
+    emit thumbsCached();
+}
+
+QImage KThumb::findCachedThumb(const QString path)
+{
+    QImage img;
+    m_clipManager->pixmapCache->findImage(path, &img);
+    return img;
+}
+#endif
 
 #include "kthumb.moc"
 
index 489001752d75fe1b2ae7601af691974497dee4ab..1d71582dd762e07cb4b682c4521593cc36978b85 100644 (file)
@@ -24,6 +24,7 @@
 #include <QFuture>
 
 #include <KUrl>
+#include <kdeversion.h>
 
 #include <mlt++/Mlt.h>
 
@@ -62,6 +63,12 @@ Q_OBJECT public:
     void updateThumbUrl(const QString &hash);
     void extractImage(int frame, int frame2);
     QPixmap extractImage(int frame, int width, int height);
+#if KDE_IS_VERSION(4,5,0)
+    /** @brief Request thumbnails for the frame range. */
+    void queryIntraThumbs(int start, int end);
+    /** @brief Query cached thumbnail. */
+    QImage findCachedThumb(const QString path);
+#endif
 
 public slots:
     void updateClipUrl(KUrl url, const QString &hash);
@@ -82,6 +89,10 @@ public slots:
 private slots:
     void slotAudioThumbOver();
     void slotCreateAudioThumbs();
+#if KDE_IS_VERSION(4,5,0)
+    /** @brief Fetch all requested frames. */ 
+    void slotGetIntraThumbs();
+#endif
 
 private:
     QFuture<void> m_audioThumbProducer;
@@ -92,7 +103,10 @@ private:
     ClipManager *m_clipManager;
     QString m_id;
     QList <int> m_requestedThumbs;
+    /** @brief Controls the thumbnails process. */
     QFuture<void> m_future;
+    /** @brief Controls the intra frames thumbnails process (cached thumbnails). */
+    QFuture<void> m_intra;
     QFile m_audioThumbFile;
     bool m_stopAudioThumbs;
     double m_frame;
@@ -100,12 +114,16 @@ private:
     int m_frequency;
     int m_channels;
     int m_arrayWidth;
+    /** @brief List of frame numbers from which we want to extract thumbnails. */
+    QList <int> m_intraFramesQueue;
     void doGetThumbs();
 
 signals:
     void thumbReady(int, QImage);
     void mainThumbReady(const QString &, QPixmap);
     void audioThumbReady(QMap <int, QMap <int, QByteArray> >);
+    /** @brief We have finished caching all requested thumbs. */
+    void thumbsCached();
 };
 
 #endif