Sophie

Sophie

distrib > Mandriva > 2010.1 > x86_64 > by-pkgid > 43bf380c7711490bf2a7d476770dded3 > files > 2

kdemultimedia4-4.4.5-0.2mdv2010.2.src.rpm

Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt  (Revision 1123743)
+++ CMakeLists.txt  (Arbeitskopie)
@@ -17,6 +17,10 @@
 
 alsa_configure_file(${CMAKE_BINARY_DIR}/config-alsa.h)
 
+macro_optional_find_package(FFmpeg)
+macro_log_feature(FFMPEG_FOUND "FFmpeg" "FFmpeg libraries" "FFmpeg" FALSE "" "FFmpeg required for FFMpegVideoPreview backend")
+macro_log_feature(SWSCALE_FOUND "swscale" "FFmpeg video scaling libraries" "swscale" FALSE "" "swscale required for FFMpegVideoPreview backend")
+
 macro_optional_find_package(Xine)
 macro_log_feature(XINE_XCB_FOUND "Xine XCB" "Xine libraries" "http://www.xine-project.org/" FALSE "" "Xine and phonon-xine must be compiled with XCB support.")
 
@@ -39,6 +43,12 @@
 add_subdirectory(libkcompactdisc)
 add_subdirectory(mplayerthumbs)
 
+if (FFMPEG_FOUND)
+  if (SWSCALE_FOUND)
+     macro_optional_add_subdirectory(ffmpegthumbs)
+  endif(SWSCALE_FOUND)
+endif (FFMPEG_FOUND)
+
 if (TAGLIB_FOUND)
   macro_optional_add_subdirectory(juk)
 endif(TAGLIB_FOUND)
Index: ffmpegthumbs/CMakeLists.txt
===================================================================
--- ffmpegthumbs/CMakeLists.txt (Revision 0)
+++ ffmpegthumbs/CMakeLists.txt (Revision 0)
@@ -0,0 +1,55 @@
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR} ${AVUTIL_INCLUDES} ${AVFORMAT_INCLUDES} ${AVCODEC_INCLUDES} ${SWSCALE_INCLUDES} )
+
+set(FFMPEG_API FALSE)
+
+CHECK_INCLUDE_FILE(ffmpeg/avcodec.h HAVE_FFMPEG_AVCODEC)
+CHECK_INCLUDE_FILE(ffmpeg/avformat.h HAVE_FFMPEG_AVFORMAT)
+CHECK_INCLUDE_FILE(ffmpeg/avutil.h HAVE_FFMPEG_AVUTIL)
+CHECK_INCLUDE_FILE(libswscale/swscale.h HAVE_FFMPEG_SWSCALE)
+
+if(FFMPEG_FOUND)
+    set (FFMPEG_API 1)
+endif(FFMPEG_FOUND)
+
+if (HAVE_FFMPEG_AVFORMAT)
+   SET( CMAKE_CXX_FLAGS "-D FFMPEG_AVFORMAT_API=1" )
+endif(HAVE_FFMPEG_AVFORMAT)
+
+if (HAVE_FFMPEG_AVCODEC)
+   SET( CMAKE_CXX_FLAGS "-D FFMPEG_AVCODEC_API=1" )
+endif(HAVE_FFMPEG_AVCODEC)
+
+if (HAVE_FFMPEG_SWSCALE)
+   SET( CMAKE_CXX_FLAGS "-D FFMPEG_SWSCALE_API=1" )
+endif(HAVE_FFMPEG_SWSCALE)
+
+
+if( FFMPEG_API )
+  set( ffmpegthumbs_PART_SRCS
+
+  ffmpegthumbnailer.cpp
+  ffmpegthumbnailer/filmstripfilter.cpp
+  ffmpegthumbnailer/moviedecoder.cpp
+  ffmpegthumbnailer/imagewriter.cpp
+  ffmpegthumbnailer/videothumbnailer.cpp
+)
+endif( FFMPEG_API )
+
+
+kde4_add_plugin(ffmpegthumbs ${ffmpegthumbs_PART_SRCS})
+
+
+if ( FFMPEG_API )
+    target_link_libraries(ffmpegthumbs  ${KDE4_KIO_LIBS} ${AVUTIL_LIBRARIES} ${AVFORMAT_LIBRARIES} ${AVCODEC_LIBRARIES} ${SWSCALE_LIBRARIES} )
+endif ( FFMPEG_API )
+
+install(TARGETS ffmpegthumbs DESTINATION ${PLUGIN_INSTALL_DIR})
+
+
+########### install files ###############
+
+install(FILES  ffmpegthumbs.desktop DESTINATION ${SERVICES_INSTALL_DIR})
+add_subdirectory(tests)
+
+
Index: ffmpegthumbs/ffmpegthumbnailer.h
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer.h    (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer.h    (Revision 0)
@@ -0,0 +1,40 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef KFFMPEG_THUMBNAILER_H
+#define KFFMPEG_THUMBNAILER_H
+
+#include <QObject>
+#include <kio/thumbcreator.h>
+
+#include <ffmpegthumbnailer/videothumbnailer.h>
+#include <ffmpegthumbnailer/filmstripfilter.h>
+
+class FFMpegThumbnailer : public QObject, public ThumbCreator
+{
+Q_OBJECT
+public:
+   FFMpegThumbnailer();
+   virtual ~FFMpegThumbnailer();
+   virtual bool create(const QString& path, int width, int height, QImage& img);
+   virtual Flags flags() const;
+       
+private:
+   ffmpegthumbnailer::VideoThumbnailer m_Thumbnailer; 
+   ffmpegthumbnailer::FilmStripFilter  m_FilmStrip;
+};
+
+#endif
Index: ffmpegthumbs/ffmpegthumbnailer.cpp
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer.cpp  (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer.cpp  (Revision 0)
@@ -0,0 +1,55 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "ffmpegthumbnailer.h"
+#include <kdebug.h>
+#include <QImage>
+
+extern "C"
+{
+   KDE_EXPORT ThumbCreator* new_creator()
+   {
+       return new FFMpegThumbnailer();
+   }
+}
+
+
+FFMpegThumbnailer::FFMpegThumbnailer()
+{
+   m_Thumbnailer.addFilter(&m_FilmStrip);
+}
+
+FFMpegThumbnailer::~FFMpegThumbnailer()
+{
+}
+
+bool FFMpegThumbnailer::create(const QString& path, int width, int /*heigth*/, QImage& img)
+{
+   m_Thumbnailer.setThumbnailSize(width);
+   // 20% seek inside the video to generate the preview
+   m_Thumbnailer.setSeekPercentage(25); 
+   //Smart frame selection is very slow compared to the fixed detection
+   //m_Thumbnailer.setSmartFrameSelection(true);
+   m_Thumbnailer.generateThumbnail(path, img);
+
+   return !img.isNull();
+}
+
+ThumbCreator::Flags FFMpegThumbnailer::flags() const
+{
+   return (Flags)(DrawFrame);
+}
+
Index: ffmpegthumbs/ffmpegthumbnailer/.directory
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/.directory   (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/.directory   (Revision 0)
@@ -0,0 +1,5 @@
+[Dolphin]
+Timestamp=2010,4,27,14,23,9
+
+[Settings]
+ShowDotFiles=true
Index: ffmpegthumbs/ffmpegthumbnailer/AUTHORS
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/AUTHORS  (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/AUTHORS  (Revision 0)
@@ -0,0 +1,2 @@
+Dirk Vanden Boer <dirk.vdb@gmail.com>
+Andreas Scherf <ascherfy@googlemail.com> (KDE changes)

Eigenschaftsänderungen: ffmpegthumbs/ffmpegthumbnailer/AUTHORS
___________________________________________________________________
Hinzugefügt: svn:executable
   + *

Index: ffmpegthumbs/ffmpegthumbnailer/ChangeLog
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/ChangeLog    (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/ChangeLog    (Revision 0)
@@ -0,0 +1,101 @@
+FFmpegThumbnailer
+
+Version 2.0.1
+- Setting the thumbnail size to 0 will use the original video size (thanks to John Fremlin)
+- Fix for video files containing lots of audio packets before a video packet
+- Fixed libs in pkgconfig file (thanks to magnus.tuominen)
+
+version 2.0.0
+- Fixed some issues in package-config file (Thanks to ambrop7)
+- C++ library has been put in a namespace
+- C library functions have been renamed
+
+version 1.5.6
+- Fixed segmentation fault when seek in video file fails
+- Command line option added to specify output format of the image regardless of the filename
+- Fixed memory leak in MovieDecoder (thanks to Ulrich Völkel)
+
+version 1.5.5
+- Fixed build issue with certain versions of autoconf
+- Fixed build issue with recent versions of gcc
+- Fixed thumbnail generation for ogm files
+- Fixed ffmpegthumbnailer hanging on certain filetypes caused by AVFMT_FLAG_GENPTS flag of video decoder
+
+version 1.5.4
+- Fixed support for large files
+
+version 1.5.3
+- Memory alignment fix causing segmentation in ffmpeg with altivec enabled
+
+version 1.5.2
+- Fixed soname version
+
+version 1.5.1
+- Optional compilation of jpeg and png support
+- Fixed ffmpeg CFLAGS issue (causing compilation errors on Fedora)
+- Fixed build error against latest ffmpeg (verified against ffmpeg revision 18769)
+- Fixed missing include files for library usage (thanks to gustavo.boiko)
+
+version 1.5.0
+- Aspect ratio bug fix (Thanks to S. Eguchi)
+- Support input files from stdin (will ignore seek time)
+- Fixed build error against latest ffmpeg (verified against ffmpeg release 0.5)
+
+version 1.4.0
+- Filter support added that allows library users to implement filters that will be applied to the frame data
+- Fixed compilation error with gcc 4.4
+
+version 1.3.0
+- Option added to ignore aspect ratio and generate square thumbnails
+- Quality option added for jpeg thumbnails
+- Man page added (thanks to Lionel Le Folgoc)
+- Added option to seek to absolute time in stead of percentage
+
+version 1.2.6
+- Fixed seeking in large files due to integer overflow (Thanks to AWaters1)
+- Fixed possible linker error (Thanks to pressh)
+
+version 1.2.5
+- Fixed crash when thumbnailing raw avi files
+
+version 1.2.4
+- Fixed missing includes when compiling with gcc 4.3 (thanks to Samuli Suominen)
+
+version 1.2.3
+- ffmegthumbnailer now compiles against latest ffmpeg revisions (thanks to Alexis Ballier)
+
+version 1.2.2
+- Fixed linker errors when using certain ldflags
+
+version 1.2.1
+- Fixed compilation error in c interface when compiled with c compiler
+- Error handling added to c interface
+
+version 1.2.0
+- Option to output files in jpeg
+- ffmpegthumbnailer can now be accessed as a library (libffmpegthumbnailer) by other applications
+
+version 1.1.5
+- Support for large files (files larger than 2Gb)
+- Seeking in h264 files is enabled again, use -w option from commandline to disable this if you have 100% cpu usage (using older versions of ffmpeg)
+- Give up reading packets from a file after a number of attempts to avoid a hanging ffmpegthumbnailer for certain file types (noticed on h264 and ac3 in vob container)
+
+version 1.1.4
+- License information added to source files
+
+version 1.1.3
+- Use PkgConfig for ffmpeg to avoid build problems
+
+version 1.1.2
+- Fixed compilation error when using latest ffmpeg (thanks to Samuli Suominen)
+
+version 1.1.1
+- Fixed compilation error when using latest ffmpeg
+- Disabled seeking in h264 files, because this causes 100% CPU usage in ffmpeglib (workaround)
+
+version 1.1
+- Updated command line argument parser
+- Possibility to add a movie strip overlay
+
+version 1.0
+- Initial release of the FFmpegThumbnailer
Index: ffmpegthumbs/ffmpegthumbnailer/README
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/README   (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/README   (Revision 0)
@@ -0,0 +1,7 @@
+FFmpegthumbnailer is a lightweight video thumbnailer that can be used by file
+managers to create thumbnails for your video files. The thumbnailer uses ffmpeg
+o decode frames from the video files, so supported videoformats depend on the
+configuration flags of ffmpeg.
+
+This thumbnailer was designed to be as fast and lightweight as possible. The
+only dependencies are ffmpeglibraies and libswscale .

Eigenschaftsänderungen: ffmpegthumbs/ffmpegthumbnailer/README
___________________________________________________________________
Hinzugefügt: svn:executable
   + *

Index: ffmpegthumbs/ffmpegthumbnailer/filmstripfilter.h
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/filmstripfilter.h    (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/filmstripfilter.h    (Revision 0)
@@ -0,0 +1,33 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef FILMSTRIPFILTER_H
+#define FILMSTRIPFILTER_H
+
+#include "ifilter.h"
+
+namespace ffmpegthumbnailer
+{
+
+class FilmStripFilter : public IFilter
+{
+public:
+    virtual void process(VideoFrame& videoFrame);
+};
+
+}
+
+#endif
Index: ffmpegthumbs/ffmpegthumbnailer/filmstripfilter.cpp
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/filmstripfilter.cpp  (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/filmstripfilter.cpp  (Revision 0)
@@ -0,0 +1,69 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "filmstripfilter.h"
+
+namespace ffmpegthumbnailer
+{
+
+static const int FILMHOLE_WIDTH = 12;
+static const int FILMHOLE_HEIGHT = 10;
+
+static const uint8_t filmHole[FILMHOLE_WIDTH * FILMHOLE_HEIGHT * 3] = {
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x23, 0x23, 0x7a, 0x7a, 0x7a, 0x83, 0x83, 0x83, 0x8c, 0x8c, 0x8c, 0x90, 0x90, 0x90, 0x8e, 0x8e, 0x8e, 0x52, 0x52, 0x52, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x6e, 0x6e, 0x83, 0x83, 0x83, 0x93, 0x93, 0x93, 0xa3, 0xa3, 0xa3, 0xab, 0xab, 0xab, 0xa8, 0xa8, 0xa8, 0x9b, 0x9b, 0x9b, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x72, 0x72, 0x8e, 0x8e, 0x8e, 0xa4, 0xa4, 0xa4, 0xbb, 0xbb, 0xbb, 0xc4, 0xc4, 0xc4, 0xc1, 0xc1, 0xc1, 0xaf, 0xaf, 0xaf, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x3e, 0x3e, 0x90, 0x90, 0x90, 0xa6, 0xa6, 0xa6, 0xbe, 0xbe, 0xbe, 0xc8, 0xc8, 0xc8, 0xc4, 0xc4, 0xc4, 0x8e, 0x8e, 0x8e, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+
+void FilmStripFilter::process(VideoFrame& videoFrame)
+{
+    if (videoFrame.width < FILMHOLE_WIDTH * 2)
+    {
+        return;
+    }
+
+    int frameIndex = 0;
+    int filmHoleIndex = 0;
+    int offset = (videoFrame.width * 3) - 3;
+
+    for (int i = 0; i < videoFrame.height; ++i)
+    {
+        for (int j = 0; j < FILMHOLE_WIDTH * 3; j+=3)
+        {
+            int currentFilmHoleIndex = filmHoleIndex + j;
+
+            videoFrame.frameData[frameIndex + j]     = filmHole[currentFilmHoleIndex];
+            videoFrame.frameData[frameIndex + j + 1] = filmHole[currentFilmHoleIndex + 1];
+            videoFrame.frameData[frameIndex + j + 2] = filmHole[currentFilmHoleIndex + 2];
+
+            videoFrame.frameData[frameIndex + offset - j]     = filmHole[currentFilmHoleIndex];
+            videoFrame.frameData[frameIndex + offset - j + 1] = filmHole[currentFilmHoleIndex + 1];
+            videoFrame.frameData[frameIndex + offset - j + 2] = filmHole[currentFilmHoleIndex + 2];
+        }
+        frameIndex += videoFrame.lineSize;
+        filmHoleIndex = (i % FILMHOLE_HEIGHT) * FILMHOLE_WIDTH * 3;
+    }
+}
+
+}
Index: ffmpegthumbs/ffmpegthumbnailer/histogram.h
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/histogram.h  (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/histogram.h  (Revision 0)
@@ -0,0 +1,42 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef HISTOGRAM_H
+#define HISTOGRAM_H
+
+#include <string.h>
+
+namespace ffmpegthumbnailer
+{
+
+template <typename T>
+struct Histogram
+{
+    T r[256];
+    T g[256];
+    T b[256];
+
+    Histogram()
+    {
+        memset(r, 0, 255 * sizeof(T));
+        memset(g, 0, 255 * sizeof(T));
+        memset(b, 0, 255 * sizeof(T));
+    }
+};
+
+}
+
+#endif
Index: ffmpegthumbs/ffmpegthumbnailer/ifilter.h
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/ifilter.h    (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/ifilter.h    (Revision 0)
@@ -0,0 +1,33 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef IFILTER_H
+#define IFILTER_H
+
+#include "videoframe.h"
+
+namespace ffmpegthumbnailer
+{
+
+class IFilter
+{
+public:
+    virtual void process(VideoFrame& frameData) = 0;
+};
+
+}
+
+#endif
Index: ffmpegthumbs/ffmpegthumbnailer/imagewriter.h
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/imagewriter.h    (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/imagewriter.h    (Revision 0)
@@ -0,0 +1,38 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef IMAGE_WRITER_H
+#define IMAGE_WRITER_H
+#include "videoframe.h"
+#include <string>
+#include <inttypes.h>
+#include <QString>
+#include <QImage>
+namespace ffmpegthumbnailer
+{
+
+class ImageWriter
+{
+public:
+   ImageWriter();
+    virtual ~ImageWriter() {}
+
+   virtual void writeFrame(VideoFrame& frame, QImage& image);
+};
+
+}
+
+#endif
Index: ffmpegthumbs/ffmpegthumbnailer/imagewriter.cpp
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/imagewriter.cpp  (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/imagewriter.cpp  (Revision 0)
@@ -0,0 +1,42 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "imagewriter.h"
+#include <kdebug.h>
+#include <iostream>
+
+
+using namespace std;
+
+namespace ffmpegthumbnailer
+{
+   
+   ImageWriter::ImageWriter()
+   {
+   }
+   
+   void ImageWriter::writeFrame(VideoFrame& frame,  QImage& image)
+   {
+       QImage previewImage( frame.width,frame.height,QImage::Format_RGB888);
+       for(unsigned int y=0;y<frame.height;y++)
+       {
+           // Copy each line ..
+           memcpy(previewImage.scanLine(y),&frame.frameData[0+y*frame.lineSize],frame.width*3);
+       }
+
+       image=previewImage;
+   }
+}
Index: ffmpegthumbs/ffmpegthumbnailer/moviedecoder.h
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/moviedecoder.h   (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/moviedecoder.h   (Revision 0)
@@ -0,0 +1,93 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef MOVIEDECODER_H
+#define MOVIEDECODER_H
+
+#define __STDC_CONSTANT_MACROS
+#define INT64_C
+#include <inttypes.h>
+
+#include <string>
+#include <vector>
+
+#include "videoframe.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+extern "C" {
+#if FFMPEG_AVCODEC_API
+#include <ffmpeg/avcodec.h>
+#else
+#include <libavcodec/avcodec.h>
+#endif
+#if FFMPEG_AVFORMAT_API
+#include <ffmpeg/avformat.h>
+#else
+#include <libavformat/avformat.h>
+#endif
+}
+
+#include <QString>
+
+namespace ffmpegthumbnailer
+{
+
+class MovieDecoder
+{
+public:
+    MovieDecoder(const QString& filename, AVFormatContext* pavContext = NULL);
+    ~MovieDecoder();
+
+    std::string getCodec();
+    void seek(int timeInSeconds);
+    void decodeVideoFrame();
+    void getScaledVideoFrame(int scaledSize, bool maintainAspectRatio, VideoFrame& videoFrame);
+
+    int getWidth();
+    int getHeight();
+    int getDuration();
+    
+    void initialize(const QString& filename);
+    void destroy();
+    
+private:
+    void initializeVideo();
+    
+    bool decodeVideoPacket();
+    bool getVideoPacket();
+    void convertAndScaleFrame(PixelFormat format, int scaledSize, bool maintainAspectRatio, int& scaledWidth, int& scaledHeight);
+    void createAVFrame(AVFrame** avFrame, uint8_t** frameBuffer, int width, int height, PixelFormat format);
+    void calculateDimensions(int squareSize, bool maintainAspectRatio, int& destWidth, int& destHeight);
+
+private:
+    int                     m_VideoStream;
+    AVFormatContext*        m_pFormatContext;
+    AVCodecContext*         m_pVideoCodecContext;
+    AVCodec*                m_pVideoCodec;
+    AVStream*               m_pVideoStream;
+    AVFrame*                m_pFrame;
+    uint8_t*                m_pFrameBuffer;
+    AVPacket*               m_pPacket;
+    bool                    m_FormatContextWasGiven;
+    bool                    m_AllowSeek;
+};
+
+}
+
+#endif
Index: ffmpegthumbs/ffmpegthumbnailer/moviedecoder.cpp
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/moviedecoder.cpp (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/moviedecoder.cpp (Revision 0)
@@ -0,0 +1,406 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "moviedecoder.h"
+#include <stdexcept>
+
+
+#include <cstring>
+#include <kdebug.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+extern "C" {
+#if FFMPEG_SWSCALE_API
+#include <ffmpeg/swscale.h>
+#else
+#include <libswscale/swscale.h>
+#endif
+}
+
+using namespace std;
+
+namespace ffmpegthumbnailer
+{
+
+MovieDecoder::MovieDecoder(const QString& filename, AVFormatContext* pavContext)
+: m_VideoStream(-1)
+, m_pFormatContext(pavContext)
+, m_pVideoCodecContext(NULL)
+, m_pVideoCodec(NULL)
+, m_pVideoStream(NULL)
+, m_pFrame(NULL)
+, m_pFrameBuffer(NULL)
+, m_pPacket(NULL)
+, m_FormatContextWasGiven(pavContext != NULL)
+, m_AllowSeek(filename != "-")
+{
+    initialize(filename);
+}
+
+MovieDecoder::~MovieDecoder()
+{
+    destroy();
+}
+
+void MovieDecoder::initialize(const QString& filename)
+{
+    av_register_all();
+    avcodec_init();
+    avcodec_register_all();
+
+    QString inputFile = filename == "-" ? "pipe:" : filename;
+
+    if ((!m_FormatContextWasGiven) && av_open_input_file(&m_pFormatContext, inputFile.toAscii().data(), NULL, 0, NULL) != 0)
+    {
+       kDebug() <<  "Could not open input file: " << filename;
+    }
+
+    if (av_find_stream_info(m_pFormatContext) < 0)
+    {
+       kDebug() << "Could not find stream information";
+    }
+
+    initializeVideo();
+    m_pFrame = avcodec_alloc_frame();
+}
+
+void MovieDecoder::destroy()
+{
+    if (m_pVideoCodecContext)
+    {
+        avcodec_close(m_pVideoCodecContext);
+        m_pVideoCodecContext = NULL;
+    }
+
+    if ((!m_FormatContextWasGiven) && m_pFormatContext)
+    {
+        av_close_input_file(m_pFormatContext);
+        m_pFormatContext = NULL;
+    }
+
+    if (m_pPacket)
+    {
+        av_free_packet(m_pPacket);
+        delete m_pPacket;
+        m_pPacket = NULL;
+    }
+
+    if (m_pFrame)
+    {
+        av_free(m_pFrame);
+        m_pFrame = NULL;
+    }
+
+    if (m_pFrameBuffer)
+    {
+        av_free(m_pFrameBuffer);
+        m_pFrameBuffer = NULL;
+    }
+}
+
+string MovieDecoder::getCodec()
+{
+    if (m_pVideoCodec)
+    {
+        return m_pVideoCodec->name;
+    }
+
+    return "";
+}
+
+void MovieDecoder::initializeVideo()
+{
+    for(unsigned int i = 0; i < m_pFormatContext->nb_streams; i++)
+    {
+        if (m_pFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
+        {
+            m_pVideoStream = m_pFormatContext->streams[i];
+            m_VideoStream = i;
+            break;
+        }
+    }
+
+    if (m_VideoStream == -1)
+    {
+       kDebug() << "Could not find video stream";
+       return;
+    }
+
+    m_pVideoCodecContext = m_pFormatContext->streams[m_VideoStream]->codec;
+    m_pVideoCodec = avcodec_find_decoder(m_pVideoCodecContext->codec_id);
+
+    if (m_pVideoCodec == NULL)
+    {
+        // set to NULL, otherwise avcodec_close(m_pVideoCodecContext) crashes
+        m_pVideoCodecContext = NULL;
+       kDebug() << "Video Codec not found";
+       return;
+    }
+
+    m_pVideoCodecContext->workaround_bugs = 1;
+
+    if (avcodec_open(m_pVideoCodecContext, m_pVideoCodec) < 0)
+    {
+       kDebug() << "Could not open video codec";
+    }
+}
+
+int MovieDecoder::getWidth()
+{
+    if (m_pVideoCodecContext)
+    {
+        return m_pVideoCodecContext->width;
+    }
+
+    return -1;
+}
+
+int MovieDecoder::getHeight()
+{
+    if (m_pVideoCodecContext)
+    {
+        return m_pVideoCodecContext->height;
+    }
+
+    return -1;
+}
+
+int MovieDecoder::getDuration()
+{
+    if (m_pFormatContext)
+    {
+        return static_cast<int>(m_pFormatContext->duration / AV_TIME_BASE);
+    }
+
+    return 0;
+}
+
+void MovieDecoder::seek(int timeInSeconds)
+{
+    if (!m_AllowSeek)
+    {
+        return;
+    }
+    
+    int64_t timestamp = AV_TIME_BASE * static_cast<int64_t>(timeInSeconds);
+
+    if (timestamp < 0)
+    {
+        timestamp = 0;
+    }
+
+    int ret = av_seek_frame(m_pFormatContext, -1, timestamp, 0);
+    if (ret >= 0)
+    {
+        avcodec_flush_buffers(m_pFormatContext->streams[m_VideoStream]->codec);
+    }
+    else
+    {
+       kDebug() << "Seeking in video failed";
+       return;
+    }
+
+    int keyFrameAttempts = 0;
+    bool gotFrame = 0;
+    
+    do
+    {
+        int count = 0;
+        gotFrame = 0;
+
+        while (!gotFrame && count < 20)
+        {
+           getVideoPacket();
+           gotFrame = decodeVideoPacket();
+           ++count;
+        }
+       
+        ++keyFrameAttempts;
+    } while ((!gotFrame || !m_pFrame->key_frame) && keyFrameAttempts < 200);
+    
+    if (gotFrame == 0)
+    {
+       kDebug() << "Seeking in video failed";
+    }
+}
+
+
+void MovieDecoder::decodeVideoFrame()
+{
+    bool frameFinished = false;
+
+    while(!frameFinished && getVideoPacket())
+    {
+        frameFinished = decodeVideoPacket();
+    }
+
+    if (!frameFinished)
+    {
+       kDebug() << "decodeVideoFrame() failed: frame not finished";
+       return;
+    }
+}
+
+bool MovieDecoder::decodeVideoPacket()
+{
+    if (m_pPacket->stream_index != m_VideoStream)
+    {
+        return false;
+    }
+
+    avcodec_get_frame_defaults(m_pFrame);
+    
+    int frameFinished;
+    
+#if LIBAVCODEC_VERSION_MAJOR < 53
+    int bytesDecoded = avcodec_decode_video(m_pVideoCodecContext, m_pFrame, &frameFinished, m_pPacket->data, m_pPacket->size);
+#else
+    int bytesDecoded = avcodec_decode_video2(m_pVideoCodecContext, m_pFrame, &frameFinished, m_pPacket);
+#endif
+
+    if (bytesDecoded < 0)
+    {
+       kDebug() << "Failed to decode video frame: bytesDecoded < 0";
+    }
+
+    return (frameFinished > 0);
+}
+
+bool MovieDecoder::getVideoPacket()
+{
+    bool framesAvailable = true;
+    bool frameDecoded = false;
+
+    int attempts = 0;
+    
+    if (m_pPacket)
+    {
+        av_free_packet(m_pPacket);
+        delete m_pPacket;
+    }
+
+    m_pPacket = new AVPacket();
+
+    while (framesAvailable && !frameDecoded && (attempts++ < 1000))
+    {
+        framesAvailable = av_read_frame(m_pFormatContext, m_pPacket) >= 0;
+        if (framesAvailable)
+        {
+            frameDecoded = m_pPacket->stream_index == m_VideoStream;
+            if (!frameDecoded)
+            {
+                av_free_packet(m_pPacket);
+            }
+        }
+    }
+    
+    return frameDecoded;
+}
+
+void MovieDecoder::getScaledVideoFrame(int scaledSize, bool maintainAspectRatio, VideoFrame& videoFrame)
+{
+    if (m_pFrame->interlaced_frame)
+    {
+        avpicture_deinterlace((AVPicture*) m_pFrame, (AVPicture*) m_pFrame, m_pVideoCodecContext->pix_fmt,
+                              m_pVideoCodecContext->width, m_pVideoCodecContext->height);
+    }
+
+    int scaledWidth, scaledHeight;
+    convertAndScaleFrame(PIX_FMT_RGB24, scaledSize, maintainAspectRatio, scaledWidth, scaledHeight);
+
+    videoFrame.width = scaledWidth;
+    videoFrame.height = scaledHeight;
+    videoFrame.lineSize = m_pFrame->linesize[0];
+
+    videoFrame.frameData.clear();
+    videoFrame.frameData.resize(videoFrame.lineSize * videoFrame.height);
+    memcpy((&(videoFrame.frameData.front())), m_pFrame->data[0], videoFrame.lineSize * videoFrame.height);
+}
+
+void MovieDecoder::convertAndScaleFrame(PixelFormat format, int scaledSize, bool maintainAspectRatio, int& scaledWidth, int& scaledHeight)
+{
+    calculateDimensions(scaledSize, maintainAspectRatio, scaledWidth, scaledHeight);
+    SwsContext* scaleContext = sws_getContext(m_pVideoCodecContext->width, m_pVideoCodecContext->height,
+                                              m_pVideoCodecContext->pix_fmt, scaledWidth, scaledHeight,
+                                              format, SWS_BICUBIC, NULL, NULL, NULL);
+
+    if (NULL == scaleContext)
+    {
+       kDebug() << "Failed to create resize context";
+       return;
+    }
+
+    AVFrame* convertedFrame = NULL;
+    uint8_t* convertedFrameBuffer = NULL;
+
+    createAVFrame(&convertedFrame, &convertedFrameBuffer, scaledWidth, scaledHeight, format);
+    
+    sws_scale(scaleContext, m_pFrame->data, m_pFrame->linesize, 0, m_pVideoCodecContext->height,
+              convertedFrame->data, convertedFrame->linesize);
+    sws_freeContext(scaleContext);
+
+    av_free(m_pFrame);
+    av_free(m_pFrameBuffer);
+    
+    m_pFrame        = convertedFrame;
+    m_pFrameBuffer  = convertedFrameBuffer;
+}
+
+void MovieDecoder::calculateDimensions(int squareSize, bool maintainAspectRatio, int& destWidth, int& destHeight)
+{
+    if (!maintainAspectRatio)
+    {
+        destWidth = squareSize;
+        destHeight = squareSize;
+    }
+    else
+    {
+        int srcWidth            = m_pVideoCodecContext->width;
+        int srcHeight           = m_pVideoCodecContext->height;
+        int ascpectNominator    = m_pVideoCodecContext->sample_aspect_ratio.num;
+        int ascpectDenominator  = m_pVideoCodecContext->sample_aspect_ratio.den;
+        
+        if (ascpectNominator != 0 && ascpectDenominator != 0)
+        {
+            srcWidth = srcWidth * ascpectNominator / ascpectDenominator;
+        }
+        
+        if (srcWidth > srcHeight)
+        {
+            destWidth  = squareSize;
+            destHeight = static_cast<int>(static_cast<float>(squareSize) / srcWidth * srcHeight);
+        }
+        else
+        {
+            destWidth  = static_cast<int>(static_cast<float>(squareSize) / srcHeight * srcWidth);
+            destHeight = squareSize;
+        }
+    }
+}
+
+void MovieDecoder::createAVFrame(AVFrame** avFrame, uint8_t** frameBuffer, int width, int height, PixelFormat format)
+{
+    *avFrame = avcodec_alloc_frame();
+
+    int numBytes = avpicture_get_size(format, width, height);
+    *frameBuffer = reinterpret_cast<uint8_t*>(av_malloc(numBytes));
+    avpicture_fill((AVPicture*) *avFrame, *frameBuffer, format, width, height);
+}
+
+}
Index: ffmpegthumbs/ffmpegthumbnailer/videoframe.h
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/videoframe.h (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/videoframe.h (Revision 0)
@@ -0,0 +1,43 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef VIDEOFRAME_H
+#define VIDEOFRAME_H
+
+#include <inttypes.h>
+#include <vector>
+
+namespace ffmpegthumbnailer
+{
+
+struct VideoFrame
+{
+    VideoFrame()
+    : width(0), height(0), lineSize(0) {}
+    
+    VideoFrame(int width, int height, int lineSize)
+    : width(width), height(height), lineSize(lineSize) {}
+    
+    int width;
+    int height;
+    int lineSize;
+
+    std::vector<uint8_t> frameData;
+};
+
+}
+
+#endif
Index: ffmpegthumbs/ffmpegthumbnailer/videothumbnailer.h
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/videothumbnailer.h   (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/videothumbnailer.h   (Revision 0)
@@ -0,0 +1,83 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#ifndef VIDEO_THUMBNAILER_H
+#define VIDEO_THUMBNAILER_H
+
+#include <string>
+#include <vector>
+#include <map>
+#include <inttypes.h>
+
+#include "ifilter.h"
+#include "histogram.h"
+#include <QString>
+#include <QImage>
+
+
+namespace ffmpegthumbnailer
+{
+
+class VideoFrame;
+class ImageWriter;
+class MovieDecoder;
+
+class VideoThumbnailer
+{
+public:
+    VideoThumbnailer();
+    VideoThumbnailer(int thumbnailSize, bool workaroundIssues, bool maintainAspectRatio, int imageQuality, bool smartFrameSelection);
+    ~VideoThumbnailer();
+
+    void generateThumbnail(const QString& videoFile, QImage &image);
+
+    void setThumbnailSize(int size);
+    void setSeekPercentage(int percentage);
+    void setSeekTime(const QString& seekTime);
+    void setWorkAroundIssues(bool workAround);
+    void setImageQuality(int imageQuality);
+    void setMaintainAspectRatio(bool enabled);
+    void setSmartFrameSelection(bool enabled);
+    void addFilter(IFilter* filter);
+    void removeFilter(IFilter* filter);
+    void clearFilters();
+
+private:
+    void generateThumbnail(const QString& videoFile, ImageWriter& imageWriter,QImage& image);
+    void generateSmartThumbnail(MovieDecoder& movieDecoder, VideoFrame& videoFrame);
+
+    QString getMimeType(const QString& videoFile);
+    QString getExtension(const QString& videoFilename);
+
+    void generateHistogram(const VideoFrame& videoFrame, Histogram<int>& histogram);
+    int getBestThumbnailIndex(std::vector<VideoFrame>& videoFrames, const std::vector<Histogram<int> >& histograms);
+    void applyFilters(VideoFrame& frameData);
+
+private:
+    int                         m_ThumbnailSize;
+    uint16_t                    m_SeekPercentage;
+    bool                        m_OverlayFilmStrip;
+    bool                        m_WorkAroundIssues;
+    int                         m_ImageQuality;
+    bool                        m_MaintainAspectRatio;
+    bool                        m_SmartFrameSelection;
+    QString                        m_SeekTime;
+    std::vector<IFilter*>       m_Filters;
+};
+
+}
+
+#endif
Index: ffmpegthumbs/ffmpegthumbnailer/videothumbnailer.cpp
===================================================================
--- ffmpegthumbs/ffmpegthumbnailer/videothumbnailer.cpp (Revision 0)
+++ ffmpegthumbs/ffmpegthumbnailer/videothumbnailer.cpp (Revision 0)
@@ -0,0 +1,247 @@
+//    Copyright (C) 2010 Dirk Vanden Boer <dirk.vdb@gmail.com>
+//
+//    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+#include "videothumbnailer.h"
+
+#include "moviedecoder.h"
+#include "filmstripfilter.h"
+#include "imagewriter.h"
+
+#include <iostream>
+#include <cfloat>
+#include <cmath>
+#include <qglobal.h>
+#include <sys/stat.h>
+#include <QFileInfo>
+#include <QTime>
+
+
+using namespace std;
+
+namespace ffmpegthumbnailer
+{
+
+static const int SMART_FRAME_ATTEMPTS = 25;
+
+VideoThumbnailer::VideoThumbnailer()
+: m_ThumbnailSize(128)
+, m_SeekPercentage(10)
+, m_OverlayFilmStrip(false)
+, m_WorkAroundIssues(false)
+, m_ImageQuality(8)
+, m_MaintainAspectRatio(true)
+, m_SmartFrameSelection(false)
+{
+}
+
+VideoThumbnailer::VideoThumbnailer(int thumbnailSize, bool workaroundIssues, bool maintainAspectRatio, int imageQuality, bool smartFrameSelection)
+: m_ThumbnailSize(thumbnailSize)
+, m_SeekPercentage(10)
+, m_WorkAroundIssues(workaroundIssues)
+, m_ImageQuality(imageQuality)
+, m_MaintainAspectRatio(maintainAspectRatio)
+, m_SmartFrameSelection(smartFrameSelection)
+{
+}
+
+VideoThumbnailer::~VideoThumbnailer()
+{
+}
+
+void VideoThumbnailer::setSeekPercentage(int percentage)
+{
+    m_SeekTime.clear();
+    m_SeekPercentage = percentage > 95 ? 95 : percentage;
+}
+
+void VideoThumbnailer::setSeekTime(const QString& seekTime)
+{
+    m_SeekTime = seekTime;
+}
+
+void VideoThumbnailer::setThumbnailSize(int size)
+{
+    m_ThumbnailSize = size;
+}
+
+void VideoThumbnailer::setWorkAroundIssues(bool workAround)
+{
+    m_WorkAroundIssues = workAround;
+}
+
+void VideoThumbnailer::setImageQuality(int imageQuality)
+{
+    m_ImageQuality = imageQuality;
+}
+
+void VideoThumbnailer::setMaintainAspectRatio(bool enabled)
+{
+    m_MaintainAspectRatio = enabled;
+}
+
+void VideoThumbnailer::setSmartFrameSelection(bool enabled)
+{
+    m_SmartFrameSelection = enabled;
+}
+
+int timeToSeconds(const QString& time)
+{
+   return QTime::fromString(time,"hh:mm:ss").secsTo(QTime(0,0,0));
+}
+
+void VideoThumbnailer::generateThumbnail(const QString& videoFile, ImageWriter& imageWriter,QImage &image)
+{
+    MovieDecoder movieDecoder(videoFile, NULL);
+    movieDecoder.decodeVideoFrame(); //before seeking, a frame has to be decoded
+ 
+    if ((!m_WorkAroundIssues) || (movieDecoder.getCodec() != "h264")) //workaround for bug in older ffmpeg (100% cpu usage when seeking in h264 files)
+   {
+       int secondToSeekTo = m_SeekTime.isEmpty() ? movieDecoder.getDuration() * m_SeekPercentage / 100 : timeToSeconds(m_SeekTime);
+       movieDecoder.seek(secondToSeekTo);
+    }
+    
+   VideoFrame videoFrame;
+    
+    if (m_SmartFrameSelection)
+    {
+        generateSmartThumbnail(movieDecoder, videoFrame);
+    }
+    else
+    {
+        movieDecoder.getScaledVideoFrame(m_ThumbnailSize, m_MaintainAspectRatio, videoFrame);
+    }
+
+    applyFilters(videoFrame);
+   imageWriter.writeFrame(videoFrame, image);
+}
+
+void VideoThumbnailer::generateSmartThumbnail(MovieDecoder& movieDecoder, VideoFrame& videoFrame)
+{
+    vector<VideoFrame> videoFrames(SMART_FRAME_ATTEMPTS);
+    vector<Histogram<int> > histograms(SMART_FRAME_ATTEMPTS);
+    
+    for (int i = 0; i < SMART_FRAME_ATTEMPTS; ++i)
+    {
+        movieDecoder.decodeVideoFrame();
+        movieDecoder.getScaledVideoFrame(m_ThumbnailSize, m_MaintainAspectRatio, videoFrames[i]);
+        generateHistogram(videoFrames[i], histograms[i]);
+    }
+    
+    int bestFrame = getBestThumbnailIndex(videoFrames, histograms);
+    
+    Q_ASSERT(bestFrame != -1);
+    videoFrame = videoFrames[bestFrame];
+}
+
+
+void VideoThumbnailer::generateThumbnail(const QString& videoFile, QImage &image)
+{
+   ImageWriter* imageWriter = new  ImageWriter();
+    generateThumbnail(videoFile, *imageWriter,image);
+    delete imageWriter;
+}
+
+
+
+void VideoThumbnailer::addFilter(IFilter* filter)
+{
+    m_Filters.push_back(filter);
+}
+
+void VideoThumbnailer::removeFilter(IFilter* filter)
+{
+    for (vector<IFilter*>::iterator iter = m_Filters.begin();
+         iter != m_Filters.end();
+         ++iter)
+    {
+        if (*iter == filter)
+        {
+            m_Filters.erase(iter);
+            break;
+        }
+    }
+}
+
+void VideoThumbnailer::clearFilters()
+{
+    m_Filters.clear();
+}
+
+void VideoThumbnailer::applyFilters(VideoFrame& videoFrame)
+{
+    for (vector<IFilter*>::iterator iter = m_Filters.begin();
+         iter != m_Filters.end();
+         ++iter)
+    {
+        (*iter)->process(videoFrame);
+    }
+}
+
+void VideoThumbnailer::generateHistogram(const VideoFrame& videoFrame, Histogram<int>& histogram)
+{
+    for (int i = 0; i < videoFrame.height; ++i)
+    {
+        int pixelIndex = i * videoFrame.lineSize;
+        for (int j = 0; j < videoFrame.width * 3; j += 3)
+        {
+            ++histogram.r[videoFrame.frameData[pixelIndex + j]];
+            ++histogram.g[videoFrame.frameData[pixelIndex + j + 1]];
+            ++histogram.b[videoFrame.frameData[pixelIndex + j + 2]];
+        }
+    }
+}
+
+int VideoThumbnailer::getBestThumbnailIndex(vector<VideoFrame>& videoFrames, const vector<Histogram<int> >& histograms)
+{
+    Histogram<float> avgHistogram;
+    for (size_t i = 0; i < histograms.size(); ++i)
+    {
+        for (int j = 0; j < 255; ++j)
+        {
+            avgHistogram.r[j] += static_cast<float>(histograms[i].r[j]) / histograms.size();
+            avgHistogram.g[j] += static_cast<float>(histograms[i].g[j]) / histograms.size();
+            avgHistogram.b[j] += static_cast<float>(histograms[i].b[j]) / histograms.size();
+        }
+    }
+    
+    int bestFrame = -1;
+    float minRMSE = FLT_MAX;
+    for (size_t i = 0; i < histograms.size(); ++i)
+    {
+        //calculate root mean squared error
+        float rmse = 0.0;
+        for (int j = 0; j < 255; ++j)
+        {
+            float error = fabsf(avgHistogram.r[j] - histograms[i].r[j])
+                        + fabsf(avgHistogram.g[j] - histograms[i].g[j])
+                        + fabsf(avgHistogram.b[j] - histograms[i].b[j]);
+            rmse += (error * error) / 255;
+        }
+        
+        rmse = sqrtf(rmse);
+        if (rmse < minRMSE)
+        {
+            minRMSE = rmse;
+            bestFrame = i;
+        }
+    }
+#ifdef DEBUG_MODE
+    cout << "Best frame was: " << bestFrame << "(RMSE: " << minRMSE << ")" << endl;
+#endif
+    return bestFrame;
+}
+
+}
Index: ffmpegthumbs/ffmpegthumbs.desktop
===================================================================
--- ffmpegthumbs/ffmpegthumbs.desktop   (Revision 0)
+++ ffmpegthumbs/ffmpegthumbs.desktop   (Revision 0)
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Encoding=UTF-8
+Type=Service
+Name=Video Files (ffmpegthumbs)
+X-KDE-ServiceTypes=ThumbCreator
+MimeType=video/*;application/x-flash-video;application/vnd.ms-asf;application/vnd.rn-realmedia;
+X-KDE-Library=ffmpegthumbs
+ServiceTypes=ThumbCreator
+CacheThumbnail=true
+ThumbnailerVersion=2
+IgnoreMaximumSize=true
Index: ffmpegthumbs/tests/CMakeLists.txt
===================================================================
--- ffmpegthumbs/tests/CMakeLists.txt   (Revision 0)
+++ ffmpegthumbs/tests/CMakeLists.txt   (Revision 0)
@@ -0,0 +1,26 @@
+set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} )
+
+set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+########### next target ###############
+
+
+include_directories( .. )
+
+
+########### next target ###############
+set(ffmpegthumbtest_SRCS ffmpegthumbtest.cpp
+   ${CMAKE_CURRENT_SOURCE_DIR}/../ffmpegthumbnailer.cpp
+   ${CMAKE_CURRENT_SOURCE_DIR}/../ffmpegthumbnailer/filmstripfilter.cpp
+   ${CMAKE_CURRENT_SOURCE_DIR}/../ffmpegthumbnailer/moviedecoder.cpp
+   ${CMAKE_CURRENT_SOURCE_DIR}/../ffmpegthumbnailer/imagewriter.cpp
+   ${CMAKE_CURRENT_SOURCE_DIR}/../ffmpegthumbnailer/videothumbnailer.cpp
+)
+
+
+kde4_add_executable(ffmpegthumbtest ${ffmpegthumbtest_SRCS} )
+
+target_link_libraries(ffmpegthumbtest ${KDE4_KDECORE_LIBS} ${KDE4_KIO_LIBS} ${AVUTIL_LIBRARIES} ${AVFORMAT_LIBRARIES} ${AVCODEC_LIBRARIES} ${SWSCALE_LIBRARIES})
+
+
+
+
Index: ffmpegthumbs/tests/ffmpegthumbtest.cpp
===================================================================
--- ffmpegthumbs/tests/ffmpegthumbtest.cpp  (Revision 0)
+++ ffmpegthumbs/tests/ffmpegthumbtest.cpp  (Revision 0)
@@ -0,0 +1,25 @@
+
+#include "ffmpegthumbnailer.h"
+
+#include <QCoreApplication>
+#include <QDir>
+#include <iostream>
+
+#include <stdlib.h>
+
+using std::cout;
+using std::endl;
+
+
+int main( int argc, char **argv )
+{
+    QCoreApplication app( argc, argv );
+   QImage image;
+   FFMpegThumbnailer *thumbnailer = new FFMpegThumbnailer();
+   thumbnailer->create("/home/scherfa/test.mpg",128,128,image);
+   delete thumbnailer;
+    cout << "All OK" << endl;
+    return 0;
+}
+
+// vim: set et sw=4 tw=0 sta: