1 /***************************************************************************
2 Copyright (C) 2006-2008
3 by Marco Gulino <marco@kmobiletools.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 ***************************************************************************/
21 #include "westleypreview.h"
25 #include <QtCore/QVarLengthArray>
27 #include <kstandarddirs.h>
28 #include <krandomsequence.h>
29 #include <qdatetime.h>
34 #include <qfileinfo.h>
35 #include <KTemporaryFile>
44 KDE_EXPORT ThumbCreator *new_creator() {
45 return new WestleyPreview;
49 WestleyPreview::WestleyPreview()
50 : m_rand(0), m_inigoprocess(0) {
53 WestleyPreview::~WestleyPreview() {
55 delete m_inigoprocess;
58 bool WestleyPreview::startAndWaitProcess(const QStringList &args) {
59 kDebug(DBG_AREA) << "westleypreview: starting process with args: " << args << endl;
60 m_inigoprocess->start(args.join(" "));
61 if (! m_inigoprocess->waitForStarted()) {
62 kDebug(DBG_AREA) << "westleypreview: PROCESS NOT STARTED!!! exiting\n";
65 if (! m_inigoprocess->waitForFinished()) {
66 kDebug(DBG_AREA) << "westleypreview: PROCESS DIDN'T FINISH!! exiting\n";
67 m_inigoprocess->close();
70 kDebug() << "westleypreview: process started and ended correctly\n";
74 bool WestleyPreview::create(const QString &path, int width, int /*height*/, QImage &img) {
76 playerBin = KStandardDirs::findExe("inigo");
77 if (playerBin.isEmpty()) {
78 kDebug(DBG_AREA) << "westleypreview: inigo not found, exiting.\n";
85 m_rand = new KRandomSequence(QDateTime::currentDateTime().toTime_t());
86 m_inigoprocess = new QProcess();
88 kDebug(DBG_AREA) << "videopreview: url=" << furl << "; local:" << furl.isLocalFile() << endl;
89 fileinfo.towidth = width;
90 fileinfo.toheight = width * 3 / 4;
92 // if(furl.isLocalFile())
95 //TODO: modify inigo so that it can return some infos about a westley clip (duration, track number,fps,...)
96 // without actually playing the file
98 args << playerBin << QString("\"" + path + "\"") << "-file-info";
100 kDebug(DBG_AREA) << "videopreview: starting process: --_" << " " << args.join(" ") << "_--\n";
101 if (! startAndWaitProcess(args) ) return NULL;
103 QString information=QString(inigoprocess->readAllStandardOutput() );
104 QRegExp findInfos("ID_VIDEO_FPS=([\\d]*).*ID_LENGTH=([\\d]*).*");
105 if(findInfos.indexIn( information) == -1 )
107 kDebug(DBG_AREA) << "videopreview: No information found, exiting\n";
110 fileinfo.seconds =findInfos.cap(2).toInt();
111 fileinfo.fps=findInfos.cap(1).toInt();
113 fileinfo.seconds = 250;
116 const int LASTTRY = 3;
117 for (int i = 0; i <= LASTTRY; i++) {
118 pix = getFrame(path);
120 uint variance = imageVariance(pix);
121 kDebug(DBG_AREA) << "videopreview: " << QFileInfo(path).fileName() << " frame variance: " << variance << "; " <<
122 ((variance <= 40 && (i != LASTTRY - 1)) ? "!!!DROPPING!!!" : "GOOD :-)") << endl;
123 if (variance > 40 || i == LASTTRY - 1) break;
130 if (pix.depth() != 32)
131 img = pix.convertToFormat(QImage::Format_RGB32);
136 QImage WestleyPreview::getFrame(const QString &path) {
138 const int START = 25;
139 const int RANGE = 500;
141 args << playerBin << "\"" + path + "\"";
143 unsigned long start = (unsigned long)(START + (m_rand->getDouble() * RANGE));
144 args << QString("in=%1").arg(start) << QString("out=%1").arg(start) << "-consumer";
147 temp.setSuffix(".png");
149 args << QString("avformat:%1").arg(temp.fileName()) << "vframes=1" << "f=rawvideo" << "vcodec=png" << QString("s=%1x%2").arg(fileinfo.towidth).arg(fileinfo.toheight);
150 if (! startAndWaitProcess(args)) return QImage();
151 QImage retpix(temp.fileName());
157 uint WestleyPreview::imageVariance(QImage image) {
160 uint bytes = image.numBytes();
161 uint STEPS = bytes / 2;
162 QVarLengthArray<uchar> pivot(STEPS);
163 kDebug(DBG_AREA) << "Using " << STEPS << " steps\n";
164 uchar *bits = image.bits();
165 // First pass: get pivots and taking average
166 for (uint i = 0; i < STEPS ; i++) {
167 pivot[i] = bits[i*(bytes/STEPS)];
171 // Second Step: calculate delta (average?)
172 for (uint i = 0; i < STEPS; i++) {
173 int curdelta = abs(int(avg - pivot[i]));
176 return delta / STEPS;
179 ThumbCreator::Flags WestleyPreview::flags() const {
184 #include "westleypreview.moc"