summaryrefslogtreecommitdiffstats
path: root/src/videopreview.cpp
diff options
context:
space:
mode:
authorTimothy Pearson <[email protected]>2013-07-24 10:41:32 -0500
committerTimothy Pearson <[email protected]>2013-07-24 10:41:32 -0500
commitc53429a6968563f72f8b334486d6dd1f0de75ecb (patch)
tree6c6b3c6d09f776dc7a54635584bfa79a3af71ed9 /src/videopreview.cpp
downloadmplayerthumbs-c53429a6968563f72f8b334486d6dd1f0de75ecb.tar.gz
mplayerthumbs-c53429a6968563f72f8b334486d6dd1f0de75ecb.zip
Initial import of mplayerthumbs 0.5b sources
Diffstat (limited to 'src/videopreview.cpp')
-rw-r--r--src/videopreview.cpp259
1 files changed, 259 insertions, 0 deletions
diff --git a/src/videopreview.cpp b/src/videopreview.cpp
new file mode 100644
index 0000000..bf779e6
--- /dev/null
+++ b/src/videopreview.cpp
@@ -0,0 +1,259 @@
+/***************************************************************************
+ Copyright (C) 2006
+ by Marco Gulino <[email protected]>
+
+ 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 "videopreview.h"
+
+#include <qfile.h>
+#include <qpixmap.h>
+#include <qimage.h>
+
+#include <kstandarddirs.h>
+#include <kpixmapsplitter.h>
+#include <kmimetype.h>
+#include <qpainter.h>
+#include <krandomsequence.h>
+#include <qdatetime.h>
+#include <qregexp.h>
+#include "videopreview.h"
+#include <qprocess.h>
+#include <kdebug.h>
+#include <ktempdir.h>
+#include <kurl.h>
+#include <math.h>
+#include <qfileinfo.h>
+
+#include "mplayerthumbs.h"
+
+#include "config.h"
+extern "C"
+{
+ KDE_EXPORT ThumbCreator *new_creator()
+ {
+ return new VideoPreview;
+ }
+}
+
+VideoPreview::VideoPreview()
+ : m_splitter(0),
+ m_data(0),
+ m_dataSize(0)
+{
+}
+
+VideoPreview::~VideoPreview()
+{
+ delete m_splitter;
+ delete [] m_data;
+ delete tmpdir;
+ delete rand;
+ delete mplayerprocess;
+}
+
+bool VideoPreview::create(const QString &path, int width, int height, QImage &img)
+{
+ MPlayerThumbsCfg *cfg=new MPlayerThumbsCfg();
+ QFileInfo fi(path);
+ kdDebug() << "videopreview: file extension=\"" << fi.extension().stripWhiteSpace() << "\"\n";
+ if( fi.extension().stripWhiteSpace().length() && !cfg->noextensions().grep(fi.extension().stripWhiteSpace(), false)
+ .isEmpty() )
+ {
+ delete cfg;
+ kdDebug() << "videopreview: matched extension " << fi.extension().prepend('.') << "; exiting.\n";
+ return false;
+ }
+ playerBin=cfg->mplayerbin();
+ customargs=QStringList::split(" ", cfg->customargs() );
+ kdDebug() << "videopreview: customargs=" << cfg->customargs() << " ;;;; " << customargs << endl;
+ delete cfg;
+ if(playerBin.length()) kdDebug() << "videopreview: found playerbin from config: " << playerBin << endl;
+ else
+ {
+ playerBin=KStandardDirs::findExe("mplayer-bin");
+ if(!playerBin.length()) playerBin=KStandardDirs::findExe("mplayer");
+ if(!playerBin.length())
+ {
+ kdDebug() << "videopreview: mplayer not found, exiting. Run mplayerthumbsconfig to setup mplayer path manually.\n";
+ return false;
+ }
+ kdDebug() << "videopreview: found playerbin from path: " << playerBin << endl;
+ }
+ fileinfo.seconds=0;
+ fileinfo.fps=0;
+ tmpdir=new KTempDir();
+ if(tmpdir->name().isNull() ) return false;
+
+ rand=new KRandomSequence(QDateTime::currentDateTime().toTime_t());
+ mplayerprocess=new QProcess();
+ int flags=0;
+ KURL furl(path);
+ kdDebug() << "videopreview: url=" << furl << "; local:" << furl.isLocalFile() << endl;
+ fileinfo.towidth=width;
+ fileinfo.toheight=height;
+ QPixmap pix;
+// if(furl.isLocalFile())
+// {
+ flags=framerandom;
+ QStringList args;
+ args << playerBin << path << "-nocache" << "-identify" << "-vo" << "null" << "-frames" << "0"/* << "-nosound" */<< "-ao" << "null";
+ args+= customargs;
+ mplayerprocess->setArguments(args);
+ mplayerprocess->setCommunication( QProcess::Stdout );
+ mplayerprocess->start();
+ QString lineout;
+ QRegExp findsecs("^ID_LENGTH=([\\d]*)");
+ QRegExp findfps("^ID_VIDEO_FPS=([\\d]*)");
+ while (mplayerprocess->isRunning() ) usleep (10);
+ do {
+ lineout=mplayerprocess->readLineStdout();
+ if(findsecs.search( lineout) != -1)
+ fileinfo.seconds =findsecs.cap(1).toInt();
+ if(findfps.search( lineout) != -1)
+ fileinfo.fps=findfps.cap(1).toInt();
+ if( fileinfo.fps!=0 && fileinfo.seconds!=0 ) break;
+ } while (lineout != QString::null );
+ kdDebug() << "videopreview: find length=" << fileinfo.seconds << ", fps=" << fileinfo.fps << endl;
+/* } else
+ {
+ flags=frameend;
+ }*/
+#define LASTTRY 3
+ for(int i=0; i<=LASTTRY; i++)
+ {
+ kdDebug() << "videopreview: try " << i << endl;
+ pix=getFrame(path, ((i<LASTTRY) ? flags : framestart ) );
+ if(!pix.isNull()) {
+ uint variance=imageVariance(pix.convertToImage()/*.bits(),( (width+ 7) & ~0x7), width, height, 1 */);
+ kdDebug() << "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() )
+ {
+ if(tmpdir) tmpdir->unlink();
+ return false;
+ }
+ /** From videocreator.cpp - xine_artsplugin
+ Copyright (C) 2002 Simon MacMullen
+ Copyright (C) 2003 Ewald Snel <[email protected]>
+ * */
+// QPixmap pix( createThumbnail( &frame, width, height ) );
+#ifdef STRIPS_SUPPORT
+ QPainter painter( &pix );
+ QPixmap sprocket;
+
+ if (pix.height() < 60)
+ sprocket = QPixmap(locate( "data", "videothumbnail/sprocket-small.png" ));
+ else if (pix.height() < 90)
+ sprocket = QPixmap(locate( "data", "videothumbnail/sprocket-medium.png" ));
+ else
+ sprocket = QPixmap(locate( "data", "videothumbnail/sprocket-large.png" ));
+
+ for (int y = 0; y < pix.height() + sprocket.height(); y += sprocket.height()) {
+ painter.drawPixmap( 0, y, sprocket );
+ }
+
+ // End of xine-artsplugin code
+#endif
+ img = pix.convertToImage();
+
+ if(tmpdir) tmpdir->unlink();
+ return true;
+}
+
+QPixmap VideoPreview::getFrame(const QString &path, int flags)
+{
+ QStringList args;
+ kdDebug() << "videopreview: using flags " << flags << endl;
+#define START ((fileinfo.seconds*15)/100)
+#define END ((fileinfo.seconds*70)/100)
+ mplayerprocess->setCommunication( 0 );
+ mplayerprocess->clearArguments();
+ args.clear();
+ args << playerBin << path;
+ if(fileinfo.towidth>fileinfo.toheight) fileinfo.toheight=-2; else fileinfo.towidth=-2;
+// switch( flags ){
+// case random
+// }
+ if( flags & framerandom )
+ {
+ kdDebug() << "videopreview: framerandom\n";
+ unsigned long start=(unsigned long)(START+(rand->getDouble() * (END - START) ) );
+ args << "-ss" << QString::number( start )
+ << "-frames" << "4";
+ } else if (flags & frameend )
+ {
+ kdDebug() << "videopreview: frameend\n";
+ args << "-ss" << QString::number( fileinfo.seconds - 10 )
+ << "-frames" << "4";
+ } else if (flags & framestart)
+ {
+ kdDebug() << "videopreview: framestart\n";
+ if(!fileinfo.fps) fileinfo.fps=25; // if we've not autodetected a fps rate, let's assume 25fps.. even if it's wrong it shouldn't hurt.
+ // If we can't skip to a random frame, let's try playing 10 seconds.
+ args << "-frames" << QString::number( fileinfo.fps*10 );
+ }
+ args << "-nocache" << "-idx" /*@TODO check if it's too slow..*/ << "-ao" << "null"/*"-nosound" << */<< "-speed" << "99" /*<< "-sstep" << "5"*/
+ << "-vo" << QString("jpeg:outdir=%1").arg(tmpdir->name() ) << "-vf" << QString("scale=%1:%2").arg(fileinfo.towidth).arg(fileinfo.toheight);
+ args+=customargs;
+ kdDebug() << "videopreview: Starting MPlayer with" << args.join( " ") << endl;
+// return false;
+ mplayerprocess->setArguments( args);
+ mplayerprocess->start();
+ while (mplayerprocess->isRunning() ) usleep (10);
+ if (tmpdir->qDir()->entryList( "*.jpg" ).isEmpty() ) return false;
+
+ QString lastframe=tmpdir->qDir()->entryList( "*.jpg" ).last();
+ kdDebug() << "videopreview: LastFrame==" << lastframe << endl;
+ QPixmap retpix(tmpdir->name().append( lastframe ));
+ return retpix;
+}
+
+ThumbCreator::Flags VideoPreview::flags() const
+{
+ return (Flags)(DrawFrame);
+}
+
+
+uint VideoPreview::imageVariance(QImage image )
+{
+ uint delta=0;
+ uint avg=0;
+ uint bytes=image.numBytes();
+ uint STEPS=bytes/2;
+ uchar pivot[STEPS];
+ kdDebug() << "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 "videopreview.moc"
+