From 69bdaf5d1cdf2cb6a5da8371658e1c3995a71cfb Mon Sep 17 00:00:00 2001 From: Arno Date: Thu, 16 Dec 2010 19:46:34 +0100 Subject: 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. --- smglobals.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) (limited to 'smglobals.cpp') diff --git a/smglobals.cpp b/smglobals.cpp index 9b4837c..f163ac1 100644 --- a/smglobals.cpp +++ b/smglobals.cpp @@ -10,6 +10,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include #include @@ -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, 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 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 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 pair(source, pos); + mFrameCache.insert(pair, cacheFile); + } +} -- cgit v1.2.3-70-g09d2