Index: libs/libmythtv/NuppelVideoPlayer.h
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.h	(revision 8730)
+++ libs/libmythtv/NuppelVideoPlayer.h	(working copy)
@@ -14,6 +14,7 @@
 #include "recordingprofile.h"
 #include "videooutbase.h"
 #include "tv_play.h"
+#include "yuv2rgb.h"
 
 extern "C" {
 #include "filter.h"
@@ -213,6 +214,11 @@
     void DiscardVideoFrames(bool next_frame_keyframe);
     void DrawSlice(VideoFrame *frame, int x, int y, int w, int h);
 
+    // Preview Image stuff
+    const QImage &GetARGBFrame(const QSize &size);
+    const unsigned char *GetScaledFrame(QSize &size);
+    void ShutdownYUVResize(void);
+
     // Reinit
     void    ReinitOSD(void);
     void    ReinitVideo(void);
@@ -493,6 +499,22 @@
     NuppelVideoPlayer *setpipplayer;
     bool needsetpipplayer;
 
+    // Preview window support
+    bool                argb_need_copy;
+    unsigned char      *argb_buf;
+    QSize               argb_size;
+    QImage              argb_scaled_img;
+
+    yuv2rgb_fun         conv_yuv2rgba;
+
+    bool                yuv_need_copy;
+    unsigned char      *yuv_frame_scaled;
+    QSize               yuv_size_scaled;
+    QSize               yuv_size_unscaled;
+    ImgReSampleContext *yuv_scaler;
+
+    QMutex              argb_lock;
+
     // Filters
     QMutex   videofiltersLock;
     QString  videoFilterList;
Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
--- libs/libmythtv/NuppelVideoPlayer.cpp	(revision 8730)
+++ libs/libmythtv/NuppelVideoPlayer.cpp	(working copy)
@@ -126,8 +126,10 @@
       audio_samplerate(44100),      audio_stretchfactor(1.0f),
       // Picture-in-Picture
       pipplayer(NULL), setpipplayer(NULL), needsetpipplayer(false),
+      // Preview window support
+      argb_need_copy(false), argb_buf(NULL), argb_size(0,0),
       // Filters
-      videoFilterList(""),
+    videoFilterList(""),
       postfilt_width(0),            postfilt_height(0),
       videoFilters(NULL),           FiltMan(new FilterManager()),
       // Commercial filtering
@@ -185,6 +187,13 @@
     bool valid = false;
     uint tmp = mypage.toInt(&valid, 16);
     ttPageNum = (valid) ? tmp : ttPageNum;
+
+    conv_yuv2rgba     = yuv2rgb_init_mmx(32, MODE_RGB);
+    yuv_need_copy     = false;
+    yuv_frame_scaled  = NULL;
+    yuv_size_scaled   = QSize(0,0);
+    yuv_size_unscaled = QSize(0,0);
+    yuv_scaler        = NULL;
 }
 
 NuppelVideoPlayer::~NuppelVideoPlayer(void)
@@ -1054,6 +1063,104 @@
         vidExitLock.unlock();
 }
 
+void NuppelVideoPlayer::ShutdownYUVResize(void)
+{
+    if (yuv_frame_scaled)
+        delete [] yuv_frame_scaled;
+    if (yuv_scaler)
+        img_resample_close(yuv_scaler);
+
+    yuv_frame_scaled  = NULL;
+    yuv_scaler        = NULL;
+    yuv_size_unscaled = QSize(0,0);
+    yuv_size_scaled   = QSize(0,0);
+}
+
+const unsigned char *NuppelVideoPlayer::GetScaledFrame(QSize &size)
+{
+    size = QSize(size.width() & ~0x1, size.height() & ~0x1);
+
+    QSize vsize = QSize(video_width, video_height);
+    if ((vsize != yuv_size_unscaled) || (size != yuv_size_scaled))
+    {
+        ShutdownYUVResize();
+
+        uint sz = size.width() * size.height() * 3 / 2;
+        yuv_frame_scaled = new unsigned char[sz + 128];
+
+        yuv_size_unscaled = vsize;
+        yuv_size_scaled   = size;
+
+        yuv_scaler = img_resample_init(
+            size.width(), size.height(), vsize.width(), vsize.height());
+    }
+
+    argb_lock.lock();
+    yuv_need_copy = true;
+
+    while (yuv_need_copy)
+    {
+        argb_lock.unlock();
+        usleep(5000);
+        argb_lock.lock();
+    }
+    argb_lock.unlock();
+
+    return yuv_frame_scaled;
+}
+
+#if 0
+const QImage &NuppelVideoPlayer::GetARGBFrame(const QSize &size)
+{
+    argb_lock.lock();
+    argb_need_copy = true;
+
+    while (argb_need_copy)
+    {
+        argb_lock.unlock();
+        usleep(5000);
+        argb_lock.lock();
+    }
+    argb_lock.unlock();
+
+    MythTimer timer;
+    timer.start();
+    QImage img(argb_buf, argb_size.width(), argb_size.height(),
+               32, NULL, 65536 * 65536, QImage::LittleEndian);
+    argb_scaled_img = img.scale(size.width(), size.height());
+    cerr<<timer.elapsed()<<"s";
+
+    return argb_scaled_img;
+}
+#else
+const QImage &NuppelVideoPlayer::GetARGBFrame(const QSize &Xsize)
+{
+    QSize size = Xsize;
+
+    unsigned char *yuv_buf = (unsigned char*) GetScaledFrame(size);
+    if (argb_size != size)
+    { 
+        if (argb_buf)
+            delete [] argb_buf;
+        argb_buf = new unsigned char[size.width() * size.height() * 4];
+        argb_size = QSize(size.width(), size.height());
+    }
+
+    MythTimer timer;
+    timer.start();
+    uint w = argb_size.width(), h = argb_size.height();
+    conv_yuv2rgba(argb_buf,
+                  yuv_buf, yuv_buf + (w * h), yuv_buf + (w * h * 5 / 4),
+                  w, h, w * 4, w, w / 2, 0);
+
+    argb_scaled_img = QImage(argb_buf, argb_size.width(), argb_size.height(),
+                             32, NULL, 65536 * 65536, QImage::LittleEndian);
+    cerr<<timer.elapsed()<<"c";
+
+    return argb_scaled_img;
+}
+#endif
+
 void NuppelVideoPlayer::EmbedInWidget(WId wid, int x, int y, int w, int h)
 {
     if (videoOutput)
@@ -1775,6 +1882,44 @@
 
     VideoFrame *frame = videoOutput->GetLastShownFrame();
 
+    if (argb_need_copy)
+    {
+        QMutexLocker locker(&argb_lock);
+        MythTimer timer;
+        timer.start();
+        if ((argb_size.width()  != video_width) ||
+            (argb_size.height() != video_height))
+        { 
+            if (argb_buf)
+                delete [] argb_buf;
+            argb_buf = new unsigned char[video_width * video_height * 4];
+            argb_size = QSize(video_width, video_height);
+        }
+        unsigned char *yuv_buf = frame->buf;
+        uint w = video_width, h = video_height;
+        conv_yuv2rgba(argb_buf,
+                      yuv_buf, yuv_buf + (w * h), yuv_buf + (w * h * 5 / 4),
+                      w, h, w * 4, w, w / 2, 0);
+        argb_need_copy = false;
+        cerr<<timer.elapsed()<<"c";
+    }
+
+    if (yuv_need_copy)
+    {
+        QMutexLocker locker(&argb_lock);
+        MythTimer timer;
+        timer.start();
+        AVPicture img_out, img_in;
+        avpicture_fill(&img_out, yuv_frame_scaled, PIX_FMT_YUV420P,
+                       yuv_size_scaled.width(), yuv_size_scaled.height());
+        avpicture_fill(&img_in, frame->buf, PIX_FMT_YUV420P,
+                       yuv_size_unscaled.width(), yuv_size_unscaled.height());
+
+        img_resample(yuv_scaler, &img_out, &img_in);
+        yuv_need_copy = false;
+        cerr<<timer.elapsed()<<"s";
+    }
+
     if (subtitlesOn)
     {
         ShowText();
Index: libs/libmythtv/videoout_null.cpp
===================================================================
--- libs/libmythtv/videoout_null.cpp	(revision 8730)
+++ libs/libmythtv/videoout_null.cpp	(working copy)
@@ -6,7 +6,7 @@
 #include "videoout_null.h"
 
 const int kNumBuffers = 31;
-const int kNeedFreeFrames = 1;
+const int kNeedFreeFrames = 2;
 const int kPrebufferFramesNormal = 12;
 const int kPrebufferFramesSmall = 4;
 const int kKeepPrebuffer = 2;
Index: libs/libmythtv/tv_rec.cpp
===================================================================
--- libs/libmythtv/tv_rec.cpp	(revision 8730)
+++ libs/libmythtv/tv_rec.cpp	(working copy)
@@ -1212,46 +1212,28 @@
         if (curRecording)
             curRecording->UpdateInUseMark();
 
+        // Check for the end of the current program..
         if (GetState() == kState_WatchingLiveTV)
         {
-            bool enable_livetv_ui = false;
-            if (pseudoLiveTVRecording &&
-                (QDateTime::currentDateTime() > recordEndTime ||
-                 HasFlags(kFlagFinishRecording)))
-            {
+#define LIVETV_END (now >= curRecording->endts)
+// use the following instead to test ringbuffer switching
+//#define LIVETV_END (now >= curRecording->recstartts.addSecs(60))
+
+            QDateTime now   = QDateTime::currentDateTime();
+            bool has_finish = HasFlags(kFlagFinishRecording);
+            bool has_rec    = pseudoLiveTVRecording;
+            bool rec_soon   = pendingRecording;
+            bool enable_ui  = true;
+
+            if (has_rec && (has_finish || (now > recordEndTime)))
                 SetPseudoLiveTVRecording(NULL);
-                enable_livetv_ui = true;
-            }
-            else if (curRecording &&
-                     !pseudoLiveTVRecording && !pendingRecording)
+            else if (!has_rec && !rec_soon && curRecording && LIVETV_END)
+                SwitchLiveTVRingBuffer();
+            else
+                enable_ui = false;
+
+            if (enable_ui)
             {
-//#define TESTING_RING_BUFFER_SWITCHING
-#ifdef TESTING_RING_BUFFER_SWITCHING
-                if ((QDateTime::currentDateTime() >=
-                     curRecording->recstartts.addSecs(60)))
-#else
-                if ((QDateTime::currentDateTime() >= curRecording->endts))
-#endif
-                {
-                    CheckForRecGroupChange();
-                    if (pseudoLiveTVRecording)
-                    {
-                        // If the last recording was flagged for keeping
-                        // in the frontend, then add the recording rule
-                        // so that transcode, commfrag, etc can be run.
-                        recordEndTime = 
-                            GetRecordEndTime(pseudoLiveTVRecording);
-                        NotifySchedulerOfRecording(curRecording);
-                    }
-                    else
-                    {
-                        SwitchLiveTVRingBuffer();
-                        enable_livetv_ui = true;
-                    }
-                }
-            }
-            if (enable_livetv_ui)
-            {
                 VERBOSE(VB_IMPORTANT, LOC + "Enabling Full LiveTV UI.");
                 QString message = QString("LIVETV_WATCH %1 0").arg(cardid);
                 MythEvent me(message);
Index: libs/libmythtv/videobuffers.cpp
===================================================================
--- libs/libmythtv/videobuffers.cpp	(revision 8730)
+++ libs/libmythtv/videobuffers.cpp	(working copy)
@@ -10,7 +10,7 @@
 #include "videoout_xv.h" // for xvmc stuff
 #endif
 
-#define DEBUG_FRAME_LOCKS 0
+#define DEBUG_FRAME_LOCKS 1
 
 #define TRY_LOCK_SPINS                 100
 #define TRY_LOCK_SPINS_BEFORE_WARNING   10
Index: programs/mythfrontend/playbackbox.cpp
===================================================================
--- programs/mythfrontend/playbackbox.cpp	(revision 8730)
+++ programs/mythfrontend/playbackbox.cpp	(working copy)
@@ -867,38 +867,10 @@
             state = kStopped;
     }
 
-    /* if we are playing and nvp is running, then grab a new video frame */
     if ((state == kPlaying) && nvp->IsPlaying() && !playingSomething)
     {
-        int w = 0, h = 0;
-        VideoFrame *frame = nvp->GetCurrentFrame(w, h);
-
-        if (w == 0 || h == 0 || !frame || !(frame->buf))
-        {
-            nvp->ReleaseCurrentFrame(frame);
-            return;
-        }
-
-        unsigned char *yuv_buf = frame->buf;
-        if (conv_rgba_size.width() != w || conv_rgba_size.height() != h)
-        { 
-            if (conv_rgba_buf)
-                delete [] conv_rgba_buf;
-            conv_rgba_buf = new unsigned char[w * h * 4];
-            conv_rgba_size = QSize(w, h);
-        }
-
-        conv_yuv2rgba(conv_rgba_buf,
-                      yuv_buf, yuv_buf + (w * h), yuv_buf + (w * h * 5 / 4),
-                      w, h, w * 4, w, w / 2, 0);
-
-        nvp->ReleaseCurrentFrame(frame);
-
-        QImage img(conv_rgba_buf, w, h, 32, NULL, 65536 * 65536, 
-                   QImage::LittleEndian);
-        img = img.scale(videoRect.width(), videoRect.height());
-
-        p->drawImage(videoRect.x(), videoRect.y(), img);
+        const QImage &frame = nvp->GetARGBFrame(videoRect.size());
+        p->drawImage(videoRect.x(), videoRect.y(), frame);
     }
 
     /* have we timed out waiting for nvp to start? */
Index: programs/mythfrontend/playbackbox.h
===================================================================
--- programs/mythfrontend/playbackbox.h	(revision 8730)
+++ programs/mythfrontend/playbackbox.h	(working copy)
@@ -349,6 +349,9 @@
 
     mutable QMutex previewGeneratorLock;
     QMap<QString, PreviewGenerator*> previewGenerator;
+
+
+    QMutex xxx;
 };
 
 #endif
