diff -Naur vdr-1.6.0-orig/config.c vdr-1.6.0-bw/config.c
--- vdr-1.6.0-orig/config.c	2008-02-17 14:39:00.000000000 +0100
+++ vdr-1.6.0-bw/config.c	2010-02-13 18:07:07.000000000 +0100
@@ -240,6 +240,7 @@
   SubtitleOffset = 0;
   SubtitleFgTransparency = 0;
   SubtitleBgTransparency = 0;
+  FFDVBBandwidthLimit = 0;
   EPGLanguages[0] = -1;
   EPGScanTimeout = 5;
   EPGBugfixLevel = 3;
@@ -413,6 +414,7 @@
   else if (!strcasecmp(Name, "SubtitleOffset"))      SubtitleOffset     = atoi(Value);
   else if (!strcasecmp(Name, "SubtitleFgTransparency")) SubtitleFgTransparency = atoi(Value);
   else if (!strcasecmp(Name, "SubtitleBgTransparency")) SubtitleBgTransparency = atoi(Value);
+  else if (!strcasecmp(Name, "FFDVBBandwidthLimit")) FFDVBBandwidthLimit = atoi(Value);
   else if (!strcasecmp(Name, "EPGLanguages"))        return ParseLanguages(Value, EPGLanguages);
   else if (!strcasecmp(Name, "EPGScanTimeout"))      EPGScanTimeout     = atoi(Value);
   else if (!strcasecmp(Name, "EPGBugfixLevel"))      EPGBugfixLevel     = atoi(Value);
@@ -496,6 +498,7 @@
   Store("SubtitleOffset",     SubtitleOffset);
   Store("SubtitleFgTransparency", SubtitleFgTransparency);
   Store("SubtitleBgTransparency", SubtitleBgTransparency);
+  Store("FFDVBBandwidthLimit", FFDVBBandwidthLimit);
   StoreLanguages("EPGLanguages", EPGLanguages);
   Store("EPGScanTimeout",     EPGScanTimeout);
   Store("EPGBugfixLevel",     EPGBugfixLevel);
diff -Naur vdr-1.6.0-orig/config.h vdr-1.6.0-bw/config.h
--- vdr-1.6.0-orig/config.h	2008-03-23 11:26:10.000000000 +0100
+++ vdr-1.6.0-bw/config.h	2010-02-13 18:07:07.000000000 +0100
@@ -224,6 +224,7 @@
   int SubtitleLanguages[I18N_MAX_LANGUAGES + 1];
   int SubtitleOffset;
   int SubtitleFgTransparency, SubtitleBgTransparency;
+  int FFDVBBandwidthLimit;
   int EPGLanguages[I18N_MAX_LANGUAGES + 1];
   int EPGScanTimeout;
   int EPGBugfixLevel;
diff -Naur vdr-1.6.0-orig/dvbdevice.c vdr-1.6.0-bw/dvbdevice.c
--- vdr-1.6.0-orig/dvbdevice.c	2008-02-09 17:11:44.000000000 +0100
+++ vdr-1.6.0-bw/dvbdevice.c	2010-02-13 18:08:30.000000000 +0100
@@ -360,6 +360,13 @@
   digitalAudio = false;
   playMode = pmNone;
 
+  BandwidthMode = PLAY_ALL;
+  PlaysIFrame = false;
+
+  ftime(&LastBandwidthTime);
+  BandwidthIndex = 0;
+  memset(Bandwidth, 0, sizeof(Bandwidth));
+
   // Devices that are present on all card types:
 
   int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK);
@@ -1170,14 +1177,141 @@
   return true;
 }
 
+void cDvbDevice::CheckBandwidthStats()
+{
+  if (!HasDecoder())
+     return; // Not a DVB card with playback capability
+
+  timeb Now;
+  ftime(&Now);
+  int deltaMS = (Now.time - LastBandwidthTime.time) * 1000 + Now.millitm - LastBandwidthTime.millitm;
+  if (deltaMS < 0)
+     deltaMS = 0;
+
+  // Shift index
+  int OldBandwidthIndex;
+
+  OldBandwidthIndex = BandwidthIndex;
+  BandwidthIndex = (BandwidthIndex+1 < 10) ? BandwidthIndex+1 : 0;
+
+  Bandwidth[OldBandwidthIndex].DeltaMS = deltaMS;
+
+  // Check play mode
+  int TotalBandwidth = ::Setup.FFDVBBandwidthLimit > 0 ? ::Setup.FFDVBBandwidthLimit*1000/8 : INT_MAX;
+
+  enumBandwidthMode newBandwidthMode = PLAY_ALL;
+  for (int i=0; i<10; i++) {
+      if (Bandwidth[i].DeltaMS <= 0 || Bandwidth[i].DeltaMS > 4000)
+         continue;
+      // Scale up to one second    
+      int Receive         = Bandwidth[i].Receive         * 1000 / Bandwidth[i].DeltaMS;
+      int PlaybackAudio   = Bandwidth[i].PlaybackAudio   * 1000 / Bandwidth[i].DeltaMS;
+      int PlaybackIVideo  = Bandwidth[i].PlaybackIVideo  * 1000 / Bandwidth[i].DeltaMS;
+      int PlaybackPBVideo = Bandwidth[i].PlaybackPBVideo * 1000 / Bandwidth[i].DeltaMS;
+
+	  int total = Receive + PlaybackAudio;
+
+      if (newBandwidthMode > PLAY_NONE && total > TotalBandwidth)
+         newBandwidthMode = PLAY_NONE; // Not enough bandwidth for audio
+
+      total += PlaybackIVideo;
+      if (newBandwidthMode > PLAY_AUDIO && total > TotalBandwidth)
+         newBandwidthMode = PLAY_AUDIO; // Not enough bandwidth for I-Frames
+
+      total += PlaybackPBVideo;
+      if (newBandwidthMode > PLAY_IFRAME && total > TotalBandwidth)
+         newBandwidthMode = PLAY_IFRAME; // Not enough bandwidth for PB-Frames
+      }
+  BandwidthMode = newBandwidthMode;
+
+  // Reset stats for this second
+  Bandwidth[BandwidthIndex].Receive = 0;
+  Bandwidth[BandwidthIndex].PlaybackIVideo = 0;
+  Bandwidth[BandwidthIndex].PlaybackPBVideo = 0;
+  Bandwidth[BandwidthIndex].PlaybackAudio = 0;
+
+  LastBandwidthTime = Now;
+
+/*
+  if (Bandwidth[OldBandwidthIndex].DeltaMS > 0) {
+     int Receive         = Bandwidth[OldBandwidthIndex].Receive         * 1000 / Bandwidth[OldBandwidthIndex].DeltaMS;
+     int PlaybackAudio   = Bandwidth[OldBandwidthIndex].PlaybackAudio   * 1000 / Bandwidth[OldBandwidthIndex].DeltaMS;
+     int PlaybackIVideo  = Bandwidth[OldBandwidthIndex].PlaybackIVideo  * 1000 / Bandwidth[OldBandwidthIndex].DeltaMS;
+     int PlaybackPBVideo = Bandwidth[OldBandwidthIndex].PlaybackPBVideo * 1000 / Bandwidth[OldBandwidthIndex].DeltaMS;
+
+     printf("BW: R=%5i A=%5i I=%5i PB=%5i RA=%5i RAI=%5i RAIPB=%5i M=%s\n", 
+            Receive*8/1000,
+            PlaybackAudio*8/1000,
+            PlaybackIVideo*8/1000,
+            PlaybackPBVideo*8/1000,
+			(Receive+PlaybackAudio)*8/1000,
+			(Receive+PlaybackAudio+PlaybackIVideo)*8/1000,
+			(Receive+PlaybackAudio+PlaybackIVideo+PlaybackPBVideo)*8/1000,
+			BandwidthMode == PLAY_NONE ? "None" :
+			BandwidthMode == PLAY_AUDIO ? "Audio" :
+			BandwidthMode == PLAY_IFRAME ? "IFrame" :
+			BandwidthMode == PLAY_ALL ? "All" : "?");
+     }
+*/
+}
+
 int cDvbDevice::PlayVideo(const uchar *Data, int Length)
 {
-  return WriteAllOrNothing(fd_video, Data, Length, 1000, 10);
+  // scan for frame type
+  const uchar *p = Data + 2;
+  const uchar *pLimit = Data + Length - 3;
+  bool HasFrame = false;
+  bool HasIFrame = false;
+  while (p < pLimit && (p = (const uchar *)memchr(p, 0x01, pLimit - p))) {
+         if (!p[-2] && !p[-1]) { // found 0x000001
+            if (p[1] == 0) {
+               HasFrame = true;
+               if (((p[3] >> 3) & 0x07) == 1)
+                  HasIFrame = true;
+               }
+            p += 4; // continue scanning after 0x01ssxxyy
+            }
+         else
+            p += 3; // continue scanning after 0x01xxyy
+         }
+
+  if (!PlaysIFrame && HasIFrame)
+     // New I-Frame starts, re-calculate bandwidth
+     CheckBandwidthStats();
+
+  if (HasFrame)
+     PlaysIFrame = HasIFrame;
+
+  int written = 0;  
+  bool PlayThisFrame = PlaysIFrame ? BandwidthMode >= PLAY_IFRAME : BandwidthMode >= PLAY_ALL;
+
+  if (PlayThisFrame)
+     written = WriteAllOrNothing(fd_video, Data, Length, 1000, 10);
+  else
+     written = Length;
+
+  if (written >= 0) {
+     if (PlaysIFrame)
+        Bandwidth[BandwidthIndex].PlaybackIVideo += written;
+     else
+        Bandwidth[BandwidthIndex].PlaybackPBVideo += written;
+     }
+
+  return written;
 }
 
 int cDvbDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
 {
-  return WriteAllOrNothing(fd_audio, Data, Length, 1000, 10);
+  int written = 0;
+  if (BandwidthMode >= PLAY_AUDIO)
+     written = WriteAllOrNothing(fd_audio, Data, Length, 1000, 10);
+  else
+     written = Length;
+
+  if (written >= 0)
+     Bandwidth[BandwidthIndex].PlaybackAudio += written;
+
+  return written;
 }
 
 bool cDvbDevice::OpenDvr(void)
@@ -1203,6 +1337,9 @@
 {
   if (tsBuffer) {
      Data = tsBuffer->Get();
+     if (Data)
+        Bandwidth[BandwidthIndex].Receive += 188;
+
      return true;
      }
   return false;
diff -Naur vdr-1.6.0-orig/dvbdevice.h vdr-1.6.0-bw/dvbdevice.h
--- vdr-1.6.0-orig/dvbdevice.h	2008-02-08 14:48:31.000000000 +0100
+++ vdr-1.6.0-bw/dvbdevice.h	2010-02-13 18:07:07.000000000 +0100
@@ -12,6 +12,7 @@
 
 #include <linux/dvb/frontend.h>
 #include <linux/dvb/version.h>
+#include <sys/timeb.h>
 #include "device.h"
 #include "dvbspu.h"
 
@@ -155,6 +156,31 @@
   virtual bool OpenDvr(void);
   virtual void CloseDvr(void);
   virtual bool GetTSPacket(uchar *&Data);
+
+private:
+  bool PlaysIFrame;
+
+  enum enumBandwidthMode {
+       PLAY_NONE,
+       PLAY_AUDIO,
+       PLAY_IFRAME,
+       PLAY_ALL
+       };
+  enumBandwidthMode BandwidthMode;  
+
+  timeb LastBandwidthTime;
+  int BandwidthIndex;
+  struct sBandwidth {
+    int Receive;
+    int PlaybackIVideo;
+    int PlaybackPBVideo;
+    int PlaybackAudio;
+    int DeltaMS;
+    };
+
+  sBandwidth Bandwidth[10];
+
+  void CheckBandwidthStats();
   };
 
 #endif //__DVBDEVICE_H
diff -Naur vdr-1.6.0-orig/menu.c vdr-1.6.0-bw/menu.c
--- vdr-1.6.0-orig/menu.c	2008-03-16 12:15:28.000000000 +0100
+++ vdr-1.6.0-bw/menu.c	2010-02-13 18:07:07.000000000 +0100
@@ -2502,6 +2502,7 @@
      Add(new cMenuEditIntItem( tr("Setup.DVB$Subtitle foreground transparency"), &data.SubtitleFgTransparency, 0, 9));
      Add(new cMenuEditIntItem( tr("Setup.DVB$Subtitle background transparency"), &data.SubtitleBgTransparency, 0, 10));
      }
+  Add(new cMenuEditIntItem( tr("Setup.DVB$FF DVB Bandwidth Limit (kbit)"), &data.FFDVBBandwidthLimit, 0, 100000));
 
   SetCurrent(Get(current));
   Display();
