Index: libs/libmythtv/NuppelVideoPlayer.h
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.h	(revision 8819)
+++ libs/libmythtv/NuppelVideoPlayer.h	(working copy)
@@ -141,6 +141,7 @@
     bool    IsPlaying(void) const             { return playing; }
     bool    AtNormalSpeed(void) const         { return next_normal_speed; }
     bool    IsDecoderThreadAlive(void) const  { return decoder_thread_alive; }
+    bool    IsReallyNearEnd(void) const;
     bool    IsNearEnd(long long framesRemaining = -1) const;
     bool    PlayingSlowForPrebuffer(void) const { return m_playing_slower; }
     bool    HasAudioIn(void) const            { return !no_audio_in; }
Index: libs/libmythtv/nuppeldecoder.cpp
===================================================================
--- libs/libmythtv/nuppeldecoder.cpp	(revision 8819)
+++ libs/libmythtv/nuppeldecoder.cpp	(working copy)
@@ -541,7 +541,7 @@
     if (usingextradata && extradata.video_fourcc == MKTAG('D', 'I', 'V', 'X'))
         setreadahead = true;
 
-    ringBuffer->CalcReadAheadThresh(0);
+    ringBuffer->UpdateRawBitrate(0);
 
     videosizetotal = 0;
     videoframesread = 0;
@@ -1083,7 +1083,7 @@
                     float bps = videosizetotal * 8.0 / 1024 * video_frame_rate;
                     bps = bps * 3 / 2;
 
-                    ringBuffer->CalcReadAheadThresh((int)bps);
+                    ringBuffer->UpdateRawBitrate((uint) bps);
                     setreadahead = true;
                 }
             }
Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.cpp	(revision 8819)
+++ libs/libmythtv/NuppelVideoPlayer.cpp	(working copy)
@@ -2145,13 +2145,9 @@
 
 void NuppelVideoPlayer::SwitchToProgram(void)
 {
-    if (videoOutput)
-    {
-        int  sz  = ringBuffer->DataInReadAhead();
-        uint vvf = videoOutput->ValidVideoFrames();
-        if ((vvf > 3 && sz > 128000) || (sz > 256000))
-            return;
-    }
+    if (!IsReallyNearEnd())
+        return;
+    VERBOSE(VB_IMPORTANT, "SwitchToProgram(void)");
 
     bool discontinuity = false, newtype = false;
     ProgramInfo *pginfo = livetvchain->GetSwitchProgram(discontinuity, newtype);
@@ -2242,6 +2238,7 @@
 
 void NuppelVideoPlayer::JumpToProgram(void)
 {
+    VERBOSE(VB_IMPORTANT, "JumpToProgram(void)");
     bool discontinuity = false, newtype = false;
     ProgramInfo *pginfo = livetvchain->GetSwitchProgram(discontinuity, newtype);
     if (!pginfo)
@@ -2487,7 +2484,10 @@
                 decoderThreadPaused.wakeAll();
             }
             else
+            {
+                ringBuffer->UpdatePlaySpeed(play_speed);
                 DoPlay();
+            }
 
             decoder_lock.unlock();
             continue;
@@ -3162,6 +3162,39 @@
     return ret;
 }
 
+/** \fn NuppelVideoPlayer::IsReallyNearEnd(void) const
+ *  \brief Returns true iff really near end of recording.
+ *
+ *   This is used by SwitchToProgram() to determine if we are so
+ *   close to the end that we need to switch to the next program.
+ */
+bool NuppelVideoPlayer::IsReallyNearEnd(void) const
+{
+    if (!videoOutput)
+        return false;
+
+    int  sz  = ringBuffer->DataInReadAhead();
+    uint vvf = videoOutput->ValidVideoFrames();
+
+    uint kbytes_per_sec = ringBuffer->GetBitrate() / 8;
+    double inv_fps = 1.0 / GetDecoder()->GetFPS();
+    double bytes_per_frame = kbytes_per_sec * 1000 * inv_fps;
+    double rh_frames = sz / bytes_per_frame;
+
+    bool near_end = !((vvf > 3 && sz > 128000) || (sz > 256000));
+    //bool near_end = (vvf + rh_frames < 10);
+
+    VERBOSE(VB_IMPORTANT, LOC + "IsReallyNearEnd()"
+            <<" br("<<kbytes_per_sec<<"KB)"
+            <<" sz("<<(sz / 1000)<<"KB)"
+            <<" vfl("<<vvf<<")"
+            <<" fps("<<((uint)(1.0/inv_fps))<<")"
+            <<" frh("<<((uint)rh_frames)<<")"
+            <<" ne:"<<near_end);
+
+    return near_end;
+}
+
 /** \fn NuppelVideoPlayer::IsNearEnd(long long) const
  *  \brief Returns true iff near end of recording.
  *  \param margin minimum number of frames we want before being near end,
Index: libs/libmythtv/RingBuffer.cpp
===================================================================
--- libs/libmythtv/RingBuffer.cpp	(revision 8819)
+++ libs/libmythtv/RingBuffer.cpp	(working copy)
@@ -86,6 +86,7 @@
       rbrpos(0),                rbwpos(0),
       internalreadpos(0),       ateof(false),
       readsallowed(false),      wantseek(false),
+      last_rawbitrate(8000),    last_playspeed(1.0f),
       fill_threshold(-1),       fill_min(-1),
       readblocksize(128000),    wanttoread(0),
       numfailures(0),           commserror(false),
@@ -443,39 +444,75 @@
     return ret;
 }
 
-/** \fn RingBuffer::CalcReadAheadThresh(uint)
- *  \brief Calculates fill_min, fill_threshold, and readblocksize from
- *         the estimated bitrate of the stream.
+/** \fn RingBuffer::UpdateRawBitrate(uint)
  *  \param estbitrate Streams average number of kilobits per second.
  */
-void RingBuffer::CalcReadAheadThresh(uint estbitrate)
+void RingBuffer::UpdateRawBitrate(uint rawbitrate)
 {
+    pthread_rwlock_wrlock(&rwlock);
+    last_rawbitrate = rawbitrate;
+    pthread_rwlock_unlock(&rwlock);
+    CalcReadAheadThresh();
+}
+
+uint RingBuffer::GetBitrate(void) const
+{
+    //pthread_rwlock_wrlock(&rwlock);
+    uint estrate = (uint) (last_rawbitrate * last_playspeed);
+    //pthread_rwlock_unlock(&rwlock);
+
+    return estrate;
+}
+
+/** \fn RingBuffer::UpdatePlaySpeed(float)
+ *  \param estbitrate Streams average number of kilobits per second.
+ */
+void RingBuffer::UpdatePlaySpeed(float playspeed)
+{
+    pthread_rwlock_wrlock(&rwlock);
+    last_playspeed = playspeed;
+    pthread_rwlock_unlock(&rwlock);
+    CalcReadAheadThresh();
+}
+
+/** \fn RingBuffer::CalcReadAheadThresh(void)
+ *  \brief Calculates fill_min, fill_threshold, and readblocksize
+ *         from the estimated bitrate of the stream.
+ */
+void RingBuffer::CalcReadAheadThresh(void)
+{
+    const uint KB128 = 128*1024;
+    const uint KB256 = 256*1024;
+    const uint KB512 = 512*1024;
+
     wantseek = true;
     pthread_rwlock_wrlock(&rwlock);
 
+    uint estbitrate = GetBitrate();
+
     wantseek       = false;
     readsallowed   = false;
     fill_min       = 1;
-    readblocksize  = (estbitrate > 12000) ? 256000 : 128000;
+    readblocksize  = (estbitrate > 12000) ? KB256 : KB128;
 
 #if 1
     fill_threshold = 0;
 
     if (remotefile)
-        fill_threshold += 256000;
+        fill_threshold += KB256;
 
     if (estbitrate > 6000)
-        fill_threshold += 256000;
+        fill_threshold += KB256;
 
     if (estbitrate > 10000)
-        fill_threshold += 256000;
+        fill_threshold += KB256;
 
     if (estbitrate > 12000)
-        fill_threshold += 256000;
+        fill_threshold += KB256;
 
     fill_threshold = (fill_threshold) ? fill_threshold : -1;
 #else
-    fill_threshold = (remotefile) ? 256000 : 0;
+    fill_threshold = (remotefile) ? KB256 : 0;
     fill_threshold = max(0, estbitrate) * 60*10;
     fill_threshold = (fill_threshold) ? fill_threshold : -1;
 #endif
Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
--- libs/libmythtv/avformatdecoder.cpp	(revision 8819)
+++ libs/libmythtv/avformatdecoder.cpp	(working copy)
@@ -1172,9 +1172,9 @@
 
     if (bitrate > 0)
     {
-        bitrate /= 1000;
+        bitrate = (bitrate + 999) / 1000;
         if (ringBuffer)
-            ringBuffer->CalcReadAheadThresh(bitrate);
+            ringBuffer->UpdateRawBitrate(bitrate);
     }
 
     // Select a new track at the next opportunity.
Index: libs/libmythtv/decoderbase.h
===================================================================
--- libs/libmythtv/decoderbase.h	(revision 8819)
+++ libs/libmythtv/decoderbase.h	(working copy)
@@ -52,6 +52,7 @@
     virtual long UpdateStoredFrameNum(long frame) = 0;
 
     virtual QString GetEncodingType(void) const = 0;
+    virtual double  GetFPS(void) const { return fps; }
 
     virtual void UpdateFramesPlayed(void);
     long long GetFramesRead(void) const { return framesRead; };
Index: libs/libmythtv/RingBuffer.h
===================================================================
--- libs/libmythtv/RingBuffer.h	(revision 8819)
+++ libs/libmythtv/RingBuffer.h	(working copy)
@@ -22,7 +22,8 @@
     // Sets
     void SetWriteBufferSize(int newSize);
     void SetWriteBufferMinWriteSize(int newMinSize);
-    void CalcReadAheadThresh(uint estbitrate);
+    void UpdateRawBitrate(uint rawbitrate);
+    void UpdatePlaySpeed(float playspeed);
 
     // Gets
     /// Returns name of file used by this RingBuffer
@@ -39,6 +40,7 @@
     long long GetReadPosition(void)  const;
     long long GetWritePosition(void) const;
     long long GetRealFileSize(void)  const;
+    uint      GetBitrate(void)       const;
     bool      IsOpen(void)           const;
 
     // General Commands
@@ -90,6 +92,7 @@
     void ReadAheadThread(void);
 
   private:
+    void CalcReadAheadThresh(void);
     int safe_read_dvd(void *data, uint sz);
     int safe_read(int fd, void *data, uint sz);
     int safe_read(RemoteFile *rf, void *data, uint sz);
@@ -136,10 +139,12 @@
     bool ateof;
     bool readsallowed;
     bool wantseek;
-    int fill_threshold;
-    int fill_min;
 
-    int readblocksize;
+    uint  last_rawbitrate;
+    float last_playspeed;
+    int   fill_threshold;
+    int   fill_min;
+    int   readblocksize;
 
     QWaitCondition pauseWait;
 
Index: libs/libmythtv/ivtvdecoder.cpp
===================================================================
--- libs/libmythtv/ivtvdecoder.cpp	(revision 8819)
+++ libs/libmythtv/ivtvdecoder.cpp	(working copy)
@@ -268,7 +268,7 @@
     GetNVP()->SetVideoParams(720 /*width*/, (ntsc) ? 480 : 576 /*height*/,
                              (ntsc) ? 29.97f : 25.0f, keyframedist, 1.33);
      
-    ringBuffer->CalcReadAheadThresh(8000);
+    ringBuffer->UpdateRawBitrate(8000);
 
     if (m_playbackinfo || livetv || watchingrecording)
     {
