diff --git a/mythtv/libs/libmythtv/mythplayer.cpp b/mythtv/libs/libmythtv/mythplayer.cpp
index 0e0e208..b6dad9e 100644
--- a/mythtv/libs/libmythtv/mythplayer.cpp
+++ b/mythtv/libs/libmythtv/mythplayer.cpp
@@ -1682,6 +1682,16 @@ void MythPlayer::InitAVSync(void)
     }
 }
 
+int64_t MythPlayer::AVSyncGetAudiotime(void)
+{
+    int64_t currentaudiotime = 0;
+    if (normal_speed)
+    {
+        currentaudiotime = audio.GetAudioTime();
+    }
+    return currentaudiotime;
+}
+
 #define MAXDIVERGE  3.0f
 #define DIVERGELIMIT 30.0f
 void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay)
@@ -1698,6 +1708,8 @@ void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay)
 
     float diverge = 0.0f;
     int frameDelay = m_double_framerate ? frame_interval / 2 : frame_interval;
+    int vsync_delay_clock = 0;
+    int64_t currentaudiotime = 0;
 
     // attempt to reduce fps for standalone PIP
     if (player_ctx->IsPIP() && framesPlayed % 2)
@@ -1758,6 +1770,7 @@ void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay)
         // Reset A/V Sync
         lastsync = true;
 
+        currentaudiotime = AVSyncGetAudiotime();
         if (!using_null_videoout &&
             videoOutput->hasHWAcceleration() &&
            !videoOutput->IsSyncLocked())
@@ -1786,7 +1799,9 @@ void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay)
         osdLock.unlock();
         VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + QString("AVSync waitforframe %1 %2")
                 .arg(avsync_adjustment).arg(m_double_framerate));
-        videosync->WaitForFrame(frameDelay + avsync_adjustment + repeat_delay);
+        vsync_delay_clock = videosync->WaitForFrame
+                            (frameDelay + avsync_adjustment + repeat_delay);
+        currentaudiotime = AVSyncGetAudiotime();
         VERBOSE(VB_PLAYBACK|VB_TIMESTAMP, LOC + "AVSync show");
         videoOutput->Show(ps);
 
@@ -1815,7 +1830,7 @@ void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay)
             videoOutput->PrepareFrame(buffer, ps, osd);
             osdLock.unlock();
             // Display the second field
-            videosync->WaitForFrame(frameDelay + avsync_adjustment);
+            vsync_delay_clock = videosync->WaitForFrame(frameDelay + avsync_adjustment);
             videoOutput->Show(ps);
         }
 
@@ -1827,19 +1842,27 @@ void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay)
     }
     else
     {
-        videosync->WaitForFrame(frameDelay);
+        vsync_delay_clock = videosync->WaitForFrame(frameDelay);
+        currentaudiotime = AVSyncGetAudiotime();
     }
 
     if (output_jmeter)
-        output_jmeter->RecordCycleTime();
-
+    {
+        if (output_jmeter->RecordCycleTime())
+        {
+            VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V avsync_delay: %1, "
+                    "avsync_avg: %2")
+                    .arg(avsync_delay / 1000).arg(avsync_avg / 1000)
+                    );
+        }
+    }
     avsync_adjustment = 0;
 
     if (diverge > MAXDIVERGE)
     {
         // If audio is way behind of video, adjust for it...
         // by cutting the frame rate in half for the length of this frame
-        avsync_adjustment = refreshrate;
+        avsync_adjustment = frame_interval;
         lastsync = true;
         VERBOSE(VB_PLAYBACK, LOC +
                 QString("Video is %1 frames ahead of audio,\n"
@@ -1848,57 +1871,65 @@ void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay)
 
     if (audio.HasAudioOut() && normal_speed)
     {
+        // must be sampled here due to Show delays
         int64_t currentaudiotime = audio.GetAudioTime();
-        VERBOSE(VB_TIMESTAMP, LOC + QString(
+        VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString(
                     "A/V timecodes audio %1 video %2 frameinterval %3 "
                     "avdel %4 avg %5 tcoffset %6 "
-                    "avp %7 avpen %8")
+                    "avp %7 avpen %8 avdc %9")
                 .arg(currentaudiotime)
                 .arg(timecode)
                 .arg(frame_interval)
-                .arg(timecode - currentaudiotime)
+                .arg(timecode - currentaudiotime - (int)(vsync_delay_clock*audio.GetStretchFactor()+500)/1000)
                 .arg(avsync_avg)
                 .arg(tc_wrap[TC_AUDIO])
                 .arg(avsync_predictor)
                 .arg(avsync_predictor_enabled)
+                .arg(vsync_delay_clock)
                  );
         if (currentaudiotime != 0 && timecode != 0)
         { // currentaudiotime == 0 after a seek
             // The time at the start of this frame (ie, now) is given by
             // last->timecode
-            int delta = (int)((timecode - prevtc)/play_speed) - (frame_interval / 1000);
-            prevtc = timecode;
-            //cerr << delta << " ";
-
-            // If the timecode is off by a frame (dropped frame) wait to sync
-            if (delta > (int) frame_interval / 1200 &&
-                delta < (int) frame_interval / 1000 * 3 &&
-                prevrp == 0)
+            if (prevtc != 0)
             {
-                // wait an extra frame interval
-                avsync_adjustment += frame_interval;
+                int delta = (int)((timecode - prevtc)/play_speed) - (frame_interval / 1000);
+                // If the timecode is off by a frame (dropped frame) wait to sync
+                if (delta > (int) frame_interval / 1200 &&
+                    delta < (int) frame_interval / 1000 * 3 &&
+                    prevrp == 0)
+                {
+                    // wait an extra frame interval
+                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V delay %1").arg(delta));
+                    avsync_adjustment += frame_interval;
+                }
             }
+            prevtc = timecode;
             prevrp = repeat_pict;
 
-            avsync_delay = (timecode - currentaudiotime) * 1000;//usec
+            avsync_delay = (timecode - currentaudiotime) * 1000 - (int)(vsync_delay_clock*audio.GetStretchFactor());  //usec
             // prevents major jitter when pts resets during dvd title
             if (avsync_delay > 2000000 && limit_delay)
                 avsync_delay = 90000;
             avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4;
 
+            int avsync_used = avsync_avg;
+            if (labs(avsync_used) > labs(avsync_delay))
+                avsync_used = avsync_delay;
+
             /* If the audio time codes and video diverge, shift
                the video by one interlaced field (1/2 frame) */
             if (!lastsync)
             {
-                if (avsync_avg > frame_interval * 3 / 2)
+                if (avsync_used > refreshrate)
                 {
                     avsync_adjustment += refreshrate;
-                    lastsync = true;
+                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V avg high extend");
                 }
-                else if (avsync_avg < 0 - frame_interval * 3 / 2)
+                else if (avsync_avg < 0 - refreshrate)
                 {
                     avsync_adjustment -= refreshrate;
-                    lastsync = true;
+                    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + "A/V avg high skip");
                 }
             }
             else
@@ -1909,6 +1940,10 @@ void MythPlayer::AVSync(VideoFrame *buffer, bool limit_delay)
             ResetAVSync();
         }
     }
+    else
+    {
+        VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC + QString("A/V no sync proc ns:%1").arg(normal_speed));
+    }
 }
 
 void MythPlayer::RefreshPauseFrame(void)
diff --git a/mythtv/libs/libmythtv/mythplayer.h b/mythtv/libs/libmythtv/mythplayer.h
index c4744bf..293f8ac 100644
--- a/mythtv/libs/libmythtv/mythplayer.h
+++ b/mythtv/libs/libmythtv/mythplayer.h
@@ -514,6 +514,7 @@ class MPUBLIC MythPlayer
     void  InitAVSync(void);
     virtual void AVSync(VideoFrame *buffer, bool limit_delay = false);
     void  ResetAVSync(void);
+    int64_t AVSyncGetAudiotime(void);
     void  SetFrameInterval(FrameScanType scan, double speed);
     void  FallbackDeint(void);
     void  CheckExtraAudioDecode(void);
diff --git a/mythtv/libs/libmythtv/vsync.cpp b/mythtv/libs/libmythtv/vsync.cpp
index 6e1b891..9d0a005 100644
--- a/mythtv/libs/libmythtv/vsync.cpp
+++ b/mythtv/libs/libmythtv/vsync.cpp
@@ -178,7 +178,7 @@ int VideoSync::CalcDelay()
         m_nexttrigger = now + ret_val;
     }
 
-    if (ret_val < -m_frame_interval)
+    if (ret_val < -m_frame_interval && m_frame_interval >= m_refresh_interval)
     {
         ret_val = -m_frame_interval;
 
@@ -293,7 +293,7 @@ void DRMVideoSync::Start(void)
     VideoSync::Start();
 }
 
-void DRMVideoSync::WaitForFrame(int sync_delay)
+int DRMVideoSync::WaitForFrame(int sync_delay)
 {
     // Offset for externally-provided A/V sync delay
     m_nexttrigger += sync_delay;
@@ -316,7 +316,7 @@ void DRMVideoSync::WaitForFrame(int sync_delay)
     if (m_delay > 0)
     {
         // Wait for any remaining retrace intervals in one pass.
-        int n = m_delay / m_refresh_interval + 1;
+        int n = (m_delay + m_refresh_interval - 1) / m_refresh_interval;
 
         drm_wait_vblank_t blank;
         blank.request.type = DRM_VBLANK_RELATIVE;
@@ -327,6 +327,8 @@ void DRMVideoSync::WaitForFrame(int sync_delay)
         //cerr  << " Delay " << m_delay << endl;
     }
 
+    return m_delay;
+
     KeepPhase();
 }
 #endif /* !_WIN32 */
@@ -397,7 +399,7 @@ void OpenGLVideoSync::Start(void)
 #endif /* USING_OPENGL_VSYNC */
 }
 
-void OpenGLVideoSync::WaitForFrame(int sync_delay)
+int OpenGLVideoSync::WaitForFrame(int sync_delay)
 {
     (void) sync_delay;
 #ifdef USING_OPENGL_VSYNC
@@ -409,11 +411,11 @@ void OpenGLVideoSync::WaitForFrame(int sync_delay)
         m_delay = CalcDelay();
         if (m_delay > 0)
             usleep(m_delay);
-        return;
+        return 0;
     }
 
     if (!m_context)
-        return;
+        return 0;
 
     unsigned int frameNum = m_context->GetVideoSyncCount();
 
@@ -427,11 +429,13 @@ void OpenGLVideoSync::WaitForFrame(int sync_delay)
     // Wait for any remaining retrace intervals in one pass.
     if (m_delay > 0)
     {
-        uint n = m_delay / m_refresh_interval + 1;
+        uint n = (m_delay + m_refresh_interval - 1) / m_refresh_interval;
         m_context->WaitForVideoSync((n+1), (frameNum+n)%(n+1), &frameNum);
         m_delay = CalcDelay();
     }
 
+    return m_delay;
+
     KeepPhase();
 #endif /* USING_OPENGL_VSYNC */
 }
@@ -479,7 +483,7 @@ bool RTCVideoSync::TryInit(void)
     return true;
 }
 
-void RTCVideoSync::WaitForFrame(int sync_delay)
+int RTCVideoSync::WaitForFrame(int sync_delay)
 {
     m_nexttrigger += sync_delay;
 
@@ -494,6 +498,7 @@ void RTCVideoSync::WaitForFrame(int sync_delay)
         if ((val < 0) && (m_delay > 0))
             usleep(m_delay);
     }
+    return 0;
 }
 #endif /* __linux__ */
 
@@ -517,7 +522,7 @@ bool VDPAUVideoSync::TryInit(void)
     return true;
 }
 
-void VDPAUVideoSync::WaitForFrame(int sync_delay)
+int VDPAUVideoSync::WaitForFrame(int sync_delay)
 {
     // Offset for externally-provided A/V sync delay
     m_nexttrigger += sync_delay;
@@ -528,6 +533,7 @@ void VDPAUVideoSync::WaitForFrame(int sync_delay)
 
     VideoOutputVDPAU *vo = (VideoOutputVDPAU *)(m_video_output);
     vo->SetNextFrameDisplayTimeOffset(m_delay);
+    return 0;
 }
 #endif
 
@@ -548,7 +554,7 @@ bool BusyWaitVideoSync::TryInit(void)
     return true;
 }
 
-void BusyWaitVideoSync::WaitForFrame(int sync_delay)
+int BusyWaitVideoSync::WaitForFrame(int sync_delay)
 {
     // Offset for externally-provided A/V sync delay
     m_nexttrigger += sync_delay;
@@ -577,6 +583,7 @@ void BusyWaitVideoSync::WaitForFrame(int sync_delay)
         if (cnt > 1)
             m_cheat -= 200;
     }
+    return 0;
 }
 
 USleepVideoSync::USleepVideoSync(VideoOutput *vo,
@@ -594,7 +601,7 @@ bool USleepVideoSync::TryInit(void)
     return true;
 }
 
-void USleepVideoSync::WaitForFrame(int sync_delay)
+int USleepVideoSync::WaitForFrame(int sync_delay)
 {
     // Offset for externally-provided A/V sync delay
     m_nexttrigger += sync_delay;
@@ -602,5 +609,6 @@ void USleepVideoSync::WaitForFrame(int sync_delay)
     m_delay = CalcDelay();
     if (m_delay > 0)
         usleep(m_delay);
+    return 0;
 }
 
diff --git a/mythtv/libs/libmythtv/vsync.h b/mythtv/libs/libmythtv/vsync.h
index 310d866..3db298b 100644
--- a/mythtv/libs/libmythtv/vsync.h
+++ b/mythtv/libs/libmythtv/vsync.h
@@ -64,6 +64,7 @@ class VideoSync
     virtual void Start(void);
 
     /** \brief Waits for next a frame or field.
+     *   Returns delay to real frame timing in usec
      *
      *   Start(void), WaitForFrame(void), and Stop(void) should
      *   always be called from same thread, to prevent bad
@@ -72,7 +73,7 @@ class VideoSync
      *  \param sync_delay time until the desired frame or field
      *  \sa CalcDelay(void), KeepPhase(void)
      */
-    virtual void WaitForFrame(int sync_delay) = 0;
+    virtual int WaitForFrame(int sync_delay) = 0;
 
     /// \brief Returns the (minimum) refresh interval of the output device.
     int getRefreshInterval(void) const { return m_refresh_interval; }
@@ -123,7 +124,7 @@ class DRMVideoSync : public VideoSync
     QString getName(void) const { return QString("DRM"); }
     bool TryInit(void);
     void Start(void);
-    void WaitForFrame(int sync_delay);
+    int WaitForFrame(int sync_delay);
 
   private:
     int m_dri_fd;
@@ -164,7 +165,7 @@ class OpenGLVideoSync : public VideoSync
     QString getName(void) const { return QString("SGI OpenGL"); }
     bool TryInit(void);
     void Start(void);
-    void WaitForFrame(int sync_delay);
+    int WaitForFrame(int sync_delay);
 
   private:
     MythRenderOpenGL  *m_context;
@@ -192,7 +193,7 @@ class RTCVideoSync : public VideoSync
 
     QString getName(void) const { return QString("RTC"); }
     bool TryInit(void);
-    void WaitForFrame(int sync_delay);
+    int WaitForFrame(int sync_delay);
 
   private:
     int m_rtcfd;
@@ -212,7 +213,7 @@ class VDPAUVideoSync : public VideoSync
 
     QString getName(void) const { return QString("VDPAU"); }
     bool TryInit(void);
-    void WaitForFrame(int sync_delay);
+    int WaitForFrame(int sync_delay);
 
   private:
 };
@@ -239,7 +240,7 @@ class BusyWaitVideoSync : public VideoSync
 
     QString getName(void) const { return QString("USleep with busy wait"); }
     bool TryInit(void);
-    void WaitForFrame(int sync_delay);
+    int WaitForFrame(int sync_delay);
 
   private:
     int m_cheat;
@@ -266,6 +267,6 @@ class USleepVideoSync : public VideoSync
 
     QString getName(void) const { return QString("USleep"); }
     bool TryInit(void);
-    void WaitForFrame(int sync_delay);
+    int WaitForFrame(int sync_delay);
 };
 #endif /* VSYNC_H_INCLUDED */
