diff options
author | Timothy Pearson <[email protected]> | 2013-07-24 10:41:32 -0500 |
---|---|---|
committer | Timothy Pearson <[email protected]> | 2013-07-24 10:41:32 -0500 |
commit | c53429a6968563f72f8b334486d6dd1f0de75ecb (patch) | |
tree | 6c6b3c6d09f776dc7a54635584bfa79a3af71ed9 /src/videopreview.cpp | |
download | mplayerthumbs-c53429a6968563f72f8b334486d6dd1f0de75ecb.tar.gz mplayerthumbs-c53429a6968563f72f8b334486d6dd1f0de75ecb.zip |
Initial import of mplayerthumbs 0.5b sources
Diffstat (limited to 'src/videopreview.cpp')
-rw-r--r-- | src/videopreview.cpp | 259 |
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" + |