]> git.sesse.net Git - kdenlive/commitdiff
* new: thumbnailer for preview of kdenlive/westley files in KDE4 apps
authorJean-Baptiste Mardelle <jb@kdenlive.org>
Thu, 28 Aug 2008 17:53:43 +0000 (17:53 +0000)
committerJean-Baptiste Mardelle <jb@kdenlive.org>
Thu, 28 Aug 2008 17:53:43 +0000 (17:53 +0000)
svn path=/branches/KDE4/; revision=2386

CMakeLists.txt
src/mimetypes/westley.xml
thumbnailer/CMakeLists.txt [new file with mode: 0644]
thumbnailer/westleypreview.cpp [new file with mode: 0644]
thumbnailer/westleypreview.desktop [new file with mode: 0644]
thumbnailer/westleypreview.h [new file with mode: 0644]

index e9b87f954fe78514ed5abd0b533b21c0be32d793..00e43f49c3710e99736200fac0fb8812f82a050e 100644 (file)
@@ -27,6 +27,7 @@ find_program(XGETTEXT_EXECUTABLE xgettext)
 
 add_subdirectory(src src/cmake_bindir)
 add_subdirectory(renderer renderer/cmake_bindir)
+add_subdirectory(thumbnailer thumbnailer/cmake_bindir)
 add_subdirectory(effects )
 add_subdirectory(export ) 
 add_subdirectory(icons )
index 80b99701139b7e7eaebd7cdb336057c0cf0e52ec..f2aa2162fbf1bca9516cbc8818089931803a7e47 100644 (file)
@@ -2,7 +2,7 @@
 <mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
   <mime-type type="video/mlt-playlist">
     <comment>MLT video playlist</comment>
+    <sub-class-of type="application/xml"/>
     <glob pattern="*.westley"/>
-    <glob pattern="*.kdenlive"/>
   </mime-type>
 </mime-info>
diff --git a/thumbnailer/CMakeLists.txt b/thumbnailer/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a56b839
--- /dev/null
@@ -0,0 +1,17 @@
+
+
+########### next target ###############
+
+set(westleypreview_PART_SRCS westleypreview.cpp)
+
+kde4_add_plugin(westleypreview ${westleypreview_PART_SRCS})
+
+target_link_libraries(westleypreview ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${KDE4_KDEUI_LIBS} ${KDE4_KDECORE_LIBS})
+
+install(TARGETS westleypreview DESTINATION ${PLUGIN_INSTALL_DIR})
+
+
+########### install files ###############
+
+install(FILES westleypreview.desktop DESTINATION ${SERVICES_INSTALL_DIR})
+
diff --git a/thumbnailer/westleypreview.cpp b/thumbnailer/westleypreview.cpp
new file mode 100644 (file)
index 0000000..af1a58c
--- /dev/null
@@ -0,0 +1,202 @@
+/***************************************************************************
+   Copyright (C) 2006-2008
+   by Marco Gulino <marco@kmobiletools.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+#include <qfile.h>
+#include <qpixmap.h>
+#include <qimage.h>
+#include <QtCore/QVarLengthArray>
+
+#include <kstandarddirs.h>
+#include <kmimetype.h>
+#include <QDir>
+#include <qpainter.h>
+#include <krandomsequence.h>
+#include <qdatetime.h>
+#include <qregexp.h>
+#include <QProcess>
+#include <kdebug.h>
+#include <ktempdir.h>
+#include <kurl.h>
+#include <math.h>
+#include <qfileinfo.h>
+#include <kcodecs.h>
+#include <KTemporaryFile>
+
+#include <unistd.h>
+
+#include "westleypreview.h"
+
+#define DBG_AREA
+
+//#include "config.h"
+extern "C"
+{
+    KDE_EXPORT ThumbCreator *new_creator()
+    {
+        return new WestleyPreview;
+    }
+}
+
+WestleyPreview::WestleyPreview()
+{
+}
+
+WestleyPreview::~WestleyPreview()
+{
+    delete rand;
+    delete inigoprocess;
+}
+
+bool WestleyPreview::startAndWaitProcess(const QStringList &args) {
+    kDebug(DBG_AREA) << "westleypreview: starting process with args: " << args << endl;
+    inigoprocess->start( args.join(" ") );
+    if(! inigoprocess->waitForStarted() ) {
+        kDebug(DBG_AREA) << "westleypreview: PROCESS NOT STARTED!!! exiting\n";
+        return false;
+    }
+    if(! inigoprocess->waitForFinished() ) {
+        kDebug(DBG_AREA) << "westleypreview: PROCESS DIDN'T FINISH!! exiting\n";
+        inigoprocess->close();
+        return false;
+    }
+  kDebug() << "westleypreview: process started and ended correctly\n";
+  return true;
+}
+
+bool WestleyPreview::create(const QString &path, int width, int height, QImage &img)
+{
+    QFileInfo fi(path);
+    /*if (fi.suffix().trimmed() != "westley" && fi.suffix().trimmed() != "kdenlive")
+    {
+        kDebug(DBG_AREA) << "westleypreview: matched extension " << fi.suffix().prepend('.') << "; exiting.\n";
+        return false;
+    }*/
+    playerBin=KStandardDirs::findExe("inigo");
+    if(playerBin.isEmpty())
+    {
+       kDebug(DBG_AREA) << "westleypreview: inigo not found, exiting.\n";
+        return false;
+    }
+
+    fileinfo.seconds=0;
+    fileinfo.fps=0;
+
+    rand=new KRandomSequence(QDateTime::currentDateTime().toTime_t());
+    inigoprocess=new QProcess();
+    KUrl furl(path);
+    kDebug(DBG_AREA) << "videopreview: url=" << furl << "; local:" << furl.isLocalFile() << endl;
+    fileinfo.towidth=width;
+    fileinfo.toheight=height;
+    QPixmap pix;
+//    if(furl.isLocalFile())
+//    {
+    QStringList args;
+    //TODO: modify inigo so that it can return some infos about a westley clip (duration, track number,fps,...) 
+    // without actually playing the file
+/*
+    args << playerBin << QString("\"" + path + "\"") << "-file-info";
+
+    kDebug(DBG_AREA) << "videopreview: starting process: --_" << " " << args.join(" ") << "_--\n";
+    if (! startAndWaitProcess(args) ) return NULL;
+
+    QString information=QString(inigoprocess->readAllStandardOutput() );
+    QRegExp findInfos("ID_VIDEO_FPS=([\\d]*).*ID_LENGTH=([\\d]*).*");
+    if(findInfos.indexIn( information) == -1 )
+    {
+        kDebug(DBG_AREA) << "videopreview: No information found, exiting\n";
+        return NULL;
+    }
+    fileinfo.seconds =findInfos.cap(2).toInt();
+    fileinfo.fps=findInfos.cap(1).toInt();
+    */
+    fileinfo.seconds = 250;
+    fileinfo.fps = 25;
+    
+    //kDebug(DBG_AREA) << "videopreview: find length=" << fileinfo.seconds << ", fps=" << fileinfo.fps << endl;
+
+    const int LASTTRY = 3;
+    for(int i=0; i<=LASTTRY; i++)
+    {
+        pix=getFrame(path);
+        if(!pix.isNull()) {
+            uint variance=imageVariance(pix.toImage()/*.bits(),( (width+ 7) & ~0x7), width, height, 1 */);
+            kDebug(DBG_AREA) << "videopreview: " << QFileInfo(path).fileName() << " frame variance: " << variance << "; " << 
+                    ((variance<=40 && ( i!=LASTTRY-1))? "!!!DROPPING!!!" : "GOOD :-)" ) << endl;
+            if(variance>40 || i==LASTTRY-1 ) break;
+        }
+    }
+    if(pix.isNull() )
+    {
+        return false;
+    }
+    img = pix.toImage();
+    return true;
+}
+
+QPixmap WestleyPreview::getFrame(const QString &path)
+{
+    QStringList args;
+    #define START ((fileinfo.seconds*15)/100)
+    #define END ((fileinfo.seconds*70)/100)
+    args.clear();
+    args << playerBin << "\"" + path + "\"";
+    if(fileinfo.towidth>fileinfo.toheight) fileinfo.toheight=-2; else fileinfo.towidth=-2;
+//     switch( flags ){
+//         case random
+//     }
+    unsigned long start=(unsigned long)(START+(rand->getDouble() * (END - START) ) );
+    args << QString("in=%1").arg(start)<< QString("out=%1").arg(start)<<"-consumer";
+
+    KTemporaryFile temp;
+    temp.setSuffix(".png");
+    temp.open();
+    args << QString("avformat:%1").arg(temp.fileName()) << "vframes=1"<< "f=rawvideo"<< "vcodec=png"<< QString("s=%1x%2").arg(fileinfo.towidth).arg(fileinfo.toheight);
+    if (! startAndWaitProcess(args) ) return NULL;
+    QPixmap retpix(temp.fileName());
+    temp.close();
+    return retpix;
+}
+
+
+uint WestleyPreview::imageVariance(QImage image )
+{
+    uint delta=0;
+    uint avg=0;
+    uint bytes=image.numBytes();
+    uint STEPS=bytes/2;
+    QVarLengthArray<uchar> pivot(STEPS);
+    kDebug(DBG_AREA) << "Using " << STEPS << " steps\n";
+    uchar *bits=image.bits();
+    // First pass: get pivots and taking average
+    for( uint i=0; i<STEPS ; i++ ){
+        pivot[i]=bits[i*(bytes/STEPS)];
+        avg+=pivot[i];
+    }
+    avg=avg/STEPS;
+    // Second Step: calculate delta (average?)
+    for (uint i=0; i<STEPS; i++)
+    {
+        int curdelta=abs(int(avg-pivot[i]));
+        delta+=curdelta;
+    }
+    return delta/STEPS;
+}
+#include "westleypreview.moc"
+
diff --git a/thumbnailer/westleypreview.desktop b/thumbnailer/westleypreview.desktop
new file mode 100644 (file)
index 0000000..1e0dd15
--- /dev/null
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Type=Service
+Name=Westley Playlists
+ServiceTypes=ThumbCreator
+CacheThumbnail=true
+IgnoreMaximumSize=true
+MimeType=video/mlt-playlist;application/x-kdenlive;
+X-KDE-Library=westleypreview
diff --git a/thumbnailer/westleypreview.h b/thumbnailer/westleypreview.h
new file mode 100644 (file)
index 0000000..4595d45
--- /dev/null
@@ -0,0 +1,62 @@
+/***************************************************************************
+   Copyright (C) 2006-2008
+   by Marco Gulino <marco@kmobiletools.org>
+   adapted for MLT video preview by Jean-Baptiste Mardelle <jb@kdenlive.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+ ***************************************************************************/
+
+
+#ifndef _westleypreview_H_
+#define _westleypreview_H_
+
+#include <qstring.h>
+#include <q3cstring.h>
+
+#include <qpixmap.h>
+#include <kio/thumbcreator.h>
+
+class QProcess;
+class Q3CString;
+class KTempDir;
+class KRandomSequence;
+#include <qobject.h>
+
+
+
+class WestleyPreview : public QObject, public ThumbCreator
+{
+Q_OBJECT
+    public:
+        WestleyPreview();
+        virtual ~WestleyPreview();
+        virtual bool create(const QString &path, int width, int height, QImage &img);
+    protected:
+        QPixmap getFrame(const QString &path);
+        static uint imageVariance(QImage image );
+
+    private:
+        QPixmap m_pixmap;
+        QProcess *inigoprocess;
+        QStringList customargs;
+        KRandomSequence *rand;
+        QString playerBin;
+        bool startAndWaitProcess(const QStringList &args);
+        enum frameflags { framerandom=0x1, framestart=0x2, frameend=0x4 };
+        struct { int towidth; int toheight; int fps; int seconds; } fileinfo;
+};
+
+#endif