diff --git a/src/Makefile.in b/src/Makefile.in
index 8f88942..b9ee7c5 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -70,7 +70,8 @@ MOC = \
 	moc_mplayererrorbase.cpp \
 	moc_progressstatusbar.cpp \
 	moc_progresswindow.cpp \
-	moc_progresswindowbase.cpp
+	moc_progresswindowbase.cpp \
+	moc_framesequence.cpp
 
 UIC = \
 	uic_dvbcutbase.cpp \
@@ -84,7 +85,8 @@ SRCS = \
 	imageprovider.cpp index.cpp lavfmuxer.cpp logoutput.cpp \
 	main.cpp mpegmuxer.cpp mpgfile.cpp playaudio.cpp \
 	progressstatusbar.cpp progresswindow.cpp psfile.cpp \
-	pts.cpp streamdata.cpp tsfile.cpp settings.cpp $(MOC) $(UIC) \
+	pts.cpp streamdata.cpp tsfile.cpp settings.cpp framesequence.cpp \
+	$(MOC) $(UIC) \
 	$(STDLIB)
 
 OBJS = $(SRCS:.cpp=.$(OBJEXT))
diff --git a/src/dvbcut.cpp b/src/dvbcut.cpp
index fda4c7a..20fd245 100644
--- a/src/dvbcut.cpp
+++ b/src/dvbcut.cpp
@@ -51,6 +51,7 @@
 #include <qsettings.h>
 #include <qregexp.h>
 #include <qstatusbar.h>
+#include <qlayout.h>
 
 #include "port.h"
 #include "dvbcut.h"
@@ -68,6 +69,7 @@
 #include "exportdialog.h"
 #include "settings.h"
 #include "exception.h"
+#include "framesequence.h"
 
 #include "version.h"
 
@@ -131,8 +133,19 @@ dvbcut::dvbcut(QWidget *parent, const char *name, WFlags fl)
     jogsliding(false), jogmiddlepic(0),
     mplayer_process(0), imgp(0), busy(0),
     viewscalefactor(1.0),
-    nogui(false)
+    nogui(false),
+    frameseq_(0)
 {
+  frameseq_ = new framesequence(imagedisplay->parentWidget(), settings().frameseq_nframes, this);
+  layout7->addLayout(frameseq_->layout());
+  QStringList distances = QStringList::split(' ', settings().frameseq_distances);
+  for (QStringList::iterator i = distances.begin(); i != distances.end(); ++i)
+    frameseqinput->insertItem(*i);
+
+  frameseqinput->setCurrentText(settings().frameseq_home_distance);
+  frameseqhome->setText(settings().frameseq_home_distance);
+  frameseq_->distance(string2frameno(settings().frameseq_home_distance, 1500));
+  updateframeseqbuttons();
 #ifndef HAVE_LIB_AO
   playAudio1Action->setEnabled(false);
   playAudio2Action->setEnabled(false);
@@ -187,6 +200,8 @@ dvbcut::~dvbcut()
     delete imgp;
   if (mpg)
     delete mpg;
+
+  delete frameseq_;
 }
 
 // **************************************************************************
@@ -1122,6 +1137,11 @@ void dvbcut::playPlay()
   goinput->setEnabled(false);
   gobutton2->setEnabled(false);
   goinput2->setEnabled(false);
+  frameseqbutton->setEnabled(false);
+  frameseqinput->setEnabled(false);
+  frameseqprev->setEnabled(false);
+  frameseqnext->setEnabled(false);
+  frameseqhome->setEnabled(false);
 
 #ifdef HAVE_LIB_AO
 
@@ -1429,15 +1449,8 @@ void dvbcut::eventlistcontextmenu(QListBoxItem *lbi, const QPoint &point)
 void dvbcut::clickedgo()
 {
   QString text=goinput->text();
-  text.stripWhiteSpace();
   bool okay=false;
-  int inpic;
-  if (text.contains(':') || text.contains('.')) {
-    okay=true;
-    inpic=string2pts(text)/getTimePerFrame();
-  }
-  else
-    inpic=text.toInt(&okay,0);
+  int inpic = string2frameno(okay, text);
   if (okay) {
     fine=true;
     linslider->setValue(inpic);
@@ -1449,15 +1462,8 @@ void dvbcut::clickedgo()
 void dvbcut::clickedgo2()
 {
   QString text=goinput2->text();
-  text.stripWhiteSpace();
   bool okay=false;
-  int inpic, outpic;
-  if (text.contains(':') || text.contains('.')) {
-    okay=true;
-    outpic=string2pts(text)/getTimePerFrame();
-  }
-  else
-    outpic=text.toInt(&okay,0);
+  int inpic, outpic = string2frameno(okay, text);
   if (okay && !quick_picture_lookup.empty()) {
     // find the entry in the quick_picture_lookup table that corresponds to given output picture
     quick_picture_lookup_t::iterator it=
@@ -1470,6 +1476,65 @@ void dvbcut::clickedgo2()
   //goinput2->clear();
 }
 
+void dvbcut::clickedframeseq()
+{
+  QString text = frameseqinput->currentText();
+  bool okay = false;
+  int dist = string2frameno(okay, text);
+  if (okay) {
+    frameseq_->distance(dist);
+    frameseq_->update(curpic);
+    updateframeseqbuttons();
+  }
+  //frameseqinput->clear();
+}
+
+void dvbcut::updateframeseqbuttons()
+{
+  int item = frameseqinput->currentItem();
+  if (item <= 0) {
+    frameseqprev->setEnabled(false);
+    frameseqprev->setText("Previous");
+  } else {
+    frameseqprev->setEnabled(true);
+    QString s = frameseqinput->text(item - 1);
+    frameseqprev->setText(s);
+  }
+
+  if (item >= frameseqinput->count() - 1) {
+    frameseqnext->setEnabled(false);
+    frameseqnext->setText("Next");
+  } else {
+    frameseqnext->setEnabled(true);
+    QString s = frameseqinput->text(item + 1);
+    frameseqnext->setText(s);
+  }
+}
+
+void dvbcut::clickedframeseqprev()
+{
+  int item = frameseqinput->currentItem();
+  if (item > 0) {
+    frameseqinput->setCurrentItem(item - 1);
+    clickedframeseq();
+  }
+}
+
+void dvbcut::clickedframeseqnext()
+{
+  int item = frameseqinput->currentItem();
+  if (item < frameseqinput->count() - 1) {
+    frameseqinput->setCurrentItem(item + 1);
+    clickedframeseq();
+  }
+}
+
+void dvbcut::clickedframeseqhome()
+{
+  frameseqinput->setCurrentText(settings().frameseq_home_distance);
+  clickedframeseq();
+}
+
 void dvbcut::mplayer_exited()
 {
   if (mplayer_process) {
@@ -1492,6 +1557,11 @@ void dvbcut::mplayer_exited()
   goinput->setEnabled(true);
   gobutton2->setEnabled(true);
   goinput2->setEnabled(true);
+  frameseqbutton->setEnabled(true);
+  frameseqinput->setEnabled(true);
+  frameseqprev->setEnabled(true);
+  frameseqnext->setEnabled(true);
+  frameseqhome->setEnabled(true);
 
 #ifdef HAVE_LIB_AO
 
@@ -1580,10 +1650,16 @@ void dvbcut::updateimagedisplay()
   if (showimage) {
     if (!imgp)
       imgp=new imageprovider(*mpg,new dvbcutbusy(this),false,viewscalefactor);
+
     QPixmap px=imgp->getimage(curpic,fine);
     imagedisplay->setMinimumSize(px.size());
     imagedisplay->setPixmap(px);
     qApp->processEvents();
+
+    if (!frameseq_->imgp())
+      frameseq_->imgp(new imageprovider(*mpg, new dvbcutbusy(this), false, viewscalefactor * 7.));
+
+    frameseq_->update(curpic);
   }
 }
 
@@ -1672,6 +1748,8 @@ void dvbcut::open(std::list<std::string> filenames, std::string idxfilename, std
     delete imgp;
     imgp=0;
   }
+
+  frameseq_->imgp(0);
   eventlist->clear();
   imagedisplay->setBackgroundMode(Qt::PaletteBackground);
   imagedisplay->setMinimumSize(QSize(0,0));
@@ -1728,6 +1806,11 @@ void dvbcut::open(std::list<std::string> filenames, std::string idxfilename, std
   gobutton->setEnabled(false);
   goinput2->setEnabled(false);
   gobutton2->setEnabled(false);
+  frameseqbutton->setEnabled(false);
+  frameseqinput->setEnabled(false);
+  frameseqprev->setEnabled(false);
+  frameseqnext->setEnabled(false);
+  frameseqhome->setEnabled(false);
   linslider->setEnabled(false);
   jogslider->setEnabled(false);
 
@@ -2019,14 +2102,8 @@ void dvbcut::open(std::list<std::string> filenames, std::string idxfilename, std
       else
         continue;
       bool okay=false;
-      int picnum;
       QString str=e.attribute("picture","-1");
-      if (str.contains(':') || str.contains('.')) {
-        okay=true;
-        picnum=string2pts(str)/getTimePerFrame();
-      }
-      else
-        picnum=str.toInt(&okay,0);
+      int picnum = string2frameno(okay, str);
       if (okay && picnum>=0 && picnum<pictures) {
         new EventListItem(eventlist,imgp->getimage(picnum),evt,picnum,(*mpg)[picnum].getpicturetype(),(*mpg)[picnum].getpts()-firstpts);
         qApp->processEvents();
@@ -2076,6 +2153,11 @@ void dvbcut::open(std::list<std::string> filenames, std::string idxfilename, std
   gobutton->setEnabled(true);
   goinput2->setEnabled(true);
   gobutton2->setEnabled(true);
+  frameseqbutton->setEnabled(true);
+  frameseqinput->setEnabled(true);
+  frameseqprev->setEnabled(true);
+  frameseqnext->setEnabled(true);
+  frameseqhome->setEnabled(true);
   linslider->setEnabled(true);
   jogslider->setEnabled(true);
 
@@ -2468,3 +2550,28 @@ void dvbcut::helpContentAction_activated()
       tr("Help file %1 not available").arg(helpFile));
   }
 }
+
+int dvbcut::string2frameno(const QString &s, int default_value)
+{
+	bool valid;
+	int frameno = string2frameno(valid, s);
+	return valid ? frameno : default_value;
+}
+
+int dvbcut::string2frameno(bool &valid, const QString &s)
+{
+  if (s.contains(':') || s.contains('.')) {
+    valid = true;
+    return string2pts(s.stripWhiteSpace()) / getTimePerFrame();
+  }
+
+  return s.toInt(&valid, 0);
+}
+
+void dvbcut::gotoFrame(int frameno)
+{
+  bool save = fine;
+  fine = true;
+  linslider->setValue(frameno);
+  fine = save;
+}
diff --git a/src/dvbcut.h b/src/dvbcut.h
index dd4aacc..488b927 100644
--- a/src/dvbcut.h
+++ b/src/dvbcut.h
@@ -31,6 +31,7 @@
 
 class QProcess;
 class imageprovider;
+class framesequence;
 
 class dvbcut: public dvbcutbase
   {
@@ -102,6 +103,7 @@ protected:
   int exportformat; 
   bool start_bof; 
   bool stop_eof; 
+  framesequence *frameseq_;
 
 protected:
   //   QPixmap getpixmap(int picture, bool allgop=false);
@@ -145,6 +147,10 @@ public:
   // static dvbcut *New(std::string filename=std::string(), std::string idxfilename=std::string());
   void addStartStopItems(std::vector<int>, int option=0);
   int getTimePerFrame() { return timeperframe>0 && timeperframe<5000 ? timeperframe : 3003; };
+  int string2frameno(const QString &s, int default_value);
+  int string2frameno(bool &valid, const QString &s);
+  void gotoFrame(int frameno);
+  void updateframeseqbuttons();
 
 public slots:
   virtual void fileNew();
@@ -186,6 +192,10 @@ public slots:
   virtual void mplayer_readstdout();
   virtual void clickedgo();
   virtual void clickedgo2();
+  virtual void clickedframeseq();
+  virtual void clickedframeseqprev();
+  virtual void clickedframeseqnext();
+  virtual void clickedframeseqhome();
   virtual void updateimagedisplay();
   virtual void audiotrackchosen(int id);
   virtual void loadrecentfile(int id);
diff --git a/src/dvbcutbase.ui b/src/dvbcutbase.ui
index 2148f44..48c5709 100644
--- a/src/dvbcutbase.ui
+++ b/src/dvbcutbase.ui
@@ -363,6 +363,105 @@
                             </widget>
                         </hbox>
                     </widget>
+                    <widget class="QLayoutWidget">
+                        <property name="name">
+                            <cstring>layout6</cstring>
+                        </property>
+                        <hbox>
+                            <property name="name">
+                                <cstring>unnamed</cstring>
+                            </property>
+                            <spacer>
+                                <property name="name">
+                                    <cstring>spacer6</cstring>
+                                </property>
+                                <property name="orientation">
+                                    <enum>Horizontal</enum>
+                                </property>
+                                <property name="sizeType">
+                                    <enum>Expanding</enum>
+                                </property>
+                                <property name="sizeHint">
+                                    <size>
+                                        <width>2</width>
+                                        <height>10</height>
+                                    </size>
+                                </property>
+                            </spacer>
+                            <widget class="QPushButton">
+                                <property name="name">
+                                    <cstring>frameseqprev</cstring>
+                                </property>
+                                <property name="enabled">
+                                    <bool>false</bool>
+                                </property>
+                                <property name="text">
+                                    <string>Previous</string>
+                                </property>
+                            </widget>
+			    <widget class="QComboBox">
+				<property name="name">
+				    <cstring>frameseqinput</cstring>
+				</property>
+				<property name="editable">
+				    <bool>true</bool>
+				</property>
+				<property name="duplicatesEnabled">
+				    <bool>false</bool>
+				</property>
+			    </widget>
+                            <widget class="QPushButton">
+                                <property name="name">
+                                    <cstring>frameseqbutton</cstring>
+                                </property>
+                                <property name="enabled">
+                                    <bool>false</bool>
+                                </property>
+                                <property name="text">
+                                    <string>go</string>
+                                </property>
+                            </widget>
+                            <widget class="QPushButton">
+                                <property name="name">
+                                    <cstring>frameseqnext</cstring>
+                                </property>
+                                <property name="enabled">
+                                    <bool>false</bool>
+                                </property>
+                                <property name="text">
+                                    <string>Next</string>
+                                </property>
+                            </widget>
+                            <widget class="QPushButton">
+                                <property name="name">
+                                    <cstring>frameseqhome</cstring>
+                                </property>
+                                <property name="enabled">
+                                    <bool>false</bool>
+                                </property>
+                                <property name="text">
+                                    <string>Home</string>
+                                </property>
+                            </widget>
+                            <spacer>
+                                <property name="name">
+                                    <cstring>spacer6</cstring>
+                                </property>
+                                <property name="orientation">
+                                    <enum>Horizontal</enum>
+                                </property>
+                                <property name="sizeType">
+                                    <enum>Expanding</enum>
+                                </property>
+                                <property name="sizeHint">
+                                    <size>
+                                        <width>2</width>
+                                        <height>10</height>
+                                    </size>
+                                </property>
+                            </spacer>
+                        </hbox>
+                    </widget>
                 </vbox>
             </widget>
         </widget>
@@ -1159,6 +1258,36 @@
         <slot>clickedgo2()</slot>
     </connection>
     <connection>
+        <sender>frameseqbutton</sender>
+        <signal>clicked()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseq()</slot>
+    </connection>
+    <connection>
+        <sender>frameseqinput</sender>
+        <signal>activated(const QString&amp;)</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseq()</slot>
+    </connection>
+    <connection>
+        <sender>frameseqprev</sender>
+        <signal>clicked()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseqprev()</slot>
+    </connection>
+    <connection>
+        <sender>frameseqnext</sender>
+        <signal>clicked()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseqnext()</slot>
+    </connection>
+    <connection>
+        <sender>frameseqhome</sender>
+        <signal>clicked()</signal>
+        <receiver>dvbcutbase</receiver>
+        <slot>clickedframeseqhome()</slot>
+    </connection>
+    <connection>
         <sender>playPlayAction</sender>
         <signal>activated()</signal>
         <receiver>dvbcutbase</receiver>
@@ -1306,6 +1435,10 @@
     <slot>eventlistcontextmenu(QListBoxItem *, const QPoint &amp;)</slot>
     <slot>clickedgo()</slot>
     <slot>clickedgo2()</slot>
+    <slot>clickedframeseq()</slot>
+    <slot>clickedframeseqprev()</slot>
+    <slot>clickedframeseqnext()</slot>
+    <slot>clickedframeseqhome()</slot>
     <slot>playPlay()</slot>
     <slot>playStop()</slot>
     <slot>playAudio1()</slot>
diff --git a/src/framesequence.cpp b/src/framesequence.cpp
new file mode 100644
index 0000000..c9ad104
--- /dev/null
+++ b/src/framesequence.cpp
@@ -0,0 +1,81 @@
+// -*- mode: c++ -*-
+// Copyright (c) 2009 Olaf Dietsche
+
+#include "framesequence.h"
+#include <sstream>
+#include <qlayout.h>
+#include <qpushbutton.h>
+#include "imageprovider.h"
+#include "dvbcut.h"
+
+void frame::gotoFrame()
+{
+	dvbcut_->gotoFrame(frameno_);
+}
+
+framesequence::framesequence(QWidget *parent, int nframes, dvbcut *main, imageprovider *imgp)
+	: layout_(0),
+	  imgp_(imgp),
+	  distance_(1500)
+{
+	createWidgets(parent, nframes, main);
+}
+
+framesequence::~framesequence()
+{
+	for (std::vector<frame*>::iterator i = frames_.begin(); i != frames_.end(); ++i)
+		delete *i;
+
+	frames_.clear();
+	delete imgp_;
+// FIXME	delete layout_;
+}
+
+void framesequence::imgp(imageprovider *imgp)
+{
+	delete imgp_;
+	imgp_ = imgp;
+}
+
+void framesequence::update(int frameno)
+{
+	if (!imgp_)
+		return;
+
+	bool decodeallgop = distance_ == 1;
+	int n = frames_.size();
+	frameno -= n / 2 * distance_;
+	if (frameno < 0)
+		frameno = 0;
+
+	for (std::vector<frame*>::iterator i = frames_.begin(); i != frames_.end(); ++i, frameno += distance_) {
+		QPixmap px = imgp_->getimage(frameno, decodeallgop);
+		if (px.isNull()) {
+			(*i)->image_->hide();
+		} else {
+			(*i)->frameno_ = frameno;
+			(*i)->image_->show();
+			(*i)->image_->setMinimumSize(px.size());
+			(*i)->image_->setPixmap(px);
+		}
+	}
+}
+
+void framesequence::createWidgets(QWidget *parent, int nframes, dvbcut *main)
+{
+	layout_ = new QHBoxLayout(-1, "framesequence");
+	for (int i = 0; i < nframes; ++i) {
+		QPushButton *w = new QPushButton(parent);
+		w->setFlat(true);
+		layout_->addWidget(w);
+		frame *f = new frame();
+		f->image_ = w;
+		f->dvbcut_ = main;
+		frames_.push_back(f);
+		QObject::connect(w, SIGNAL(clicked()), f, SLOT(gotoFrame()));
+		w->hide();
+	}
+
+	QSpacerItem *spacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum);
+	layout_->addItem(spacer);
+}
diff --git a/src/framesequence.h b/src/framesequence.h
new file mode 100644
index 0000000..1f46f11
--- /dev/null
+++ b/src/framesequence.h
@@ -0,0 +1,48 @@
+#ifndef __framesequence_h_included__
+#define __framesequence_h_included__
+
+// -*- mode: c++ -*-
+// Copyright (c) 2009 Olaf Dietsche
+
+#include <vector>
+#include <qobject.h>
+class QBoxLayout;
+class QPushButton;
+class QWidget;
+class dvbcut;
+class imageprovider;
+
+class frame : public QObject {
+	Q_OBJECT
+public:
+	QPushButton *image_;
+	int frameno_;
+	dvbcut *dvbcut_;
+public slots:
+	void gotoFrame();
+};
+
+class framesequence {
+public:
+	framesequence(QWidget *parent, int nframes, dvbcut *main, imageprovider *imgp = 0);
+	virtual ~framesequence();
+
+	QBoxLayout *layout() const { return layout_; }
+	imageprovider *imgp() const { return imgp_; }
+	void imgp(imageprovider *imgp);
+	void distance(int distance) { distance_ = distance; }
+	void update(int frameno);
+
+private:
+	framesequence(const framesequence&);
+	framesequence& operator=(const framesequence&);
+
+	void createWidgets(QWidget *parent, int nframes, dvbcut *main);
+
+	QBoxLayout *layout_;
+	std::vector<frame*> frames_;
+	imageprovider *imgp_;
+	int distance_;
+};
+
+#endif
diff --git a/src/settings.cpp b/src/settings.cpp
index 30d1b9c..5c43a4c 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -58,6 +58,11 @@
 #define DVBCUT_DEFAULT_PIPE_LABEL \
         "DVD-Video titleset (dvdauthor)"
 #define DVBCUT_DEFAULT_PIPE_FORMAT (0)
+
+#define DVBCUT_DEFAULT_FRAMESEQ_NFRAMES 7
+#define DVBCUT_DEFAULT_FRAMESEQ_HOME_DISTANCE "1:0"
+#define DVBCUT_DEFAULT_FRAMESEQ_DISTANCES "1 0:1 0:10 1:0 5:0"
+	
 /* 
 // SOME OTHER EXAMPLES for the settings file ~/.qt/dvbcut.sf.netrc 
 // (ok, for time consuming conversions one does not save any time, but it may be convenient...) 
@@ -284,6 +289,11 @@ dvbcut_settings::load_settings() {
     // minimal length of a chapter
     chapter_minimum = readNumEntry("/minimum", 200*25);
   endGroup();	// auto chapters
+  beginGroup("/frameseq");
+    frameseq_nframes = readNumEntry("/nframes", DVBCUT_DEFAULT_FRAMESEQ_NFRAMES);
+    frameseq_home_distance = readEntry("/home_distance", DVBCUT_DEFAULT_FRAMESEQ_HOME_DISTANCE);
+    frameseq_distances = readEntry("/distances", DVBCUT_DEFAULT_FRAMESEQ_DISTANCES);
+  endGroup();	// frameseq
 }
 
 void
@@ -380,6 +390,11 @@ dvbcut_settings::save_settings() {
     writeEntry("/threshold", chapter_threshold);
     writeEntry("/minimum", chapter_minimum);
   endGroup();	// auto chapters
+  beginGroup("/frameseq");
+    writeEntry("/nframes", frameseq_nframes);
+    writeEntry("/home_distance", frameseq_home_distance);
+    writeEntry("/distances", frameseq_distances);
+  endGroup();	// frameseq
 }
 
 // private settings variable
diff --git a/src/settings.h b/src/settings.h
index 8050731..b27026f 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -85,7 +85,9 @@ public:
   int chapter_tolerance;
   double chapter_threshold;
   int chapter_minimum;
-
+  int frameseq_nframes;
+  QString frameseq_home_distance;
+  QString frameseq_distances;
 };
 
 // access function

