Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.cpp.orig
+++ libs/libmythtv/NuppelVideoPlayer.cpp
@@ -254,6 +254,9 @@ NuppelVideoPlayer::NuppelVideoPlayer(boo
     for (int i = 0; i < MAXTBUFFER; i++)
         txtbuffers[i].buffer = new unsigned char[text_size + 1];
 
+    m_frame_skip = m_frame_show = 0;
+    m_frame_skip_idx = m_frame_show_idx = 0;
+
     memset(&CC708DelayedDeletes, 0, sizeof(CC708DelayedDeletes));
 }
 
@@ -1014,6 +1017,107 @@ void NuppelVideoPlayer::AutoDeint(VideoF
     m_scan_locked  = false;
 }
 
+void NuppelVideoPlayer::PredictFrameSkip(FrameScanType scan)
+{
+    m_frame_skip = m_frame_show = 0;
+
+    if (play_speed <= 1 || play_speed > 2 || scan != kScan_Progressive)
+        return;
+
+    switch ((int)(play_speed * 100.0 + 0.5))
+    {
+      case 105:
+        m_frame_show = 20;
+        m_frame_skip = 1;
+        break;
+      case 110:
+        m_frame_show = 10;
+        m_frame_skip = 1;
+        break;
+      case 115:
+        m_frame_show = 5;
+        m_frame_skip = 1;
+        break;
+      case 120:
+        m_frame_show = 5;
+        m_frame_skip = 1;
+        break;
+      case 125:
+        m_frame_show = 4;
+        m_frame_skip = 1;
+        break;
+      case 130:
+        m_frame_show = 4;
+        m_frame_skip = 1;
+        break;
+      case 135:
+        m_frame_show = 3;
+        m_frame_skip = 1;
+        break;
+      case 140:
+        m_frame_show = 5;
+        m_frame_skip = 2;
+        break;
+      case 145:
+        m_frame_show = 5;
+        m_frame_skip = 2;
+        break;
+      case 150:
+        m_frame_show = 2;
+        m_frame_skip = 1;
+        break;
+      case 155:
+        m_frame_show = 2;
+        m_frame_skip = 1;
+        break;
+      case 160:
+        m_frame_show = 5;
+        m_frame_skip = 3;
+        break;
+      case 165:
+        m_frame_show = 5;
+        m_frame_skip = 3;
+        break;
+      case 170:
+        m_frame_show = 5;
+        m_frame_skip = 3;
+        break;
+      case 175:
+        m_frame_show = 5;
+        m_frame_skip = 3;
+        break;
+      case 180:
+        m_frame_show = 5;
+        m_frame_skip = 3;
+        break;
+      case 185:
+        m_frame_show = 5;
+        m_frame_skip = 3;
+        break;
+      case 190:
+        m_frame_show = 5;
+        m_frame_skip = 3;
+        break;
+      case 195:
+        m_frame_show = 5;
+        m_frame_skip = 3;
+        break;
+      case 200:
+        m_frame_show = 5;
+        m_frame_skip = 4;
+        break;
+      default:
+        m_frame_show = 0;
+        m_frame_skip = 0;
+        break;
+    }
+
+    VERBOSE(VB_PLAYBACK, QString("PredictFrameSkip: speed %1 show %2 skip %3")
+            .arg(play_speed).arg(m_frame_show).arg(m_frame_skip));
+
+    m_frame_skip_idx = m_frame_show_idx = 0;
+}
+
 void NuppelVideoPlayer::SetScanType(FrameScanType scan)
 {
     QMutexLocker locker(&videofiltersLock);
@@ -1037,6 +1141,7 @@ void NuppelVideoPlayer::SetScanType(Fram
     {
         m_scan = scan;
         videosync->SetFrameInterval(frame_interval, false);
+        PredictFrameSkip(scan);
         return;
     }
 
@@ -1084,6 +1189,9 @@ void NuppelVideoPlayer::SetScanType(Fram
             (frame_interval>>1) : frame_interval);
     }
 
+    if (m_scan != scan)
+        PredictFrameSkip(scan);
+
     m_scan = scan;
 }
 
@@ -2377,110 +2485,139 @@ void NuppelVideoPlayer::AVSync(void)
         ps = kScan_Progressive;
 
     bool dropframe = false;
-    if (diverge < -MAXDIVERGE)
-    {
-        dropframe = true;
-        // If video is way behind of audio, adjust for it...
-        QString dbg = QString("Video is %1 frames behind audio (too slow), ")
-            .arg(-diverge);
 
-        // Reset A/V Sync
-        lastsync = true;
-
-        if (buffer && !using_null_videoout &&
-            videoOutput->hasHWAcceleration() &&
-           !videoOutput->IsSyncLocked())
-        {
-            // If we are using certain hardware decoders, so we've already done
-            // the decoding; display the frame, but don't wait for A/V Sync.
-            // Excludes HW decoder/render methods that are locked to
-            // the vertical sync (e.g. VDPAU)
-            videoOutput->PrepareFrame(buffer, kScan_Intr2ndField);
-            videoOutput->Show(kScan_Intr2ndField);
-            VERBOSE(VB_PLAYBACK, LOC + dbg + "skipping A/V wait.");
+    if (m_frame_show > 0)
+    {
+        if (m_frame_show_idx == m_frame_show)
+        {
+            if (m_frame_skip_idx++ == m_frame_skip)
+            {
+                m_frame_show_idx = 1;
+                m_frame_skip_idx = 0;
+//                VERBOSE(VB_PLAYBACK, QString("SHOW %1").arg(m_frame_show_idx));
+            }
+            else
+            {
+//                VERBOSE(VB_PLAYBACK, QString("SKIP %1").arg(m_frame_skip_idx));;
+                dropframe = true;
+                lastsync = true;
+            }
         }
         else
         {
-            // If we are using software decoding, skip this frame altogether.
-            VERBOSE(VB_PLAYBACK, LOC + dbg + "dropping frame to catch up.");
+            ++m_frame_show_idx;
+//            VERBOSE(VB_PLAYBACK, QString("SHOW %1").arg(m_frame_show_idx));
         }
     }
-    else if (!using_null_videoout)
-    {
-        // if we get here, we're actually going to do video output
-        if (buffer)
-            videoOutput->PrepareFrame(buffer, ps);
 
-        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2")
-                .arg(avsync_adjustment).arg(m_double_framerate));
-        videosync->WaitForFrame(avsync_adjustment + repeat_delay);
-        VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show");
-        if (!resetvideo)
-            videoOutput->Show(ps);
-
-        if (videoOutput->IsErrored())
+    if (!dropframe)
+    {
+        if (diverge < -MAXDIVERGE)
         {
-            VERBOSE(VB_IMPORTANT, "NVP: Error condition detected "
-                    "in videoOutput after Show(), aborting playback.");
-            SetErrored(QObject::tr("Serious error detected in Video Output"));
-            return;
+            dropframe = true;
+            // If video is way behind of audio, adjust for it...
+            QString dbg = QString("Video is %1 frames behind audio (too slow), ")
+                          .arg(-diverge);
+
+            // Reset A/V Sync
+            lastsync = true;
+
+            if (buffer && !using_null_videoout &&
+                videoOutput->hasHWAcceleration() &&
+                !videoOutput->IsSyncLocked())
+            {
+                // If we are using certain hardware decoders, so we've already done
+                // the decoding; display the frame, but don't wait for A/V Sync.
+                // Excludes HW decoder/render methods that are locked to
+                // the vertical sync (e.g. VDPAU)
+                videoOutput->PrepareFrame(buffer, kScan_Intr2ndField);
+                videoOutput->Show(kScan_Intr2ndField);
+                VERBOSE(VB_PLAYBACK, LOC + dbg + "skipping A/V wait.");
+            }
+            else
+            {
+                // If we are using software decoding, skip this frame altogether.
+                VERBOSE(VB_PLAYBACK, LOC + dbg + "dropping frame to catch up.");
+            }
         }
-
-        if (m_double_framerate)
+        else if (!using_null_videoout)
         {
-            //second stage of deinterlacer processing
-            ps = (kScan_Intr2ndField == ps) ?
-                kScan_Interlaced : kScan_Intr2ndField;
-
-            if (m_double_process && ps != kScan_Progressive)
-            {
-                videofiltersLock.lock();
-                if (player_ctx->buffer->isDVD() &&
-                    player_ctx->buffer->DVD()->InStillFrame() &&
-                    videoOutput->ValidVideoFrames() < 3)
-                {
-                    videoOutput->ProcessFrame(buffer, NULL, NULL,
-                                              pip_players, ps);
-                }
-                else
+            // if we get here, we're actually going to do video output
+            if (buffer)
+                videoOutput->PrepareFrame(buffer, ps);
+
+            VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, QString("AVSync waitforframe %1 %2")
+                    .arg(avsync_adjustment).arg(m_double_framerate));
+            videosync->WaitForFrame(avsync_adjustment + repeat_delay);
+            VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, "AVSync show");
+            if (!resetvideo)
+                videoOutput->Show(ps);
+
+            if (videoOutput->IsErrored())
+            {
+                VERBOSE(VB_IMPORTANT, "NVP: Error condition detected "
+                        "in videoOutput after Show(), aborting playback.");
+                SetErrored(QObject::tr("Serious error detected in Video Output"));
+                return;
+            }
+
+            if (m_double_framerate)
+            {
+                //second stage of deinterlacer processing
+                ps = (kScan_Intr2ndField == ps) ?
+                     kScan_Interlaced : kScan_Intr2ndField;
+
+                if (m_double_process && ps != kScan_Progressive)
                 {
-                    videoOutput->ProcessFrame(
-                        buffer, osd, videoFilters, pip_players, ps);
+                    videofiltersLock.lock();
+                    if (player_ctx->buffer->isDVD() &&
+                        player_ctx->buffer->DVD()->InStillFrame() &&
+                        videoOutput->ValidVideoFrames() < 3)
+                    {
+                        videoOutput->ProcessFrame(buffer, NULL, NULL,
+                                                  pip_players, ps);
+                    }
+                    else
+                    {
+                        videoOutput->ProcessFrame(
+                                                  buffer, osd, videoFilters, pip_players, ps);
+                    }
+                    videofiltersLock.unlock();
                 }
-                videofiltersLock.unlock();
-            }
 
-            if (buffer)
-                videoOutput->PrepareFrame(buffer, ps);
+                if (buffer)
+                    videoOutput->PrepareFrame(buffer, ps);
 
-            // Display the second field
-            videosync->AdvanceTrigger();
+                // Display the second field
+                videosync->AdvanceTrigger();
 #ifdef NEW_AVSYNC
-            videosync->WaitForFrame(avsync_adjustment);
+                videosync->WaitForFrame(avsync_adjustment);
 #else
-            videosync->WaitForFrame(0);
+                videosync->WaitForFrame(0);
 #endif
-            if (!resetvideo)
-            {
-                videoOutput->Show(ps);
+                if (!resetvideo)
+                {
+                    videoOutput->Show(ps);
+                }
             }
-        }
 
-        repeat_delay = frame_interval * buffer->repeat_pict * 0.5;
+            repeat_delay = frame_interval * buffer->repeat_pict * 0.5;
 
-        if (repeat_delay)
-            VERBOSE(VB_TIMESTAMP, QString("A/V repeat_pict, adding %1 repeat "
-                    "delay").arg(repeat_delay));
-    }
-    else
-    {
-        videosync->WaitForFrame(0);
+            if (repeat_delay)
+                VERBOSE(VB_TIMESTAMP,
+                        QString("A/V repeat_pict, adding %1 repeat "
+                                "delay").arg(repeat_delay));
+        }
+        else
+        {
+            videosync->WaitForFrame(0);
+        }
     }
 
     if (output_jmeter && output_jmeter->RecordCycleTime())
     {
         VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, QString("A/V avsync_delay: %1, "
-                "avsync_avg: %2, warpfactor: %3, warpfactor_avg: %4")
+                                                  "avsync_avg: %2, warpfactor: %3, warpfactor_avg: %4")
                 .arg(avsync_delay / 1000).arg(avsync_avg / 1000)
                 .arg(warpfactor).arg(warpfactor_avg));
     }
@@ -2512,15 +2649,15 @@ void NuppelVideoPlayer::AVSync(void)
         audio_lock.unlock();
 #if 0
         VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, QString(
-                    "A/V timecodes audio %1 video %2 frameinterval %3 "
-                    "avdel %4 avg %5 tcoffset %6")
+                                                  "A/V timecodes audio %1 video %2 frameinterval %3 "
+                                                  "avdel %4 avg %5 tcoffset %6")
                 .arg(currentaudiotime)
                 .arg(buffer->timecode)
                 .arg(frame_interval)
                 .arg(buffer->timecode - currentaudiotime)
                 .arg(avsync_avg)
                 .arg(tc_wrap[TC_AUDIO])
-                 );
+                );
 #endif
         if (currentaudiotime != 0 && buffer->timecode != 0)
         { // currentaudiotime == 0 after a seek
@@ -3550,8 +3687,11 @@ bool NuppelVideoPlayer::StartPlaying(boo
 
             play_speed = next_play_speed;
             normal_speed = next_normal_speed;
+
             VERBOSE(VB_PLAYBACK, LOC + "Changing speed to " << play_speed);
 
+            PredictFrameSkip(m_scan);
+
             if (play_speed == 0.0)
             {
                 DoPause();
Index: libs/libmythtv/NuppelVideoPlayer.h
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.h.orig
+++ libs/libmythtv/NuppelVideoPlayer.h
@@ -431,6 +431,7 @@ class MPUBLIC NuppelVideoPlayer : public
     FrameScanType detectInterlace(FrameScanType newScan, FrameScanType scan,
                                   float fps, int video_height);
     void AutoDeint(VideoFrame*);
+    void PredictFrameSkip(FrameScanType scan);
 
     // Private Sets
     void SetPlayingInfo(const ProgramInfo &pginfo);
@@ -805,6 +806,11 @@ class MPUBLIC NuppelVideoPlayer : public
     bool       audio_paused;
     int        repeat_delay;
 
+    int        m_frame_skip;
+    int        m_frame_show;
+    int        m_frame_skip_idx;
+    int        m_frame_show_idx;
+
     // Audio warping stuff
     float      warpfactor;
     float      warpfactor_avg;
