diff options
author | Arno <am@disconnect.de> | 2010-12-16 19:46:34 +0100 |
---|---|---|
committer | Arno <am@disconnect.de> | 2010-12-16 19:46:34 +0100 |
commit | 69bdaf5d1cdf2cb6a5da8371658e1c3995a71cfb (patch) | |
tree | e307f53d30b4ad59f6ab592c97adcf58008a8c6c | |
parent | c7bffca4cfc626c62c0eae6bc6b06d92cb2a8340 (diff) | |
download | SheMov-69bdaf5d1cdf2cb6a5da8371658e1c3995a71cfb.tar.gz SheMov-69bdaf5d1cdf2cb6a5da8371658e1c3995a71cfb.tar.bz2 SheMov-69bdaf5d1cdf2cb6a5da8371658e1c3995a71cfb.zip |
Cache for frame grabbing
Implemetented a cache for hovering over movies, saving the pictures from
ffmpeg. For that SmGlobals got a new member *frameCache, handling all
the dirty file access.
I first tried to implement it as a helper, but that produced too much
duplicate code.
-rw-r--r-- | filestreewidget.cpp | 2 | ||||
-rw-r--r-- | helper.cpp | 21 | ||||
-rw-r--r-- | helper.h | 1 | ||||
-rw-r--r-- | smglobals.cpp | 99 | ||||
-rw-r--r-- | smglobals.h | 25 |
5 files changed, 124 insertions, 24 deletions
diff --git a/filestreewidget.cpp b/filestreewidget.cpp index b6189c5..857b848 100644 --- a/filestreewidget.cpp +++ b/filestreewidget.cpp @@ -408,7 +408,7 @@ void FilesTreeView::doHover(const QModelIndex &idx){ bool scale = true; mCurHover = idx; if(idx.data(FilesTreeModel::FileTypeRole).toInt() == FilesTreeModel::Movie){ - pm = Helper::grabFrame(idx.data(FilesTreeModel::FullPathRole).toString()); + pm = SmGlobals::instance()->frameCache()->entry(idx.data(FilesTreeModel::FullPathRole).toString()); if(pm.isNull()){ return; } @@ -167,27 +167,6 @@ namespace Helper { return retval; } - const QPixmap grabFrame(const QString &file, QString when){ - QSettings s; - QString ffMpegPath = s.value("paths/ffmpeg").toString(); - if(when.isEmpty()){ - when = s.value("ui/grabframe", "00:00:00").toString(); - } - QString tmptmp = QString("%1/smhover-XXXXXX.png").arg(QDir::tempPath()); - QTemporaryFile tmpPic(tmptmp); - if(tmpPic.open()){ - QStringList ffMpegArgs = QStringList() << "-vframes" << "1" << "-ss" << when << "-i" << file << "-y" << tmpPic.fileName(); - QProcess ffmpeg; - ffmpeg.start(ffMpegPath, ffMpegArgs); - if(!ffmpeg.waitForStarted()){ - return QPixmap(); - } - ffmpeg.waitForFinished(); - return QPixmap(tmpPic.fileName()); - } - return QPixmap(); - } - bool SortFileInfoList::operator ()(const QFileInfo &lhs, const QFileInfo &rhs) const { return lhs.fileName().toLower() < rhs.fileName().toLower(); } @@ -25,7 +25,6 @@ namespace Helper { const QString createArchivePath(const QString &path, const QString &md5, bool withMd5 = false); QPair<QString, QStringList> programData(const QString &prefix, const QString &preferred = QString()); const QString durationFromSecs(qint64 secs); - const QPixmap grabFrame(const QString &file, QString when = QString()); class SortFileInfoList : public std::binary_function<QFileInfo, QFileInfo, bool> { public: bool operator()(const QFileInfo &lhs, const QFileInfo &rhs) const; diff --git a/smglobals.cpp b/smglobals.cpp index 9b4837c..f163ac1 100644 --- a/smglobals.cpp +++ b/smglobals.cpp @@ -10,6 +10,12 @@ #include <QStringList> #include <QMessageBox> #include <QSettings> +#include <QDir> +#include <QFile> +#include <QDataStream> +#include <QFileInfo> +#include <QTemporaryFile> +#include <QProcess> #include <QX11Info> #include <X11/Xlib.h> @@ -28,6 +34,7 @@ SmGlobals::~SmGlobals(){ delete model; } QSqlDatabase::removeDatabase("treedb"); + delete mFrameCache; } SmGlobals *SmGlobals::instance(){ @@ -84,6 +91,13 @@ PictureViewer *SmGlobals::pictureViewer() { return mPictureViewer; } +SmGlobals::FrameCache *SmGlobals::frameCache() { + if(!mFrameCache){ + mFrameCache = new SmGlobals::FrameCache; + } + return mFrameCache; +} + QSize SmGlobals::cursorSize() { if(!mCursorSize.isValid()){ XFixesCursorImage *curImage = XFixesGetCursorImage(QX11Info::display()); @@ -93,4 +107,87 @@ QSize SmGlobals::cursorSize() { return mCursorSize; } -SmGlobals::SmGlobals() : mPictureViewer(0) {} +SmGlobals::SmGlobals() : mPictureViewer(0), mFrameCache(0) {} + +//FrameCache +SmGlobals::FrameCache::FrameCache(QObject *parent) : QObject(parent), mMagic(0xDEADBEEF), mCacheSubDir(".frameCache"), mCacheFileName("cache") { + readConfig(); + readCache(); +} + +SmGlobals::FrameCache::~FrameCache(){ + QFile outfile(mCacheFile); + outfile.open(QIODevice::WriteOnly | QIODevice::Truncate); + QDataStream ds(&outfile); + ds << (qint32)mMagic; + for(QHash<QPair<QString, QString>, QString>::const_iterator it = mFrameCache.constBegin(); it != mFrameCache.constEnd(); ++it){ + ds << it.key().first << it.key().second << it.value(); + } + outfile.close(); +} + +void SmGlobals::FrameCache::readConfig(){ + QSettings s; + QString archive = s.value("paths/archivedir").toString(); + if(archive.isEmpty()){ + return; + } + QDir archiveDir(archive); + if(!archiveDir.exists(mCacheSubDir)){ + archiveDir.mkdir(mCacheSubDir); + } + mCacheDir = QString("%1/%2").arg(archive).arg(mCacheSubDir); + mCacheFile = QString("%1/%2").arg(mCacheDir).arg(mCacheFileName); + mWhen = s.value("ui/grabframe", "00:00:00").toString(); + mFfMpegPath = s.value("paths/ffmpeg").toString(); +} + +const QPixmap SmGlobals::FrameCache::entry(const QString &sourcePath, const QString &when){ + QString realWhen = when; + if(realWhen.isEmpty()){ + realWhen = mWhen; + } + const QPair<QString, QString> source(sourcePath, realWhen); + if(!mFrameCache.contains(source)){ + grabFrame(sourcePath, realWhen); + } + return QPixmap(mFrameCache.value(source)); +} + +void SmGlobals::FrameCache::grabFrame(const QString &sourceFile, QString when){ + QFileInfo sourceInfo(sourceFile); + if(!sourceInfo.exists()){ + return; + } + QString tmpTemplate = QString("%1/%2_%3-XXXXXX.png").arg(mCacheDir).arg(sourceInfo.fileName()).arg(when); + QTemporaryFile tempFile(tmpTemplate); + tempFile.setAutoRemove(false); + if(tempFile.open()){ + QStringList ffMpegArgs = QStringList() << "-vframes" << "1" << "-ss" << when << "-i" << sourceFile << "-y" << tempFile.fileName(); + QProcess ffmpeg; + ffmpeg.start(mFfMpegPath, ffMpegArgs); + if(!ffmpeg.waitForStarted()){ + return; + } + ffmpeg.waitForFinished(); + QPair<QString, QString> pair(sourceFile, when); + mFrameCache.insert(pair, tempFile.fileName()); + } +} + +void SmGlobals::FrameCache::readCache(){ + QFile cache(mCacheFile); + cache.open(QIODevice::ReadOnly); + QDataStream ds(&cache); + qint32 magic; + ds >> magic; + if(magic != mMagic){ + return; + } + while(!ds.atEnd()){ + QString source, pos, cacheFile; + ds >> source >> pos >> cacheFile; + QPair<QString, QString> pair(source, pos); + mFrameCache.insert(pair, cacheFile); + } +} diff --git a/smglobals.h b/smglobals.h index 06d7b43..b994b53 100644 --- a/smglobals.h +++ b/smglobals.h @@ -10,17 +10,41 @@ #include <QHash> #include <QSize> +#include <QPair> class QAbstractItemModel; class PictureViewer; +class QPixmap; class SmGlobals : public QObject { Q_OBJECT public: + class FrameCache : public QObject { + public: + FrameCache(QObject *parent = 0); + ~FrameCache(); + void readConfig(); + const QPixmap entry(const QString &sourcePath, const QString &when = QString()); + + private: + void readCache(); + void grabFrame(const QString &sourceFile, QString when); + QHash<QPair<QString, QString>, QString> mFrameCache; + const qint32 mMagic; + const QString mCacheSubDir; + const QString mCacheFileName; + QString mCacheDir; + QString mCacheFile; + QString mWhen; + QString mFfMpegPath; + + }; + ~SmGlobals(); static SmGlobals *instance(); QAbstractItemModel *model(const QString &which); PictureViewer *pictureViewer(); + FrameCache *frameCache(); QSize cursorSize(); private: @@ -30,6 +54,7 @@ class SmGlobals : public QObject { static SmGlobals *mInstance; QHash<QString, QAbstractItemModel*> mModels; PictureViewer *mPictureViewer; + SmGlobals::FrameCache *mFrameCache; QSize mCursorSize; }; |